Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ace0b5a792 | ||
|
|
04f22e6f47 | ||
|
|
e8c0fcdf63 | ||
|
|
7cf7ffe025 | ||
|
|
a2b700cf40 | ||
|
|
dfe8a20e2e | ||
|
|
3cfddbe75b | ||
|
|
8c610b6e36 | ||
|
|
2de890da5c | ||
|
|
bb673cc1a4 | ||
|
|
f6c8ef6246 | ||
|
|
01d382c0d3 | ||
|
|
f86fb256b2 | ||
|
|
ac85ab6f07 | ||
|
|
cfde3bcb0f | ||
|
|
a4ae8df66f | ||
|
|
3108661b0a | ||
|
|
3b076ea372 | ||
|
|
6369fb0cf3 |
@@ -1,12 +1,11 @@
|
||||
This library is fully staticly linked. There should be no external dependencies.
|
||||
|
||||
When building, use build.sh, not make. When building for tests use build.sh -t
|
||||
When building, use build.sh, not make.
|
||||
|
||||
Use it as follows: build.sh -m "useful comment on changes being made"
|
||||
|
||||
When making TUI menus, try to use the first leter of the command and the key to press to execute that command. For example, if the command is "Open file" try to use a keypress of "o" upper or lower case to signal to open the file. Use this instead of number keyed menus when possible. In the command, the letter should be underlined that signifies the command.
|
||||
|
||||
When deleting, everything gets moved to the Trash folder.
|
||||
|
||||
MAKEFILE POLICY: There should be only ONE Makefile in the entire project. All build logic (library, tests, examples, websocket) must be consolidated into the root Makefile. Do not create separate Makefiles in subdirectories as this creates testing inconsistencies where you test with one Makefile but run with another.
|
||||
|
||||
TESTS POLICY: On the printout, dont just show pass or fail, show the expected values, and what the actual result was. If dealing with nostr events, print the entire json event. If dealing with relay communication, show the whole communication.
|
||||
|
||||
|
||||
+3
-22
@@ -7,9 +7,10 @@ nips/
|
||||
node_modules/
|
||||
nostr-tools/
|
||||
tiny-AES-c/
|
||||
blossom/
|
||||
ndk/
|
||||
|
||||
|
||||
|
||||
secp256k1/
|
||||
Trash/debug_tests/
|
||||
node_modules/
|
||||
|
||||
@@ -20,23 +21,3 @@ node_modules/
|
||||
*.dll
|
||||
build/
|
||||
|
||||
# Build outputs/binaries (do not track)
|
||||
/websocket_debug
|
||||
/libnostr_core_arm64.a
|
||||
/tests/websocket_debug
|
||||
/tests/*_test
|
||||
/examples/input_detection
|
||||
/examples/keypair_generation
|
||||
/examples/mnemonic_derivation
|
||||
/examples/mnemonic_generation
|
||||
/examples/ots_tool
|
||||
/examples/relay_pool
|
||||
/examples/send_nip17_dm
|
||||
/examples/simple_keygen
|
||||
/examples/timestamping
|
||||
/examples/utility_functions
|
||||
/examples/version_test
|
||||
|
||||
# Local OpenTimestamps CLI output
|
||||
/examples/timestamped_*
|
||||
/examples/*.ots
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
description: "Increments and pushes the repo"
|
||||
---
|
||||
|
||||
Run increment_and_push.sh followed in the command line with a good description of the changes that were made.
|
||||
|
||||
For example: ./increment_and_push.sh "Fixed that nasty bug"
|
||||
@@ -0,0 +1,223 @@
|
||||
# NOSTR Core Library - Automatic Versioning System
|
||||
|
||||
## Overview
|
||||
|
||||
The NOSTR Core Library now features an automatic version increment system that automatically increments the patch version (e.g., v0.2.0 → v0.2.1) with each build. This ensures consistent versioning and traceability across builds.
|
||||
|
||||
## How It Works
|
||||
|
||||
### Version Format
|
||||
The library uses semantic versioning with the format: `vMAJOR.MINOR.PATCH`
|
||||
|
||||
- **MAJOR**: Incremented for breaking changes (manual)
|
||||
- **MINOR**: Incremented for new features (manual)
|
||||
- **PATCH**: Incremented automatically with each build
|
||||
|
||||
### Automatic Increment Process
|
||||
|
||||
1. **Version Detection**: The build system scans all git tags matching `v*.*.*` pattern
|
||||
2. **Highest Version**: Uses `sort -V` to find the numerically highest version (not chronologically latest)
|
||||
3. **Patch Increment**: Increments the patch number by 1
|
||||
4. **Git Tag Creation**: Creates a new git tag for the incremented version
|
||||
5. **File Generation**: Generates `nostr_core/version.h` and `nostr_core/version.c` with build metadata
|
||||
|
||||
### Generated Files
|
||||
|
||||
The system automatically generates two files during each build:
|
||||
|
||||
#### `nostr_core/version.h`
|
||||
```c
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 1
|
||||
#define VERSION_STRING "0.2.1"
|
||||
#define VERSION_TAG "v0.2.1"
|
||||
|
||||
#define BUILD_DATE "2025-08-09"
|
||||
#define BUILD_TIME "10:42:45"
|
||||
#define BUILD_TIMESTAMP "2025-08-09 10:42:45"
|
||||
|
||||
#define GIT_HASH "ca6b475"
|
||||
#define GIT_BRANCH "master"
|
||||
|
||||
// API functions
|
||||
const char* nostr_core_get_version(void);
|
||||
const char* nostr_core_get_version_full(void);
|
||||
const char* nostr_core_get_build_info(void);
|
||||
```
|
||||
|
||||
#### `nostr_core/version.c`
|
||||
Contains the implementation of the version API functions.
|
||||
|
||||
## Usage
|
||||
|
||||
### Building with Auto-Versioning
|
||||
|
||||
All major build targets automatically increment the version:
|
||||
|
||||
```bash
|
||||
# Build static library (increments version)
|
||||
./build.sh lib
|
||||
|
||||
# Build shared library (increments version)
|
||||
./build.sh shared
|
||||
|
||||
# Build all libraries (increments version)
|
||||
./build.sh all
|
||||
|
||||
# Build examples (increments version)
|
||||
./build.sh examples
|
||||
|
||||
# Install to system (increments version)
|
||||
./build.sh install
|
||||
```
|
||||
|
||||
### Non-Versioned Builds
|
||||
|
||||
Some targets do not increment versions:
|
||||
|
||||
```bash
|
||||
# Clean build artifacts (no version increment)
|
||||
./build.sh clean
|
||||
|
||||
# Run tests (no version increment)
|
||||
./build.sh test
|
||||
```
|
||||
|
||||
### Using Version Information in Code
|
||||
|
||||
```c
|
||||
#include "version.h"
|
||||
|
||||
// Get version string
|
||||
printf("Version: %s\n", nostr_core_get_version());
|
||||
|
||||
// Get full version with timestamp and commit
|
||||
printf("Full: %s\n", nostr_core_get_version_full());
|
||||
|
||||
// Get detailed build information
|
||||
printf("Build: %s\n", nostr_core_get_build_info());
|
||||
|
||||
// Use version macros
|
||||
#if VERSION_MAJOR >= 1
|
||||
// Use new API
|
||||
#else
|
||||
// Use legacy API
|
||||
#endif
|
||||
```
|
||||
|
||||
### Testing Version System
|
||||
|
||||
A version test example is provided:
|
||||
|
||||
```bash
|
||||
# Build and run version test
|
||||
gcc -I. -Inostr_core examples/version_test.c -o examples/version_test ./libnostr_core.a ./secp256k1/.libs/libsecp256k1.a -lm
|
||||
./examples/version_test
|
||||
```
|
||||
|
||||
## Version History Tracking
|
||||
|
||||
### View All Versions
|
||||
```bash
|
||||
# List all version tags
|
||||
git tag --list
|
||||
|
||||
# View version history
|
||||
git log --oneline --decorate --graph
|
||||
```
|
||||
|
||||
### Current Version
|
||||
```bash
|
||||
# Check current version
|
||||
cat VERSION
|
||||
|
||||
# Or check the latest git tag
|
||||
git describe --tags --abbrev=0
|
||||
```
|
||||
|
||||
## Manual Version Management
|
||||
|
||||
### Major/Minor Version Bumps
|
||||
|
||||
For major or minor version changes, manually create the appropriate tag:
|
||||
|
||||
```bash
|
||||
# For a minor version bump (new features)
|
||||
git tag v0.3.0
|
||||
|
||||
# For a major version bump (breaking changes)
|
||||
git tag v1.0.0
|
||||
```
|
||||
|
||||
The next build will automatically increment from the new base version.
|
||||
|
||||
### Resetting Version
|
||||
|
||||
To reset or fix version numbering:
|
||||
|
||||
```bash
|
||||
# Delete incorrect tags (if needed)
|
||||
git tag -d v0.2.1
|
||||
git push origin --delete v0.2.1
|
||||
|
||||
# Create correct base version
|
||||
git tag v0.2.0
|
||||
|
||||
# Next build will create v0.2.1
|
||||
```
|
||||
|
||||
## Integration Notes
|
||||
|
||||
### Makefile Integration
|
||||
- The `version.c` file is automatically included in `LIB_SOURCES`
|
||||
- Version files are compiled and linked with the library
|
||||
- Clean targets remove generated version object files
|
||||
|
||||
### Git Integration
|
||||
- Version files (`version.h`, `version.c`) are excluded from git via `.gitignore`
|
||||
- Only version tags and the `VERSION` file are tracked
|
||||
- Build system works in any git repository with version tags
|
||||
|
||||
### Build System Integration
|
||||
- Version increment is integrated directly into `build.sh`
|
||||
- No separate scripts or external dependencies required
|
||||
- Self-contained and portable across systems
|
||||
|
||||
## Example Output
|
||||
|
||||
When building, you'll see output like:
|
||||
|
||||
```
|
||||
[INFO] Incrementing version...
|
||||
[INFO] Current version: v0.2.0
|
||||
[INFO] New version: v0.2.1
|
||||
[SUCCESS] Created new version tag: v0.2.1
|
||||
[SUCCESS] Generated version.h and version.c
|
||||
[SUCCESS] Updated VERSION file to 0.2.1
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Version Not Incrementing
|
||||
- Ensure you're in a git repository
|
||||
- Check that git tags exist with `git tag --list`
|
||||
- Verify tag format matches `v*.*.*` pattern
|
||||
|
||||
### Tag Already Exists
|
||||
If a tag already exists, the build will continue with the existing version:
|
||||
|
||||
```
|
||||
[WARNING] Tag v0.2.1 already exists - using existing version
|
||||
```
|
||||
|
||||
### Missing Git Information
|
||||
If git is not available, version files will show "unknown" for git hash and branch.
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Automatic Traceability**: Every build has a unique version
|
||||
2. **Build Metadata**: Includes timestamp, git commit, and branch information
|
||||
3. **API Integration**: Version information accessible via C API
|
||||
4. **Zero Maintenance**: No manual version file editing required
|
||||
5. **Git Integration**: Automatic git tag creation for version history
|
||||
+183
-115
@@ -1,119 +1,187 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project(nostr_core VERSION 1.0.0 LANGUAGES C)
|
||||
|
||||
if(ESP_PLATFORM)
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"nostr_core/nostr_common.c"
|
||||
"nostr_core/nostr_log.c"
|
||||
"nostr_core/nip001.c"
|
||||
"nostr_core/nip004.c"
|
||||
"nostr_core/nip006.c"
|
||||
"nostr_core/nostr_signer.c"
|
||||
"nostr_core/nip019.c"
|
||||
"nostr_core/utils.c"
|
||||
"nostr_core/crypto/nostr_secp256k1.c"
|
||||
"nostr_core/crypto/nostr_aes.c"
|
||||
"nostr_core/crypto/nostr_chacha20.c"
|
||||
"cjson/cJSON.c"
|
||||
"platform/esp32/nostr_platform_esp32.c"
|
||||
"platform/esp32/nostr_http_esp32.c"
|
||||
"platform/esp32/nostr_websocket_esp32.c"
|
||||
INCLUDE_DIRS
|
||||
"."
|
||||
"nostr_core"
|
||||
"nostr_core/crypto"
|
||||
"cjson"
|
||||
"nostr_websocket"
|
||||
REQUIRES
|
||||
secp256k1
|
||||
esp_hw_support
|
||||
esp_http_client
|
||||
esp-tls
|
||||
tcp_transport
|
||||
mbedtls
|
||||
)
|
||||
# Set C standard
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE NOSTR_NO_FILESYSTEM=1)
|
||||
else()
|
||||
project(nostr_core_lib C)
|
||||
# Build options
|
||||
option(NOSTR_BUILD_STATIC "Build static library" ON)
|
||||
option(NOSTR_BUILD_SHARED "Build shared library" ON)
|
||||
option(NOSTR_BUILD_EXAMPLES "Build examples" ON)
|
||||
option(NOSTR_BUILD_TESTS "Build tests" ON)
|
||||
option(NOSTR_ENABLE_WEBSOCKETS "Enable WebSocket support" ON)
|
||||
option(NOSTR_USE_MBEDTLS "Use mbedTLS for crypto (otherwise use built-in)" OFF)
|
||||
|
||||
add_library(nostr_core STATIC
|
||||
nostr_core/nostr_common.c
|
||||
nostr_core/nostr_log.c
|
||||
nostr_core/request_validator.c
|
||||
nostr_core/nip001.c
|
||||
nostr_core/nip003.c
|
||||
nostr_core/nip004.c
|
||||
nostr_core/nip005.c
|
||||
nostr_core/nip006.c
|
||||
nostr_core/nip011.c
|
||||
nostr_core/nip013.c
|
||||
nostr_core/nip017.c
|
||||
nostr_core/nip019.c
|
||||
nostr_core/nip021.c
|
||||
nostr_core/nip042.c
|
||||
nostr_core/nip044.c
|
||||
nostr_core/nip046.c
|
||||
nostr_core/nip059.c
|
||||
nostr_core/nip060.c
|
||||
nostr_core/nip061.c
|
||||
nostr_core/nostr_signer.c
|
||||
nostr_core/nsigner_transport.c
|
||||
nostr_core/nsigner_client.c
|
||||
nostr_core/utils.c
|
||||
nostr_core/nostr_http.c
|
||||
nostr_core/core_relays.c
|
||||
nostr_core/core_relay_pool.c
|
||||
nostr_core/cashu_mint.c
|
||||
nostr_core/blossom_client.c
|
||||
nostr_core/crypto/nostr_secp256k1.c
|
||||
nostr_core/crypto/nostr_aes.c
|
||||
nostr_core/crypto/nostr_chacha20.c
|
||||
nostr_core/crypto/nostr_poly1305.c
|
||||
nostr_core/crypto/nostr_chacha20poly1305.c
|
||||
cjson/cJSON.c
|
||||
nostr_websocket/nostr_websocket_openssl.c
|
||||
platform/linux.c
|
||||
)
|
||||
|
||||
target_include_directories(nostr_core PUBLIC
|
||||
.
|
||||
nostr_core
|
||||
nostr_core/crypto
|
||||
cjson
|
||||
nostr_websocket
|
||||
)
|
||||
target_compile_definitions(nostr_core PRIVATE NOSTR_ENABLE_NSIGNER_CLIENT=1)
|
||||
target_compile_definitions(nostr_core PRIVATE ENABLE_FILE_LOGGING ENABLE_WEBSOCKET_LOGGING ENABLE_DEBUG_LOGGING)
|
||||
|
||||
# Link system dependencies
|
||||
find_package(PkgConfig QUIET)
|
||||
if(PkgConfig_FOUND)
|
||||
pkg_check_modules(SECP256K1 QUIET libsecp256k1)
|
||||
pkg_check_modules(OPENSSL QUIET openssl)
|
||||
pkg_check_modules(CURL QUIET libcurl)
|
||||
endif()
|
||||
|
||||
if(SECP256K1_FOUND)
|
||||
target_include_directories(nostr_core PRIVATE ${SECP256K1_INCLUDE_DIRS})
|
||||
target_link_libraries(nostr_core PRIVATE ${SECP256K1_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(nostr_core PRIVATE secp256k1)
|
||||
endif()
|
||||
|
||||
if(OPENSSL_FOUND)
|
||||
target_include_directories(nostr_core PRIVATE ${OPENSSL_INCLUDE_DIRS})
|
||||
target_link_libraries(nostr_core PRIVATE ${OPENSSL_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(nostr_core PRIVATE ssl crypto)
|
||||
endif()
|
||||
|
||||
if(CURL_FOUND)
|
||||
target_include_directories(nostr_core PRIVATE ${CURL_INCLUDE_DIRS})
|
||||
target_link_libraries(nostr_core PRIVATE ${CURL_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(nostr_core PRIVATE curl)
|
||||
endif()
|
||||
|
||||
target_link_libraries(nostr_core PRIVATE z dl pthread m)
|
||||
# Compiler flags
|
||||
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror")
|
||||
set(CMAKE_C_FLAGS_DEBUG "-g -O0")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG")
|
||||
endif()
|
||||
|
||||
# Include directories
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cjson)
|
||||
|
||||
# Source files
|
||||
set(NOSTR_CORE_SOURCES
|
||||
nostr_core/core.c
|
||||
nostr_core/core_relays.c
|
||||
nostr_core/core_relay_pool.c
|
||||
nostr_core/nostr_crypto.c
|
||||
nostr_core/nostr_secp256k1.c
|
||||
cjson/cJSON.c
|
||||
)
|
||||
|
||||
set(NOSTR_CORE_HEADERS
|
||||
nostr_core.h
|
||||
nostr_crypto.h
|
||||
cjson/cJSON.h
|
||||
)
|
||||
|
||||
# Add mbedTLS if enabled
|
||||
if(NOSTR_USE_MBEDTLS)
|
||||
add_subdirectory(mbedtls)
|
||||
list(APPEND NOSTR_CORE_SOURCES mbedtls_wrapper.c)
|
||||
add_definitions(-DNOSTR_USE_MBEDTLS=1)
|
||||
endif()
|
||||
|
||||
# Add WebSocket support if enabled
|
||||
if(NOSTR_ENABLE_WEBSOCKETS)
|
||||
file(GLOB WEBSOCKET_SOURCES "nostr_websocket/*.c")
|
||||
file(GLOB WEBSOCKET_HEADERS "nostr_websocket/*.h")
|
||||
list(APPEND NOSTR_CORE_SOURCES ${WEBSOCKET_SOURCES})
|
||||
list(APPEND NOSTR_CORE_HEADERS ${WEBSOCKET_HEADERS})
|
||||
add_definitions(-DNOSTR_ENABLE_WEBSOCKETS=1)
|
||||
endif()
|
||||
|
||||
# Create static library
|
||||
if(NOSTR_BUILD_STATIC)
|
||||
add_library(nostr_core_static STATIC ${NOSTR_CORE_SOURCES})
|
||||
set_target_properties(nostr_core_static PROPERTIES OUTPUT_NAME nostr_core)
|
||||
target_link_libraries(nostr_core_static m)
|
||||
|
||||
if(NOSTR_USE_MBEDTLS)
|
||||
target_link_libraries(nostr_core_static mbedcrypto mbedx509 mbedtls)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Create shared library
|
||||
if(NOSTR_BUILD_SHARED)
|
||||
add_library(nostr_core_shared SHARED ${NOSTR_CORE_SOURCES})
|
||||
set_target_properties(nostr_core_shared PROPERTIES OUTPUT_NAME nostr_core)
|
||||
target_link_libraries(nostr_core_shared m)
|
||||
|
||||
if(NOSTR_USE_MBEDTLS)
|
||||
target_link_libraries(nostr_core_shared mbedcrypto mbedx509 mbedtls)
|
||||
endif()
|
||||
|
||||
# Set version information
|
||||
set_target_properties(nostr_core_shared PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION 1
|
||||
)
|
||||
endif()
|
||||
|
||||
# Create alias targets for easier integration
|
||||
if(NOSTR_BUILD_STATIC)
|
||||
add_library(nostr_core::static ALIAS nostr_core_static)
|
||||
endif()
|
||||
|
||||
if(NOSTR_BUILD_SHARED)
|
||||
add_library(nostr_core::shared ALIAS nostr_core_shared)
|
||||
endif()
|
||||
|
||||
# Examples
|
||||
if(NOSTR_BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
# Tests
|
||||
if(NOSTR_BUILD_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
# Installation
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Install libraries
|
||||
if(NOSTR_BUILD_STATIC)
|
||||
install(TARGETS nostr_core_static
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOSTR_BUILD_SHARED)
|
||||
install(TARGETS nostr_core_shared
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Install headers
|
||||
install(FILES ${NOSTR_CORE_HEADERS}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/nostr
|
||||
)
|
||||
|
||||
# Install pkg-config file
|
||||
configure_file(nostr_core.pc.in nostr_core.pc @ONLY)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/nostr_core.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
||||
)
|
||||
|
||||
# Generate export configuration
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
configure_package_config_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/nostr_core-config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/nostr_core-config.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/nostr_core
|
||||
)
|
||||
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/nostr_core-config-version.cmake
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
install(FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/nostr_core-config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/nostr_core-config-version.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/nostr_core
|
||||
)
|
||||
|
||||
# Export targets
|
||||
if(NOSTR_BUILD_STATIC OR NOSTR_BUILD_SHARED)
|
||||
set(EXPORT_TARGETS "")
|
||||
if(NOSTR_BUILD_STATIC)
|
||||
list(APPEND EXPORT_TARGETS nostr_core_static)
|
||||
endif()
|
||||
if(NOSTR_BUILD_SHARED)
|
||||
list(APPEND EXPORT_TARGETS nostr_core_shared)
|
||||
endif()
|
||||
|
||||
install(EXPORT nostr_core-targets
|
||||
FILE nostr_core-targets.cmake
|
||||
NAMESPACE nostr_core::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/nostr_core
|
||||
)
|
||||
|
||||
export(TARGETS ${EXPORT_TARGETS}
|
||||
FILE ${CMAKE_CURRENT_BINARY_DIR}/nostr_core-targets.cmake
|
||||
NAMESPACE nostr_core::
|
||||
)
|
||||
endif()
|
||||
|
||||
# Summary
|
||||
message(STATUS "NOSTR Core Library Configuration:")
|
||||
message(STATUS " Version: ${PROJECT_VERSION}")
|
||||
message(STATUS " Build static library: ${NOSTR_BUILD_STATIC}")
|
||||
message(STATUS " Build shared library: ${NOSTR_BUILD_SHARED}")
|
||||
message(STATUS " Build examples: ${NOSTR_BUILD_EXAMPLES}")
|
||||
message(STATUS " Build tests: ${NOSTR_BUILD_TESTS}")
|
||||
message(STATUS " Enable WebSockets: ${NOSTR_ENABLE_WEBSOCKETS}")
|
||||
message(STATUS " Use mbedTLS: ${NOSTR_USE_MBEDTLS}")
|
||||
message(STATUS " Install prefix: ${CMAKE_INSTALL_PREFIX}")
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
# Exportable C NOSTR Library Design Guide
|
||||
|
||||
This document outlines the design principles and structure for making the C NOSTR library easily exportable and reusable across multiple projects.
|
||||
|
||||
## Overview
|
||||
|
||||
The C NOSTR library is designed as a modular, self-contained implementation that can be easily integrated into other projects while maintaining compatibility with the broader NOSTR ecosystem.
|
||||
|
||||
## Design Principles
|
||||
|
||||
### 1. Modular Architecture
|
||||
- **Core Layer**: Essential NOSTR functionality (`nostr_core.c/h`)
|
||||
- **Crypto Layer**: Self-contained cryptographic primitives (`nostr_crypto.c/h`)
|
||||
- **WebSocket Layer**: Optional networking functionality (`nostr_websocket/`)
|
||||
- **Dependencies**: Minimal external dependencies (only cJSON and mbedTLS)
|
||||
|
||||
### 2. Clean API Surface
|
||||
- Consistent function naming with `nostr_` prefix
|
||||
- Clear return codes using `NOSTR_SUCCESS`/`NOSTR_ERROR_*` constants
|
||||
- Well-documented function signatures
|
||||
- No global state where possible
|
||||
|
||||
### 3. Self-Contained Crypto
|
||||
- Custom implementations of SHA-256, HMAC, secp256k1
|
||||
- BIP39 wordlist embedded in code
|
||||
- No external crypto library dependencies for core functionality
|
||||
- Optional mbedTLS integration for enhanced security
|
||||
|
||||
### 4. Cross-Platform Compatibility
|
||||
- Standard C99 code
|
||||
- Platform-specific code isolated in separate modules
|
||||
- ARM64 and x86_64 tested builds
|
||||
- Static library compilation support
|
||||
|
||||
## Library Structure
|
||||
|
||||
```
|
||||
c_nostr/
|
||||
├── nostr_core.h # High-level API
|
||||
├── nostr_core.c # Implementation
|
||||
├── nostr_crypto.h # Crypto primitives API
|
||||
├── nostr_crypto.c # Self-contained crypto
|
||||
├── libnostr_core.a # Static library (x86_64)
|
||||
├── libnostr_core.so # Shared library (x86_64)
|
||||
├── cjson/ # JSON parsing (vendored)
|
||||
├── mbedtls/ # Optional crypto backend
|
||||
├── examples/ # Usage examples
|
||||
├── tests/ # Test suites
|
||||
└── nostr_websocket/ # Optional WebSocket layer
|
||||
```
|
||||
|
||||
## Integration Methods
|
||||
|
||||
### Method 1: Static Library Linking
|
||||
|
||||
**Best for**: Applications that want a single binary with all NOSTR functionality embedded.
|
||||
|
||||
```bash
|
||||
# Build the library
|
||||
make lib
|
||||
|
||||
# In your project Makefile:
|
||||
CFLAGS += -I/path/to/c_nostr
|
||||
LDFLAGS += -L/path/to/c_nostr -lnostr_core -lm -static
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```c
|
||||
#include "nostr_core.h"
|
||||
|
||||
int main() {
|
||||
if (nostr_init() != NOSTR_SUCCESS) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char private_key[32], public_key[32];
|
||||
nostr_generate_keypair(private_key, public_key);
|
||||
|
||||
cJSON* event = nostr_create_text_event("Hello NOSTR!", private_key);
|
||||
// ... use event
|
||||
|
||||
nostr_cleanup();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Method 2: Source Code Integration
|
||||
|
||||
**Best for**: Applications that want to customize the crypto backend or minimize dependencies.
|
||||
|
||||
```bash
|
||||
# Copy essential files to your project:
|
||||
cp nostr_core.{c,h} your_project/src/
|
||||
cp nostr_crypto.{c,h} your_project/src/
|
||||
cp -r cjson/ your_project/src/
|
||||
```
|
||||
|
||||
**Compile with your project:**
|
||||
```c
|
||||
// In your source
|
||||
#include "nostr_core.h"
|
||||
// Use NOSTR functions directly
|
||||
```
|
||||
|
||||
### Method 3: Git Submodule
|
||||
|
||||
**Best for**: Projects that want to track upstream changes and contribute back.
|
||||
|
||||
```bash
|
||||
# In your project root:
|
||||
git submodule add https://github.com/yourorg/c_nostr.git deps/c_nostr
|
||||
git submodule update --init --recursive
|
||||
|
||||
# In your Makefile:
|
||||
CFLAGS += -Ideps/c_nostr
|
||||
LDFLAGS += -Ldeps/c_nostr -lnostr_core
|
||||
```
|
||||
|
||||
### Method 4: Shared Library
|
||||
|
||||
**Best for**: System-wide installation or multiple applications sharing the same NOSTR implementation.
|
||||
|
||||
```bash
|
||||
# Install system-wide
|
||||
sudo make install
|
||||
|
||||
# In your project:
|
||||
CFLAGS += $(pkg-config --cflags nostr_core)
|
||||
LDFLAGS += $(pkg-config --libs nostr_core)
|
||||
```
|
||||
|
||||
## API Design for Exportability
|
||||
|
||||
### Consistent Error Handling
|
||||
```c
|
||||
typedef enum {
|
||||
NOSTR_SUCCESS = 0,
|
||||
NOSTR_ERROR_INVALID_INPUT = -1,
|
||||
NOSTR_ERROR_CRYPTO_FAILED = -2,
|
||||
NOSTR_ERROR_MEMORY_ALLOCATION = -3,
|
||||
NOSTR_ERROR_JSON_PARSE = -4,
|
||||
NOSTR_ERROR_NETWORK = -5
|
||||
} nostr_error_t;
|
||||
|
||||
const char* nostr_strerror(int error_code);
|
||||
```
|
||||
|
||||
### Clean Resource Management
|
||||
```c
|
||||
// Always provide cleanup functions
|
||||
int nostr_init(void);
|
||||
void nostr_cleanup(void);
|
||||
|
||||
// JSON objects returned should be freed by caller
|
||||
cJSON* nostr_create_text_event(const char* content, const unsigned char* private_key);
|
||||
// Caller must call cJSON_Delete(event) when done
|
||||
```
|
||||
|
||||
### Optional Features
|
||||
```c
|
||||
// Compile-time feature toggles
|
||||
#ifndef NOSTR_DISABLE_WEBSOCKETS
|
||||
int nostr_connect_relay(const char* url);
|
||||
#endif
|
||||
|
||||
#ifndef NOSTR_DISABLE_IDENTITY_PERSISTENCE
|
||||
int nostr_save_identity(const unsigned char* private_key, const char* password, int account);
|
||||
#endif
|
||||
```
|
||||
|
||||
## Configuration System
|
||||
|
||||
### Build-Time Configuration
|
||||
```c
|
||||
// nostr_config.h (generated during build)
|
||||
#define NOSTR_VERSION "1.0.0"
|
||||
#define NOSTR_HAS_MBEDTLS 1
|
||||
#define NOSTR_HAS_WEBSOCKETS 1
|
||||
#define NOSTR_STATIC_BUILD 1
|
||||
```
|
||||
|
||||
### Runtime Configuration
|
||||
```c
|
||||
typedef struct {
|
||||
int log_level;
|
||||
char* identity_file_path;
|
||||
int default_account;
|
||||
int enable_networking;
|
||||
} nostr_config_t;
|
||||
|
||||
int nostr_set_config(const nostr_config_t* config);
|
||||
const nostr_config_t* nostr_get_config(void);
|
||||
```
|
||||
|
||||
## Testing and Validation
|
||||
|
||||
### Ecosystem Compatibility Testing
|
||||
The library includes comprehensive test suites that validate compatibility with reference implementations like `nak`:
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
cd tests && make test
|
||||
|
||||
# Test specific functionality
|
||||
make test-crypto # Cryptographic primitives
|
||||
make test-core # High-level NOSTR functions
|
||||
```
|
||||
|
||||
### Test Vectors
|
||||
Real-world test vectors are generated using `nak` to ensure ecosystem compatibility:
|
||||
- Key generation and derivation (BIP39/BIP32)
|
||||
- Event creation and signing
|
||||
- Bech32 encoding/decoding
|
||||
- Message serialization
|
||||
|
||||
## Documentation for Exporters
|
||||
|
||||
### Essential Files Checklist
|
||||
For projects integrating this library, you need:
|
||||
|
||||
**Core Files (Required):**
|
||||
- `nostr_core.h` - Main API
|
||||
- `nostr_core.c` - Implementation
|
||||
- `nostr_crypto.h` - Crypto API
|
||||
- `nostr_crypto.c` - Self-contained crypto
|
||||
- `cjson/` directory - JSON parsing
|
||||
|
||||
**Optional Files:**
|
||||
- `nostr_websocket/` - WebSocket relay support
|
||||
- `mbedtls/` - Enhanced crypto backend
|
||||
- `examples/` - Usage examples
|
||||
- `tests/` - Validation tests
|
||||
|
||||
### Minimal Integration Example
|
||||
```c
|
||||
// minimal_nostr.c - Smallest possible integration
|
||||
#include "nostr_core.h"
|
||||
|
||||
int main() {
|
||||
// Initialize library
|
||||
nostr_init();
|
||||
|
||||
// Generate keypair
|
||||
unsigned char priv[32], pub[32];
|
||||
nostr_generate_keypair(priv, pub);
|
||||
|
||||
// Create and sign event
|
||||
cJSON* event = nostr_create_text_event("Hello from my app!", priv);
|
||||
char* json_string = cJSON_Print(event);
|
||||
printf("Event: %s\n", json_string);
|
||||
|
||||
// Cleanup
|
||||
free(json_string);
|
||||
cJSON_Delete(event);
|
||||
nostr_cleanup();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**Compile:**
|
||||
```bash
|
||||
gcc -I. minimal_nostr.c nostr_core.c nostr_crypto.c cjson/cJSON.c -lm -o minimal_nostr
|
||||
```
|
||||
|
||||
## Future Considerations
|
||||
|
||||
### Language Bindings
|
||||
The C library is designed to be easily wrapped:
|
||||
- **Python**: Use ctypes or cffi
|
||||
- **JavaScript**: Use Node.js FFI or WASM compilation
|
||||
- **Go**: Use cgo
|
||||
- **Rust**: Use bindgen for FFI bindings
|
||||
|
||||
### WebAssembly Support
|
||||
The library can be compiled to WebAssembly for browser usage:
|
||||
```bash
|
||||
emcc -O3 -s WASM=1 -s EXPORTED_FUNCTIONS='["_nostr_init", "_nostr_generate_keypair"]' \
|
||||
nostr_core.c nostr_crypto.c cjson/cJSON.c -o nostr.wasm
|
||||
```
|
||||
|
||||
### Package Manager Support
|
||||
Future versions may include:
|
||||
- pkgconfig files for system installation
|
||||
- CMake integration for easier builds
|
||||
- vcpkg/Conan package definitions
|
||||
|
||||
## Contributing Back
|
||||
|
||||
Projects using this library are encouraged to:
|
||||
1. Report compatibility issues
|
||||
2. Submit test vectors from their use cases
|
||||
3. Contribute performance improvements
|
||||
4. Add support for additional NIPs
|
||||
|
||||
## Version Compatibility
|
||||
|
||||
The library follows semantic versioning:
|
||||
- **Major**: Breaking API changes
|
||||
- **Minor**: New features, backward compatible
|
||||
- **Patch**: Bug fixes
|
||||
|
||||
API stability guarantees:
|
||||
- All functions prefixed with `nostr_` are part of the stable API
|
||||
- Internal functions (static or prefixed with `_`) may change
|
||||
- Configuration structures may be extended but not modified
|
||||
|
||||
---
|
||||
|
||||
This design ensures the C NOSTR library can be easily adopted by other projects while maintaining high compatibility with the NOSTR ecosystem standards.
|
||||
@@ -0,0 +1,29 @@
|
||||
# c-nostr Export and Implementation Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This guide provides essential information for developers using the `c-nostr` library, particularly regarding the capabilities and limitations of its self-contained modules, such as the HTTP client.
|
||||
|
||||
## HTTP Client (`http_client.c`)
|
||||
|
||||
The `http_client` module is a lightweight, self-contained HTTP/HTTPS client designed for simple and direct web requests. It is ideal for tasks like fetching NIP-11 information from Nostr relays or interacting with standard, permissive web APIs.
|
||||
|
||||
### Key Features
|
||||
|
||||
* **Self-Contained**: It is built with `mbedTLS` and has no external dependencies beyond standard C libraries, making it highly portable.
|
||||
* **Simplicity**: It provides a straightforward `http_get()` function for making web requests.
|
||||
* **TLS Support**: It supports HTTPS and basic TLS 1.3/1.2 features, including SNI (Server Name Indication) and ALPN (Application-Layer Protocol Negotiation).
|
||||
|
||||
### Limitations
|
||||
|
||||
The `http_client` is intentionally simple and is **not a full-featured web browser**. Due to its minimalist design, it will likely be blocked by websites that employ advanced anti-bot protection systems.
|
||||
|
||||
* **Incompatibility with Advanced Bot Protection**: Sites like Google, Cloudflare, and others use sophisticated fingerprinting techniques to distinguish between real browsers and automated clients. They analyze the exact combination of TLS cipher suites, TLS extensions, and HTTP headers. Our client's fingerprint does not match a standard browser, so these sites will preemptively drop the connection, typically resulting in a `HTTP_ERROR_NETWORK` error.
|
||||
|
||||
* **Intended Use Case**: This client is best suited for interacting with known, friendly APIs and Nostr relays. It is **not** designed for general web scraping or for accessing services that are heavily guarded against automated traffic.
|
||||
|
||||
### Best Practices
|
||||
|
||||
* **Use for APIs and Relays**: Rely on this client for fetching data from well-defined, public endpoints that do not have aggressive bot-detection measures in place.
|
||||
* **Avoid Protected Sites**: Do not attempt to use this client to access services like Google Search, as such attempts will fail. For those use cases, a full-featured library like `libcurl` or a dedicated web-scraping framework is required.
|
||||
* **Check the Test Suite**: The `tests/http_client_test.c` file contains test cases that demonstrate both the successful use cases (e.g., `httpbin.org`) and the expected failures (e.g., `google.com`), providing a clear reference for the client's capabilities.
|
||||
@@ -0,0 +1,361 @@
|
||||
# Generic Automatic Version Increment System for Any Repository
|
||||
|
||||
Here's a generalized implementation guide for adding automatic versioning to any project:
|
||||
|
||||
## Core Concept
|
||||
**Automatic patch version increment with each build** - Every build automatically increments the patch version: v0.1.0 → v0.1.1 → v0.1.2, etc.
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### 1. Add Version Increment Function to Build Script
|
||||
Add this function to your build script (bash example):
|
||||
|
||||
```bash
|
||||
# Function to automatically increment version
|
||||
increment_version() {
|
||||
echo "[INFO] Incrementing version..."
|
||||
|
||||
# Check if we're in a git repository
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo "[WARNING] Not in a git repository - skipping version increment"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Get the highest version tag (not chronologically latest)
|
||||
LATEST_TAG=$(git tag -l 'v*.*.*' | sort -V | tail -n 1 || echo "v0.1.0")
|
||||
if [[ -z "$LATEST_TAG" ]]; then
|
||||
LATEST_TAG="v0.1.0"
|
||||
fi
|
||||
|
||||
# Extract version components (remove 'v' prefix)
|
||||
VERSION=${LATEST_TAG#v}
|
||||
|
||||
# Parse major.minor.patch using regex
|
||||
if [[ $VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
|
||||
MAJOR=${BASH_REMATCH[1]}
|
||||
MINOR=${BASH_REMATCH[2]}
|
||||
PATCH=${BASH_REMATCH[3]}
|
||||
else
|
||||
echo "[ERROR] Invalid version format in tag: $LATEST_TAG"
|
||||
echo "[ERROR] Expected format: v0.1.0"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Increment patch version
|
||||
NEW_PATCH=$((PATCH + 1))
|
||||
NEW_VERSION="v${MAJOR}.${MINOR}.${NEW_PATCH}"
|
||||
|
||||
echo "[INFO] Current version: $LATEST_TAG"
|
||||
echo "[INFO] New version: $NEW_VERSION"
|
||||
|
||||
# Create new git tag
|
||||
if git tag "$NEW_VERSION" 2>/dev/null; then
|
||||
echo "[SUCCESS] Created new version tag: $NEW_VERSION"
|
||||
else
|
||||
echo "[WARNING] Tag $NEW_VERSION already exists - using existing version"
|
||||
NEW_VERSION=$LATEST_TAG
|
||||
fi
|
||||
|
||||
# Update VERSION file for compatibility
|
||||
echo "${NEW_VERSION#v}" > VERSION
|
||||
echo "[SUCCESS] Updated VERSION file to ${NEW_VERSION#v}"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Generate Version Header Files (For C/C++ Projects)
|
||||
Add this to the increment_version function:
|
||||
|
||||
```bash
|
||||
# Generate version.h header file (adjust path as needed)
|
||||
cat > src/version.h << EOF
|
||||
/*
|
||||
* Auto-Generated Version Header
|
||||
* DO NOT EDIT THIS FILE MANUALLY - Generated by build script
|
||||
*/
|
||||
|
||||
#ifndef VERSION_H
|
||||
#define VERSION_H
|
||||
|
||||
#define VERSION_MAJOR ${MAJOR}
|
||||
#define VERSION_MINOR ${MINOR}
|
||||
#define VERSION_PATCH ${NEW_PATCH}
|
||||
#define VERSION_STRING "${MAJOR}.${MINOR}.${NEW_PATCH}"
|
||||
#define VERSION_TAG "${NEW_VERSION}"
|
||||
|
||||
/* Build information */
|
||||
#define BUILD_DATE "$(date +%Y-%m-%d)"
|
||||
#define BUILD_TIME "$(date +%H:%M:%S)"
|
||||
#define BUILD_TIMESTAMP "$(date '+%Y-%m-%d %H:%M:%S')"
|
||||
|
||||
/* Git information */
|
||||
#define GIT_HASH "$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')"
|
||||
#define GIT_BRANCH "$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
|
||||
|
||||
/* Display versions */
|
||||
#define VERSION_DISPLAY "${NEW_VERSION}"
|
||||
#define VERSION_FULL_DISPLAY "${NEW_VERSION} ($(date '+%Y-%m-%d %H:%M:%S'), $(git rev-parse --short HEAD 2>/dev/null || echo 'unknown'))"
|
||||
|
||||
/* Version API functions */
|
||||
const char* get_version(void);
|
||||
const char* get_version_full(void);
|
||||
const char* get_build_info(void);
|
||||
|
||||
#endif /* VERSION_H */
|
||||
EOF
|
||||
|
||||
# Generate version.c implementation file
|
||||
cat > src/version.c << EOF
|
||||
/*
|
||||
* Auto-Generated Version Implementation
|
||||
* DO NOT EDIT THIS FILE MANUALLY - Generated by build script
|
||||
*/
|
||||
|
||||
#include "version.h"
|
||||
|
||||
const char* get_version(void) {
|
||||
return VERSION_TAG;
|
||||
}
|
||||
|
||||
const char* get_version_full(void) {
|
||||
return VERSION_FULL_DISPLAY;
|
||||
}
|
||||
|
||||
const char* get_build_info(void) {
|
||||
return "Built on " BUILD_DATE " at " BUILD_TIME " from commit " GIT_HASH " on branch " GIT_BRANCH;
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
### 3. Generate Version File for Other Languages
|
||||
|
||||
**Python (`src/__version__.py`):**
|
||||
```bash
|
||||
cat > src/__version__.py << EOF
|
||||
"""Auto-generated version file"""
|
||||
__version__ = "${MAJOR}.${MINOR}.${NEW_PATCH}"
|
||||
__version_tag__ = "${NEW_VERSION}"
|
||||
__build_date__ = "$(date +%Y-%m-%d)"
|
||||
__build_time__ = "$(date +%H:%M:%S)"
|
||||
__git_hash__ = "$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')"
|
||||
__git_branch__ = "$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
|
||||
EOF
|
||||
```
|
||||
|
||||
**JavaScript/Node.js (update `package.json`):**
|
||||
```bash
|
||||
# Update package.json version field
|
||||
if [ -f package.json ]; then
|
||||
sed -i "s/\"version\": \".*\"/\"version\": \"${MAJOR}.${MINOR}.${NEW_PATCH}\"/" package.json
|
||||
fi
|
||||
```
|
||||
|
||||
**Rust (update `Cargo.toml`):**
|
||||
```bash
|
||||
if [ -f Cargo.toml ]; then
|
||||
sed -i "s/^version = \".*\"/version = \"${MAJOR}.${MINOR}.${NEW_PATCH}\"/" Cargo.toml
|
||||
fi
|
||||
```
|
||||
|
||||
**Go (generate `version.go`):**
|
||||
```bash
|
||||
cat > version.go << EOF
|
||||
// Auto-generated version file
|
||||
package main
|
||||
|
||||
const (
|
||||
VersionMajor = ${MAJOR}
|
||||
VersionMinor = ${MINOR}
|
||||
VersionPatch = ${NEW_PATCH}
|
||||
VersionString = "${MAJOR}.${MINOR}.${NEW_PATCH}"
|
||||
VersionTag = "${NEW_VERSION}"
|
||||
BuildDate = "$(date +%Y-%m-%d)"
|
||||
BuildTime = "$(date +%H:%M:%S)"
|
||||
GitHash = "$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')"
|
||||
GitBranch = "$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
|
||||
)
|
||||
EOF
|
||||
```
|
||||
|
||||
**Java (generate `Version.java`):**
|
||||
```bash
|
||||
cat > src/main/java/Version.java << EOF
|
||||
// Auto-generated version class
|
||||
public class Version {
|
||||
public static final int VERSION_MAJOR = ${MAJOR};
|
||||
public static final int VERSION_MINOR = ${MINOR};
|
||||
public static final int VERSION_PATCH = ${NEW_PATCH};
|
||||
public static final String VERSION_STRING = "${MAJOR}.${MINOR}.${NEW_PATCH}";
|
||||
public static final String VERSION_TAG = "${NEW_VERSION}";
|
||||
public static final String BUILD_DATE = "$(date +%Y-%m-%d)";
|
||||
public static final String BUILD_TIME = "$(date +%H:%M:%S)";
|
||||
public static final String GIT_HASH = "$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')";
|
||||
public static final String GIT_BRANCH = "$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')";
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
### 4. Integrate into Build Targets
|
||||
Call `increment_version` before your main build commands:
|
||||
|
||||
```bash
|
||||
build_library() {
|
||||
increment_version
|
||||
echo "[INFO] Building library..."
|
||||
# Your actual build commands here
|
||||
make clean && make
|
||||
}
|
||||
|
||||
build_release() {
|
||||
increment_version
|
||||
echo "[INFO] Building release..."
|
||||
# Your release build commands
|
||||
}
|
||||
|
||||
build_package() {
|
||||
increment_version
|
||||
echo "[INFO] Building package..."
|
||||
# Your packaging commands
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Update .gitignore
|
||||
Add generated version files to `.gitignore`:
|
||||
|
||||
```gitignore
|
||||
# Auto-generated version files
|
||||
src/version.h
|
||||
src/version.c
|
||||
src/__version__.py
|
||||
version.go
|
||||
src/main/java/Version.java
|
||||
VERSION
|
||||
```
|
||||
|
||||
### 6. Update Build System Files
|
||||
|
||||
**For Makefile projects:**
|
||||
```makefile
|
||||
# Add version.c to your source files
|
||||
SOURCES = main.c utils.c version.c
|
||||
```
|
||||
|
||||
**For CMake projects:**
|
||||
```cmake
|
||||
# Add version files to your target
|
||||
target_sources(your_target PRIVATE src/version.c)
|
||||
```
|
||||
|
||||
**For Node.js projects:**
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"build": "node build.js && increment_version",
|
||||
"version": "node -e \"console.log(require('./package.json').version)\""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Create Initial Version Tag
|
||||
```bash
|
||||
# Start with initial version
|
||||
git tag v0.1.0
|
||||
```
|
||||
|
||||
## Usage Pattern
|
||||
```bash
|
||||
./build.sh # v0.1.0 → v0.1.1
|
||||
./build.sh release # v0.1.1 → v0.1.2
|
||||
./build.sh package # v0.1.2 → v0.1.3
|
||||
```
|
||||
|
||||
## Manual Version Control
|
||||
|
||||
### Major/Minor Version Bumps
|
||||
```bash
|
||||
# For feature releases (minor bump)
|
||||
git tag v0.2.0 # Next build: v0.2.1
|
||||
|
||||
# For breaking changes (major bump)
|
||||
git tag v1.0.0 # Next build: v1.0.1
|
||||
```
|
||||
|
||||
### Version Reset
|
||||
```bash
|
||||
# Delete incorrect tags (if needed)
|
||||
git tag -d v0.2.1
|
||||
git push origin --delete v0.2.1 # If pushed to remote
|
||||
|
||||
# Create correct base version
|
||||
git tag v0.2.0
|
||||
|
||||
# Next build will create v0.2.1
|
||||
```
|
||||
|
||||
## Example Build Script Template
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
print_status() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
||||
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
||||
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
# Insert increment_version function here
|
||||
|
||||
case "${1:-build}" in
|
||||
build)
|
||||
increment_version
|
||||
print_status "Building project..."
|
||||
# Your build commands
|
||||
;;
|
||||
clean)
|
||||
print_status "Cleaning build artifacts..."
|
||||
# Your clean commands
|
||||
;;
|
||||
test)
|
||||
print_status "Running tests..."
|
||||
# Your test commands (no version increment)
|
||||
;;
|
||||
release)
|
||||
increment_version
|
||||
print_status "Building release..."
|
||||
# Your release commands
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {build|clean|test|release}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
```
|
||||
|
||||
## Benefits
|
||||
1. **Zero maintenance** - No manual version editing
|
||||
2. **Build traceability** - Every build has unique version + metadata
|
||||
3. **Git integration** - Automatic version tags
|
||||
4. **Language agnostic** - Adapt generation for any language
|
||||
5. **CI/CD friendly** - Works in automated environments
|
||||
6. **Rollback friendly** - Easy to revert to previous versions
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Version Not Incrementing
|
||||
- Ensure you're in a git repository
|
||||
- Check that git tags exist: `git tag --list`
|
||||
- Verify tag format matches `v*.*.*` pattern
|
||||
|
||||
### Tag Already Exists
|
||||
If a tag already exists, the build continues with existing version:
|
||||
```
|
||||
[WARNING] Tag v0.2.1 already exists - using existing version
|
||||
```
|
||||
|
||||
### Missing Git Information
|
||||
If git is unavailable, version files show "unknown" for git hash and branch.
|
||||
@@ -0,0 +1,266 @@
|
||||
# NOSTR Core Library - Usage Guide
|
||||
|
||||
## Overview
|
||||
|
||||
The NOSTR Core Library (`libnostr_core`) is a self-contained, exportable C library for NOSTR protocol implementation. It requires **no external cryptographic dependencies** (no OpenSSL, no libwally) and can be easily integrated into other projects.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Self-Contained Crypto**: All cryptographic operations implemented from scratch
|
||||
- **Zero External Dependencies**: Only requires standard C library, cJSON, and libwebsockets
|
||||
- **Cross-Platform**: Builds on Linux, macOS, Windows (with appropriate toolchain)
|
||||
- **NIP-06 Compliant**: Proper BIP39/BIP32 implementation for key derivation
|
||||
- **Thread-Safe**: Core cryptographic functions are stateless and thread-safe
|
||||
- **Easy Integration**: Simple C API with clear error handling
|
||||
|
||||
## File Structure for Export
|
||||
|
||||
### Core Library Files (Required)
|
||||
```
|
||||
libnostr_core/
|
||||
├── nostr_core.h # Main public API header
|
||||
├── nostr_core.c # Core implementation
|
||||
├── nostr_crypto.h # Crypto implementation header
|
||||
├── nostr_crypto.c # Self-contained crypto implementation
|
||||
├── Makefile # Build configuration
|
||||
└── cjson/ # JSON library (can be replaced with system cJSON)
|
||||
├── cJSON.h
|
||||
└── cJSON.c
|
||||
```
|
||||
|
||||
### Optional Files
|
||||
```
|
||||
├── examples/ # Usage examples (helpful for integration)
|
||||
├── LIBRARY_USAGE.md # This usage guide
|
||||
├── SELF_CONTAINED_CRYPTO.md # Crypto implementation details
|
||||
└── CROSS_PLATFORM_GUIDE.md # Platform-specific build notes
|
||||
```
|
||||
|
||||
## Integration Methods
|
||||
|
||||
### Method 1: Static Library Integration
|
||||
|
||||
1. **Copy Required Files**:
|
||||
```bash
|
||||
cp nostr_core.h nostr_core.c nostr_crypto.h nostr_crypto.c /path/to/your/project/
|
||||
cp -r cjson/ /path/to/your/project/
|
||||
```
|
||||
|
||||
2. **Build Static Library**:
|
||||
```bash
|
||||
gcc -c -fPIC nostr_core.c nostr_crypto.c cjson/cJSON.c
|
||||
ar rcs libnostr_core.a nostr_core.o nostr_crypto.o cJSON.o
|
||||
```
|
||||
|
||||
3. **Link in Your Project**:
|
||||
```bash
|
||||
gcc your_project.c -L. -lnostr_core -lm -o your_project
|
||||
```
|
||||
|
||||
### Method 2: Direct Source Integration
|
||||
|
||||
Simply include the source files directly in your project:
|
||||
|
||||
```c
|
||||
// In your project
|
||||
#include "nostr_core.h"
|
||||
|
||||
// Compile with:
|
||||
// gcc your_project.c nostr_core.c nostr_crypto.c cjson/cJSON.c -lm
|
||||
```
|
||||
|
||||
### Method 3: Shared Library Integration
|
||||
|
||||
1. **Build Shared Library**:
|
||||
```bash
|
||||
make libnostr_core.so
|
||||
```
|
||||
|
||||
2. **Install System-Wide** (optional):
|
||||
```bash
|
||||
sudo cp libnostr_core.so /usr/local/lib/
|
||||
sudo cp nostr_core.h /usr/local/include/
|
||||
sudo ldconfig
|
||||
```
|
||||
|
||||
3. **Use in Projects**:
|
||||
```bash
|
||||
gcc your_project.c -lnostr_core -lm
|
||||
```
|
||||
|
||||
## Basic Usage Example
|
||||
|
||||
```c
|
||||
#include "nostr_core.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
// Initialize the library
|
||||
if (nostr_init() != NOSTR_SUCCESS) {
|
||||
fprintf(stderr, "Failed to initialize NOSTR library\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Generate a keypair
|
||||
unsigned char private_key[32];
|
||||
unsigned char public_key[32];
|
||||
|
||||
if (nostr_generate_keypair(private_key, public_key) != NOSTR_SUCCESS) {
|
||||
fprintf(stderr, "Failed to generate keypair\n");
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Convert to hex and bech32
|
||||
char private_hex[65], public_hex[65];
|
||||
char nsec[100], npub[100];
|
||||
|
||||
nostr_bytes_to_hex(private_key, 32, private_hex);
|
||||
nostr_bytes_to_hex(public_key, 32, public_hex);
|
||||
nostr_key_to_bech32(private_key, "nsec", nsec);
|
||||
nostr_key_to_bech32(public_key, "npub", npub);
|
||||
|
||||
printf("Private Key: %s\n", private_hex);
|
||||
printf("Public Key: %s\n", public_hex);
|
||||
printf("nsec: %s\n", nsec);
|
||||
printf("npub: %s\n", npub);
|
||||
|
||||
// Create and sign an event
|
||||
cJSON* event = nostr_create_text_event("Hello NOSTR!", private_key);
|
||||
if (event) {
|
||||
char* event_json = cJSON_Print(event);
|
||||
printf("Signed Event: %s\n", event_json);
|
||||
free(event_json);
|
||||
cJSON_Delete(event);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
nostr_cleanup();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Dependency Management
|
||||
|
||||
### Required Dependencies
|
||||
- **Standard C Library**: malloc, string functions, file I/O
|
||||
- **Math Library**: `-lm` (for cryptographic calculations)
|
||||
- **cJSON**: JSON parsing (included, or use system version)
|
||||
|
||||
### Optional Dependencies
|
||||
- **libwebsockets**: Only needed for relay communication functions
|
||||
- **System cJSON**: Can replace bundled version
|
||||
|
||||
### Minimal Integration (Crypto Only)
|
||||
If you only need key generation and signing:
|
||||
|
||||
```bash
|
||||
# Build with minimal dependencies
|
||||
gcc -DNOSTR_CRYPTO_ONLY your_project.c nostr_crypto.c -lm
|
||||
```
|
||||
|
||||
## Cross-Platform Considerations
|
||||
|
||||
### Linux
|
||||
- Works out of the box with GCC
|
||||
- Install build-essential: `sudo apt install build-essential`
|
||||
|
||||
### macOS
|
||||
- Works with Xcode command line tools
|
||||
- May need: `xcode-select --install`
|
||||
|
||||
### Windows
|
||||
- Use MinGW-w64 or MSYS2
|
||||
- Or integrate with Visual Studio project
|
||||
|
||||
### Embedded Systems
|
||||
- Library is designed to work on resource-constrained systems
|
||||
- No heap allocations in core crypto functions
|
||||
- Stack usage is predictable and bounded
|
||||
|
||||
## API Reference
|
||||
|
||||
### Initialization
|
||||
```c
|
||||
int nostr_init(void); // Initialize library
|
||||
void nostr_cleanup(void); // Cleanup resources
|
||||
const char* nostr_strerror(int error); // Get error string
|
||||
```
|
||||
|
||||
### Key Generation
|
||||
```c
|
||||
int nostr_generate_keypair(unsigned char* private_key, unsigned char* public_key);
|
||||
int nostr_generate_mnemonic_and_keys(char* mnemonic, size_t mnemonic_size,
|
||||
int account, unsigned char* private_key,
|
||||
unsigned char* public_key);
|
||||
int nostr_derive_keys_from_mnemonic(const char* mnemonic, int account,
|
||||
unsigned char* private_key, unsigned char* public_key);
|
||||
```
|
||||
|
||||
### Event Creation
|
||||
```c
|
||||
cJSON* nostr_create_text_event(const char* content, const unsigned char* private_key);
|
||||
cJSON* nostr_create_profile_event(const char* name, const char* about,
|
||||
const unsigned char* private_key);
|
||||
int nostr_sign_event(cJSON* event, const unsigned char* private_key);
|
||||
```
|
||||
|
||||
### Utilities
|
||||
```c
|
||||
void nostr_bytes_to_hex(const unsigned char* bytes, size_t len, char* hex);
|
||||
int nostr_hex_to_bytes(const char* hex, unsigned char* bytes, size_t len);
|
||||
int nostr_key_to_bech32(const unsigned char* key, const char* hrp, char* output);
|
||||
nostr_input_type_t nostr_detect_input_type(const char* input);
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All functions return standardized error codes:
|
||||
|
||||
- `NOSTR_SUCCESS` (0): Operation successful
|
||||
- `NOSTR_ERROR_INVALID_INPUT` (-1): Invalid parameters
|
||||
- `NOSTR_ERROR_CRYPTO_FAILED` (-2): Cryptographic operation failed
|
||||
- `NOSTR_ERROR_MEMORY_FAILED` (-3): Memory allocation failed
|
||||
- `NOSTR_ERROR_IO_FAILED` (-4): File I/O operation failed
|
||||
- `NOSTR_ERROR_NETWORK_FAILED` (-5): Network operation failed
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Private Key Handling**: Always clear private keys from memory when done
|
||||
2. **Random Number Generation**: Uses `/dev/urandom` on Unix systems
|
||||
3. **Memory Safety**: All buffers are bounds-checked
|
||||
4. **Constant-Time Operations**: Critical crypto operations are timing-attack resistant
|
||||
|
||||
## Testing Your Integration
|
||||
|
||||
Use the provided examples to verify your integration:
|
||||
|
||||
```bash
|
||||
# Test key generation
|
||||
./examples/simple_keygen
|
||||
|
||||
# Test mnemonic functionality
|
||||
./examples/mnemonic_generation
|
||||
|
||||
# Test event creation
|
||||
./examples/text_event
|
||||
|
||||
# Test all functionality
|
||||
./examples/utility_functions
|
||||
```
|
||||
|
||||
## Support and Documentation
|
||||
|
||||
- See `examples/` directory for comprehensive usage examples
|
||||
- Check `SELF_CONTAINED_CRYPTO.md` for cryptographic implementation details
|
||||
- Review `CROSS_PLATFORM_GUIDE.md` for platform-specific notes
|
||||
- All functions are documented in `nostr_core.h`
|
||||
|
||||
## License
|
||||
|
||||
This library is designed to be freely integrable into other projects. Check the individual file headers for specific licensing information.
|
||||
|
||||
---
|
||||
|
||||
**Quick Start**: Copy `nostr_core.h`, `nostr_core.c`, `nostr_crypto.h`, `nostr_crypto.c`, and the `cjson/` folder to your project, then compile with `-lm`. That's it!
|
||||
@@ -0,0 +1,495 @@
|
||||
# NOSTR Core Library Makefile
|
||||
# Standalone library build system
|
||||
|
||||
CC = gcc
|
||||
AR = ar
|
||||
CFLAGS = -Wall -Wextra -std=c99 -fPIC -O2
|
||||
DEBUG_CFLAGS = -Wall -Wextra -std=c99 -fPIC -g -DDEBUG
|
||||
STATIC_CFLAGS = -Wall -Wextra -std=c99 -O2 -static
|
||||
|
||||
# Logging compile flags
|
||||
LOGGING_FLAGS ?= -DENABLE_FILE_LOGGING -DENABLE_WEBSOCKET_LOGGING -DENABLE_DEBUG_LOGGING
|
||||
ifneq ($(ENABLE_LOGGING),)
|
||||
LOGGING_FLAGS += -DENABLE_FILE_LOGGING -DENABLE_WEBSOCKET_LOGGING -DENABLE_DEBUG_LOGGING
|
||||
endif
|
||||
|
||||
# Include paths
|
||||
INCLUDES = -I. -Inostr_core -Icjson -Isecp256k1/include -Inostr_websocket -I./openssl-install/include
|
||||
|
||||
# Library source files
|
||||
LIB_SOURCES = nostr_core/core.c nostr_core/core_relays.c nostr_core/nostr_crypto.c nostr_core/nostr_secp256k1.c nostr_core/nostr_aes.c nostr_core/nostr_chacha20.c nostr_websocket/nostr_websocket_openssl.c cjson/cJSON.c
|
||||
LIB_OBJECTS = $(LIB_SOURCES:.c=.o)
|
||||
ARM64_LIB_OBJECTS = $(LIB_SOURCES:.c=.arm64.o)
|
||||
|
||||
# secp256k1 library paths
|
||||
SECP256K1_LIB = ./secp256k1/.libs/libsecp256k1.a
|
||||
SECP256K1_PRECOMPUTED_LIB = ./secp256k1/.libs/libsecp256k1_precomputed.a
|
||||
|
||||
# ARM64 secp256k1 library paths
|
||||
SECP256K1_ARM64_LIB = ./secp256k1/.libs/libsecp256k1_arm64.a
|
||||
SECP256K1_ARM64_PRECOMPUTED_LIB = ./secp256k1/.libs/libsecp256k1_precomputed_arm64.a
|
||||
|
||||
# OpenSSL library paths
|
||||
OPENSSL_LIB_SSL = ./openssl-install/lib64/libssl.a
|
||||
OPENSSL_LIB_CRYPTO = ./openssl-install/lib64/libcrypto.a
|
||||
|
||||
# curl library paths
|
||||
CURL_LIB = ./curl-install/lib/libcurl.a
|
||||
|
||||
# Library outputs (static only)
|
||||
STATIC_LIB = libnostr_core.a
|
||||
ARM64_STATIC_LIB = libnostr_core_arm64.a
|
||||
|
||||
# Example files
|
||||
EXAMPLE_SOURCES = $(wildcard examples/*.c)
|
||||
EXAMPLE_TARGETS = $(EXAMPLE_SOURCES:.c=)
|
||||
|
||||
# Default target - build both x64 and ARM64 static libraries
|
||||
default: $(STATIC_LIB) $(ARM64_STATIC_LIB)
|
||||
|
||||
# Build all targets (static only)
|
||||
all: $(STATIC_LIB) $(ARM64_STATIC_LIB) examples
|
||||
|
||||
# Build secp256k1 for x86_64
|
||||
$(SECP256K1_LIB): secp256k1/configure
|
||||
@echo "Building secp256k1 for x86_64..."
|
||||
@cd secp256k1 && \
|
||||
if [ ! -f .libs/libsecp256k1.a ]; then \
|
||||
echo "Cleaning and configuring secp256k1..."; \
|
||||
make distclean >/dev/null 2>&1 || true; \
|
||||
./configure --enable-module-schnorrsig --enable-module-ecdh --enable-experimental --disable-shared --enable-static --with-pic; \
|
||||
echo "Building secp256k1 library..."; \
|
||||
make -j$(shell nproc 2>/dev/null || echo 4); \
|
||||
else \
|
||||
echo "secp256k1 library already exists, skipping build"; \
|
||||
fi
|
||||
@echo "x86_64 secp256k1 library built successfully"
|
||||
|
||||
# Build OpenSSL for x86_64 (minimal build optimized for curl)
|
||||
$(OPENSSL_LIB_SSL) $(OPENSSL_LIB_CRYPTO): openssl-3.4.2/Configure
|
||||
@echo "Building minimal OpenSSL for x86_64 (optimized for curl)..."
|
||||
@cd openssl-3.4.2 && \
|
||||
if [ ! -f ../openssl-install/lib64/libssl.a ] || [ ! -f ../openssl-install/lib64/libcrypto.a ]; then \
|
||||
echo "Configuring minimal OpenSSL..."; \
|
||||
make distclean >/dev/null 2>&1 || true; \
|
||||
./Configure linux-x86_64 \
|
||||
--prefix=$(PWD)/openssl-install \
|
||||
--openssldir=$(PWD)/openssl-install/ssl \
|
||||
no-shared no-dso no-apps no-docs \
|
||||
no-ssl3 no-tls1 no-tls1_1 \
|
||||
no-engine no-comp no-legacy \
|
||||
no-gost no-idea no-seed no-md2 no-md4 \
|
||||
no-mdc2 no-rmd160 no-camellia no-rc5 \
|
||||
no-bf no-cast no-des \
|
||||
enable-tls1_2 enable-tls1_3; \
|
||||
echo "Building minimal OpenSSL libraries..."; \
|
||||
make -j$(shell nproc 2>/dev/null || echo 4); \
|
||||
make install_sw >/dev/null 2>&1; \
|
||||
else \
|
||||
echo "OpenSSL libraries already exist, skipping build"; \
|
||||
fi
|
||||
@echo "x86_64 minimal OpenSSL libraries built successfully"
|
||||
|
||||
# Build curl for x86_64 (minimal HTTPS-only build)
|
||||
$(CURL_LIB): curl-8.15.0/curl-8.15.0/configure $(OPENSSL_LIB_SSL)
|
||||
@echo "Building minimal curl for x86_64 (HTTPS-only)..."
|
||||
@cd curl-8.15.0/curl-8.15.0 && \
|
||||
if [ ! -f ../../curl-install/lib/libcurl.a ]; then \
|
||||
echo "Configuring minimal curl..."; \
|
||||
make distclean >/dev/null 2>&1 || true; \
|
||||
./configure --prefix=$(PWD)/curl-install \
|
||||
--with-openssl=$(PWD)/openssl-install \
|
||||
--disable-shared --enable-static \
|
||||
--disable-ftp --disable-file --disable-ldap --disable-ldaps \
|
||||
--disable-pop3 --disable-imap --disable-smtp \
|
||||
--disable-gopher --disable-smb --disable-telnet \
|
||||
--disable-tftp --disable-dict --disable-rtsp \
|
||||
--disable-manual --disable-libcurl-option \
|
||||
--without-libpsl --without-nghttp2 --without-brotli --without-zstd \
|
||||
--without-libidn2 --without-librtmp --without-libssh2; \
|
||||
echo "Building minimal curl library..."; \
|
||||
make -j$(shell nproc 2>/dev/null || echo 4); \
|
||||
make install >/dev/null 2>&1; \
|
||||
else \
|
||||
echo "curl library already exists, skipping build"; \
|
||||
fi
|
||||
@echo "x86_64 minimal curl library built successfully"
|
||||
|
||||
# Static library - includes secp256k1 and OpenSSL objects for self-contained library
|
||||
$(STATIC_LIB): $(LIB_OBJECTS) $(SECP256K1_LIB) $(OPENSSL_LIB_SSL) $(OPENSSL_LIB_CRYPTO)
|
||||
@echo "Creating self-contained static library: $@"
|
||||
@echo "Extracting secp256k1 objects..."
|
||||
@mkdir -p .tmp_secp256k1
|
||||
@cd .tmp_secp256k1 && $(AR) x ../$(SECP256K1_LIB)
|
||||
@if [ -f $(SECP256K1_PRECOMPUTED_LIB) ]; then \
|
||||
echo "Extracting secp256k1_precomputed objects..."; \
|
||||
cd .tmp_secp256k1 && $(AR) x ../$(SECP256K1_PRECOMPUTED_LIB); \
|
||||
fi
|
||||
@echo "Extracting OpenSSL objects..."
|
||||
@mkdir -p .tmp_openssl
|
||||
@cd .tmp_openssl && $(AR) x ../$(OPENSSL_LIB_SSL)
|
||||
@cd .tmp_openssl && $(AR) x ../$(OPENSSL_LIB_CRYPTO)
|
||||
@echo "Combining all objects into $@..."
|
||||
$(AR) rcs $@ $(LIB_OBJECTS) .tmp_secp256k1/*.o .tmp_openssl/*.o
|
||||
@rm -rf .tmp_secp256k1 .tmp_openssl
|
||||
@echo "Self-contained static library created: $@"
|
||||
|
||||
# ARM64 cross-compilation settings
|
||||
ARM64_CC = aarch64-linux-gnu-gcc
|
||||
ARM64_AR = aarch64-linux-gnu-ar
|
||||
ARM64_INCLUDES = -I. -Inostr_core -Icjson -Isecp256k1/include -Inostr_websocket -I./openssl-install/include -I./curl-install/include
|
||||
|
||||
# ARM64 static library - includes secp256k1 objects for self-contained library (OpenSSL handled separately for cross-compile)
|
||||
$(ARM64_STATIC_LIB): $(ARM64_LIB_OBJECTS) $(SECP256K1_ARM64_LIB)
|
||||
@echo "Creating self-contained ARM64 static library: $@"
|
||||
@echo "Extracting ARM64 secp256k1 objects..."
|
||||
@mkdir -p .tmp_secp256k1_arm64
|
||||
@cd .tmp_secp256k1_arm64 && $(ARM64_AR) x ../$(SECP256K1_ARM64_LIB)
|
||||
@if [ -f $(SECP256K1_ARM64_PRECOMPUTED_LIB) ]; then \
|
||||
echo "Extracting ARM64 secp256k1_precomputed objects..."; \
|
||||
cd .tmp_secp256k1_arm64 && $(ARM64_AR) x ../$(SECP256K1_ARM64_PRECOMPUTED_LIB); \
|
||||
fi
|
||||
@echo "Note: ARM64 users need to link with OpenSSL separately: -lssl -lcrypto"
|
||||
@echo "Combining all ARM64 objects into $@..."
|
||||
$(ARM64_AR) rcs $@ $(ARM64_LIB_OBJECTS) .tmp_secp256k1_arm64/*.o
|
||||
@rm -rf .tmp_secp256k1_arm64
|
||||
@echo "Self-contained ARM64 static library created: $@"
|
||||
|
||||
# Build secp256k1 for ARM64
|
||||
$(SECP256K1_ARM64_LIB): secp256k1/configure
|
||||
@echo "Building secp256k1 for ARM64..."
|
||||
@echo "Cleaning secp256k1 source directory first..."
|
||||
@cd secp256k1 && make distclean 2>/dev/null || true
|
||||
@mkdir -p secp256k1/build_arm64
|
||||
@cd secp256k1/build_arm64 && \
|
||||
CC=$(ARM64_CC) AR=$(ARM64_AR) \
|
||||
../configure --host=aarch64-linux-gnu \
|
||||
--enable-module-schnorrsig \
|
||||
--enable-module-ecdh \
|
||||
--enable-experimental \
|
||||
--disable-shared \
|
||||
--enable-static \
|
||||
--with-pic \
|
||||
--prefix=$(PWD)/secp256k1/install_arm64 && \
|
||||
make -j$(shell nproc 2>/dev/null || echo 4)
|
||||
@mkdir -p secp256k1/.libs
|
||||
@cp secp256k1/build_arm64/.libs/libsecp256k1.a $(SECP256K1_ARM64_LIB)
|
||||
@if [ -f secp256k1/build_arm64/.libs/libsecp256k1_precomputed.a ]; then \
|
||||
cp secp256k1/build_arm64/.libs/libsecp256k1_precomputed.a $(SECP256K1_ARM64_PRECOMPUTED_LIB); \
|
||||
fi
|
||||
@echo "ARM64 secp256k1 libraries built successfully"
|
||||
@echo "Restoring x64 secp256k1 build..."
|
||||
@cd secp256k1 && ./configure --enable-module-schnorrsig --enable-module-ecdh --enable-experimental --disable-shared --enable-static --with-pic >/dev/null 2>&1 && make -j$(shell nproc 2>/dev/null || echo 4) >/dev/null 2>&1 || true
|
||||
|
||||
# Object files (x86_64)
|
||||
%.o: %.c
|
||||
@echo "Compiling: $<"
|
||||
$(CC) $(CFLAGS) $(LOGGING_FLAGS) $(INCLUDES) -c $< -o $@
|
||||
|
||||
# ARM64 object files
|
||||
%.arm64.o: %.c
|
||||
@echo "Compiling for ARM64: $<"
|
||||
$(ARM64_CC) $(CFLAGS) $(LOGGING_FLAGS) $(ARM64_INCLUDES) -c $< -o $@
|
||||
|
||||
# Examples
|
||||
examples: $(EXAMPLE_TARGETS)
|
||||
|
||||
examples/%: examples/%.c $(STATIC_LIB)
|
||||
@echo "Building example: $@"
|
||||
$(CC) $(STATIC_CFLAGS) $(LOGGING_FLAGS) $(INCLUDES) $< -o $@ ./libnostr_core.a -lm
|
||||
|
||||
# Architecture-specific targets
|
||||
x64: $(STATIC_LIB)
|
||||
x64-only: $(STATIC_LIB)
|
||||
|
||||
# ARM64 targets
|
||||
arm64: $(ARM64_STATIC_LIB)
|
||||
arm64-all: $(ARM64_STATIC_LIB)
|
||||
arm64-only: $(ARM64_STATIC_LIB)
|
||||
|
||||
# Debug build
|
||||
debug: CFLAGS = $(DEBUG_CFLAGS)
|
||||
debug: clean default
|
||||
|
||||
# Install library to system (static only)
|
||||
install: $(STATIC_LIB)
|
||||
@echo "Installing static library..."
|
||||
sudo cp $(STATIC_LIB) /usr/local/lib/
|
||||
sudo cp nostr_core/nostr_core.h /usr/local/include/
|
||||
sudo cp nostr_core/nostr_crypto.h /usr/local/include/
|
||||
|
||||
# Uninstall library
|
||||
uninstall:
|
||||
@echo "Uninstalling library..."
|
||||
sudo rm -f /usr/local/lib/$(STATIC_LIB)
|
||||
sudo rm -f /usr/local/include/nostr_core.h
|
||||
sudo rm -f /usr/local/include/nostr_crypto.h
|
||||
|
||||
# Test executables
|
||||
CRYPTO_TEST_EXEC = tests/nostr_crypto_test
|
||||
CORE_TEST_EXEC = tests/nostr_core_test
|
||||
RELAY_POOL_TEST_EXEC = tests/relay_pool_test
|
||||
EVENT_GEN_TEST_EXEC = tests/test_event_generation
|
||||
POW_LOOP_TEST_EXEC = tests/test_pow_loop
|
||||
NIP04_TEST_EXEC = tests/nip04_test
|
||||
HTTP_TEST_EXEC = tests/http_test
|
||||
WSS_TEST_EXEC = tests/wss_test
|
||||
STATIC_LINKING_TEST_EXEC = tests/static_linking_only_test
|
||||
MAKEFILE_STATIC_TEST_EXEC = tests/makefile_static_test
|
||||
NIP05_TEST_EXEC = tests/nip05_test
|
||||
NIP11_TEST_EXEC = tests/nip11_test
|
||||
ARM64_CRYPTO_TEST_EXEC = tests/nostr_crypto_test_arm64
|
||||
ARM64_CORE_TEST_EXEC = tests/nostr_core_test_arm64
|
||||
ARM64_RELAY_POOL_TEST_EXEC = tests/relay_pool_test_arm64
|
||||
ARM64_NIP04_TEST_EXEC = tests/nip04_test_arm64
|
||||
|
||||
# Test compilation flags
|
||||
TEST_CFLAGS = -Wall -Wextra -std=c99 -g -I. -I./secp256k1/include -I./openssl-install/include -DDISABLE_NIP05
|
||||
TEST_LDFLAGS = -L. -lnostr_core -lm -static
|
||||
ARM64_TEST_CFLAGS = -Wall -Wextra -std=c99 -g -I. -DDISABLE_NIP05
|
||||
ARM64_TEST_LDFLAGS = -L. -lnostr_core_arm64 -lssl -lcrypto -lm -static
|
||||
|
||||
# Build crypto test executable (x86_64)
|
||||
$(CRYPTO_TEST_EXEC): tests/nostr_crypto_test.c $(STATIC_LIB)
|
||||
@echo "Building crypto test suite (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) $< -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
# Build core test executable (x86_64)
|
||||
$(CORE_TEST_EXEC): tests/nostr_core_test.c $(STATIC_LIB)
|
||||
@echo "Building core test suite (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) $< -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
# Build relay pool test executable (x86_64)
|
||||
$(RELAY_POOL_TEST_EXEC): tests/relay_pool_test.c $(STATIC_LIB)
|
||||
@echo "Building relay pool test suite (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) $< -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
# Build event generation test executable (x86_64)
|
||||
$(EVENT_GEN_TEST_EXEC): tests/test_event_generation.c $(STATIC_LIB)
|
||||
@echo "Building event generation test suite (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) $< -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
# Build PoW loop test executable (x86_64)
|
||||
$(POW_LOOP_TEST_EXEC): tests/test_pow_loop.c $(STATIC_LIB)
|
||||
@echo "Building PoW loop test program (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) $< -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
# Build NIP-04 test executable (x86_64)
|
||||
$(NIP04_TEST_EXEC): tests/nip04_test.c $(STATIC_LIB)
|
||||
@echo "Building NIP-04 encryption test suite (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) $< -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
# Build HTTP test executable (x86_64) - Uses static curl for compatibility testing
|
||||
$(HTTP_TEST_EXEC): tests/http_test.c
|
||||
@echo "Building HTTP/curl compatibility test (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) -I./curl-install/include $< -o $@ ./curl-install/lib/libcurl.a -lssl -lcrypto -lz -ldl -lpthread -static
|
||||
|
||||
# Build WebSocket SSL test executable (x86_64)
|
||||
$(WSS_TEST_EXEC): tests/wss_test.c $(STATIC_LIB)
|
||||
@echo "Building WebSocket SSL/OpenSSL compatibility test (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) $< -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
# Build static linking test executable (x86_64)
|
||||
$(STATIC_LINKING_TEST_EXEC): tests/static_linking_only_test.c $(STATIC_LIB)
|
||||
@echo "Building static linking verification test (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) $< -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
# Build Makefile-based static test executable (x86_64) - No library dependency, just parses Makefile
|
||||
$(MAKEFILE_STATIC_TEST_EXEC): tests/makefile_static_test.c
|
||||
@echo "Building Makefile-based static configuration test (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) $< -o $@ -static
|
||||
|
||||
# Build NIP-05 test executable (x86_64) - NIP-05 enabled with static curl
|
||||
$(NIP05_TEST_EXEC): tests/nip05_test.c $(STATIC_LIB)
|
||||
@echo "Building NIP-05 identifier verification test (x86_64)..."
|
||||
$(CC) -Wall -Wextra -std=c99 -g -I. -I./secp256k1/include -I./openssl-install/include -I./curl-install/include $< -o $@ -L. -L./openssl-install/lib64 -lnostr_core ./curl-install/lib/libcurl.a ./openssl-install/lib64/libssl.a ./openssl-install/lib64/libcrypto.a -lz -ldl -lpthread -lm -static
|
||||
|
||||
# Build NIP-11 test executable (x86_64) - NIP-11 enabled with static curl
|
||||
$(NIP11_TEST_EXEC): tests/nip11_test.c $(STATIC_LIB)
|
||||
@echo "Building NIP-11 relay information test (x86_64)..."
|
||||
$(CC) -Wall -Wextra -std=c99 -g -I. -I./secp256k1/include -I./openssl-install/include -I./curl-install/include $< -o $@ -L. -L./openssl-install/lib64 -lnostr_core ./curl-install/lib/libcurl.a ./openssl-install/lib64/libssl.a ./openssl-install/lib64/libcrypto.a -lz -ldl -lpthread -lm -static
|
||||
|
||||
# Build simple initialization test executable (x86_64)
|
||||
tests/simple_init_test: tests/simple_init_test.c $(STATIC_LIB)
|
||||
@echo "Building simple initialization test program (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) $< -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
# Build ChaCha20 test executable (x86_64)
|
||||
tests/chacha20_test: tests/chacha20_test.c $(STATIC_LIB)
|
||||
@echo "Building ChaCha20 RFC 8439 test suite (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) $< -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
# Build sync test executable (x86_64)
|
||||
tests/sync_test: tests/sync_test.c $(STATIC_LIB)
|
||||
@echo "Building synchronous relay query test program (x86_64)..."
|
||||
$(CC) $(TEST_CFLAGS) $< -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
# Build crypto test ARM64 executable
|
||||
$(ARM64_CRYPTO_TEST_EXEC): tests/nostr_crypto_test.c $(ARM64_STATIC_LIB)
|
||||
@echo "Building crypto test suite (ARM64)..."
|
||||
$(ARM64_CC) $(ARM64_TEST_CFLAGS) $< -o $@ $(ARM64_TEST_LDFLAGS)
|
||||
|
||||
# Build core test ARM64 executable
|
||||
$(ARM64_CORE_TEST_EXEC): tests/nostr_core_test.c $(ARM64_STATIC_LIB)
|
||||
@echo "Building core test suite (ARM64)..."
|
||||
$(ARM64_CC) $(ARM64_TEST_CFLAGS) $< -o $@ $(ARM64_TEST_LDFLAGS)
|
||||
|
||||
# Build relay pool test ARM64 executable
|
||||
$(ARM64_RELAY_POOL_TEST_EXEC): tests/relay_pool_test.c $(ARM64_STATIC_LIB)
|
||||
@echo "Building relay pool test suite (ARM64)..."
|
||||
$(ARM64_CC) $(ARM64_TEST_CFLAGS) $< -o $@ $(ARM64_TEST_LDFLAGS)
|
||||
|
||||
# Build NIP-04 test ARM64 executable
|
||||
$(ARM64_NIP04_TEST_EXEC): tests/nip04_test.c $(ARM64_STATIC_LIB)
|
||||
@echo "Building NIP-04 encryption test suite (ARM64)..."
|
||||
$(ARM64_CC) $(ARM64_TEST_CFLAGS) $< -o $@ $(ARM64_TEST_LDFLAGS)
|
||||
|
||||
# Run crypto tests (x86_64)
|
||||
test-crypto: $(CRYPTO_TEST_EXEC)
|
||||
@echo "Running crypto tests (x86_64)..."
|
||||
./$(CRYPTO_TEST_EXEC)
|
||||
|
||||
# Run core tests (x86_64)
|
||||
test-core: $(CORE_TEST_EXEC)
|
||||
@echo "Running core tests (x86_64)..."
|
||||
./$(CORE_TEST_EXEC)
|
||||
|
||||
# Run relay pool tests (x86_64)
|
||||
test-relay-pool: $(RELAY_POOL_TEST_EXEC)
|
||||
@echo "Running relay pool tests (x86_64)..."
|
||||
./$(RELAY_POOL_TEST_EXEC)
|
||||
|
||||
# Run NIP-04 tests (x86_64)
|
||||
test-nip04: $(NIP04_TEST_EXEC)
|
||||
@echo "Running NIP-04 encryption tests (x86_64)..."
|
||||
./$(NIP04_TEST_EXEC)
|
||||
|
||||
# Run HTTP tests (x86_64)
|
||||
test-http: $(HTTP_TEST_EXEC)
|
||||
@echo "Running HTTP/curl compatibility tests (x86_64)..."
|
||||
./$(HTTP_TEST_EXEC)
|
||||
|
||||
# Run WebSocket SSL tests (x86_64)
|
||||
test-wss: $(WSS_TEST_EXEC)
|
||||
@echo "Running WebSocket SSL/OpenSSL compatibility tests (x86_64)..."
|
||||
./$(WSS_TEST_EXEC)
|
||||
|
||||
# Run static linking verification test (x86_64)
|
||||
test-static-linking: $(STATIC_LINKING_TEST_EXEC)
|
||||
@echo "Running static linking verification test (x86_64)..."
|
||||
./$(STATIC_LINKING_TEST_EXEC)
|
||||
|
||||
# Run Makefile-based static configuration test (x86_64)
|
||||
test-makefile-static: $(MAKEFILE_STATIC_TEST_EXEC)
|
||||
@echo "Running Makefile-based static configuration test (x86_64)..."
|
||||
./$(MAKEFILE_STATIC_TEST_EXEC)
|
||||
|
||||
# Run NIP-05 tests (x86_64)
|
||||
test-nip05: $(NIP05_TEST_EXEC)
|
||||
@echo "Running NIP-05 identifier verification tests (x86_64)..."
|
||||
./$(NIP05_TEST_EXEC)
|
||||
|
||||
# Run NIP-11 tests (x86_64)
|
||||
test-nip11: $(NIP11_TEST_EXEC)
|
||||
@echo "Running NIP-11 relay information tests (x86_64)..."
|
||||
./$(NIP11_TEST_EXEC)
|
||||
|
||||
# Run all test suites (x86_64)
|
||||
test: test-crypto test-core test-relay-pool test-nip04 test-http test-wss test-static-linking test-makefile-static test-nip05 test-nip11
|
||||
|
||||
# Run crypto tests ARM64 (requires qemu-user-static or ARM64 system)
|
||||
test-crypto-arm64: $(ARM64_CRYPTO_TEST_EXEC)
|
||||
@echo "Running crypto tests (ARM64)..."
|
||||
@if command -v qemu-aarch64-static >/dev/null 2>&1; then \
|
||||
echo "Using qemu-aarch64-static to run ARM64 binary..."; \
|
||||
qemu-aarch64-static ./$(ARM64_CRYPTO_TEST_EXEC); \
|
||||
else \
|
||||
echo "qemu-aarch64-static not found. ARM64 binary built but cannot run on x86_64."; \
|
||||
echo "To run: copy $(ARM64_CRYPTO_TEST_EXEC) to ARM64 system and execute."; \
|
||||
file ./$(ARM64_CRYPTO_TEST_EXEC); \
|
||||
fi
|
||||
|
||||
# Run core tests ARM64 (requires qemu-user-static or ARM64 system)
|
||||
test-core-arm64: $(ARM64_CORE_TEST_EXEC)
|
||||
@echo "Running core tests (ARM64)..."
|
||||
@if command -v qemu-aarch64-static >/dev/null 2>&1; then \
|
||||
echo "Using qemu-aarch64-static to run ARM64 binary..."; \
|
||||
qemu-aarch64-static ./$(ARM64_CORE_TEST_EXEC); \
|
||||
else \
|
||||
echo "qemu-aarch64-static not found. ARM64 binary built but cannot run on x86_64."; \
|
||||
echo "To run: copy $(ARM64_CORE_TEST_EXEC) to ARM64 system and execute."; \
|
||||
file ./$(ARM64_CORE_TEST_EXEC); \
|
||||
fi
|
||||
|
||||
# Run relay pool tests ARM64 (requires qemu-user-static or ARM64 system)
|
||||
test-relay-pool-arm64: $(ARM64_RELAY_POOL_TEST_EXEC)
|
||||
@echo "Running relay pool tests (ARM64)..."
|
||||
@if command -v qemu-aarch64-static >/dev/null 2>&1; then \
|
||||
echo "Using qemu-aarch64-static to run ARM64 binary..."; \
|
||||
qemu-aarch64-static ./$(ARM64_RELAY_POOL_TEST_EXEC); \
|
||||
else \
|
||||
echo "qemu-aarch64-static not found. ARM64 binary built but cannot run on x86_64."; \
|
||||
echo "To run: copy $(ARM64_RELAY_POOL_TEST_EXEC) to ARM64 system and execute."; \
|
||||
file ./$(ARM64_RELAY_POOL_TEST_EXEC); \
|
||||
fi
|
||||
|
||||
# Run all test suites on ARM64
|
||||
test-arm64: test-crypto-arm64 test-core-arm64 test-relay-pool-arm64
|
||||
|
||||
# Run tests on both architectures
|
||||
test-all: test test-arm64
|
||||
|
||||
# Test the library with simple example
|
||||
test-simple: examples/simple_keygen
|
||||
@echo "Running simple key generation test..."
|
||||
./examples/simple_keygen
|
||||
|
||||
# Clean build artifacts
|
||||
clean:
|
||||
@echo "Cleaning build artifacts..."
|
||||
rm -f $(LIB_OBJECTS) $(ARM64_LIB_OBJECTS)
|
||||
rm -f $(STATIC_LIB) $(ARM64_STATIC_LIB)
|
||||
rm -f $(SECP256K1_ARM64_LIB) $(SECP256K1_ARM64_PRECOMPUTED_LIB)
|
||||
rm -f $(EXAMPLE_TARGETS)
|
||||
rm -rf .tmp_secp256k1 .tmp_secp256k1_arm64 .tmp_openssl
|
||||
rm -rf secp256k1/build_arm64 secp256k1/install_arm64
|
||||
|
||||
# Create distribution package
|
||||
dist: clean
|
||||
@echo "Creating distribution package..."
|
||||
mkdir -p dist/nostr_core
|
||||
cp -r *.h *.c Makefile examples/ tests/ README.md LICENSE dist/nostr_core/ 2>/dev/null || true
|
||||
cd dist && tar -czf nostr_core.tar.gz nostr_core/
|
||||
@echo "Distribution package created: dist/nostr_core.tar.gz"
|
||||
|
||||
# Help
|
||||
help:
|
||||
@echo "NOSTR Core Library Build System"
|
||||
@echo "==============================="
|
||||
@echo ""
|
||||
@echo "Available targets:"
|
||||
@echo " default - Build both x64 and ARM64 static libraries (recommended)"
|
||||
@echo " all - Build both architectures and examples"
|
||||
@echo " x64 - Build x64 static library only"
|
||||
@echo " x64-only - Build x64 static library only"
|
||||
@echo " arm64 - Build ARM64 static library only"
|
||||
@echo " arm64-only - Build ARM64 static library only"
|
||||
@echo " arm64-all - Build ARM64 static library only"
|
||||
@echo " debug - Build with debug symbols (both architectures)"
|
||||
@echo " examples - Build example programs"
|
||||
@echo " test - Run simple test"
|
||||
@echo " test-crypto - Run comprehensive crypto test suite"
|
||||
@echo " install - Install static library to system (/usr/local)"
|
||||
@echo " uninstall - Remove library from system"
|
||||
@echo " clean - Remove build artifacts"
|
||||
@echo " dist - Create distribution package"
|
||||
@echo " help - Show this help"
|
||||
@echo ""
|
||||
@echo "Library outputs (static only, self-contained):"
|
||||
@echo " $(STATIC_LIB) - x86_64 static library (includes secp256k1 + OpenSSL)"
|
||||
@echo " $(ARM64_STATIC_LIB) - ARM64 static library (includes secp256k1, needs OpenSSL)"
|
||||
@echo ""
|
||||
@echo "x64 library: Users only need to link with the library + -lm"
|
||||
@echo "ARM64 library: Users need to link with the library + -lssl -lcrypto -lm"
|
||||
|
||||
.PHONY: default all x64 x64-only arm64 arm64-all arm64-only debug examples test test-crypto install uninstall clean dist help
|
||||
-777
@@ -1,777 +0,0 @@
|
||||
# Relay Pool API Reference
|
||||
|
||||
This document describes the public API for the Nostr Relay Pool implementation in [`core_relay_pool.c`](nostr_core/core_relay_pool.c).
|
||||
|
||||
## Function Summary
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| [`nostr_relay_pool_create()`](nostr_core/core_relay_pool.c:594) | Create and initialize a new relay pool |
|
||||
| [`nostr_relay_pool_destroy()`](nostr_core/core_relay_pool.c:733) | Destroy pool and cleanup all resources |
|
||||
| [`nostr_relay_pool_add_relay()`](nostr_core/core_relay_pool.c:648) | Add a relay URL to the pool |
|
||||
| [`nostr_relay_pool_remove_relay()`](nostr_core/core_relay_pool.c:702) | Remove a relay URL from the pool |
|
||||
| [`nostr_relay_pool_set_auth()`](nostr_core/core_relay_pool.c:616) | Configure pool-wide NIP-42 authentication key and enable flag |
|
||||
| [`nostr_relay_pool_subscribe()`](nostr_core/core_relay_pool.c:778) | Create async subscription with callbacks |
|
||||
| [`nostr_pool_subscription_close()`](nostr_core/core_relay_pool.c:491) | Close subscription and free resources |
|
||||
| [`nostr_relay_pool_run()`](nostr_core/core_relay_pool.c:1192) | Run event loop for specified timeout |
|
||||
| [`nostr_relay_pool_poll()`](nostr_core/core_relay_pool.c:1232) | Single iteration poll and dispatch |
|
||||
| [`nostr_relay_pool_query_sync()`](nostr_core/core_relay_pool.c:695) | Synchronous query returning event array |
|
||||
| [`nostr_relay_pool_get_event()`](nostr_core/core_relay_pool.c:825) | Get single most recent event |
|
||||
| [`nostr_relay_pool_publish_async()`](nostr_core/core_relay_pool.c:866) | Publish event with async callbacks |
|
||||
| [`nostr_relay_pool_get_relay_status()`](nostr_core/core_relay_pool.c:944) | Get connection status for a relay |
|
||||
| [`nostr_relay_pool_list_relays()`](nostr_core/core_relay_pool.c:960) | List all relays and their statuses |
|
||||
| [`nostr_relay_pool_get_relay_stats()`](nostr_core/core_relay_pool.c:992) | Get detailed statistics for a relay |
|
||||
| [`nostr_relay_pool_reset_relay_stats()`](nostr_core/core_relay_pool.c:1008) | Reset statistics for a relay |
|
||||
| [`nostr_relay_pool_get_relay_query_latency()`](nostr_core/core_relay_pool.c:1045) | Get average query latency for a relay |
|
||||
|
||||
## Pool Lifecycle
|
||||
|
||||
### Create Pool
|
||||
**Function:** [`nostr_relay_pool_create()`](nostr_core/core_relay_pool.c:219)
|
||||
```c
|
||||
nostr_relay_pool_t* nostr_relay_pool_create(void);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
#include "nostr_core.h"
|
||||
|
||||
int main() {
|
||||
// Create a new relay pool
|
||||
nostr_relay_pool_t* pool = nostr_relay_pool_create();
|
||||
if (!pool) {
|
||||
fprintf(stderr, "Failed to create relay pool\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Use the pool...
|
||||
|
||||
// Clean up
|
||||
nostr_relay_pool_destroy(pool);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Destroy Pool
|
||||
**Function:** [`nostr_relay_pool_destroy()`](nostr_core/core_relay_pool.c:304)
|
||||
```c
|
||||
void nostr_relay_pool_destroy(nostr_relay_pool_t* pool);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
// Properly cleanup a relay pool
|
||||
void cleanup_pool(nostr_relay_pool_t* pool) {
|
||||
if (pool) {
|
||||
// This will close all active subscriptions and relay connections
|
||||
nostr_relay_pool_destroy(pool);
|
||||
pool = NULL;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Relay Management
|
||||
|
||||
### Configure Pool Authentication (NIP-42)
|
||||
**Function:** [`nostr_relay_pool_set_auth()`](nostr_core/core_relay_pool.c:616)
|
||||
```c
|
||||
int nostr_relay_pool_set_auth(nostr_relay_pool_t* pool, const unsigned char* private_key, int enable);
|
||||
```
|
||||
|
||||
**Description:**
|
||||
- Sets a pool-wide private key used to sign NIP-42 `AUTH` responses.
|
||||
- Enables/disables NIP-42 handling for all relays in the pool.
|
||||
- Propagates auth-enabled state to existing relay connections.
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
unsigned char privkey[32];
|
||||
nostr_hex_to_bytes("91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe", privkey, 32);
|
||||
|
||||
nostr_relay_pool_t* pool = nostr_relay_pool_create(nostr_pool_reconnect_config_default());
|
||||
nostr_relay_pool_set_auth(pool, privkey, 1); // enable NIP-42 auto AUTH handling
|
||||
```
|
||||
|
||||
### Add Relay
|
||||
**Function:** [`nostr_relay_pool_add_relay()`](nostr_core/core_relay_pool.c:229)
|
||||
```c
|
||||
int nostr_relay_pool_add_relay(nostr_relay_pool_t* pool, const char* relay_url);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
int setup_relays(nostr_relay_pool_t* pool) {
|
||||
const char* relays[] = {
|
||||
"wss://relay.damus.io",
|
||||
"wss://nos.lol",
|
||||
"wss://relay.nostr.band"
|
||||
};
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int result = nostr_relay_pool_add_relay(pool, relays[i]);
|
||||
if (result != NOSTR_SUCCESS) {
|
||||
fprintf(stderr, "Failed to add relay %s: %d\n", relays[i], result);
|
||||
return -1;
|
||||
}
|
||||
printf("Added relay: %s\n", relays[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Remove Relay
|
||||
**Function:** [`nostr_relay_pool_remove_relay()`](nostr_core/core_relay_pool.c:273)
|
||||
```c
|
||||
int nostr_relay_pool_remove_relay(nostr_relay_pool_t* pool, const char* relay_url);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
int remove_slow_relay(nostr_relay_pool_t* pool) {
|
||||
const char* slow_relay = "wss://slow-relay.example.com";
|
||||
|
||||
int result = nostr_relay_pool_remove_relay(pool, slow_relay);
|
||||
if (result == NOSTR_SUCCESS) {
|
||||
printf("Successfully removed relay: %s\n", slow_relay);
|
||||
} else {
|
||||
printf("Failed to remove relay %s (may not exist)\n", slow_relay);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
## Subscriptions (Asynchronous)
|
||||
|
||||
### Subscribe to Events
|
||||
**Function:** [`nostr_relay_pool_subscribe()`](nostr_core/core_relay_pool.c:399)
|
||||
```c
|
||||
nostr_pool_subscription_t* nostr_relay_pool_subscribe(
|
||||
nostr_relay_pool_t* pool,
|
||||
const char** relay_urls,
|
||||
int relay_count,
|
||||
cJSON* filter,
|
||||
void (*on_event)(cJSON* event, const char* relay_url, void* user_data),
|
||||
void (*on_eose)(void* user_data),
|
||||
void* user_data);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
#include "cjson/cJSON.h"
|
||||
|
||||
// Event callback - called for each received event
|
||||
void handle_event(cJSON* event, const char* relay_url, void* user_data) {
|
||||
cJSON* content = cJSON_GetObjectItem(event, "content");
|
||||
cJSON* pubkey = cJSON_GetObjectItem(event, "pubkey");
|
||||
|
||||
if (content && pubkey) {
|
||||
printf("Event from %s: %s (by %s)\n",
|
||||
relay_url,
|
||||
cJSON_GetStringValue(content),
|
||||
cJSON_GetStringValue(pubkey));
|
||||
}
|
||||
}
|
||||
|
||||
// EOSE callback - called when all relays finish sending stored events
|
||||
void handle_eose(void* user_data) {
|
||||
printf("All relays finished sending stored events\n");
|
||||
}
|
||||
|
||||
int subscribe_to_notes(nostr_relay_pool_t* pool) {
|
||||
// Create filter for kind 1 (text notes) from last hour
|
||||
cJSON* filter = cJSON_CreateObject();
|
||||
cJSON* kinds = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(kinds, cJSON_CreateNumber(1));
|
||||
cJSON_AddItemToObject(filter, "kinds", kinds);
|
||||
|
||||
time_t since = time(NULL) - 3600; // Last hour
|
||||
cJSON_AddItemToObject(filter, "since", cJSON_CreateNumber(since));
|
||||
cJSON_AddItemToObject(filter, "limit", cJSON_CreateNumber(50));
|
||||
|
||||
// Subscribe to specific relays
|
||||
const char* relay_urls[] = {
|
||||
"wss://relay.damus.io",
|
||||
"wss://nos.lol"
|
||||
};
|
||||
|
||||
nostr_pool_subscription_t* sub = nostr_relay_pool_subscribe(
|
||||
pool,
|
||||
relay_urls,
|
||||
2,
|
||||
filter,
|
||||
handle_event,
|
||||
handle_eose,
|
||||
NULL // user_data
|
||||
);
|
||||
|
||||
cJSON_Delete(filter); // Pool makes its own copy
|
||||
|
||||
if (!sub) {
|
||||
fprintf(stderr, "Failed to create subscription\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Drive the event loop to receive events
|
||||
printf("Listening for events for 30 seconds...\n");
|
||||
nostr_relay_pool_run(pool, 30000); // 30 seconds
|
||||
|
||||
// Close subscription
|
||||
nostr_pool_subscription_close(sub);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Close Subscription
|
||||
**Function:** [`nostr_pool_subscription_close()`](nostr_core/core_relay_pool.c:491)
|
||||
```c
|
||||
int nostr_pool_subscription_close(nostr_pool_subscription_t* subscription);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
// Subscription management with cleanup
|
||||
typedef struct {
|
||||
nostr_pool_subscription_t* subscription;
|
||||
int event_count;
|
||||
int should_stop;
|
||||
} subscription_context_t;
|
||||
|
||||
void event_counter(cJSON* event, const char* relay_url, void* user_data) {
|
||||
subscription_context_t* ctx = (subscription_context_t*)user_data;
|
||||
ctx->event_count++;
|
||||
|
||||
printf("Received event #%d from %s\n", ctx->event_count, relay_url);
|
||||
|
||||
// Stop after 10 events
|
||||
if (ctx->event_count >= 10) {
|
||||
ctx->should_stop = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int limited_subscription(nostr_relay_pool_t* pool) {
|
||||
subscription_context_t ctx = {0};
|
||||
|
||||
// Create filter
|
||||
cJSON* filter = cJSON_CreateObject();
|
||||
cJSON* kinds = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(kinds, cJSON_CreateNumber(1));
|
||||
cJSON_AddItemToObject(filter, "kinds", kinds);
|
||||
|
||||
const char* relay_urls[] = {"wss://relay.damus.io"};
|
||||
|
||||
ctx.subscription = nostr_relay_pool_subscribe(
|
||||
pool, relay_urls, 1, filter, event_counter, NULL, &ctx);
|
||||
|
||||
cJSON_Delete(filter);
|
||||
|
||||
if (!ctx.subscription) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Poll until we should stop
|
||||
while (!ctx.should_stop) {
|
||||
int events = nostr_relay_pool_poll(pool, 100);
|
||||
if (events < 0) break;
|
||||
}
|
||||
|
||||
// Clean up
|
||||
int result = nostr_pool_subscription_close(ctx.subscription);
|
||||
printf("Subscription closed with result: %d\n", result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Event Loop
|
||||
|
||||
### Run Timed Loop
|
||||
**Function:** [`nostr_relay_pool_run()`](nostr_core/core_relay_pool.c:1192)
|
||||
```c
|
||||
int nostr_relay_pool_run(nostr_relay_pool_t* pool, int timeout_ms);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
int run_event_loop(nostr_relay_pool_t* pool) {
|
||||
printf("Starting event loop for 60 seconds...\n");
|
||||
|
||||
// Run for 60 seconds, processing all incoming events
|
||||
int total_events = nostr_relay_pool_run(pool, 60000);
|
||||
|
||||
if (total_events < 0) {
|
||||
fprintf(stderr, "Event loop error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Processed %d events total\n", total_events);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Single Poll Iteration
|
||||
**Function:** [`nostr_relay_pool_poll()`](nostr_core/core_relay_pool.c:1232)
|
||||
```c
|
||||
int nostr_relay_pool_poll(nostr_relay_pool_t* pool, int timeout_ms);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
// Integration with custom main loop
|
||||
int custom_main_loop(nostr_relay_pool_t* pool) {
|
||||
int running = 1;
|
||||
int total_events = 0;
|
||||
|
||||
while (running) {
|
||||
// Poll for Nostr events (non-blocking with 50ms timeout)
|
||||
int events = nostr_relay_pool_poll(pool, 50);
|
||||
if (events > 0) {
|
||||
total_events += events;
|
||||
printf("Processed %d events this iteration\n", events);
|
||||
}
|
||||
|
||||
// Do other work in your application
|
||||
// handle_ui_events();
|
||||
// process_background_tasks();
|
||||
|
||||
// Check exit condition
|
||||
// running = !should_exit();
|
||||
|
||||
// Simple exit after 100 events for demo
|
||||
if (total_events >= 100) {
|
||||
running = 0;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Main loop finished, processed %d total events\n", total_events);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Synchronous Operations
|
||||
|
||||
### Query Multiple Events
|
||||
**Function:** [`nostr_relay_pool_query_sync()`](nostr_core/core_relay_pool.c:695)
|
||||
```c
|
||||
cJSON** nostr_relay_pool_query_sync(
|
||||
nostr_relay_pool_t* pool,
|
||||
const char** relay_urls,
|
||||
int relay_count,
|
||||
cJSON* filter,
|
||||
int* event_count,
|
||||
int timeout_ms);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
int query_recent_notes(nostr_relay_pool_t* pool) {
|
||||
// Create filter for recent text notes
|
||||
cJSON* filter = cJSON_CreateObject();
|
||||
cJSON* kinds = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(kinds, cJSON_CreateNumber(1));
|
||||
cJSON_AddItemToObject(filter, "kinds", kinds);
|
||||
cJSON_AddItemToObject(filter, "limit", cJSON_CreateNumber(20));
|
||||
|
||||
const char* relay_urls[] = {
|
||||
"wss://relay.damus.io",
|
||||
"wss://nos.lol"
|
||||
};
|
||||
|
||||
int event_count = 0;
|
||||
cJSON** events = nostr_relay_pool_query_sync(
|
||||
pool, relay_urls, 2, filter, &event_count, 10000); // 10 second timeout
|
||||
|
||||
cJSON_Delete(filter);
|
||||
|
||||
if (!events) {
|
||||
printf("No events received or query failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Received %d events:\n", event_count);
|
||||
for (int i = 0; i < event_count; i++) {
|
||||
cJSON* content = cJSON_GetObjectItem(events[i], "content");
|
||||
if (content) {
|
||||
printf(" %d: %s\n", i + 1, cJSON_GetStringValue(content));
|
||||
}
|
||||
|
||||
// Free each event
|
||||
cJSON_Delete(events[i]);
|
||||
}
|
||||
|
||||
// Free the events array
|
||||
free(events);
|
||||
return event_count;
|
||||
}
|
||||
```
|
||||
|
||||
### Get Single Most Recent Event
|
||||
**Function:** [`nostr_relay_pool_get_event()`](nostr_core/core_relay_pool.c:825)
|
||||
```c
|
||||
cJSON* nostr_relay_pool_get_event(
|
||||
nostr_relay_pool_t* pool,
|
||||
const char** relay_urls,
|
||||
int relay_count,
|
||||
cJSON* filter,
|
||||
int timeout_ms);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
int get_latest_note_from_pubkey(nostr_relay_pool_t* pool, const char* pubkey_hex) {
|
||||
// Create filter for specific author's notes
|
||||
cJSON* filter = cJSON_CreateObject();
|
||||
cJSON* kinds = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(kinds, cJSON_CreateNumber(1));
|
||||
cJSON_AddItemToObject(filter, "kinds", kinds);
|
||||
|
||||
cJSON* authors = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(authors, cJSON_CreateString(pubkey_hex));
|
||||
cJSON_AddItemToObject(filter, "authors", authors);
|
||||
|
||||
cJSON_AddItemToObject(filter, "limit", cJSON_CreateNumber(1));
|
||||
|
||||
const char* relay_urls[] = {"wss://relay.damus.io"};
|
||||
|
||||
cJSON* event = nostr_relay_pool_get_event(
|
||||
pool, relay_urls, 1, filter, 5000); // 5 second timeout
|
||||
|
||||
cJSON_Delete(filter);
|
||||
|
||||
if (!event) {
|
||||
printf("No recent event found for pubkey %s\n", pubkey_hex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cJSON* content = cJSON_GetObjectItem(event, "content");
|
||||
cJSON* created_at = cJSON_GetObjectItem(event, "created_at");
|
||||
|
||||
if (content && created_at) {
|
||||
printf("Latest note: %s (created at %ld)\n",
|
||||
cJSON_GetStringValue(content),
|
||||
(long)cJSON_GetNumberValue(created_at));
|
||||
}
|
||||
|
||||
cJSON_Delete(event);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Publish Event
|
||||
**Function:** [`nostr_relay_pool_publish_async()`](nostr_core/core_relay_pool.c:866)
|
||||
```c
|
||||
int nostr_relay_pool_publish_async(
|
||||
nostr_relay_pool_t* pool,
|
||||
const char** relay_urls,
|
||||
int relay_count,
|
||||
cJSON* event);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
int publish_text_note(nostr_relay_pool_t* pool, const char* content) {
|
||||
// Create a basic text note event (this is simplified - real implementation
|
||||
// would need proper signing with private key)
|
||||
cJSON* event = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(event, "kind", cJSON_CreateNumber(1));
|
||||
cJSON_AddItemToObject(event, "content", cJSON_CreateString(content));
|
||||
cJSON_AddItemToObject(event, "created_at", cJSON_CreateNumber(time(NULL)));
|
||||
|
||||
// In real usage, you'd add pubkey, id, sig fields here
|
||||
cJSON_AddItemToObject(event, "pubkey", cJSON_CreateString("your_pubkey_hex"));
|
||||
cJSON_AddItemToObject(event, "id", cJSON_CreateString("event_id_hash"));
|
||||
cJSON_AddItemToObject(event, "sig", cJSON_CreateString("event_signature"));
|
||||
cJSON_AddItemToObject(event, "tags", cJSON_CreateArray());
|
||||
|
||||
const char* relay_urls[] = {
|
||||
"wss://relay.damus.io",
|
||||
"wss://nos.lol",
|
||||
"wss://relay.nostr.band"
|
||||
};
|
||||
|
||||
printf("Publishing note: %s\n", content);
|
||||
|
||||
int success_count = nostr_relay_pool_publish_async(
|
||||
pool, relay_urls, 3, event, my_callback, user_data);
|
||||
|
||||
cJSON_Delete(event);
|
||||
|
||||
printf("Successfully published to %d out of 3 relays\n", success_count);
|
||||
|
||||
if (success_count == 0) {
|
||||
fprintf(stderr, "Failed to publish to any relay\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return success_count;
|
||||
}
|
||||
```
|
||||
|
||||
## Status and Statistics
|
||||
|
||||
### Get Relay Status
|
||||
**Function:** [`nostr_relay_pool_get_relay_status()`](nostr_core/core_relay_pool.c:944)
|
||||
```c
|
||||
nostr_pool_relay_status_t nostr_relay_pool_get_relay_status(
|
||||
nostr_relay_pool_t* pool,
|
||||
const char* relay_url);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
void check_relay_status(nostr_relay_pool_t* pool, const char* relay_url) {
|
||||
nostr_pool_relay_status_t status = nostr_relay_pool_get_relay_status(pool, relay_url);
|
||||
|
||||
const char* status_str;
|
||||
switch (status) {
|
||||
case NOSTR_POOL_RELAY_DISCONNECTED:
|
||||
status_str = "DISCONNECTED";
|
||||
break;
|
||||
case NOSTR_POOL_RELAY_CONNECTING:
|
||||
status_str = "CONNECTING";
|
||||
break;
|
||||
case NOSTR_POOL_RELAY_CONNECTED:
|
||||
status_str = "CONNECTED";
|
||||
break;
|
||||
case NOSTR_POOL_RELAY_ERROR:
|
||||
status_str = "ERROR";
|
||||
break;
|
||||
default:
|
||||
status_str = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Relay %s status: %s\n", relay_url, status_str);
|
||||
}
|
||||
```
|
||||
|
||||
### List All Relays
|
||||
**Function:** [`nostr_relay_pool_list_relays()`](nostr_core/core_relay_pool.c:960)
|
||||
```c
|
||||
int nostr_relay_pool_list_relays(
|
||||
nostr_relay_pool_t* pool,
|
||||
char*** relay_urls,
|
||||
nostr_pool_relay_status_t** statuses);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
void print_all_relays(nostr_relay_pool_t* pool) {
|
||||
char** relay_urls = NULL;
|
||||
nostr_pool_relay_status_t* statuses = NULL;
|
||||
|
||||
int count = nostr_relay_pool_list_relays(pool, &relay_urls, &statuses);
|
||||
|
||||
if (count < 0) {
|
||||
printf("Failed to list relays\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
printf("No relays configured\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Configured relays (%d):\n", count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
const char* status_str = (statuses[i] == NOSTR_POOL_RELAY_CONNECTED) ?
|
||||
"CONNECTED" : "DISCONNECTED";
|
||||
printf(" %s - %s\n", relay_urls[i], status_str);
|
||||
|
||||
// Free the duplicated URL string
|
||||
free(relay_urls[i]);
|
||||
}
|
||||
|
||||
// Free the arrays
|
||||
free(relay_urls);
|
||||
free(statuses);
|
||||
}
|
||||
```
|
||||
|
||||
### Get Relay Statistics
|
||||
**Function:** [`nostr_relay_pool_get_relay_stats()`](nostr_core/core_relay_pool.c:992)
|
||||
```c
|
||||
const nostr_relay_stats_t* nostr_relay_pool_get_relay_stats(
|
||||
nostr_relay_pool_t* pool,
|
||||
const char* relay_url);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
void print_relay_stats(nostr_relay_pool_t* pool, const char* relay_url) {
|
||||
const nostr_relay_stats_t* stats = nostr_relay_pool_get_relay_stats(pool, relay_url);
|
||||
|
||||
if (!stats) {
|
||||
printf("No stats available for relay %s\n", relay_url);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Statistics for %s:\n", relay_url);
|
||||
printf(" Connection attempts: %d\n", stats->connection_attempts);
|
||||
printf(" Connection failures: %d\n", stats->connection_failures);
|
||||
printf(" Events received: %d\n", stats->events_received);
|
||||
printf(" Events published: %d\n", stats->events_published);
|
||||
printf(" Events published OK: %d\n", stats->events_published_ok);
|
||||
printf(" Events published failed: %d\n", stats->events_published_failed);
|
||||
printf(" Query latency avg: %.2f ms\n", stats->query_latency_avg);
|
||||
printf(" Query samples: %d\n", stats->query_samples);
|
||||
printf(" Publish latency avg: %.2f ms\n", stats->publish_latency_avg);
|
||||
printf(" Publish samples: %d\n", stats->publish_samples);
|
||||
|
||||
if (stats->last_event_time > 0) {
|
||||
printf(" Last event: %ld seconds ago\n",
|
||||
time(NULL) - stats->last_event_time);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Reset Relay Statistics
|
||||
**Function:** [`nostr_relay_pool_reset_relay_stats()`](nostr_core/core_relay_pool.c:1008)
|
||||
```c
|
||||
int nostr_relay_pool_reset_relay_stats(
|
||||
nostr_relay_pool_t* pool,
|
||||
const char* relay_url);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
void reset_stats_for_relay(nostr_relay_pool_t* pool, const char* relay_url) {
|
||||
int result = nostr_relay_pool_reset_relay_stats(pool, relay_url);
|
||||
|
||||
if (result == NOSTR_SUCCESS) {
|
||||
printf("Successfully reset statistics for %s\n", relay_url);
|
||||
} else {
|
||||
printf("Failed to reset statistics for %s\n", relay_url);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Get Query Latency
|
||||
**Function:** [`nostr_relay_pool_get_relay_query_latency()`](nostr_core/core_relay_pool.c:1045)
|
||||
```c
|
||||
double nostr_relay_pool_get_relay_query_latency(
|
||||
nostr_relay_pool_t* pool,
|
||||
const char* relay_url);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```c
|
||||
void check_relay_performance(nostr_relay_pool_t* pool) {
|
||||
const char* relays[] = {
|
||||
"wss://relay.damus.io",
|
||||
"wss://nos.lol",
|
||||
"wss://relay.nostr.band"
|
||||
};
|
||||
|
||||
printf("Relay performance comparison:\n");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
double latency = nostr_relay_pool_get_relay_query_latency(pool, relays[i]);
|
||||
|
||||
if (latency >= 0) {
|
||||
printf(" %s: %.2f ms average query latency\n", relays[i], latency);
|
||||
} else {
|
||||
printf(" %s: No latency data available\n", relays[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Complete Example Application
|
||||
|
||||
```c
|
||||
#include "nostr_core.h"
|
||||
#include "cjson/cJSON.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Global context for the example
|
||||
typedef struct {
|
||||
int event_count;
|
||||
int max_events;
|
||||
} app_context_t;
|
||||
|
||||
void on_text_note(cJSON* event, const char* relay_url, void* user_data) {
|
||||
app_context_t* ctx = (app_context_t*)user_data;
|
||||
|
||||
cJSON* content = cJSON_GetObjectItem(event, "content");
|
||||
if (content && cJSON_IsString(content)) {
|
||||
printf("[%s] Note #%d: %s\n",
|
||||
relay_url, ++ctx->event_count, cJSON_GetStringValue(content));
|
||||
}
|
||||
}
|
||||
|
||||
void on_subscription_complete(void* user_data) {
|
||||
printf("All relays finished sending stored events\n");
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Initialize pool
|
||||
nostr_relay_pool_t* pool = nostr_relay_pool_create();
|
||||
if (!pool) {
|
||||
fprintf(stderr, "Failed to create relay pool\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Add relays
|
||||
const char* relays[] = {
|
||||
"wss://relay.damus.io",
|
||||
"wss://nos.lol"
|
||||
};
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (nostr_relay_pool_add_relay(pool, relays[i]) != NOSTR_SUCCESS) {
|
||||
fprintf(stderr, "Failed to add relay: %s\n", relays[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create filter for recent text notes
|
||||
cJSON* filter = cJSON_CreateObject();
|
||||
cJSON* kinds = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(kinds, cJSON_CreateNumber(1));
|
||||
cJSON_AddItemToObject(filter, "kinds", kinds);
|
||||
cJSON_AddItemToObject(filter, "limit", cJSON_CreateNumber(10));
|
||||
|
||||
// Set up context
|
||||
app_context_t ctx = {0, 10};
|
||||
|
||||
// Subscribe
|
||||
nostr_pool_subscription_t* sub = nostr_relay_pool_subscribe(
|
||||
pool, relays, 2, filter, on_text_note, on_subscription_complete, &ctx);
|
||||
|
||||
cJSON_Delete(filter);
|
||||
|
||||
if (!sub) {
|
||||
fprintf(stderr, "Failed to create subscription\n");
|
||||
nostr_relay_pool_destroy(pool);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Run event loop for 30 seconds
|
||||
printf("Listening for events...\n");
|
||||
nostr_relay_pool_run(pool, 30000);
|
||||
|
||||
// Print final stats
|
||||
for (int i = 0; i < 2; i++) {
|
||||
print_relay_stats(pool, relays[i]);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
nostr_pool_subscription_close(sub);
|
||||
nostr_relay_pool_destroy(pool);
|
||||
|
||||
printf("Application finished. Received %d events total.\n", ctx.event_count);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- All functions are **not thread-safe**. Use from a single thread or add external synchronization.
|
||||
- **Memory ownership**: The pool duplicates filters and URLs internally. Caller owns returned events and must free them.
|
||||
- **Event deduplication** is applied pool-wide using a circular buffer of 1000 event IDs.
|
||||
- **Ping functionality** is currently disabled in this build.
|
||||
- **NIP-42 behavior**: With [`nostr_relay_pool_set_auth()`](nostr_core/core_relay_pool.c:616) enabled, the pool will respond to relay `AUTH` challenges automatically using [`nostr_nip42_create_auth_event()`](nostr_core/nip042.c:26) and [`nostr_nip42_create_auth_message()`](nostr_core/nip042.c:84).
|
||||
- **Reconnection** happens on-demand when sending, but active subscriptions are not automatically re-sent after reconnect.
|
||||
- **Polling model**: You must drive the event loop via [`nostr_relay_pool_run()`](nostr_core/core_relay_pool.c:1745) or [`nostr_relay_pool_poll()`](nostr_core/core_relay_pool.c:1785) to receive events.
|
||||
@@ -1,103 +1,46 @@
|
||||
# NOSTR Core Library
|
||||
|
||||
A C library for NOSTR protocol implementation. Work in progress.
|
||||
A comprehensive, production-ready C library for NOSTR protocol implementation with OpenSSL-based cryptography and extensive protocol support.
|
||||
|
||||
[](VERSION)
|
||||
[](VERSION)
|
||||
[](#license)
|
||||
[](#building)
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
## 📋 NIP Implementation Status
|
||||
### Core Protocol Support
|
||||
- **NIP-01**: Basic protocol flow - event creation, signing, and validation
|
||||
- **NIP-04**: Encrypted direct messages (ECDH + AES-CBC + Base64)
|
||||
- **NIP-05**: DNS-based internet identifier verification
|
||||
- **NIP-06**: Key derivation from mnemonic (BIP39/BIP32 compliant)
|
||||
- **NIP-11**: Relay information documents
|
||||
- **NIP-13**: Proof of Work for events
|
||||
- **NIP-44**: Versioned encrypted direct messages (ECDH + ChaCha20 + HMAC)
|
||||
|
||||
### Core Protocol NIPs
|
||||
- [x] [NIP-01](nips/01.md) - Basic protocol flow - event creation, signing, and validation
|
||||
- [ ] [NIP-02](nips/02.md) - Contact List and Petnames
|
||||
- [x] [NIP-03](nips/03.md) - OpenTimestamps Attestations for Events
|
||||
- [x] [NIP-04](nips/04.md) - Encrypted Direct Messages (legacy)
|
||||
- [x] [NIP-05](nips/05.md) - Mapping Nostr keys to DNS-based internet identifiers
|
||||
- [x] [NIP-06](nips/06.md) - Basic key derivation from mnemonic seed phrase
|
||||
- [-] [NIP-07](nips/07.md) - `window.nostr` capability for web browsers
|
||||
- [ ] [NIP-08](nips/08.md) - Handling Mentions
|
||||
- [ ] [NIP-09](nips/09.md) - Event Deletion
|
||||
- [ ] [NIP-10](nips/10.md) - Conventions for clients' use of `e` and `p` tags in text events
|
||||
- [x] [NIP-11](nips/11.md) - Relay Information Document
|
||||
- [ ] [NIP-12](nips/12.md) - Generic Tag Queries
|
||||
- [x] [NIP-13](nips/13.md) - Proof of Work
|
||||
- [ ] [NIP-14](nips/14.md) - Subject tag in text events
|
||||
- [ ] [NIP-15](nips/15.md) - Nostr Marketplace (for resilient marketplaces)
|
||||
- [ ] [NIP-16](nips/16.md) - Event Treatment
|
||||
- [x] [NIP-17](nips/17.md) - Private Direct Messages
|
||||
- [ ] [NIP-18](nips/18.md) - Reposts
|
||||
- [x] [NIP-19](nips/19.md) - bech32-encoded entities
|
||||
- [ ] [NIP-20](nips/20.md) - Command Results
|
||||
- [x] [NIP-21](nips/21.md) - `nostr:` URI scheme
|
||||
- [ ] [NIP-22](nips/22.md) - Event `created_at` Limits
|
||||
- [ ] [NIP-23](nips/23.md) - Long-form Content
|
||||
- [ ] [NIP-24](nips/24.md) - Extra metadata fields and tags
|
||||
- [ ] [NIP-25](nips/25.md) - Reactions
|
||||
- [ ] [NIP-26](nips/26.md) - Delegated Event Signing
|
||||
- [ ] [NIP-27](nips/27.md) - Text Note References
|
||||
- [ ] [NIP-28](nips/28.md) - Public Chat
|
||||
- [ ] [NIP-29](nips/29.md) - Relay-based Groups
|
||||
- [ ] [NIP-30](nips/30.md) - Custom Emoji
|
||||
- [ ] [NIP-31](nips/31.md) - Dealing with Unknown Events
|
||||
- [ ] [NIP-32](nips/32.md) - Labeling
|
||||
- [ ] [NIP-33](nips/33.md) - Parameterized Replaceable Events
|
||||
- [ ] [NIP-34](nips/34.md) - `git` stuff
|
||||
- [ ] [NIP-35](nips/35.md) - Torrents
|
||||
- [ ] [NIP-36](nips/36.md) - Sensitive Content / Content Warning
|
||||
- [ ] [NIP-37](nips/37.md) - Draft Events
|
||||
- [ ] [NIP-38](nips/38.md) - User Statuses
|
||||
- [ ] [NIP-39](nips/39.md) - External Identities in Profiles
|
||||
- [ ] [NIP-40](nips/40.md) - Expiration Timestamp
|
||||
- [x] [NIP-42](nips/42.md) - Authentication of clients to relays
|
||||
- [x] [NIP-44](nips/44.md) - Versioned Encryption
|
||||
- [ ] [NIP-45](nips/45.md) - Counting results
|
||||
- [x] [NIP-46](nips/46.md) - Nostr Remote Signing
|
||||
- [ ] [NIP-47](nips/47.md) - Wallet Connect
|
||||
- [ ] [NIP-48](nips/48.md) - Proxy Tags
|
||||
- [ ] [NIP-49](nips/49.md) - Private Key Encryption
|
||||
- [ ] [NIP-50](nips/50.md) - Search Capability
|
||||
- [ ] [NIP-51](nips/51.md) - Lists
|
||||
- [ ] [NIP-52](nips/52.md) - Calendar Events
|
||||
- [ ] [NIP-53](nips/53.md) - Live Activities
|
||||
- [ ] [NIP-54](nips/54.md) - Wiki
|
||||
- [-] [NIP-55](nips/55.md) - Android Signer Application
|
||||
- [ ] [NIP-56](nips/56.md) - Reporting
|
||||
- [ ] [NIP-57](nips/57.md) - Lightning Zaps
|
||||
- [ ] [NIP-58](nips/58.md) - Badges
|
||||
- [x] [NIP-59](nips/59.md) - Gift Wrap
|
||||
- [ ] [NIP-60](nips/60.md) - Cashu Wallet
|
||||
- [ ] [NIP-61](nips/61.md) - Nutzaps
|
||||
- [ ] [NIP-62](nips/62.md) - Log events
|
||||
- [-] [NIP-64](nips/64.md) - Chess (PGN)
|
||||
- [ ] [NIP-65](nips/65.md) - Relay List Metadata
|
||||
- [ ] [NIP-66](nips/66.md) - Relay Monitor
|
||||
- [-] [NIP-68](nips/68.md) - Web badges
|
||||
- [ ] [NIP-69](nips/69.md) - Peer-to-peer Order events
|
||||
- [ ] [NIP-70](nips/70.md) - Protected Events
|
||||
- [ ] [NIP-71](nips/71.md) - Video Events
|
||||
- [ ] [NIP-72](nips/72.md) - Moderated Communities
|
||||
- [ ] [NIP-73](nips/73.md) - External Content IDs
|
||||
- [ ] [NIP-75](nips/75.md) - Zap Goals
|
||||
- [ ] [NIP-77](nips/77.md) - Arbitrary custom app data
|
||||
- [ ] [NIP-78](nips/78.md) - Application-specific data
|
||||
- [ ] [NIP-84](nips/84.md) - Highlights
|
||||
- [ ] [NIP-86](nips/86.md) - Relay Management API
|
||||
- [ ] [NIP-87](nips/87.md) - Relay List Recommendations
|
||||
- [-] [NIP-88](nips/88.md) - Stella: A Stellar Relay
|
||||
- [ ] [NIP-89](nips/89.md) - Recommended Application Handlers
|
||||
- [ ] [NIP-90](nips/90.md) - Data Vending Machines
|
||||
- [ ] [NIP-92](nips/92.md) - Media Attachments
|
||||
- [ ] [NIP-94](nips/94.md) - File Metadata
|
||||
- [ ] [NIP-96](nips/96.md) - HTTP File Storage Integration
|
||||
- [ ] [NIP-98](nips/98.md) - HTTP Auth
|
||||
- [ ] [NIP-99](nips/99.md) - Classified Listings
|
||||
### Cryptographic Features
|
||||
- **OpenSSL-Based**: Production-grade cryptography with OpenSSL backend
|
||||
- **Secp256k1**: Complete elliptic curve implementation bundled
|
||||
- **BIP39**: Mnemonic phrase generation and validation
|
||||
- **BIP32**: Hierarchical deterministic key derivation
|
||||
- **ChaCha20**: Stream cipher for NIP-44 encryption
|
||||
- **AES-CBC**: Block cipher for NIP-04 encryption
|
||||
- **Schnorr Signatures**: BIP-340 compliant signing and verification
|
||||
|
||||
**Legend:** ✅ Fully Implemented | ⚠️ Partial Implementation | ❌ Not Implemented | ➖ Not Applicable
|
||||
|
||||
**Implementation Summary:** 13 of 96+ NIPs fully implemented (13.5%)
|
||||
### Networking & Relay Support
|
||||
- **Multi-Relay Queries**: Synchronous querying with progress callbacks
|
||||
- **Relay Pools**: Asynchronous connection management with statistics
|
||||
- **OpenSSL WebSocket Communication**: Full relay protocol support with TLS
|
||||
- **NIP-05 Identifier Verification**: DNS-based identity resolution
|
||||
- **NIP-11 Relay Information**: Automatic relay capability discovery
|
||||
- **Event Deduplication**: Automatic handling of duplicate events across relays
|
||||
- **Connection Management**: Automatic reconnection and error handling
|
||||
|
||||
### Developer Experience
|
||||
- **Minimal Dependencies**: Only requires OpenSSL, standard C library and math library
|
||||
- **Thread-Safe**: Core cryptographic functions are stateless
|
||||
- **Cross-Platform**: Builds on Linux, macOS, Windows
|
||||
- **Comprehensive Examples**: Ready-to-run demonstration programs
|
||||
- **Automatic Versioning**: Git-tag based version management
|
||||
|
||||
## 📦 Quick Start
|
||||
|
||||
@@ -111,12 +54,12 @@ A C library for NOSTR protocol implementation. Work in progress.
|
||||
|
||||
2. **Build the library:**
|
||||
```bash
|
||||
./build.sh
|
||||
./build.sh lib
|
||||
```
|
||||
|
||||
3. **Build and run examples:**
|
||||
3. **Run examples:**
|
||||
```bash
|
||||
./build.sh -e
|
||||
./build.sh examples
|
||||
./examples/simple_keygen
|
||||
```
|
||||
|
||||
@@ -161,7 +104,7 @@ int main() {
|
||||
|
||||
**Compile and run:**
|
||||
```bash
|
||||
gcc example.c -o example ./libnostr_core_x64.a -lz -ldl -lpthread -lm -lssl -lcrypto -lcurl -lsecp256k1
|
||||
gcc example.c -o example ./libnostr_core.a -lm
|
||||
./example
|
||||
```
|
||||
|
||||
@@ -170,43 +113,44 @@ gcc example.c -o example ./libnostr_core_x64.a -lz -ldl -lpthread -lm -lssl -lcr
|
||||
### Build Targets
|
||||
|
||||
```bash
|
||||
./build.sh # Build static library (default)
|
||||
./build.sh --nips=all # Force build with all available NIPs
|
||||
./build.sh -t # Build all test executables in tests/
|
||||
./build.sh -e # Build all examples in examples/
|
||||
./build.sh -t -e # Build library + tests + examples
|
||||
./build.sh --nips=46 # Build specifically with NIP-046 support
|
||||
./build.sh --help # Show all options
|
||||
./build.sh lib # Build static library (default)
|
||||
./build.sh examples # Build examples
|
||||
./build.sh test # Run test suite
|
||||
./build.sh clean # Clean build artifacts
|
||||
./build.sh install # Install to system
|
||||
```
|
||||
|
||||
### Manual Building
|
||||
|
||||
```bash
|
||||
# Build static library
|
||||
make
|
||||
|
||||
# Build examples
|
||||
make examples
|
||||
|
||||
# Run tests
|
||||
make test-crypto
|
||||
|
||||
# Clean
|
||||
make clean
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
|
||||
**Required System Dependencies:**
|
||||
**Required:**
|
||||
- GCC or compatible C compiler
|
||||
- Standard C library and math library (`-lm`)
|
||||
- OpenSSL development libraries (`-lssl -lcrypto`)
|
||||
- curl development libraries (`-lcurl`)
|
||||
- secp256k1 development libraries (`-lsecp256k1`)
|
||||
- Standard C library
|
||||
- Math library (`-lm`)
|
||||
|
||||
**Install on Ubuntu/Debian:**
|
||||
```bash
|
||||
sudo apt install build-essential libssl-dev libcurl4-openssl-dev libsecp256k1-dev
|
||||
```
|
||||
**Included & Embedded (x64):**
|
||||
- cJSON (JSON parsing)
|
||||
- secp256k1 (elliptic curve cryptography)
|
||||
- OpenSSL (complete cryptographic backend + TLS)
|
||||
- curl (HTTP/HTTPS for NIP-05/NIP-11)
|
||||
|
||||
**Install on CentOS/RHEL:**
|
||||
```bash
|
||||
sudo yum install gcc openssl-devel libcurl-devel libsecp256k1-devel
|
||||
```
|
||||
|
||||
**Install on macOS:**
|
||||
```bash
|
||||
brew install openssl curl secp256k1
|
||||
```
|
||||
|
||||
**Still Bundled:**
|
||||
- cJSON (JSON parsing - internal copy)
|
||||
- TinyAES-c (AES encryption for NIP-04)
|
||||
- ChaCha20 (stream cipher for NIP-44)
|
||||
**ARM64 Additional Requirements:**
|
||||
- System OpenSSL libraries (`-lssl -lcrypto`)
|
||||
|
||||
## 📚 API Documentation
|
||||
|
||||
@@ -288,38 +232,20 @@ publish_result_t* synchronous_publish_event_with_progress(const char** relay_url
|
||||
|
||||
### Relay Pools (Asynchronous)
|
||||
```c
|
||||
// Create and manage relay pool with reconnection
|
||||
nostr_pool_reconnect_config_t* config = nostr_pool_reconnect_config_default();
|
||||
nostr_relay_pool_t* nostr_relay_pool_create(nostr_pool_reconnect_config_t* config);
|
||||
// Create and manage relay pool
|
||||
nostr_relay_pool_t* nostr_relay_pool_create(void);
|
||||
int nostr_relay_pool_add_relay(nostr_relay_pool_t* pool, const char* relay_url);
|
||||
int nostr_relay_pool_set_auth(nostr_relay_pool_t* pool, const unsigned char* private_key, int enable);
|
||||
void nostr_relay_pool_destroy(nostr_relay_pool_t* pool);
|
||||
|
||||
// Subscribe to events (with auto-reconnection)
|
||||
// Subscribe to events
|
||||
nostr_pool_subscription_t* nostr_relay_pool_subscribe(
|
||||
nostr_relay_pool_t* pool, const char** relay_urls, int relay_count, cJSON* filter,
|
||||
void (*on_event)(cJSON* event, const char* relay_url, void* user_data),
|
||||
void (*on_eose)(void* user_data), void* user_data, int close_on_eose);
|
||||
void (*on_eose)(void* user_data), void* user_data);
|
||||
|
||||
// Enable NIP-42 auth (auto-responds to relay AUTH challenges)
|
||||
unsigned char private_key[32];
|
||||
nostr_hex_to_bytes("91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe", private_key, 32);
|
||||
nostr_relay_pool_set_auth(pool, private_key, 1);
|
||||
|
||||
// Run event loop (handles reconnection + incoming AUTH/NOTICE/OK messages)
|
||||
// Run event loop
|
||||
int nostr_relay_pool_run(nostr_relay_pool_t* pool, int timeout_ms);
|
||||
int nostr_relay_pool_poll(nostr_relay_pool_t* pool, int timeout_ms);
|
||||
|
||||
// Reconnection configuration
|
||||
typedef struct {
|
||||
int enable_auto_reconnect; // Enable automatic reconnection
|
||||
int max_reconnect_attempts; // Maximum retry attempts
|
||||
int initial_reconnect_delay_ms; // Initial delay between attempts
|
||||
int max_reconnect_delay_ms; // Maximum delay cap
|
||||
int reconnect_backoff_multiplier; // Exponential backoff factor
|
||||
int ping_interval_seconds; // Health check ping interval
|
||||
int pong_timeout_seconds; // Pong response timeout
|
||||
} nostr_pool_reconnect_config_t;
|
||||
```
|
||||
|
||||
### NIP-05 Identifier Verification
|
||||
@@ -346,171 +272,6 @@ int nostr_nip11_fetch_relay_info(const char* relay_url, nostr_relay_info_t** inf
|
||||
void nostr_nip11_relay_info_free(nostr_relay_info_t* info);
|
||||
```
|
||||
|
||||
## Signer abstraction & nsigner integration
|
||||
|
||||
All signing/encryption operations can run through an opaque `nostr_signer_t` handle. This provides:
|
||||
|
||||
- **LOCAL backend** (`nostr_signer_local`) using a raw 32-byte private key (output-equivalent to legacy raw-key APIs).
|
||||
- **REMOTE backends** (`nostr_signer_nsigner_*`) that call a running `n_signer` process/device over supported transports.
|
||||
|
||||
### Core signer verbs (exact signatures)
|
||||
|
||||
```c
|
||||
/* Lifecycle */
|
||||
nostr_signer_t* nostr_signer_local(const unsigned char private_key[32]);
|
||||
void nostr_signer_free(nostr_signer_t* signer);
|
||||
|
||||
/* Core verbs */
|
||||
int nostr_signer_get_public_key(nostr_signer_t* signer, char out_pubkey_hex[65]);
|
||||
int nostr_signer_sign_event(nostr_signer_t* signer, const cJSON* unsigned_event, cJSON** signed_event_out);
|
||||
|
||||
/* Encryption verbs */
|
||||
int nostr_signer_nip04_encrypt(nostr_signer_t* signer,
|
||||
const char* peer_pubkey_hex,
|
||||
const char* plaintext,
|
||||
char** ciphertext_out);
|
||||
int nostr_signer_nip04_decrypt(nostr_signer_t* signer,
|
||||
const char* peer_pubkey_hex,
|
||||
const char* ciphertext,
|
||||
char** plaintext_out);
|
||||
int nostr_signer_nip44_encrypt(nostr_signer_t* signer,
|
||||
const char* peer_pubkey_hex,
|
||||
const char* plaintext,
|
||||
char** ciphertext_out);
|
||||
int nostr_signer_nip44_decrypt(nostr_signer_t* signer,
|
||||
const char* peer_pubkey_hex,
|
||||
const char* ciphertext,
|
||||
char** plaintext_out);
|
||||
```
|
||||
|
||||
### Backends / transports
|
||||
|
||||
Remote signer factories (available when `NOSTR_ENABLE_NSIGNER_CLIENT` is enabled):
|
||||
|
||||
```c
|
||||
nostr_signer_t* nostr_signer_nsigner_unix(const char* socket_name, const char* role, int timeout_ms);
|
||||
nostr_signer_t* nostr_signer_nsigner_serial(const char* device_path, const char* role, int timeout_ms);
|
||||
nostr_signer_t* nostr_signer_nsigner_tcp(const char* host, int port, const char* role, int timeout_ms);
|
||||
nostr_signer_t* nostr_signer_nsigner_fds(int read_fd, int write_fd, const char* role, int timeout_ms);
|
||||
int nostr_signer_nsigner_set_auth(nostr_signer_t* signer,
|
||||
const unsigned char auth_privkey[32],
|
||||
const char* label);
|
||||
```
|
||||
|
||||
Transport layer constructors and discovery helpers:
|
||||
|
||||
```c
|
||||
nsigner_transport_t* nsigner_transport_open_unix(const char* socket_name, int timeout_ms);
|
||||
nsigner_transport_t* nsigner_transport_open_tcp(const char* host, int port, int timeout_ms);
|
||||
nsigner_transport_t* nsigner_transport_open_serial(const char* device_path, int timeout_ms);
|
||||
nsigner_transport_t* nsigner_transport_open_fds(int read_fd, int write_fd, int timeout_ms);
|
||||
int nsigner_transport_list_unix(char names[][64], int max_names);
|
||||
int nsigner_transport_list_serial(char paths[][64], int max_paths);
|
||||
```
|
||||
|
||||
Supported transport modes:
|
||||
- UNIX abstract socket (`unix:<name>`, no leading `@` in API input)
|
||||
- USB CDC-ACM serial (`serial:/dev/ttyACM0`)
|
||||
- TCP (`tcp:<host>:<port>`)
|
||||
- Existing framed fd pair (`fds:<read_fd>:<write_fd>`, useful for stdio/qrexec-style bridges)
|
||||
|
||||
Build gating:
|
||||
- Desktop builds enable `NOSTR_ENABLE_NSIGNER_CLIENT`.
|
||||
- ESP32 builds exclude the nsigner client transport/client sources and do not define the flag.
|
||||
- n_signer’s own build keeps this client side disabled.
|
||||
|
||||
Wire contract (high level):
|
||||
- Framing is **4-byte big-endian length + JSON payload**.
|
||||
- Payload length must be in `[1, 65536]` bytes.
|
||||
- TCP uses a kind-27235 auth envelope (`nsigner_rpc`, `nsigner_method`, `nsigner_body_hash`).
|
||||
- See n_signer docs for authoritative protocol details.
|
||||
|
||||
### Using a signer in higher-level APIs
|
||||
|
||||
Pattern: existing raw-private-key functions remain unchanged; signer-aware siblings are provided as `*_with_signer` variants.
|
||||
|
||||
Covered modules and functions:
|
||||
|
||||
- NIP-01 (`nostr_core/nip001.h`)
|
||||
- `cJSON* nostr_create_and_sign_event_with_signer(int kind, const char* content, cJSON* tags, nostr_signer_t* signer, time_t timestamp);`
|
||||
|
||||
- NIP-03 OpenTimestamps (`nostr_core/nip003.h`)
|
||||
- `cJSON* nostr_nip03_create_proof_event_with_signer(const char* target_event_id, int target_event_kind, const char* ots_data_base64, const char* relay_url, nostr_signer_t* signer);`
|
||||
- `char* nostr_nip03_request_timestamp(const char* event_id_hex, const char* calendar_url, int timeout_seconds);`
|
||||
- `int nostr_nip03_is_proof_complete(const char* ots_data_base64);`
|
||||
- `int nostr_nip03_get_attestation_info(const char* ots_data_base64, int* has_bitcoin, int* has_litecoin, int* has_pending, uint64_t* bitcoin_height, uint64_t* litecoin_height, char** pending_uri_out);`
|
||||
- `char* nostr_nip03_upgrade_proof(const char* ots_data_base64, const char* calendar_url, int timeout_seconds);`
|
||||
- `int nostr_nip03_verify_proof(const char* ots_data_base64, const char* target_digest_hex, uint64_t* block_height_out, time_t* block_time_out);`
|
||||
|
||||
- NIP-17 (`nostr_core/nip017.h`)
|
||||
- `cJSON* nostr_nip17_create_relay_list_event_with_signer(const char** relay_urls, int num_relays, nostr_signer_t* signer);`
|
||||
- `int nostr_nip17_send_dm_with_signer(cJSON* dm_event, const char** recipient_pubkeys, int num_recipients, nostr_signer_t* signer, cJSON** gift_wraps_out, int max_gift_wraps, long max_delay_sec);`
|
||||
- `cJSON* nostr_nip17_receive_dm_with_signer(cJSON* gift_wrap, nostr_signer_t* signer);`
|
||||
|
||||
- NIP-42 (`nostr_core/nip042.h`)
|
||||
- `cJSON* nostr_nip42_create_auth_event_with_signer(const char* challenge, const char* relay_url, nostr_signer_t* signer, time_t timestamp);`
|
||||
|
||||
- NIP-46 client/event helpers (`nostr_core/nip046.h`)
|
||||
- `cJSON* nostr_nip46_create_request_event_with_signer(const nostr_nip46_request_t* request, nostr_signer_t* signer, const unsigned char* recipient_public_key, time_t timestamp);`
|
||||
- `cJSON* nostr_nip46_create_response_event_with_signer(const nostr_nip46_response_t* response, nostr_signer_t* signer, const unsigned char* recipient_public_key, time_t timestamp);`
|
||||
- `int nostr_nip46_decrypt_event_with_signer(cJSON* event, nostr_signer_t* signer, char** output_out);`
|
||||
- `int nostr_nip46_client_session_init_with_signer(nostr_nip46_client_session_t* session, nostr_signer_t* signer, const char* bunker_url);`
|
||||
|
||||
- NIP-60 (`nostr_core/nip060.h`)
|
||||
- `cJSON* nostr_nip60_create_wallet_event_with_signer(const nostr_nip60_wallet_data_t* wallet_data, nostr_signer_t* signer, time_t timestamp);`
|
||||
- `cJSON* nostr_nip60_create_token_event_with_signer(const nostr_nip60_token_data_t* token_data, nostr_signer_t* signer, time_t timestamp);`
|
||||
- `cJSON* nostr_nip60_create_token_deletion_with_signer(const char* token_event_id, nostr_signer_t* signer, time_t timestamp);`
|
||||
- `cJSON* nostr_nip60_create_rollover_token_with_signer(const nostr_nip60_token_data_t* remaining_proofs, const char** deleted_event_ids, int deleted_count, nostr_signer_t* signer, time_t timestamp);`
|
||||
- `cJSON* nostr_nip60_create_history_event_with_signer(const nostr_nip60_history_data_t* history_data, nostr_signer_t* signer, time_t timestamp);`
|
||||
- `cJSON* nostr_nip60_create_quote_event_with_signer(const char* quote_id, const char* mint_url, time_t expiration, nostr_signer_t* signer, time_t timestamp);`
|
||||
|
||||
- NIP-61 (`nostr_core/nip061.h`)
|
||||
- `cJSON* nostr_nip61_create_nutzap_info_event_with_signer(const nostr_nip61_nutzap_info_t* info, nostr_signer_t* signer, time_t timestamp);`
|
||||
- `cJSON* nostr_nip61_create_nutzap_event_with_signer(const nostr_nip61_nutzap_data_t* nutzap_data, nostr_signer_t* signer, time_t timestamp);`
|
||||
- `cJSON* nostr_nip61_create_redemption_event_with_signer(const char* nutzap_event_id, const char* nutzap_relay_hint, const char* sender_pubkey, const char* created_token_event_id, const char* created_token_relay_hint, uint64_t amount, nostr_signer_t* signer, time_t timestamp);`
|
||||
|
||||
- Blossom auth/upload/delete (`nostr_core/blossom_client.h`)
|
||||
- `char* blossom_create_auth_header_with_signer(nostr_signer_t* signer, const char* operation, const char* sha256_hex, int expiration_seconds, time_t timestamp);`
|
||||
- `int blossom_upload_with_signer(const char* server_url, const unsigned char* data, size_t data_len, const char* content_type, nostr_signer_t* signer, const char* sha256_hex, int timeout_seconds, blossom_blob_descriptor_t* descriptor_out);`
|
||||
- `int blossom_upload_file_with_signer(const char* server_url, const char* file_path, const char* content_type, nostr_signer_t* signer, int timeout_seconds, blossom_blob_descriptor_t* descriptor_out);`
|
||||
- `int blossom_delete_with_signer(const char* server_url, const char* sha256_hex, nostr_signer_t* signer, int timeout_seconds);`
|
||||
|
||||
- Relay-pool NIP-42 AUTH entry point (`nostr_core/nostr_core.h`)
|
||||
- `int nostr_relay_pool_set_auth_with_signer(nostr_relay_pool_t* pool, nostr_signer_t* signer, int enable);`
|
||||
|
||||
### Driver app: `examples/note_poster`
|
||||
|
||||
Signer modes:
|
||||
|
||||
```bash
|
||||
./examples/note_poster
|
||||
```
|
||||
|
||||
Default is local signer mode; this prompts for `nsec1...` or 64-char hex private key.
|
||||
|
||||
**WARNING:** test-key-only flow. Do not use a production key; input key material is held in process memory in plaintext.
|
||||
|
||||
```bash
|
||||
./examples/note_poster --signer unix:<name>
|
||||
./examples/note_poster --signer serial:/dev/ttyACM0
|
||||
./examples/note_poster --signer tcp:<host>:<port>
|
||||
./examples/note_poster --signer fds:<read_fd>:<write_fd>
|
||||
```
|
||||
|
||||
### Boundaries / what stays in n_signer
|
||||
|
||||
`nostr_core_lib` provides the **client side only** (transports + nsigner client + signer backends). The following stay in the `n_signer` project:
|
||||
|
||||
- process spawning/embedding and deployment packaging
|
||||
- signer program trust-boundary features (mnemonic handling, approvals, role policy)
|
||||
- hardware firmware and platform/device-specific runtime pieces
|
||||
|
||||
Dependency direction remains one-way: **`n_signer -> nostr_core_lib`**.
|
||||
|
||||
Operations requiring raw secret material outside signer verbs are not remotable as-is. Example: mint-protocol operations in Cashu mint pieces (`cashu_mint`) that require direct secret access beyond event signing/NIP-04/NIP-44.
|
||||
|
||||
For implementation plan context see `plans/nsigner_integration_plan.md`. This integration supersedes per-project hand-rolled signer clients (future migration milestone M7).
|
||||
|
||||
## 📁 Examples
|
||||
|
||||
The library includes comprehensive examples:
|
||||
@@ -521,14 +282,11 @@ The library includes comprehensive examples:
|
||||
- **`mnemonic_derivation`** - NIP-06 key derivation
|
||||
- **`utility_functions`** - General utility demonstrations
|
||||
- **`input_detection`** - Input type detection and processing
|
||||
- **`relay_pool`** - Interactive relay pool and subscription testing
|
||||
- **`send_nip17_dm`** - NIP-17 private direct message send flow
|
||||
- **`nip46_remote_signer`** - NIP-46 remote signer flow and bunker URL generation
|
||||
- **`version_test`** - Library version information
|
||||
|
||||
Build all examples:
|
||||
Run all examples:
|
||||
```bash
|
||||
./build.sh -e
|
||||
./build.sh examples
|
||||
ls -la examples/
|
||||
```
|
||||
|
||||
@@ -537,69 +295,72 @@ ls -la examples/
|
||||
The library includes extensive tests:
|
||||
|
||||
```bash
|
||||
# Build all test executables
|
||||
./build.sh -t
|
||||
# Run all tests
|
||||
./build.sh test
|
||||
|
||||
# Run the new NIP-46 test
|
||||
./tests/nip46_test
|
||||
|
||||
# Run selected tests
|
||||
./tests/nip44_test
|
||||
./tests/nip42_test
|
||||
./tests/nip17_test
|
||||
# Individual test categories
|
||||
cd tests && make test
|
||||
```
|
||||
|
||||
**Current test binaries live in [`tests/`](tests/) and are generated from `*_test.c` sources.**
|
||||
**Test Categories:**
|
||||
- **Core Functionality**: `simple_init_test`, `header_test`
|
||||
- **Cryptography**: `chacha20_test`, `nostr_crypto_test`
|
||||
- **NIP-04 Encryption**: `nip04_test`
|
||||
- **NIP-05 Identifiers**: `nip05_test`
|
||||
- **NIP-11 Relay Info**: `nip11_test`
|
||||
- **NIP-44 Encryption**: `nip44_test`, `nip44_debug_test`
|
||||
- **Key Derivation**: `nostr_test_bip32`
|
||||
- **Relay Communication**: `relay_pool_test`, `sync_test`
|
||||
- **HTTP/WebSocket**: `http_test`, `wss_test`
|
||||
- **Proof of Work**: `test_pow_loop`
|
||||
|
||||
## 🏗️ Integration
|
||||
|
||||
### Static Library Integration (Recommended)
|
||||
### Static Library Integration
|
||||
|
||||
1. **Install system dependencies first** (see Dependencies section above)
|
||||
|
||||
2. **Copy required files to your project:**
|
||||
1. **Copy required files to your project:**
|
||||
```bash
|
||||
cp libnostr_core_x64.a /path/to/your/project/
|
||||
cp libnostr_core.a /path/to/your/project/
|
||||
cp nostr_core/nostr_core.h /path/to/your/project/
|
||||
```
|
||||
|
||||
3. **Link in your project:**
|
||||
2. **Link in your project:**
|
||||
```bash
|
||||
gcc your_code.c -L. -lnostr_core -lssl -lcrypto -lcurl -lsecp256k1 -lm -o your_program
|
||||
gcc your_code.c -L. -lnostr_core -lm -o your_program
|
||||
```
|
||||
|
||||
### Source Integration
|
||||
|
||||
1. **Install system dependencies first** (see Dependencies section above)
|
||||
|
||||
2. **Copy source files:**
|
||||
1. **Copy source files:**
|
||||
```bash
|
||||
cp -r nostr_core/ /path/to/your/project/
|
||||
cp -r cjson/ /path/to/your/project/
|
||||
```
|
||||
|
||||
3. **Include in your build:**
|
||||
2. **Include in your build:**
|
||||
```bash
|
||||
gcc your_code.c nostr_core/*.c cjson/cJSON.c -lssl -lcrypto -lcurl -lsecp256k1 -lm -o your_program
|
||||
gcc your_code.c nostr_core/*.c cjson/cJSON.c -lm -o your_program
|
||||
```
|
||||
|
||||
### System Dependencies Library
|
||||
### Self-Contained Library
|
||||
|
||||
The `libnostr_core.a` library now uses **system dependencies** for all major crypto libraries:
|
||||
**x64 Library:** The `libnostr_core.a` file is completely self-contained with **no external dependencies**:
|
||||
|
||||
- ✅ **Uses system OpenSSL** (`-lssl -lcrypto`)
|
||||
- ✅ **Uses system curl** (`-lcurl`)
|
||||
- ✅ **Uses system secp256k1** (`-lsecp256k1`)
|
||||
- ✅ **Includes only internal code** (cJSON, TinyAES, ChaCha20)
|
||||
- ✅ **All OpenSSL code embedded**
|
||||
- ✅ **No libwally required**
|
||||
- ✅ **No system secp256k1 required**
|
||||
- ✅ **Only needs math library (`-lm`)**
|
||||
|
||||
**Complete linking example:**
|
||||
```bash
|
||||
gcc your_app.c ./libnostr_core_x64.a -lz -ldl -lpthread -lm -lssl -lcrypto -lcurl -lsecp256k1 -o your_app
|
||||
# x64 - This is all you need:
|
||||
gcc your_app.c ./libnostr_core.a -lm -o your_app
|
||||
```
|
||||
|
||||
**Check system dependencies:**
|
||||
**ARM64 Library:** The `libnostr_core_arm64.a` requires system OpenSSL:
|
||||
|
||||
```bash
|
||||
ldd your_app # Shows linked system libraries
|
||||
# ARM64 - Requires OpenSSL libraries:
|
||||
aarch64-linux-gnu-gcc your_app.c ./libnostr_core_arm64.a -lssl -lcrypto -lm -o your_app
|
||||
```
|
||||
|
||||
## 🔧 Configuration
|
||||
@@ -622,8 +383,8 @@ ldd your_app # Shows linked system libraries
|
||||
### Build Flags
|
||||
|
||||
```bash
|
||||
# Enable websocket and PoW debug emission (now callback-based)
|
||||
make LOGGING_FLAGS="-DENABLE_WEBSOCKET_LOGGING -DENABLE_DEBUG_LOGGING"
|
||||
# Enable all logging
|
||||
make LOGGING_FLAGS="-DENABLE_FILE_LOGGING -DENABLE_WEBSOCKET_LOGGING -DENABLE_DEBUG_LOGGING"
|
||||
|
||||
# Debug build
|
||||
make debug
|
||||
@@ -632,40 +393,6 @@ make debug
|
||||
make arm64
|
||||
```
|
||||
|
||||
### Logging Integration (Consumer-Controlled)
|
||||
|
||||
`nostr_core_lib` now supports a callback logging API so host applications can route library logs into their own logger and destination.
|
||||
|
||||
- API is exposed via [`nostr_core/nostr_log.h`](nostr_core/nostr_log.h)
|
||||
- Included automatically from [`nostr_core/nostr_core.h`](nostr_core/nostr_core.h)
|
||||
|
||||
```c
|
||||
#include "nostr_core/nostr_core.h"
|
||||
|
||||
static void my_log_cb(int level, const char* component, const char* message, void* user_data) {
|
||||
(void)user_data;
|
||||
fprintf(stderr, "[nostr][%s][%d] %s\n", component ? component : "unknown", level, message ? message : "");
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
if (nostr_init() != NOSTR_SUCCESS) return 1;
|
||||
|
||||
nostr_set_log_callback(my_log_cb, NULL);
|
||||
nostr_set_log_level(NOSTR_LOG_LEVEL_TRACE);
|
||||
|
||||
/* ... your code ... */
|
||||
|
||||
nostr_cleanup();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
#### Migration Notes
|
||||
|
||||
- Direct file logging to `debug.log` has been removed from websocket and NIP-13 internals.
|
||||
- To receive logs, register a callback with [`nostr_set_log_callback()`](nostr_core/nostr_log.h:24).
|
||||
- Use [`nostr_set_log_level()`](nostr_core/nostr_log.h:25) to reduce verbosity in production.
|
||||
|
||||
## 🌐 Supported Platforms
|
||||
|
||||
- **Linux** (x86_64, ARM64)
|
||||
@@ -673,59 +400,40 @@ int main(void) {
|
||||
- **Windows** (MinGW, MSYS2)
|
||||
- **Embedded Systems** (resource-constrained environments)
|
||||
|
||||
## 🔌 Embedded (ESP32) Support
|
||||
|
||||
`nostr_core_lib` now includes a platform abstraction layer and ESP32-native implementations for core networking and entropy APIs, while preserving desktop compatibility.
|
||||
|
||||
Implemented embedded capabilities include:
|
||||
- platform random source abstraction via `nostr_platform_random()`
|
||||
- ESP32 random provider using `esp_fill_random`
|
||||
- ESP32 HTTP client implementation via `esp_http_client`
|
||||
- ESP32 WebSocket/WSS transport via `esp_transport_ws` + TLS certificate bundle
|
||||
- NIP-04 encrypted DM flow validated on-device against public relays
|
||||
|
||||
Reference ESP-IDF example project (in this workspace):
|
||||
- `../esp32_send_kind4/` — Wi-Fi connect + `wss://` relay connect + send two kind-4 encrypted events + print relay responses
|
||||
|
||||
## 📄 Documentation
|
||||
|
||||
- **[POOL_API.md](POOL_API.md)** - Relay pool API notes
|
||||
- **[nostr_websocket/README.md](nostr_websocket/README.md)** - WebSocket module details
|
||||
- **[nostr_websocket/EXPORT_GUIDE.md](nostr_websocket/EXPORT_GUIDE.md)** - WebSocket export instructions
|
||||
- **API Reference** - Complete documentation in [`nostr_core/nostr_core.h`](nostr_core/nostr_core.h)
|
||||
- **[LIBRARY_USAGE.md](LIBRARY_USAGE.md)** - Detailed integration guide
|
||||
- **[EXPORT_GUIDE.md](EXPORT_GUIDE.md)** - Library export instructions
|
||||
- **[AUTOMATIC_VERSIONING.md](AUTOMATIC_VERSIONING.md)** - Version management
|
||||
- **API Reference** - Complete documentation in `nostr_core/nostr_core.h`
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch: `git checkout -b feature/amazing-feature`
|
||||
3. Make your changes and add tests
|
||||
4. Build tests and run key suites: `./build.sh -t && ./tests/nip46_test`
|
||||
4. Run the test suite: `./build.sh test`
|
||||
5. Commit your changes: `git commit -m 'Add amazing feature'`
|
||||
6. Push to the branch: `git push origin feature/amazing-feature`
|
||||
7. Open a Pull Request
|
||||
|
||||
## 📈 Version History
|
||||
|
||||
Current version: **0.6.0**
|
||||
Current version: **0.1.20**
|
||||
|
||||
The library uses automatic semantic versioning based on Git tags. Each build increments the patch version automatically.
|
||||
|
||||
**Recent Developments:**
|
||||
- **ESP32 Embedded Enablement**: Added PAL-based embedded support directly in `nostr_core_lib`
|
||||
- **ESP32 HTTP + WSS**: Added ESP-IDF-backed HTTP and secure websocket transport implementations
|
||||
- **NIP-04 On-Device Validation**: Verified encrypted kind-4 DM publish flow from ESP32 to live relays
|
||||
- **OpenSSL Migration**: Transitioned from mbedTLS to OpenSSL for improved compatibility
|
||||
- **NIP-05 Support**: DNS-based internet identifier verification
|
||||
- **NIP-11 Support**: Relay information document fetching and parsing
|
||||
- **NIP-19 Support**: Bech32-encoded entities (nsec/npub)
|
||||
- **Comprehensive Testing**: Extensive test suite and error handling
|
||||
- **Enhanced WebSocket**: OpenSSL-based TLS WebSocket communication
|
||||
- **Production Ready**: Comprehensive test suite and error handling
|
||||
|
||||
**Version Timeline:**
|
||||
- `v0.6.x` - Embedded-capable releases with ESP32 PAL, HTTP, and WSS support
|
||||
- `v0.4.x` - Development releases with relay pool and expanded NIP support
|
||||
- `v0.2.x` - Earlier OpenSSL-based development releases
|
||||
- `v0.1.x` - Initial development releases
|
||||
- Focus on core protocol implementation and OpenSSL-based crypto
|
||||
- Full NIP-01, NIP-04, NIP-05, NIP-06, NIP-11, NIP-13, NIP-17, NIP-19, NIP-21, NIP-42, NIP-44, NIP-46, NIP-59 support
|
||||
- Full NIP-01, NIP-04, NIP-05, NIP-06, NIP-11, NIP-13, NIP-44 support
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
@@ -733,35 +441,27 @@ The library uses automatic semantic versioning based on Git tags. Each build inc
|
||||
|
||||
**Build fails with secp256k1 errors:**
|
||||
```bash
|
||||
# Install secp256k1 with Schnorr support
|
||||
sudo apt install libsecp256k1-dev # Ubuntu/Debian
|
||||
# or
|
||||
sudo yum install libsecp256k1-devel # CentOS/RHEL
|
||||
# or
|
||||
brew install secp256k1 # macOS
|
||||
|
||||
# If still failing, build from source with Schnorr support:
|
||||
git clone https://github.com/bitcoin-core/secp256k1.git
|
||||
cd secp256k1
|
||||
./autogen.sh
|
||||
./configure --enable-module-schnorrsig --enable-module-ecdh
|
||||
make
|
||||
sudo make install
|
||||
cd ..
|
||||
./build.sh lib
|
||||
```
|
||||
|
||||
**Library size:**
|
||||
The library is small (~500KB) as it links against system libraries (secp256k1, OpenSSL, curl) rather than including them statically. This keeps the binary size manageable while maintaining full functionality.
|
||||
**Library too large:**
|
||||
The x64 library is intentionally large (~15MB) because it includes all secp256k1 cryptographic functions and OpenSSL for complete self-containment. The ARM64 library is smaller (~2.4MB) as it links against system OpenSSL.
|
||||
|
||||
**Linking errors:**
|
||||
Make sure to include the math library:
|
||||
```bash
|
||||
gcc your_code.c ./libnostr_core_x64.a -lz -ldl -lpthread -lm -lssl -lcrypto -lcurl -lsecp256k1
|
||||
gcc your_code.c ./libnostr_core.a -lm # Note the -lm flag
|
||||
```
|
||||
|
||||
### Getting Help
|
||||
|
||||
- Check the `examples/` directory for working code
|
||||
- Run `./build.sh -t` to verify your environment
|
||||
- Run `./build.sh test` to verify your environment
|
||||
- Review the comprehensive API documentation in `nostr_core/nostr_core.h`
|
||||
|
||||
## 📜 License
|
||||
@@ -781,4 +481,4 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
||||
|
||||
**Built with ❤️ for the decentralized web**
|
||||
|
||||
*OpenSSL-based • Minimal dependencies • Work in progress*
|
||||
*OpenSSL-based • Minimal dependencies • Production ready*
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
0.6.6
|
||||
Binary file not shown.
@@ -0,0 +1,40 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
# Find required dependencies
|
||||
find_dependency(Threads REQUIRED)
|
||||
|
||||
# Include targets
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/nostr_core-targets.cmake")
|
||||
|
||||
# Set variables for backward compatibility
|
||||
set(NOSTR_CORE_FOUND TRUE)
|
||||
set(NOSTR_CORE_VERSION "@PROJECT_VERSION@")
|
||||
|
||||
# Check which libraries are available
|
||||
set(NOSTR_CORE_STATIC_AVAILABLE FALSE)
|
||||
set(NOSTR_CORE_SHARED_AVAILABLE FALSE)
|
||||
|
||||
if(TARGET nostr_core::static)
|
||||
set(NOSTR_CORE_STATIC_AVAILABLE TRUE)
|
||||
endif()
|
||||
|
||||
if(TARGET nostr_core::shared)
|
||||
set(NOSTR_CORE_SHARED_AVAILABLE TRUE)
|
||||
endif()
|
||||
|
||||
# Provide convenient variables
|
||||
if(NOSTR_CORE_STATIC_AVAILABLE)
|
||||
set(NOSTR_CORE_LIBRARIES nostr_core::static)
|
||||
elseif(NOSTR_CORE_SHARED_AVAILABLE)
|
||||
set(NOSTR_CORE_LIBRARIES nostr_core::shared)
|
||||
endif()
|
||||
|
||||
set(NOSTR_CORE_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@/nostr")
|
||||
|
||||
# Feature information
|
||||
set(NOSTR_CORE_ENABLE_WEBSOCKETS @NOSTR_ENABLE_WEBSOCKETS@)
|
||||
set(NOSTR_CORE_USE_MBEDTLS @NOSTR_USE_MBEDTLS@)
|
||||
|
||||
check_required_components(nostr_core)
|
||||
Executable
+189
@@ -0,0 +1,189 @@
|
||||
#!/bin/sh
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
# shellcheck disable=SC2006
|
||||
|
||||
prefix='/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-install'
|
||||
# Used in 'libdir'
|
||||
# shellcheck disable=SC2034
|
||||
exec_prefix="${prefix}"
|
||||
# shellcheck disable=SC2034
|
||||
includedir="${prefix}/include"
|
||||
|
||||
usage()
|
||||
{
|
||||
cat <<EOF
|
||||
Usage: curl-config [OPTION]
|
||||
|
||||
Available values for OPTION include:
|
||||
|
||||
--built-shared says 'yes' if libcurl was built shared
|
||||
--ca CA bundle install path
|
||||
--cc compiler
|
||||
--cflags preprocessor and compiler flags
|
||||
--checkfor [version] check for (lib)curl of the specified version
|
||||
--configure the arguments given to configure when building curl
|
||||
--features newline separated list of enabled features
|
||||
--help display this help and exit
|
||||
--libs library linking information
|
||||
--prefix curl install prefix
|
||||
--protocols newline separated list of enabled protocols
|
||||
--ssl-backends output the SSL backends libcurl was built to support
|
||||
--static-libs static libcurl library linking information
|
||||
--version output version information
|
||||
--vernum output version as a hexadecimal number
|
||||
EOF
|
||||
|
||||
exit "$1"
|
||||
}
|
||||
|
||||
if test "$#" -eq 0; then
|
||||
usage 1
|
||||
fi
|
||||
|
||||
while test "$#" -gt 0; do
|
||||
case "$1" in
|
||||
--built-shared)
|
||||
echo 'no'
|
||||
;;
|
||||
|
||||
--ca)
|
||||
echo '/etc/ssl/certs/ca-certificates.crt'
|
||||
;;
|
||||
|
||||
--cc)
|
||||
echo 'gcc'
|
||||
;;
|
||||
|
||||
--prefix)
|
||||
echo "$prefix"
|
||||
;;
|
||||
|
||||
--feature|--features)
|
||||
for feature in alt-svc AsynchDNS HSTS IPv6 Largefile libz NTLM SSL threadsafe TLS-SRP UnixSockets ''; do
|
||||
test -n "$feature" && echo "$feature"
|
||||
done
|
||||
;;
|
||||
|
||||
--protocols)
|
||||
# shellcheck disable=SC2043
|
||||
for protocol in FILE FTP FTPS HTTP HTTPS IPFS IPNS MQTT WS WSS; do
|
||||
echo "$protocol"
|
||||
done
|
||||
;;
|
||||
|
||||
--version)
|
||||
echo 'libcurl 8.15.0'
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--checkfor)
|
||||
checkfor="$2"
|
||||
cmajor=`echo "$checkfor" | cut -d. -f1`
|
||||
cminor=`echo "$checkfor" | cut -d. -f2`
|
||||
# when extracting the patch part we strip off everything after a
|
||||
# dash as that's used for things like version 1.2.3-pre1
|
||||
cpatch=`echo "$checkfor" | cut -d. -f3 | cut -d- -f1`
|
||||
|
||||
vmajor=`echo '8.15.0' | cut -d. -f1`
|
||||
vminor=`echo '8.15.0' | cut -d. -f2`
|
||||
# when extracting the patch part we strip off everything after a
|
||||
# dash as that's used for things like version 1.2.3-pre1
|
||||
vpatch=`echo '8.15.0' | cut -d. -f3 | cut -d- -f1`
|
||||
|
||||
if test "$vmajor" -gt "$cmajor"; then
|
||||
exit 0
|
||||
fi
|
||||
if test "$vmajor" -eq "$cmajor"; then
|
||||
if test "$vminor" -gt "$cminor"; then
|
||||
exit 0
|
||||
fi
|
||||
if test "$vminor" -eq "$cminor"; then
|
||||
if test "$cpatch" -le "$vpatch"; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "requested version $checkfor is newer than existing 8.15.0"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
--vernum)
|
||||
echo '080f00'
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--help)
|
||||
usage 0
|
||||
;;
|
||||
|
||||
--cflags)
|
||||
if test "X${prefix}/include" = 'X/usr/include'; then
|
||||
echo '-DCURL_STATICLIB'
|
||||
else
|
||||
echo "-DCURL_STATICLIB -I${prefix}/include"
|
||||
fi
|
||||
;;
|
||||
|
||||
--libs)
|
||||
if test "X${exec_prefix}/lib" != 'X/usr/lib' -a "X${exec_prefix}/lib" != 'X/usr/lib64'; then
|
||||
curllibdir="-L${exec_prefix}/lib "
|
||||
else
|
||||
curllibdir=''
|
||||
fi
|
||||
if test 'Xno' = 'Xno'; then
|
||||
echo "${curllibdir}-lcurl -lssl -lcrypto -lssl -lcrypto -lz"
|
||||
else
|
||||
echo "${curllibdir}-lcurl"
|
||||
fi
|
||||
;;
|
||||
|
||||
--ssl-backends)
|
||||
echo 'OpenSSL v3+'
|
||||
;;
|
||||
|
||||
--static-libs)
|
||||
if test 'Xyes' != 'Xno'; then
|
||||
echo "${exec_prefix}/lib/libcurl.a -L/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/openssl-3.4.2/../openssl-install/lib64 -lssl -lcrypto -lssl -lcrypto -lz"
|
||||
else
|
||||
echo 'curl was built with static libraries disabled' >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
--configure)
|
||||
echo " '--disable-shared' '--enable-static' '--with-openssl=/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/openssl-install' '--without-libpsl' '--without-brotli' '--disable-ldap' '--disable-ldaps' '--disable-rtsp' '--disable-proxy' '--disable-dict' '--disable-telnet' '--disable-tftp' '--disable-pop3' '--disable-imap' '--disable-smb' '--disable-smtp' '--disable-gopher' '--disable-manual' '--prefix=/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-install'"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "unknown option: $1"
|
||||
usage 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
exit 0
|
||||
Executable
+323
@@ -0,0 +1,323 @@
|
||||
#!/bin/sh
|
||||
|
||||
# wcurl - a simple wrapper around curl to easily download files.
|
||||
#
|
||||
# Requires curl >= 7.46.0 (2015)
|
||||
#
|
||||
# Copyright (C) Samuel Henrique <samueloph@debian.org>, Sergio Durigan
|
||||
# Junior <sergiodj@debian.org> and many contributors, see the AUTHORS
|
||||
# file.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any purpose
|
||||
# with or without fee is hereby granted, provided that the above copyright
|
||||
# notice and this permission notice appear in all copies.
|
||||
#
|
||||
# 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 OF THIRD PARTY RIGHTS. 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.
|
||||
#
|
||||
# Except as contained in this notice, the name of a copyright holder shall not be
|
||||
# used in advertising or otherwise to promote the sale, use or other dealings in
|
||||
# this Software without prior written authorization of the copyright holder.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
|
||||
# Stop on errors and on usage of unset variables.
|
||||
set -eu
|
||||
|
||||
VERSION="2025.05.26"
|
||||
|
||||
PROGRAM_NAME="$(basename "$0")"
|
||||
readonly PROGRAM_NAME
|
||||
|
||||
# Display the version.
|
||||
print_version()
|
||||
{
|
||||
cat << _EOF_
|
||||
${VERSION}
|
||||
_EOF_
|
||||
}
|
||||
|
||||
# Display the program usage.
|
||||
usage()
|
||||
{
|
||||
cat << _EOF_
|
||||
${PROGRAM_NAME} -- a simple wrapper around curl to easily download files.
|
||||
|
||||
Usage: ${PROGRAM_NAME} <URL>...
|
||||
${PROGRAM_NAME} [--curl-options <CURL_OPTIONS>]... [--no-decode-filename] [-o|-O|--output <PATH>] [--dry-run] [--] <URL>...
|
||||
${PROGRAM_NAME} [--curl-options=<CURL_OPTIONS>]... [--no-decode-filename] [--output=<PATH>] [--dry-run] [--] <URL>...
|
||||
${PROGRAM_NAME} -h|--help
|
||||
${PROGRAM_NAME} -V|--version
|
||||
|
||||
Options:
|
||||
|
||||
--curl-options <CURL_OPTIONS>: Specify extra options to be passed when invoking curl. May be
|
||||
specified more than once.
|
||||
|
||||
-o, -O, --output <PATH>: Use the provided output path instead of getting it from the URL. If
|
||||
multiple URLs are provided, resulting files share the same name with a
|
||||
number appended to the end (curl >= 7.83.0). If this option is provided
|
||||
multiple times, only the last value is considered.
|
||||
|
||||
--no-decode-filename: Don't percent-decode the output filename, even if the percent-encoding in
|
||||
the URL was done by wcurl, e.g.: The URL contained whitespaces.
|
||||
|
||||
--dry-run: Don't actually execute curl, just print what would be invoked.
|
||||
|
||||
-V, --version: Print version information.
|
||||
|
||||
-h, --help: Print this usage message.
|
||||
|
||||
<CURL_OPTIONS>: Any option supported by curl can be set here. This is not used by wcurl; it is
|
||||
instead forwarded to the curl invocation.
|
||||
|
||||
<URL>: URL to be downloaded. Anything that is not a parameter is considered
|
||||
an URL. Whitespaces are percent-encoded and the URL is passed to curl, which
|
||||
then performs the parsing. May be specified more than once.
|
||||
_EOF_
|
||||
}
|
||||
|
||||
# Display an error message and bail out.
|
||||
error()
|
||||
{
|
||||
printf "%s\n" "$*" > /dev/stderr
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Extra curl options provided by the user.
|
||||
# This is set per-URL for every URL provided.
|
||||
# Some options are global, but we are erroring on the side of needlesly setting
|
||||
# them multiple times instead of causing issues with parameters that needs to
|
||||
# be set per-URL.
|
||||
CURL_OPTIONS=""
|
||||
|
||||
# The URLs to be downloaded.
|
||||
URLS=""
|
||||
|
||||
# Variable used to be set to the percent-decoded filename parsed from the URL, unless
|
||||
# --output or --no-decode-filename are used.
|
||||
OUTPUT_PATH=""
|
||||
HAS_USER_SET_OUTPUT="false"
|
||||
|
||||
# The parameters that are passed per-URL to curl.
|
||||
readonly PER_URL_PARAMETERS="\
|
||||
--fail \
|
||||
--globoff \
|
||||
--location \
|
||||
--proto-default https \
|
||||
--remote-time \
|
||||
--retry 5 "
|
||||
|
||||
# Whether to invoke curl or not.
|
||||
DRY_RUN="false"
|
||||
|
||||
# Sanitize parameters.
|
||||
sanitize()
|
||||
{
|
||||
if [ -z "${URLS}" ]; then
|
||||
error "You must provide at least one URL to download."
|
||||
fi
|
||||
|
||||
readonly CURL_OPTIONS URLS DRY_RUN HAS_USER_SET_OUTPUT
|
||||
}
|
||||
|
||||
# Indicate via exit code whether the string given in the first parameter
|
||||
# consists solely of characters from the string given in the second parameter.
|
||||
# In other words, it returns 0 if the first parameter only contains characters
|
||||
# from the second parameter, e.g.: Are $1 characters a subset of $2 characters?
|
||||
is_subset_of()
|
||||
{
|
||||
case "${1}" in
|
||||
*[!${2}]*|'') return 1;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Print the given string percent-decoded.
|
||||
percent_decode()
|
||||
{
|
||||
# Encodings of control characters (00-1F) are passed through without decoding.
|
||||
# Iterate on the input character-by-character, decoding it.
|
||||
printf "%s\n" "${1}" | fold -w1 | while IFS= read -r decode_out; do
|
||||
# If character is a "%", read the next character as decode_hex1.
|
||||
if [ "${decode_out}" = % ] && IFS= read -r decode_hex1; then
|
||||
decode_out="${decode_out}${decode_hex1}"
|
||||
# If there's one more character, read it as decode_hex2.
|
||||
if IFS= read -r decode_hex2; then
|
||||
decode_out="${decode_out}${decode_hex2}"
|
||||
# Skip decoding if this is a control character (00-1F).
|
||||
# Skip decoding if DECODE_FILENAME is not "true".
|
||||
if is_subset_of "${decode_hex1}" "23456789abcdefABCDEF" && \
|
||||
is_subset_of "${decode_hex2}" "0123456789abcdefABCDEF" && \
|
||||
[ "${DECODE_FILENAME}" = "true" ]; then
|
||||
# Use printf to decode it into octal and then decode it to the final format.
|
||||
decode_out="$(printf "%b" "\\$(printf %o "0x${decode_hex1}${decode_hex2}")")"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
printf %s "${decode_out}"
|
||||
done
|
||||
}
|
||||
|
||||
# Print the percent-decoded filename portion of the given URL.
|
||||
get_url_filename()
|
||||
{
|
||||
# Remove protocol and query string if present.
|
||||
hostname_and_path="$(printf %s "${1}" | sed -e 's,^[^/]*//,,' -e 's,?.*$,,')"
|
||||
# If what remains contains a slash, there's a path; return it percent-decoded.
|
||||
case "${hostname_and_path}" in
|
||||
# sed to remove everything preceding the last '/', e.g.: "example/something" becomes "something"
|
||||
*/*) percent_decode "$(printf %s "${hostname_and_path}" | sed -e 's,^.*/,,')";;
|
||||
esac
|
||||
# No slash means there was just a hostname and no path; return empty string.
|
||||
}
|
||||
|
||||
# Execute curl with the list of URLs provided by the user.
|
||||
exec_curl()
|
||||
{
|
||||
CMD="curl "
|
||||
|
||||
# Store version to check if it supports --no-clobber and --parallel.
|
||||
curl_version=$($CMD --version | cut -f2 -d' ' | head -n1)
|
||||
curl_version_major=$(echo "$curl_version" | cut -f1 -d.)
|
||||
curl_version_minor=$(echo "$curl_version" | cut -f2 -d.)
|
||||
|
||||
CURL_HAS_NO_CLOBBER=""
|
||||
CURL_HAS_PARALLEL=""
|
||||
# --no-clobber is only supported since 7.83.0.
|
||||
# --parallel is only supported since 7.66.0.
|
||||
if [ "${curl_version_major}" -ge 8 ]; then
|
||||
CURL_HAS_NO_CLOBBER="--no-clobber"
|
||||
CURL_HAS_PARALLEL="--parallel"
|
||||
elif [ "${curl_version_major}" -eq 7 ];then
|
||||
if [ "${curl_version_minor}" -ge 83 ]; then
|
||||
CURL_HAS_NO_CLOBBER="--no-clobber"
|
||||
fi
|
||||
if [ "${curl_version_minor}" -ge 66 ]; then
|
||||
CURL_HAS_PARALLEL="--parallel"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Detecting whether we need --parallel. It's easier to rely on
|
||||
# the shell's argument parsing.
|
||||
# shellcheck disable=SC2086
|
||||
set -- $URLS
|
||||
|
||||
if [ "$#" -gt 1 ]; then
|
||||
CURL_PARALLEL="$CURL_HAS_PARALLEL"
|
||||
else
|
||||
CURL_PARALLEL=""
|
||||
fi
|
||||
|
||||
# Start assembling the command.
|
||||
#
|
||||
# We use 'set --' here (again) because (a) we don't have arrays on
|
||||
# POSIX shell, and (b) we need better control over the way we
|
||||
# split arguments.
|
||||
#
|
||||
# shellcheck disable=SC2086
|
||||
set -- ${CMD} ${CURL_PARALLEL}
|
||||
|
||||
NEXT_PARAMETER=""
|
||||
for url in ${URLS}; do
|
||||
# If the user did not provide an output path, define one.
|
||||
if [ "${HAS_USER_SET_OUTPUT}" = "false" ]; then
|
||||
OUTPUT_PATH="$(get_url_filename "${url}")"
|
||||
# If we could not get a path from the URL, use the default: index.html.
|
||||
[ -z "${OUTPUT_PATH}" ] && OUTPUT_PATH=index.html
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
set -- "$@" ${NEXT_PARAMETER} ${PER_URL_PARAMETERS} ${CURL_HAS_NO_CLOBBER} ${CURL_OPTIONS} --output "${OUTPUT_PATH}" "${url}"
|
||||
NEXT_PARAMETER="--next"
|
||||
done
|
||||
|
||||
if [ "${DRY_RUN}" = "false" ]; then
|
||||
exec "$@"
|
||||
else
|
||||
printf "%s\n" "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
# Default to decoding the output filename
|
||||
DECODE_FILENAME="true"
|
||||
|
||||
# Use "${1-}" in order to avoid errors because of 'set -u'.
|
||||
while [ -n "${1-}" ]; do
|
||||
case "${1}" in
|
||||
--curl-options=*)
|
||||
opt=$(printf "%s\n" "${1}" | sed 's/^--curl-options=//')
|
||||
CURL_OPTIONS="${CURL_OPTIONS} ${opt}"
|
||||
;;
|
||||
|
||||
--curl-options)
|
||||
shift
|
||||
CURL_OPTIONS="${CURL_OPTIONS} ${1}"
|
||||
;;
|
||||
|
||||
--dry-run)
|
||||
DRY_RUN="true"
|
||||
;;
|
||||
|
||||
--output=*)
|
||||
opt=$(printf "%s\n" "${1}" | sed 's/^--output=//')
|
||||
HAS_USER_SET_OUTPUT="true"
|
||||
OUTPUT_PATH="${opt}"
|
||||
;;
|
||||
|
||||
-o|-O|--output)
|
||||
shift
|
||||
HAS_USER_SET_OUTPUT="true"
|
||||
OUTPUT_PATH="${1}"
|
||||
;;
|
||||
|
||||
-o*|-O*)
|
||||
opt=$(printf "%s\n" "${1}" | sed 's/^-[oO]//')
|
||||
HAS_USER_SET_OUTPUT="true"
|
||||
OUTPUT_PATH="${opt}"
|
||||
;;
|
||||
|
||||
--no-decode-filename)
|
||||
DECODE_FILENAME="false"
|
||||
;;
|
||||
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
-V|--version)
|
||||
print_version
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--)
|
||||
# This is the start of the list of URLs.
|
||||
shift
|
||||
for url in "$@"; do
|
||||
# Encode whitespaces into %20, since wget supports those URLs.
|
||||
newurl=$(printf "%s\n" "${url}" | sed 's/ /%20/g')
|
||||
URLS="${URLS} ${newurl}"
|
||||
done
|
||||
break
|
||||
;;
|
||||
|
||||
-*)
|
||||
error "Unknown option: '$1'."
|
||||
;;
|
||||
|
||||
*)
|
||||
# This must be a URL.
|
||||
# Encode whitespaces into %20, since wget supports those URLs.
|
||||
newurl=$(printf "%s\n" "${1}" | sed 's/ /%20/g')
|
||||
URLS="${URLS} ${newurl}"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
sanitize
|
||||
exec_curl
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
||||
#ifndef CURLINC_CURLVER_H
|
||||
#define CURLINC_CURLVER_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* This header file contains nothing but libcurl version info, generated by
|
||||
a script at release-time. This was made its own header file in 7.11.2 */
|
||||
|
||||
/* This is the global package copyright */
|
||||
#define LIBCURL_COPYRIGHT "Daniel Stenberg, <daniel@haxx.se>."
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "8.15.0"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 8
|
||||
#define LIBCURL_VERSION_MINOR 15
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
|
||||
always follow this syntax:
|
||||
|
||||
0xXXYYZZ
|
||||
|
||||
Where XX, YY and ZZ are the main version, release and patch numbers in
|
||||
hexadecimal (using 8 bits each). All three numbers are always represented
|
||||
using two digits. 1.2 would appear as "0x010200" while version 9.11.7
|
||||
appears as "0x090b07".
|
||||
|
||||
This 6-digit (24 bits) hexadecimal number does not show pre-release number,
|
||||
and it is always a greater number in a more recent release. It makes
|
||||
comparisons with greater than and less than work.
|
||||
|
||||
Note: This define is the full hex number and _does not_ use the
|
||||
CURL_VERSION_BITS() macro since curl's own configure script greps for it
|
||||
and needs it to contain the full number.
|
||||
*/
|
||||
#define LIBCURL_VERSION_NUM 0x080f00
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
* timestamp is not stored in git, as the timestamp is properly set in the
|
||||
* tarballs by the maketgz script.
|
||||
*
|
||||
* The format of the date follows this template:
|
||||
*
|
||||
* "2007-11-23"
|
||||
*/
|
||||
#define LIBCURL_TIMESTAMP "2025-07-16"
|
||||
|
||||
#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
|
||||
#define CURL_AT_LEAST_VERSION(x,y,z) \
|
||||
(LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
|
||||
|
||||
#endif /* CURLINC_CURLVER_H */
|
||||
@@ -0,0 +1,125 @@
|
||||
#ifndef CURLINC_EASY_H
|
||||
#define CURLINC_EASY_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Flag bits in the curl_blob struct: */
|
||||
#define CURL_BLOB_COPY 1 /* tell libcurl to copy the data */
|
||||
#define CURL_BLOB_NOCOPY 0 /* tell libcurl to NOT copy the data */
|
||||
|
||||
struct curl_blob {
|
||||
void *data;
|
||||
size_t len;
|
||||
unsigned int flags; /* bit 0 is defined, the rest are reserved and should be
|
||||
left zeroes */
|
||||
};
|
||||
|
||||
CURL_EXTERN CURL *curl_easy_init(void);
|
||||
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
|
||||
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
|
||||
CURL_EXTERN void curl_easy_cleanup(CURL *curl);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_getinfo()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Request internal information from the curl session with this function.
|
||||
* The third argument MUST be pointing to the specific type of the used option
|
||||
* which is documented in each manpage of the option. The data pointed to
|
||||
* will be filled in accordingly and can be relied upon only if the function
|
||||
* returns CURLE_OK. This function is intended to get used *AFTER* a performed
|
||||
* transfer, all results from this function are undefined until the transfer
|
||||
* is completed.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
|
||||
|
||||
|
||||
/*
|
||||
* NAME curl_easy_duphandle()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Creates a new curl session handle with the same options set for the handle
|
||||
* passed in. Duplicating a handle could only be a matter of cloning data and
|
||||
* options, internal state info and things like persistent connections cannot
|
||||
* be transferred. It is useful in multithreaded applications when you can run
|
||||
* curl_easy_duphandle() for each new thread to avoid a series of identical
|
||||
* curl_easy_setopt() invokes in every thread.
|
||||
*/
|
||||
CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_reset()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Re-initializes a curl handle to the default values. This puts back the
|
||||
* handle to the same state as it was in when it was just created.
|
||||
*
|
||||
* It does keep: live connections, the Session ID cache, the DNS cache and the
|
||||
* cookies.
|
||||
*/
|
||||
CURL_EXTERN void curl_easy_reset(CURL *curl);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_recv()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Receives data from the connected socket. Use after successful
|
||||
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
|
||||
size_t *n);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_send()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Sends data over the connected socket. Use after successful
|
||||
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
|
||||
size_t buflen, size_t *n);
|
||||
|
||||
|
||||
/*
|
||||
* NAME curl_easy_upkeep()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Performs connection upkeep for the given session handle.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,74 @@
|
||||
#ifndef CURLINC_HEADER_H
|
||||
#define CURLINC_HEADER_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct curl_header {
|
||||
char *name; /* this might not use the same case */
|
||||
char *value;
|
||||
size_t amount; /* number of headers using this name */
|
||||
size_t index; /* ... of this instance, 0 or higher */
|
||||
unsigned int origin; /* see bits below */
|
||||
void *anchor; /* handle privately used by libcurl */
|
||||
};
|
||||
|
||||
/* 'origin' bits */
|
||||
#define CURLH_HEADER (1<<0) /* plain server header */
|
||||
#define CURLH_TRAILER (1<<1) /* trailers */
|
||||
#define CURLH_CONNECT (1<<2) /* CONNECT headers */
|
||||
#define CURLH_1XX (1<<3) /* 1xx headers */
|
||||
#define CURLH_PSEUDO (1<<4) /* pseudo headers */
|
||||
|
||||
typedef enum {
|
||||
CURLHE_OK,
|
||||
CURLHE_BADINDEX, /* header exists but not with this index */
|
||||
CURLHE_MISSING, /* no such header exists */
|
||||
CURLHE_NOHEADERS, /* no headers at all exist (yet) */
|
||||
CURLHE_NOREQUEST, /* no request with this number was used */
|
||||
CURLHE_OUT_OF_MEMORY, /* out of memory while processing */
|
||||
CURLHE_BAD_ARGUMENT, /* a function argument was not okay */
|
||||
CURLHE_NOT_BUILT_IN /* if API was disabled in the build */
|
||||
} CURLHcode;
|
||||
|
||||
CURL_EXTERN CURLHcode curl_easy_header(CURL *easy,
|
||||
const char *name,
|
||||
size_t index,
|
||||
unsigned int origin,
|
||||
int request,
|
||||
struct curl_header **hout);
|
||||
|
||||
CURL_EXTERN struct curl_header *curl_easy_nextheader(CURL *easy,
|
||||
unsigned int origin,
|
||||
int request,
|
||||
struct curl_header *prev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* CURLINC_HEADER_H */
|
||||
@@ -0,0 +1,85 @@
|
||||
#ifndef CURLINC_MPRINTF_H
|
||||
#define CURLINC_MPRINTF_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h> /* needed for FILE */
|
||||
#include "curl.h" /* for CURL_EXTERN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef CURL_TEMP_PRINTF
|
||||
#if (defined(__GNUC__) || defined(__clang__) || \
|
||||
defined(__IAR_SYSTEMS_ICC__)) && \
|
||||
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
|
||||
!defined(CURL_NO_FMT_CHECKS)
|
||||
#if defined(__MINGW32__) && !defined(__clang__)
|
||||
#if defined(__MINGW_PRINTF_FORMAT) /* mingw-w64 3.0.0+. Needs stdio.h. */
|
||||
#define CURL_TEMP_PRINTF(fmt, arg) \
|
||||
__attribute__((format(__MINGW_PRINTF_FORMAT, fmt, arg)))
|
||||
#else
|
||||
#define CURL_TEMP_PRINTF(fmt, arg)
|
||||
#endif
|
||||
#else
|
||||
#define CURL_TEMP_PRINTF(fmt, arg) \
|
||||
__attribute__((format(printf, fmt, arg)))
|
||||
#endif
|
||||
#else
|
||||
#define CURL_TEMP_PRINTF(fmt, arg)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CURL_EXTERN int curl_mprintf(const char *format, ...)
|
||||
CURL_TEMP_PRINTF(1, 2);
|
||||
CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...)
|
||||
CURL_TEMP_PRINTF(2, 3);
|
||||
CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...)
|
||||
CURL_TEMP_PRINTF(2, 3);
|
||||
CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
|
||||
const char *format, ...)
|
||||
CURL_TEMP_PRINTF(3, 4);
|
||||
CURL_EXTERN int curl_mvprintf(const char *format, va_list args)
|
||||
CURL_TEMP_PRINTF(1, 0);
|
||||
CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args)
|
||||
CURL_TEMP_PRINTF(2, 0);
|
||||
CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args)
|
||||
CURL_TEMP_PRINTF(2, 0);
|
||||
CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
|
||||
const char *format, va_list args)
|
||||
CURL_TEMP_PRINTF(3, 0);
|
||||
CURL_EXTERN char *curl_maprintf(const char *format, ...)
|
||||
CURL_TEMP_PRINTF(1, 2);
|
||||
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args)
|
||||
CURL_TEMP_PRINTF(1, 0);
|
||||
|
||||
#undef CURL_TEMP_PRINTF
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* CURLINC_MPRINTF_H */
|
||||
@@ -0,0 +1,481 @@
|
||||
#ifndef CURLINC_MULTI_H
|
||||
#define CURLINC_MULTI_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
/*
|
||||
This is an "external" header file. Do not give away any internals here!
|
||||
|
||||
GOALS
|
||||
|
||||
o Enable a "pull" interface. The application that uses libcurl decides where
|
||||
and when to ask libcurl to get/send data.
|
||||
|
||||
o Enable multiple simultaneous transfers in the same thread without making it
|
||||
complicated for the application.
|
||||
|
||||
o Enable the application to select() on its own file descriptors and curl's
|
||||
file descriptors simultaneous easily.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* This header file should not really need to include "curl.h" since curl.h
|
||||
* itself includes this file and we expect user applications to do #include
|
||||
* <curl/curl.h> without the need for especially including multi.h.
|
||||
*
|
||||
* For some reason we added this include here at one point, and rather than to
|
||||
* break existing (wrongly written) libcurl applications, we leave it as-is
|
||||
* but with this warning attached.
|
||||
*/
|
||||
#include "curl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void CURLM;
|
||||
|
||||
typedef enum {
|
||||
CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
|
||||
curl_multi_socket*() soon */
|
||||
CURLM_OK,
|
||||
CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
|
||||
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
|
||||
CURLM_OUT_OF_MEMORY, /* if you ever get this, you are in deep sh*t */
|
||||
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
|
||||
CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
|
||||
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
|
||||
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
|
||||
attempted to get added - again */
|
||||
CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
|
||||
callback */
|
||||
CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */
|
||||
CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */
|
||||
CURLM_ABORTED_BY_CALLBACK,
|
||||
CURLM_UNRECOVERABLE_POLL,
|
||||
CURLM_LAST
|
||||
} CURLMcode;
|
||||
|
||||
/* just to make code nicer when using curl_multi_socket() you can now check
|
||||
for CURLM_CALL_MULTI_SOCKET too in the same style it works for
|
||||
curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
|
||||
#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
|
||||
|
||||
/* bitmask bits for CURLMOPT_PIPELINING */
|
||||
#define CURLPIPE_NOTHING 0L
|
||||
#define CURLPIPE_HTTP1 1L
|
||||
#define CURLPIPE_MULTIPLEX 2L
|
||||
|
||||
typedef enum {
|
||||
CURLMSG_NONE, /* first, not used */
|
||||
CURLMSG_DONE, /* This easy handle has completed. 'result' contains
|
||||
the CURLcode of the transfer */
|
||||
CURLMSG_LAST /* last, not used */
|
||||
} CURLMSG;
|
||||
|
||||
struct CURLMsg {
|
||||
CURLMSG msg; /* what this message means */
|
||||
CURL *easy_handle; /* the handle it concerns */
|
||||
union {
|
||||
void *whatever; /* message-specific data */
|
||||
CURLcode result; /* return code for transfer */
|
||||
} data;
|
||||
};
|
||||
typedef struct CURLMsg CURLMsg;
|
||||
|
||||
/* Based on poll(2) structure and values.
|
||||
* We do not use pollfd and POLL* constants explicitly
|
||||
* to cover platforms without poll(). */
|
||||
#define CURL_WAIT_POLLIN 0x0001
|
||||
#define CURL_WAIT_POLLPRI 0x0002
|
||||
#define CURL_WAIT_POLLOUT 0x0004
|
||||
|
||||
struct curl_waitfd {
|
||||
curl_socket_t fd;
|
||||
short events;
|
||||
short revents;
|
||||
};
|
||||
|
||||
/*
|
||||
* Name: curl_multi_init()
|
||||
*
|
||||
* Desc: initialize multi-style curl usage
|
||||
*
|
||||
* Returns: a new CURLM handle to use in all 'curl_multi' functions.
|
||||
*/
|
||||
CURL_EXTERN CURLM *curl_multi_init(void);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_add_handle()
|
||||
*
|
||||
* Desc: add a standard curl handle to the multi stack
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
CURL *curl_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_remove_handle()
|
||||
*
|
||||
* Desc: removes a curl handle from the multi stack again
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
CURL *curl_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_fdset()
|
||||
*
|
||||
* Desc: Ask curl for its fd_set sets. The app can use these to select() or
|
||||
* poll() on. We want curl_multi_perform() called as soon as one of
|
||||
* them are ready.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *exc_fd_set,
|
||||
int *max_fd);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_wait()
|
||||
*
|
||||
* Desc: Poll on all fds within a CURLM set as well as any
|
||||
* additional fds passed to the function.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
|
||||
struct curl_waitfd extra_fds[],
|
||||
unsigned int extra_nfds,
|
||||
int timeout_ms,
|
||||
int *ret);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_poll()
|
||||
*
|
||||
* Desc: Poll on all fds within a CURLM set as well as any
|
||||
* additional fds passed to the function.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle,
|
||||
struct curl_waitfd extra_fds[],
|
||||
unsigned int extra_nfds,
|
||||
int timeout_ms,
|
||||
int *ret);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_wakeup()
|
||||
*
|
||||
* Desc: wakes up a sleeping curl_multi_poll call.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_perform()
|
||||
*
|
||||
* Desc: When the app thinks there is data available for curl it calls this
|
||||
* function to read/write whatever there is right now. This returns
|
||||
* as soon as the reads and writes are done. This function does not
|
||||
* require that there actually is data available for reading or that
|
||||
* data can be written, it can be called just in case. It returns
|
||||
* the number of handles that still transfer data in the second
|
||||
* argument's integer-pointer.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
|
||||
* returns errors etc regarding the whole multi stack. There might
|
||||
* still have occurred problems on individual transfers even when
|
||||
* this returns OK.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
|
||||
int *running_handles);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_cleanup()
|
||||
*
|
||||
* Desc: Cleans up and removes a whole multi stack. It does not free or
|
||||
* touch any individual easy handles in any way. We need to define
|
||||
* in what state those handles will be if this function is called
|
||||
* in the middle of a transfer.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_info_read()
|
||||
*
|
||||
* Desc: Ask the multi handle if there is any messages/informationals from
|
||||
* the individual transfers. Messages include informationals such as
|
||||
* error code from the transfer or just the fact that a transfer is
|
||||
* completed. More details on these should be written down as well.
|
||||
*
|
||||
* Repeated calls to this function will return a new struct each
|
||||
* time, until a special "end of msgs" struct is returned as a signal
|
||||
* that there is no more to get at this point.
|
||||
*
|
||||
* The data the returned pointer points to will not survive calling
|
||||
* curl_multi_cleanup().
|
||||
*
|
||||
* The 'CURLMsg' struct is meant to be simple and only contain basic
|
||||
* information. If more involved information is wanted, we will
|
||||
* provide the particular "transfer handle" in that struct and that
|
||||
* should/could/would be used in subsequent curl_easy_getinfo() calls
|
||||
* (or similar). The point being that we must never expose complex
|
||||
* structs to applications, as then we will undoubtably get backwards
|
||||
* compatibility problems in the future.
|
||||
*
|
||||
* Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
|
||||
* of structs. It also writes the number of messages left in the
|
||||
* queue (after this read) in the integer the second argument points
|
||||
* to.
|
||||
*/
|
||||
CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
|
||||
int *msgs_in_queue);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_strerror()
|
||||
*
|
||||
* Desc: The curl_multi_strerror function may be used to turn a CURLMcode
|
||||
* value into the equivalent human readable error string. This is
|
||||
* useful for printing meaningful error messages.
|
||||
*
|
||||
* Returns: A pointer to a null-terminated error message.
|
||||
*/
|
||||
CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_socket() and
|
||||
* curl_multi_socket_all()
|
||||
*
|
||||
* Desc: An alternative version of curl_multi_perform() that allows the
|
||||
* application to pass in one of the file descriptors that have been
|
||||
* detected to have "action" on them and let libcurl perform.
|
||||
* See manpage for details.
|
||||
*/
|
||||
#define CURL_POLL_NONE 0
|
||||
#define CURL_POLL_IN 1
|
||||
#define CURL_POLL_OUT 2
|
||||
#define CURL_POLL_INOUT 3
|
||||
#define CURL_POLL_REMOVE 4
|
||||
|
||||
#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
|
||||
|
||||
#define CURL_CSELECT_IN 0x01
|
||||
#define CURL_CSELECT_OUT 0x02
|
||||
#define CURL_CSELECT_ERR 0x04
|
||||
|
||||
typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
|
||||
curl_socket_t s, /* socket */
|
||||
int what, /* see above */
|
||||
void *userp, /* private callback
|
||||
pointer */
|
||||
void *socketp); /* private socket
|
||||
pointer */
|
||||
/*
|
||||
* Name: curl_multi_timer_callback
|
||||
*
|
||||
* Desc: Called by libcurl whenever the library detects a change in the
|
||||
* maximum number of milliseconds the app is allowed to wait before
|
||||
* curl_multi_socket() or curl_multi_perform() must be called
|
||||
* (to allow libcurl's timed events to take place).
|
||||
*
|
||||
* Returns: The callback should return zero.
|
||||
*/
|
||||
typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
|
||||
long timeout_ms, /* see above */
|
||||
void *userp); /* private callback
|
||||
pointer */
|
||||
|
||||
CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()")
|
||||
curl_multi_socket(CURLM *multi_handle, curl_socket_t s, int *running_handles);
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
|
||||
curl_socket_t s,
|
||||
int ev_bitmask,
|
||||
int *running_handles);
|
||||
|
||||
CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()")
|
||||
curl_multi_socket_all(CURLM *multi_handle, int *running_handles);
|
||||
|
||||
#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
|
||||
/* This macro below was added in 7.16.3 to push users who recompile to use
|
||||
the new curl_multi_socket_action() instead of the old curl_multi_socket()
|
||||
*/
|
||||
#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Name: curl_multi_timeout()
|
||||
*
|
||||
* Desc: Returns the maximum number of milliseconds the app is allowed to
|
||||
* wait before curl_multi_socket() or curl_multi_perform() must be
|
||||
* called (to allow libcurl's timed events to take place).
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
|
||||
long *milliseconds);
|
||||
|
||||
typedef enum {
|
||||
/* This is the socket callback function pointer */
|
||||
CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1),
|
||||
|
||||
/* This is the argument passed to the socket callback */
|
||||
CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2),
|
||||
|
||||
/* set to 1 to enable pipelining for this multi handle */
|
||||
CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3),
|
||||
|
||||
/* This is the timer callback function pointer */
|
||||
CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4),
|
||||
|
||||
/* This is the argument passed to the timer callback */
|
||||
CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5),
|
||||
|
||||
/* maximum number of entries in the connection cache */
|
||||
CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6),
|
||||
|
||||
/* maximum number of (pipelining) connections to one host */
|
||||
CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7),
|
||||
|
||||
/* maximum number of requests in a pipeline */
|
||||
CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8),
|
||||
|
||||
/* a connection with a content-length longer than this
|
||||
will not be considered for pipelining */
|
||||
CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9),
|
||||
|
||||
/* a connection with a chunk length longer than this
|
||||
will not be considered for pipelining */
|
||||
CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10),
|
||||
|
||||
/* a list of site names(+port) that are blocked from pipelining */
|
||||
CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11),
|
||||
|
||||
/* a list of server types that are blocked from pipelining */
|
||||
CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12),
|
||||
|
||||
/* maximum number of open connections in total */
|
||||
CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13),
|
||||
|
||||
/* This is the server push callback function pointer */
|
||||
CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14),
|
||||
|
||||
/* This is the argument passed to the server push callback */
|
||||
CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15),
|
||||
|
||||
/* maximum number of concurrent streams to support on a connection */
|
||||
CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16),
|
||||
|
||||
CURLMOPT_LASTENTRY /* the last unused */
|
||||
} CURLMoption;
|
||||
|
||||
|
||||
/*
|
||||
* Name: curl_multi_setopt()
|
||||
*
|
||||
* Desc: Sets options for the multi handle.
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
|
||||
CURLMoption option, ...);
|
||||
|
||||
|
||||
/*
|
||||
* Name: curl_multi_assign()
|
||||
*
|
||||
* Desc: This function sets an association in the multi handle between the
|
||||
* given socket and a private pointer of the application. This is
|
||||
* (only) useful for curl_multi_socket uses.
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
|
||||
curl_socket_t sockfd, void *sockp);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_get_handles()
|
||||
*
|
||||
* Desc: Returns an allocated array holding all handles currently added to
|
||||
* the multi handle. Marks the final entry with a NULL pointer. If
|
||||
* there is no easy handle added to the multi handle, this function
|
||||
* returns an array with the first entry as a NULL pointer.
|
||||
*
|
||||
* Returns: NULL on failure, otherwise a CURL **array pointer
|
||||
*/
|
||||
CURL_EXTERN CURL **curl_multi_get_handles(CURLM *multi_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_push_callback
|
||||
*
|
||||
* Desc: This callback gets called when a new stream is being pushed by the
|
||||
* server. It approves or denies the new stream. It can also decide
|
||||
* to completely fail the connection.
|
||||
*
|
||||
* Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT
|
||||
*/
|
||||
#define CURL_PUSH_OK 0
|
||||
#define CURL_PUSH_DENY 1
|
||||
#define CURL_PUSH_ERROROUT 2 /* added in 7.72.0 */
|
||||
|
||||
struct curl_pushheaders; /* forward declaration only */
|
||||
|
||||
CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h,
|
||||
size_t num);
|
||||
CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h,
|
||||
const char *name);
|
||||
|
||||
typedef int (*curl_push_callback)(CURL *parent,
|
||||
CURL *easy,
|
||||
size_t num_headers,
|
||||
struct curl_pushheaders *headers,
|
||||
void *userp);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_waitfds()
|
||||
*
|
||||
* Desc: Ask curl for fds for polling. The app can use these to poll on.
|
||||
* We want curl_multi_perform() called as soon as one of them are
|
||||
* ready. Passing zero size allows to get just a number of fds.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_waitfds(CURLM *multi,
|
||||
struct curl_waitfd *ufds,
|
||||
unsigned int size,
|
||||
unsigned int *fd_count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef CURLINC_OPTIONS_H
|
||||
#define CURLINC_OPTIONS_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
CURLOT_LONG, /* long (a range of values) */
|
||||
CURLOT_VALUES, /* (a defined set or bitmask) */
|
||||
CURLOT_OFF_T, /* curl_off_t (a range of values) */
|
||||
CURLOT_OBJECT, /* pointer (void *) */
|
||||
CURLOT_STRING, /* (char * to null-terminated buffer) */
|
||||
CURLOT_SLIST, /* (struct curl_slist *) */
|
||||
CURLOT_CBPTR, /* (void * passed as-is to a callback) */
|
||||
CURLOT_BLOB, /* blob (struct curl_blob *) */
|
||||
CURLOT_FUNCTION /* function pointer */
|
||||
} curl_easytype;
|
||||
|
||||
/* Flag bits */
|
||||
|
||||
/* "alias" means it is provided for old programs to remain functional,
|
||||
we prefer another name */
|
||||
#define CURLOT_FLAG_ALIAS (1<<0)
|
||||
|
||||
/* The CURLOPTTYPE_* id ranges can still be used to figure out what type/size
|
||||
to use for curl_easy_setopt() for the given id */
|
||||
struct curl_easyoption {
|
||||
const char *name;
|
||||
CURLoption id;
|
||||
curl_easytype type;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
CURL_EXTERN const struct curl_easyoption *
|
||||
curl_easy_option_by_name(const char *name);
|
||||
|
||||
CURL_EXTERN const struct curl_easyoption *
|
||||
curl_easy_option_by_id(CURLoption id);
|
||||
|
||||
CURL_EXTERN const struct curl_easyoption *
|
||||
curl_easy_option_next(const struct curl_easyoption *prev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
#endif /* CURLINC_OPTIONS_H */
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef CURLINC_STDCHEADERS_H
|
||||
#define CURLINC_STDCHEADERS_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
size_t fread(void *, size_t, size_t, FILE *);
|
||||
size_t fwrite(const void *, size_t, size_t, FILE *);
|
||||
|
||||
int strcasecmp(const char *, const char *);
|
||||
int strncasecmp(const char *, const char *, size_t);
|
||||
|
||||
#endif /* CURLINC_STDCHEADERS_H */
|
||||
@@ -0,0 +1,402 @@
|
||||
#ifndef CURLINC_SYSTEM_H
|
||||
#define CURLINC_SYSTEM_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Try to keep one section per platform, compiler and architecture, otherwise,
|
||||
* if an existing section is reused for a different one and later on the
|
||||
* original is adjusted, probably the piggybacking one can be adversely
|
||||
* changed.
|
||||
*
|
||||
* In order to differentiate between platforms/compilers/architectures use
|
||||
* only compiler built-in predefined preprocessor symbols.
|
||||
*
|
||||
* curl_off_t
|
||||
* ----------
|
||||
*
|
||||
* For any given platform/compiler curl_off_t MUST be typedef'ed to a 64-bit
|
||||
* wide signed integral data type. The width of this data type must remain
|
||||
* constant and independent of any possible large file support settings.
|
||||
*
|
||||
* As a general rule, curl_off_t shall not be mapped to off_t. This rule shall
|
||||
* only be violated if off_t is the only 64-bit data type available and the
|
||||
* size of off_t is independent of large file support settings. Keep your
|
||||
* build on the safe side avoiding an off_t gating. If you have a 64-bit
|
||||
* off_t then take for sure that another 64-bit data type exists, dig deeper
|
||||
* and you will find it.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __DJGPP__
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__BORLANDC__)
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__POCC__)
|
||||
# if defined(_MSC_VER)
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__LCC__)
|
||||
# if defined(__MCST__) /* MCST eLbrus Compiler Collection */
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
# else /* Local (or Little) C Compiler */
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# endif
|
||||
|
||||
#elif defined(macintosh)
|
||||
# include <ConditionalMacros.h>
|
||||
# if TYPE_LONGLONG
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
|
||||
|
||||
#elif defined(__TANDEM)
|
||||
# if !defined(__LP64)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
|
||||
# endif
|
||||
|
||||
#elif defined(UNDER_CE)
|
||||
# if defined(__MINGW32CE__)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# endif
|
||||
|
||||
#elif defined(__MINGW32__)
|
||||
# include <inttypes.h>
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T PRId64
|
||||
# define CURL_FORMAT_CURL_OFF_TU PRIu64
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
|
||||
#elif defined(__VMS)
|
||||
# if defined(__VAX)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
|
||||
|
||||
#elif defined(__OS400__)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
#elif defined(__MVS__)
|
||||
# if defined(_LONG_LONG)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# else /* _LP64 and default */
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
#elif defined(__370__)
|
||||
# if defined(__IBMC__) || defined(__IBMCPP__)
|
||||
# if defined(_LONG_LONG)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# else /* _LP64 and default */
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
# endif
|
||||
|
||||
#elif defined(TPF)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__TINYC__) /* also known as tcc */
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */
|
||||
# if !defined(__LP64) && (defined(__ILP32) || \
|
||||
defined(__i386) || \
|
||||
defined(__sparcv8) || \
|
||||
defined(__sparcv8plus))
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(__LP64) || \
|
||||
defined(__amd64) || defined(__sparcv9)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
#elif defined(__xlc__) /* IBM xlc compiler */
|
||||
# if !defined(_LP64)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
#elif defined(__hpux) /* HP aCC compiler */
|
||||
# if !defined(_LP64)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
/* ===================================== */
|
||||
/* KEEP MSVC THE PENULTIMATE ENTRY */
|
||||
/* ===================================== */
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
# if (_MSC_VER >= 1800)
|
||||
# include <inttypes.h>
|
||||
# define CURL_FORMAT_CURL_OFF_T PRId64
|
||||
# define CURL_FORMAT_CURL_OFF_TU PRIu64
|
||||
# else
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
/* ===================================== */
|
||||
/* KEEP GENERIC GCC THE LAST ENTRY */
|
||||
/* ===================================== */
|
||||
|
||||
#elif defined(__GNUC__) && !defined(_SCO_DS)
|
||||
# if !defined(__LP64__) && \
|
||||
(defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \
|
||||
defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \
|
||||
defined(__sparc__) || defined(__mips__) || defined(__sh__) || \
|
||||
defined(__XTENSA__) || \
|
||||
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \
|
||||
(defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L))
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_POPCOUNT64(x) __builtin_popcountll(x)
|
||||
# define CURL_CTZ64(x) __builtin_ctzll(x)
|
||||
# elif defined(__LP64__) || \
|
||||
defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
|
||||
defined(__e2k__) || \
|
||||
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \
|
||||
(defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_POPCOUNT64(x) __builtin_popcountl(x)
|
||||
# define CURL_CTZ64(x) __builtin_ctzl(x)
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
#else
|
||||
/* generic "safe guess" on old 32-bit style */
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
#endif
|
||||
|
||||
#ifdef _AIX
|
||||
/* AIX needs <sys/poll.h> */
|
||||
#define CURL_PULL_SYS_POLL_H
|
||||
#endif
|
||||
|
||||
/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */
|
||||
/* sys/types.h is required here to properly make type definitions below. */
|
||||
#ifdef CURL_PULL_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */
|
||||
/* sys/socket.h is required here to properly make type definitions below. */
|
||||
#ifdef CURL_PULL_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */
|
||||
/* sys/poll.h is required here to properly make type definitions below. */
|
||||
#ifdef CURL_PULL_SYS_POLL_H
|
||||
# include <sys/poll.h>
|
||||
#endif
|
||||
|
||||
/* Data type definition of curl_socklen_t. */
|
||||
#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
|
||||
typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
|
||||
#endif
|
||||
|
||||
/* Data type definition of curl_off_t. */
|
||||
|
||||
#ifdef CURL_TYPEOF_CURL_OFF_T
|
||||
typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
|
||||
#endif
|
||||
|
||||
#endif /* CURLINC_SYSTEM_H */
|
||||
@@ -0,0 +1,867 @@
|
||||
#ifndef CURLINC_TYPECHECK_GCC_H
|
||||
#define CURLINC_TYPECHECK_GCC_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* wraps curl_easy_setopt() with typechecking */
|
||||
|
||||
/* To add a new kind of warning, add an
|
||||
* if(curlcheck_sometype_option(_curl_opt))
|
||||
* if(!curlcheck_sometype(value))
|
||||
* _curl_easy_setopt_err_sometype();
|
||||
* block and define curlcheck_sometype_option, curlcheck_sometype and
|
||||
* _curl_easy_setopt_err_sometype below
|
||||
*
|
||||
* NOTE: We use two nested 'if' statements here instead of the && operator, in
|
||||
* order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x
|
||||
* when compiling with -Wlogical-op.
|
||||
*
|
||||
* To add an option that uses the same type as an existing option, you will
|
||||
* just need to extend the appropriate _curl_*_option macro
|
||||
*/
|
||||
|
||||
#define curl_easy_setopt(handle, option, value) \
|
||||
__extension__({ \
|
||||
if(__builtin_constant_p(option)) { \
|
||||
CURL_IGNORE_DEPRECATION( \
|
||||
if(curlcheck_long_option(option)) \
|
||||
if(!curlcheck_long(value)) \
|
||||
_curl_easy_setopt_err_long(); \
|
||||
if(curlcheck_off_t_option(option)) \
|
||||
if(!curlcheck_off_t(value)) \
|
||||
_curl_easy_setopt_err_curl_off_t(); \
|
||||
if(curlcheck_string_option(option)) \
|
||||
if(!curlcheck_string(value)) \
|
||||
_curl_easy_setopt_err_string(); \
|
||||
if((option) == CURLOPT_PRIVATE) { } \
|
||||
if(curlcheck_write_cb_option(option)) \
|
||||
if(!curlcheck_write_cb(value)) \
|
||||
_curl_easy_setopt_err_write_callback(); \
|
||||
if(curlcheck_curl_option(option)) \
|
||||
if(!curlcheck_curl(value)) \
|
||||
_curl_easy_setopt_err_curl(); \
|
||||
if((option) == CURLOPT_RESOLVER_START_FUNCTION) \
|
||||
if(!curlcheck_resolver_start_callback(value)) \
|
||||
_curl_easy_setopt_err_resolver_start_callback(); \
|
||||
if((option) == CURLOPT_READFUNCTION) \
|
||||
if(!curlcheck_read_cb(value)) \
|
||||
_curl_easy_setopt_err_read_cb(); \
|
||||
if((option) == CURLOPT_IOCTLFUNCTION) \
|
||||
if(!curlcheck_ioctl_cb(value)) \
|
||||
_curl_easy_setopt_err_ioctl_cb(); \
|
||||
if((option) == CURLOPT_SOCKOPTFUNCTION) \
|
||||
if(!curlcheck_sockopt_cb(value)) \
|
||||
_curl_easy_setopt_err_sockopt_cb(); \
|
||||
if((option) == CURLOPT_OPENSOCKETFUNCTION) \
|
||||
if(!curlcheck_opensocket_cb(value)) \
|
||||
_curl_easy_setopt_err_opensocket_cb(); \
|
||||
if((option) == CURLOPT_PROGRESSFUNCTION) \
|
||||
if(!curlcheck_progress_cb(value)) \
|
||||
_curl_easy_setopt_err_progress_cb(); \
|
||||
if((option) == CURLOPT_XFERINFOFUNCTION) \
|
||||
if(!curlcheck_xferinfo_cb(value)) \
|
||||
_curl_easy_setopt_err_xferinfo_cb(); \
|
||||
if((option) == CURLOPT_DEBUGFUNCTION) \
|
||||
if(!curlcheck_debug_cb(value)) \
|
||||
_curl_easy_setopt_err_debug_cb(); \
|
||||
if((option) == CURLOPT_SSL_CTX_FUNCTION) \
|
||||
if(!curlcheck_ssl_ctx_cb(value)) \
|
||||
_curl_easy_setopt_err_ssl_ctx_cb(); \
|
||||
if(curlcheck_conv_cb_option(option)) \
|
||||
if(!curlcheck_conv_cb(value)) \
|
||||
_curl_easy_setopt_err_conv_cb(); \
|
||||
if((option) == CURLOPT_SEEKFUNCTION) \
|
||||
if(!curlcheck_seek_cb(value)) \
|
||||
_curl_easy_setopt_err_seek_cb(); \
|
||||
if((option) == CURLOPT_CHUNK_BGN_FUNCTION) \
|
||||
if(!curlcheck_chunk_bgn_cb(value)) \
|
||||
_curl_easy_setopt_err_chunk_bgn_cb(); \
|
||||
if((option) == CURLOPT_CHUNK_END_FUNCTION) \
|
||||
if(!curlcheck_chunk_end_cb(value)) \
|
||||
_curl_easy_setopt_err_chunk_end_cb(); \
|
||||
if((option) == CURLOPT_CLOSESOCKETFUNCTION) \
|
||||
if(!curlcheck_close_socket_cb(value)) \
|
||||
_curl_easy_setopt_err_close_socket_cb(); \
|
||||
if((option) == CURLOPT_FNMATCH_FUNCTION) \
|
||||
if(!curlcheck_fnmatch_cb(value)) \
|
||||
_curl_easy_setopt_err_fnmatch_cb(); \
|
||||
if((option) == CURLOPT_HSTSREADFUNCTION) \
|
||||
if(!curlcheck_hstsread_cb(value)) \
|
||||
_curl_easy_setopt_err_hstsread_cb(); \
|
||||
if((option) == CURLOPT_HSTSWRITEFUNCTION) \
|
||||
if(!curlcheck_hstswrite_cb(value)) \
|
||||
_curl_easy_setopt_err_hstswrite_cb(); \
|
||||
if((option) == CURLOPT_SSH_HOSTKEYFUNCTION) \
|
||||
if(!curlcheck_ssh_hostkey_cb(value)) \
|
||||
_curl_easy_setopt_err_ssh_hostkey_cb(); \
|
||||
if((option) == CURLOPT_SSH_KEYFUNCTION) \
|
||||
if(!curlcheck_ssh_key_cb(value)) \
|
||||
_curl_easy_setopt_err_ssh_key_cb(); \
|
||||
if((option) == CURLOPT_INTERLEAVEFUNCTION) \
|
||||
if(!curlcheck_interleave_cb(value)) \
|
||||
_curl_easy_setopt_err_interleave_cb(); \
|
||||
if((option) == CURLOPT_PREREQFUNCTION) \
|
||||
if(!curlcheck_prereq_cb(value)) \
|
||||
_curl_easy_setopt_err_prereq_cb(); \
|
||||
if((option) == CURLOPT_TRAILERFUNCTION) \
|
||||
if(!curlcheck_trailer_cb(value)) \
|
||||
_curl_easy_setopt_err_trailer_cb(); \
|
||||
if(curlcheck_cb_data_option(option)) \
|
||||
if(!curlcheck_cb_data(value)) \
|
||||
_curl_easy_setopt_err_cb_data(); \
|
||||
if((option) == CURLOPT_ERRORBUFFER) \
|
||||
if(!curlcheck_error_buffer(value)) \
|
||||
_curl_easy_setopt_err_error_buffer(); \
|
||||
if((option) == CURLOPT_CURLU) \
|
||||
if(!curlcheck_ptr((value), CURLU)) \
|
||||
_curl_easy_setopt_err_curlu(); \
|
||||
if((option) == CURLOPT_STDERR) \
|
||||
if(!curlcheck_FILE(value)) \
|
||||
_curl_easy_setopt_err_FILE(); \
|
||||
if(curlcheck_postfields_option(option)) \
|
||||
if(!curlcheck_postfields(value)) \
|
||||
_curl_easy_setopt_err_postfields(); \
|
||||
if((option) == CURLOPT_HTTPPOST) \
|
||||
if(!curlcheck_arr((value), struct curl_httppost)) \
|
||||
_curl_easy_setopt_err_curl_httpost(); \
|
||||
if((option) == CURLOPT_MIMEPOST) \
|
||||
if(!curlcheck_ptr((value), curl_mime)) \
|
||||
_curl_easy_setopt_err_curl_mimepost(); \
|
||||
if(curlcheck_slist_option(option)) \
|
||||
if(!curlcheck_arr((value), struct curl_slist)) \
|
||||
_curl_easy_setopt_err_curl_slist(); \
|
||||
if((option) == CURLOPT_SHARE) \
|
||||
if(!curlcheck_ptr((value), CURLSH)) \
|
||||
_curl_easy_setopt_err_CURLSH(); \
|
||||
) \
|
||||
} \
|
||||
curl_easy_setopt(handle, option, value); \
|
||||
})
|
||||
|
||||
/* wraps curl_easy_getinfo() with typechecking */
|
||||
#define curl_easy_getinfo(handle, info, arg) \
|
||||
__extension__({ \
|
||||
if(__builtin_constant_p(info)) { \
|
||||
CURL_IGNORE_DEPRECATION( \
|
||||
if(curlcheck_string_info(info)) \
|
||||
if(!curlcheck_arr((arg), char *)) \
|
||||
_curl_easy_getinfo_err_string(); \
|
||||
if(curlcheck_long_info(info)) \
|
||||
if(!curlcheck_arr((arg), long)) \
|
||||
_curl_easy_getinfo_err_long(); \
|
||||
if(curlcheck_double_info(info)) \
|
||||
if(!curlcheck_arr((arg), double)) \
|
||||
_curl_easy_getinfo_err_double(); \
|
||||
if(curlcheck_slist_info(info)) \
|
||||
if(!curlcheck_arr((arg), struct curl_slist *)) \
|
||||
_curl_easy_getinfo_err_curl_slist(); \
|
||||
if(curlcheck_tlssessioninfo_info(info)) \
|
||||
if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
|
||||
_curl_easy_getinfo_err_curl_tlssessioninfo(); \
|
||||
if(curlcheck_certinfo_info(info)) \
|
||||
if(!curlcheck_arr((arg), struct curl_certinfo *)) \
|
||||
_curl_easy_getinfo_err_curl_certinfo(); \
|
||||
if(curlcheck_socket_info(info)) \
|
||||
if(!curlcheck_arr((arg), curl_socket_t)) \
|
||||
_curl_easy_getinfo_err_curl_socket(); \
|
||||
if(curlcheck_off_t_info(info)) \
|
||||
if(!curlcheck_arr((arg), curl_off_t)) \
|
||||
_curl_easy_getinfo_err_curl_off_t(); \
|
||||
) \
|
||||
} \
|
||||
curl_easy_getinfo(handle, info, arg); \
|
||||
})
|
||||
|
||||
/*
|
||||
* For now, just make sure that the functions are called with three arguments
|
||||
*/
|
||||
#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
|
||||
#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
|
||||
|
||||
/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
|
||||
* functions */
|
||||
|
||||
/* To define a new warning, use _CURL_WARNING(identifier, "message") */
|
||||
#define CURLWARNING(id, message) \
|
||||
static void __attribute__((__warning__(message))) \
|
||||
__attribute__((__unused__)) __attribute__((__noinline__)) \
|
||||
id(void) { __asm__(""); }
|
||||
|
||||
CURLWARNING(_curl_easy_setopt_err_long,
|
||||
"curl_easy_setopt expects a long argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_curl_off_t,
|
||||
"curl_easy_setopt expects a curl_off_t argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_string,
|
||||
"curl_easy_setopt expects a "
|
||||
"string ('char *' or char[]) argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_write_callback,
|
||||
"curl_easy_setopt expects a curl_write_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_resolver_start_callback,
|
||||
"curl_easy_setopt expects a "
|
||||
"curl_resolver_start_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_read_cb,
|
||||
"curl_easy_setopt expects a curl_read_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_ioctl_cb,
|
||||
"curl_easy_setopt expects a curl_ioctl_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_sockopt_cb,
|
||||
"curl_easy_setopt expects a curl_sockopt_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_opensocket_cb,
|
||||
"curl_easy_setopt expects a "
|
||||
"curl_opensocket_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_progress_cb,
|
||||
"curl_easy_setopt expects a curl_progress_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_xferinfo_cb,
|
||||
"curl_easy_setopt expects a curl_xferinfo_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_debug_cb,
|
||||
"curl_easy_setopt expects a curl_debug_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_ssl_ctx_cb,
|
||||
"curl_easy_setopt expects a curl_ssl_ctx_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_conv_cb,
|
||||
"curl_easy_setopt expects a curl_conv_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_seek_cb,
|
||||
"curl_easy_setopt expects a curl_seek_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_cb_data,
|
||||
"curl_easy_setopt expects a "
|
||||
"private data pointer as argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_chunk_bgn_cb,
|
||||
"curl_easy_setopt expects a curl_chunk_bgn_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_chunk_end_cb,
|
||||
"curl_easy_setopt expects a curl_chunk_end_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_close_socket_cb,
|
||||
"curl_easy_setopt expects a curl_closesocket_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_fnmatch_cb,
|
||||
"curl_easy_setopt expects a curl_fnmatch_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_hstsread_cb,
|
||||
"curl_easy_setopt expects a curl_hstsread_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_hstswrite_cb,
|
||||
"curl_easy_setopt expects a curl_hstswrite_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_ssh_key_cb,
|
||||
"curl_easy_setopt expects a curl_sshkeycallback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_ssh_hostkey_cb,
|
||||
"curl_easy_setopt expects a curl_sshhostkeycallback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_interleave_cb,
|
||||
"curl_easy_setopt expects a curl_interleave_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_prereq_cb,
|
||||
"curl_easy_setopt expects a curl_prereq_callback argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_trailer_cb,
|
||||
"curl_easy_setopt expects a curl_trailerfunc_ok argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_error_buffer,
|
||||
"curl_easy_setopt expects a "
|
||||
"char buffer of CURL_ERROR_SIZE as argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_curlu,
|
||||
"curl_easy_setopt expects a 'CURLU *' argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_curl,
|
||||
"curl_easy_setopt expects a 'CURL *' argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_FILE,
|
||||
"curl_easy_setopt expects a 'FILE *' argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_postfields,
|
||||
"curl_easy_setopt expects a 'void *' or 'char *' argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_curl_httpost,
|
||||
"curl_easy_setopt expects a 'struct curl_httppost *' "
|
||||
"argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_curl_mimepost,
|
||||
"curl_easy_setopt expects a 'curl_mime *' "
|
||||
"argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_curl_slist,
|
||||
"curl_easy_setopt expects a 'struct curl_slist *' argument")
|
||||
CURLWARNING(_curl_easy_setopt_err_CURLSH,
|
||||
"curl_easy_setopt expects a CURLSH* argument")
|
||||
CURLWARNING(_curl_easy_getinfo_err_string,
|
||||
"curl_easy_getinfo expects a pointer to 'char *'")
|
||||
CURLWARNING(_curl_easy_getinfo_err_long,
|
||||
"curl_easy_getinfo expects a pointer to long")
|
||||
CURLWARNING(_curl_easy_getinfo_err_double,
|
||||
"curl_easy_getinfo expects a pointer to double")
|
||||
CURLWARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
"curl_easy_getinfo expects a pointer to 'struct curl_slist *'")
|
||||
CURLWARNING(_curl_easy_getinfo_err_curl_tlssessioninfo,
|
||||
"curl_easy_getinfo expects a pointer to "
|
||||
"'struct curl_tlssessioninfo *'")
|
||||
CURLWARNING(_curl_easy_getinfo_err_curl_certinfo,
|
||||
"curl_easy_getinfo expects a pointer to "
|
||||
"'struct curl_certinfo *'")
|
||||
CURLWARNING(_curl_easy_getinfo_err_curl_socket,
|
||||
"curl_easy_getinfo expects a pointer to curl_socket_t")
|
||||
CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
"curl_easy_getinfo expects a pointer to curl_off_t")
|
||||
|
||||
/* groups of curl_easy_setops options that take the same type of argument */
|
||||
|
||||
/* evaluates to true if option takes a long argument */
|
||||
#define curlcheck_long_option(option) \
|
||||
(0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
|
||||
|
||||
#define curlcheck_off_t_option(option) \
|
||||
(((option) > CURLOPTTYPE_OFF_T) && ((option) < CURLOPTTYPE_BLOB))
|
||||
|
||||
/* option takes a CURL * argument */
|
||||
#define curlcheck_curl_option(option) \
|
||||
((option) == CURLOPT_STREAM_DEPENDS || \
|
||||
(option) == CURLOPT_STREAM_DEPENDS_E || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a char* argument */
|
||||
#define curlcheck_string_option(option) \
|
||||
((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \
|
||||
(option) == CURLOPT_ACCEPT_ENCODING || \
|
||||
(option) == CURLOPT_ALTSVC || \
|
||||
(option) == CURLOPT_CAINFO || \
|
||||
(option) == CURLOPT_CAPATH || \
|
||||
(option) == CURLOPT_COOKIE || \
|
||||
(option) == CURLOPT_COOKIEFILE || \
|
||||
(option) == CURLOPT_COOKIEJAR || \
|
||||
(option) == CURLOPT_COOKIELIST || \
|
||||
(option) == CURLOPT_CRLFILE || \
|
||||
(option) == CURLOPT_CUSTOMREQUEST || \
|
||||
(option) == CURLOPT_DEFAULT_PROTOCOL || \
|
||||
(option) == CURLOPT_DNS_INTERFACE || \
|
||||
(option) == CURLOPT_DNS_LOCAL_IP4 || \
|
||||
(option) == CURLOPT_DNS_LOCAL_IP6 || \
|
||||
(option) == CURLOPT_DNS_SERVERS || \
|
||||
(option) == CURLOPT_DOH_URL || \
|
||||
(option) == CURLOPT_ECH || \
|
||||
(option) == CURLOPT_EGDSOCKET || \
|
||||
(option) == CURLOPT_FTP_ACCOUNT || \
|
||||
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
|
||||
(option) == CURLOPT_FTPPORT || \
|
||||
(option) == CURLOPT_HAPROXY_CLIENT_IP || \
|
||||
(option) == CURLOPT_HSTS || \
|
||||
(option) == CURLOPT_INTERFACE || \
|
||||
(option) == CURLOPT_ISSUERCERT || \
|
||||
(option) == CURLOPT_KEYPASSWD || \
|
||||
(option) == CURLOPT_KRBLEVEL || \
|
||||
(option) == CURLOPT_LOGIN_OPTIONS || \
|
||||
(option) == CURLOPT_MAIL_AUTH || \
|
||||
(option) == CURLOPT_MAIL_FROM || \
|
||||
(option) == CURLOPT_NETRC_FILE || \
|
||||
(option) == CURLOPT_NOPROXY || \
|
||||
(option) == CURLOPT_PASSWORD || \
|
||||
(option) == CURLOPT_PINNEDPUBLICKEY || \
|
||||
(option) == CURLOPT_PRE_PROXY || \
|
||||
(option) == CURLOPT_PROTOCOLS_STR || \
|
||||
(option) == CURLOPT_PROXY || \
|
||||
(option) == CURLOPT_PROXY_CAINFO || \
|
||||
(option) == CURLOPT_PROXY_CAPATH || \
|
||||
(option) == CURLOPT_PROXY_CRLFILE || \
|
||||
(option) == CURLOPT_PROXY_ISSUERCERT || \
|
||||
(option) == CURLOPT_PROXY_KEYPASSWD || \
|
||||
(option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
|
||||
(option) == CURLOPT_PROXY_SERVICE_NAME || \
|
||||
(option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
|
||||
(option) == CURLOPT_PROXY_SSLCERT || \
|
||||
(option) == CURLOPT_PROXY_SSLCERTTYPE || \
|
||||
(option) == CURLOPT_PROXY_SSLKEY || \
|
||||
(option) == CURLOPT_PROXY_SSLKEYTYPE || \
|
||||
(option) == CURLOPT_PROXY_TLS13_CIPHERS || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
|
||||
(option) == CURLOPT_PROXYPASSWORD || \
|
||||
(option) == CURLOPT_PROXYUSERNAME || \
|
||||
(option) == CURLOPT_PROXYUSERPWD || \
|
||||
(option) == CURLOPT_RANDOM_FILE || \
|
||||
(option) == CURLOPT_RANGE || \
|
||||
(option) == CURLOPT_REDIR_PROTOCOLS_STR || \
|
||||
(option) == CURLOPT_REFERER || \
|
||||
(option) == CURLOPT_REQUEST_TARGET || \
|
||||
(option) == CURLOPT_RTSP_SESSION_ID || \
|
||||
(option) == CURLOPT_RTSP_STREAM_URI || \
|
||||
(option) == CURLOPT_RTSP_TRANSPORT || \
|
||||
(option) == CURLOPT_SASL_AUTHZID || \
|
||||
(option) == CURLOPT_SERVICE_NAME || \
|
||||
(option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
|
||||
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
|
||||
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 || \
|
||||
(option) == CURLOPT_SSH_KNOWNHOSTS || \
|
||||
(option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
|
||||
(option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
|
||||
(option) == CURLOPT_SSLCERT || \
|
||||
(option) == CURLOPT_SSLCERTTYPE || \
|
||||
(option) == CURLOPT_SSLENGINE || \
|
||||
(option) == CURLOPT_SSLKEY || \
|
||||
(option) == CURLOPT_SSLKEYTYPE || \
|
||||
(option) == CURLOPT_SSL_CIPHER_LIST || \
|
||||
(option) == CURLOPT_SSL_EC_CURVES || \
|
||||
(option) == CURLOPT_SSL_SIGNATURE_ALGORITHMS || \
|
||||
(option) == CURLOPT_TLS13_CIPHERS || \
|
||||
(option) == CURLOPT_TLSAUTH_PASSWORD || \
|
||||
(option) == CURLOPT_TLSAUTH_TYPE || \
|
||||
(option) == CURLOPT_TLSAUTH_USERNAME || \
|
||||
(option) == CURLOPT_UNIX_SOCKET_PATH || \
|
||||
(option) == CURLOPT_URL || \
|
||||
(option) == CURLOPT_USERAGENT || \
|
||||
(option) == CURLOPT_USERNAME || \
|
||||
(option) == CURLOPT_AWS_SIGV4 || \
|
||||
(option) == CURLOPT_USERPWD || \
|
||||
(option) == CURLOPT_XOAUTH2_BEARER || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a curl_write_callback argument */
|
||||
#define curlcheck_write_cb_option(option) \
|
||||
((option) == CURLOPT_HEADERFUNCTION || \
|
||||
(option) == CURLOPT_WRITEFUNCTION)
|
||||
|
||||
/* evaluates to true if option takes a curl_conv_callback argument */
|
||||
#define curlcheck_conv_cb_option(option) \
|
||||
((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
|
||||
(option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
|
||||
(option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
|
||||
|
||||
/* evaluates to true if option takes a data argument to pass to a callback */
|
||||
#define curlcheck_cb_data_option(option) \
|
||||
((option) == CURLOPT_CHUNK_DATA || \
|
||||
(option) == CURLOPT_CLOSESOCKETDATA || \
|
||||
(option) == CURLOPT_DEBUGDATA || \
|
||||
(option) == CURLOPT_FNMATCH_DATA || \
|
||||
(option) == CURLOPT_HEADERDATA || \
|
||||
(option) == CURLOPT_HSTSREADDATA || \
|
||||
(option) == CURLOPT_HSTSWRITEDATA || \
|
||||
(option) == CURLOPT_INTERLEAVEDATA || \
|
||||
(option) == CURLOPT_IOCTLDATA || \
|
||||
(option) == CURLOPT_OPENSOCKETDATA || \
|
||||
(option) == CURLOPT_PREREQDATA || \
|
||||
(option) == CURLOPT_XFERINFODATA || \
|
||||
(option) == CURLOPT_READDATA || \
|
||||
(option) == CURLOPT_SEEKDATA || \
|
||||
(option) == CURLOPT_SOCKOPTDATA || \
|
||||
(option) == CURLOPT_SSH_KEYDATA || \
|
||||
(option) == CURLOPT_SSL_CTX_DATA || \
|
||||
(option) == CURLOPT_WRITEDATA || \
|
||||
(option) == CURLOPT_RESOLVER_START_DATA || \
|
||||
(option) == CURLOPT_TRAILERDATA || \
|
||||
(option) == CURLOPT_SSH_HOSTKEYDATA || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a POST data argument (void* or char*) */
|
||||
#define curlcheck_postfields_option(option) \
|
||||
((option) == CURLOPT_POSTFIELDS || \
|
||||
(option) == CURLOPT_COPYPOSTFIELDS || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a struct curl_slist * argument */
|
||||
#define curlcheck_slist_option(option) \
|
||||
((option) == CURLOPT_HTTP200ALIASES || \
|
||||
(option) == CURLOPT_HTTPHEADER || \
|
||||
(option) == CURLOPT_MAIL_RCPT || \
|
||||
(option) == CURLOPT_POSTQUOTE || \
|
||||
(option) == CURLOPT_PREQUOTE || \
|
||||
(option) == CURLOPT_PROXYHEADER || \
|
||||
(option) == CURLOPT_QUOTE || \
|
||||
(option) == CURLOPT_RESOLVE || \
|
||||
(option) == CURLOPT_TELNETOPTIONS || \
|
||||
(option) == CURLOPT_CONNECT_TO || \
|
||||
0)
|
||||
|
||||
/* groups of curl_easy_getinfo infos that take the same type of argument */
|
||||
|
||||
/* evaluates to true if info expects a pointer to char * argument */
|
||||
#define curlcheck_string_info(info) \
|
||||
(CURLINFO_STRING < (info) && (info) < CURLINFO_LONG && \
|
||||
(info) != CURLINFO_PRIVATE)
|
||||
|
||||
/* evaluates to true if info expects a pointer to long argument */
|
||||
#define curlcheck_long_info(info) \
|
||||
(CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
|
||||
|
||||
/* evaluates to true if info expects a pointer to double argument */
|
||||
#define curlcheck_double_info(info) \
|
||||
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
|
||||
|
||||
/* true if info expects a pointer to struct curl_slist * argument */
|
||||
#define curlcheck_slist_info(info) \
|
||||
(((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
|
||||
|
||||
/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
|
||||
#define curlcheck_tlssessioninfo_info(info) \
|
||||
(((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
|
||||
|
||||
/* true if info expects a pointer to struct curl_certinfo * argument */
|
||||
#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
|
||||
|
||||
/* true if info expects a pointer to struct curl_socket_t argument */
|
||||
#define curlcheck_socket_info(info) \
|
||||
(CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
|
||||
|
||||
/* true if info expects a pointer to curl_off_t argument */
|
||||
#define curlcheck_off_t_info(info) \
|
||||
(CURLINFO_OFF_T < (info))
|
||||
|
||||
|
||||
/* typecheck helpers -- check whether given expression has requested type */
|
||||
|
||||
/* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros,
|
||||
* otherwise define a new macro. Search for __builtin_types_compatible_p
|
||||
* in the GCC manual.
|
||||
* NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
|
||||
* the actual expression passed to the curl_easy_setopt macro. This
|
||||
* means that you can only apply the sizeof and __typeof__ operators, no
|
||||
* == or whatsoever.
|
||||
*/
|
||||
|
||||
/* XXX: should evaluate to true if expr is a pointer */
|
||||
#define curlcheck_any_ptr(expr) \
|
||||
(sizeof(expr) == sizeof(void *))
|
||||
|
||||
/* evaluates to true if expr is NULL */
|
||||
/* XXX: must not evaluate expr, so this check is not accurate */
|
||||
#define curlcheck_NULL(expr) \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
|
||||
|
||||
/* evaluates to true if expr is type*, const type* or NULL */
|
||||
#define curlcheck_ptr(expr, type) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), type *) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), const type *))
|
||||
|
||||
/* evaluates to true if expr is one of type[], type*, NULL or const type* */
|
||||
#define curlcheck_arr(expr, type) \
|
||||
(curlcheck_ptr((expr), type) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), type []))
|
||||
|
||||
/* evaluates to true if expr is a string */
|
||||
#define curlcheck_string(expr) \
|
||||
(curlcheck_arr((expr), char) || \
|
||||
curlcheck_arr((expr), signed char) || \
|
||||
curlcheck_arr((expr), unsigned char))
|
||||
|
||||
/* evaluates to true if expr is a CURL * */
|
||||
#define curlcheck_curl(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), CURL *))
|
||||
|
||||
|
||||
/* evaluates to true if expr is a long (no matter the signedness)
|
||||
* XXX: for now, int is also accepted (and therefore short and char, which
|
||||
* are promoted to int when passed to a variadic function) */
|
||||
#define curlcheck_long(expr) \
|
||||
( \
|
||||
((sizeof(long) != sizeof(int)) && \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned long))) \
|
||||
|| \
|
||||
((sizeof(long) == sizeof(int)) && \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), int) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed int) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned int) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), short) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed short) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned short) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), char) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed char) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned char))) \
|
||||
)
|
||||
|
||||
/* evaluates to true if expr is of type curl_off_t */
|
||||
#define curlcheck_off_t(expr) \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
|
||||
|
||||
/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
|
||||
/* XXX: also check size of an char[] array? */
|
||||
#define curlcheck_error_buffer(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), char *) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), char[]))
|
||||
|
||||
/* evaluates to true if expr is of type (const) void* or (const) FILE* */
|
||||
#if 0
|
||||
#define curlcheck_cb_data(expr) \
|
||||
(curlcheck_ptr((expr), void) || \
|
||||
curlcheck_ptr((expr), FILE))
|
||||
#else /* be less strict */
|
||||
#define curlcheck_cb_data(expr) \
|
||||
curlcheck_any_ptr(expr)
|
||||
#endif
|
||||
|
||||
/* evaluates to true if expr is of type FILE* */
|
||||
#define curlcheck_FILE(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), FILE *)))
|
||||
|
||||
/* evaluates to true if expr can be passed as POST data (void* or char*) */
|
||||
#define curlcheck_postfields(expr) \
|
||||
(curlcheck_ptr((expr), void) || \
|
||||
curlcheck_arr((expr), char) || \
|
||||
curlcheck_arr((expr), unsigned char))
|
||||
|
||||
/* helper: __builtin_types_compatible_p distinguishes between functions and
|
||||
* function pointers, hide it */
|
||||
#define curlcheck_cb_compatible(func, type) \
|
||||
(__builtin_types_compatible_p(__typeof__(func), type) || \
|
||||
__builtin_types_compatible_p(__typeof__(func) *, type))
|
||||
|
||||
/* evaluates to true if expr is of type curl_resolver_start_callback */
|
||||
#define curlcheck_resolver_start_callback(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_resolver_start_callback))
|
||||
|
||||
/* evaluates to true if expr is of type curl_read_callback or "similar" */
|
||||
#define curlcheck_read_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), __typeof__(fread) *) || \
|
||||
curlcheck_cb_compatible((expr), curl_read_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_read_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_read_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_read_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_read_callback4) || \
|
||||
curlcheck_cb_compatible((expr), _curl_read_callback5) || \
|
||||
curlcheck_cb_compatible((expr), _curl_read_callback6))
|
||||
typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
|
||||
typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
|
||||
typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
|
||||
typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_write_callback or "similar" */
|
||||
#define curlcheck_write_cb(expr) \
|
||||
(curlcheck_read_cb(expr) || \
|
||||
curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \
|
||||
curlcheck_cb_compatible((expr), curl_write_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_write_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_write_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_write_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_write_callback4) || \
|
||||
curlcheck_cb_compatible((expr), _curl_write_callback5) || \
|
||||
curlcheck_cb_compatible((expr), _curl_write_callback6))
|
||||
typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
|
||||
const void *);
|
||||
typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *);
|
||||
typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
|
||||
const void *);
|
||||
typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
|
||||
#define curlcheck_ioctl_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_ioctl_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ioctl_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ioctl_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ioctl_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ioctl_callback4))
|
||||
typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
|
||||
#define curlcheck_sockopt_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_sockopt_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_sockopt_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_sockopt_callback2))
|
||||
typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
|
||||
typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
|
||||
curlsocktype);
|
||||
|
||||
/* evaluates to true if expr is of type curl_opensocket_callback or
|
||||
"similar" */
|
||||
#define curlcheck_opensocket_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_opensocket_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_opensocket_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_opensocket_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_opensocket_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_opensocket_callback4))
|
||||
typedef curl_socket_t (*_curl_opensocket_callback1)
|
||||
(void *, curlsocktype, struct curl_sockaddr *);
|
||||
typedef curl_socket_t (*_curl_opensocket_callback2)
|
||||
(void *, curlsocktype, const struct curl_sockaddr *);
|
||||
typedef curl_socket_t (*_curl_opensocket_callback3)
|
||||
(const void *, curlsocktype, struct curl_sockaddr *);
|
||||
typedef curl_socket_t (*_curl_opensocket_callback4)
|
||||
(const void *, curlsocktype, const struct curl_sockaddr *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_progress_callback or "similar" */
|
||||
#define curlcheck_progress_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_progress_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_progress_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_progress_callback2))
|
||||
typedef int (*_curl_progress_callback1)(void *,
|
||||
double, double, double, double);
|
||||
typedef int (*_curl_progress_callback2)(const void *,
|
||||
double, double, double, double);
|
||||
|
||||
/* evaluates to true if expr is of type curl_xferinfo_callback */
|
||||
#define curlcheck_xferinfo_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_xferinfo_callback))
|
||||
|
||||
/* evaluates to true if expr is of type curl_debug_callback or "similar" */
|
||||
#define curlcheck_debug_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_debug_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback4) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback5) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback6) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback7) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback8))
|
||||
typedef int (*_curl_debug_callback1) (CURL *,
|
||||
curl_infotype, char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback2) (CURL *,
|
||||
curl_infotype, char *, size_t, const void *);
|
||||
typedef int (*_curl_debug_callback3) (CURL *,
|
||||
curl_infotype, const char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback4) (CURL *,
|
||||
curl_infotype, const char *, size_t, const void *);
|
||||
typedef int (*_curl_debug_callback5) (CURL *,
|
||||
curl_infotype, unsigned char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback6) (CURL *,
|
||||
curl_infotype, unsigned char *, size_t, const void *);
|
||||
typedef int (*_curl_debug_callback7) (CURL *,
|
||||
curl_infotype, const unsigned char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback8) (CURL *,
|
||||
curl_infotype, const unsigned char *, size_t, const void *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
|
||||
/* this is getting even messier... */
|
||||
#define curlcheck_ssl_ctx_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback4) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback5) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback6) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback7) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback8))
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
|
||||
const void *);
|
||||
#ifdef HEADER_SSL_H
|
||||
/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
|
||||
* this will of course break if we are included before OpenSSL headers...
|
||||
*/
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX *, const void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX *,
|
||||
const void *);
|
||||
#else
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
|
||||
#endif
|
||||
|
||||
/* evaluates to true if expr is of type curl_conv_callback or "similar" */
|
||||
#define curlcheck_conv_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_conv_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_conv_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_conv_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_conv_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_conv_callback4))
|
||||
typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
|
||||
typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
|
||||
typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
|
||||
typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
|
||||
|
||||
/* evaluates to true if expr is of type curl_seek_callback or "similar" */
|
||||
#define curlcheck_seek_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_seek_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_seek_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_seek_callback2))
|
||||
typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
|
||||
typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
|
||||
|
||||
/* evaluates to true if expr is of type curl_chunk_bgn_callback */
|
||||
#define curlcheck_chunk_bgn_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_chunk_bgn_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_chunk_bgn_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_chunk_bgn_callback2))
|
||||
typedef long (*_curl_chunk_bgn_callback1)(struct curl_fileinfo *,
|
||||
void *, int);
|
||||
typedef long (*_curl_chunk_bgn_callback2)(void *, void *, int);
|
||||
|
||||
/* evaluates to true if expr is of type curl_chunk_end_callback */
|
||||
#define curlcheck_chunk_end_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_chunk_end_callback))
|
||||
|
||||
/* evaluates to true if expr is of type curl_closesocket_callback */
|
||||
#define curlcheck_close_socket_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_closesocket_callback))
|
||||
|
||||
/* evaluates to true if expr is of type curl_fnmatch_callback */
|
||||
#define curlcheck_fnmatch_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_fnmatch_callback))
|
||||
|
||||
/* evaluates to true if expr is of type curl_hstsread_callback */
|
||||
#define curlcheck_hstsread_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_hstsread_callback))
|
||||
|
||||
/* evaluates to true if expr is of type curl_hstswrite_callback */
|
||||
#define curlcheck_hstswrite_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_hstswrite_callback))
|
||||
|
||||
/* evaluates to true if expr is of type curl_sshhostkeycallback */
|
||||
#define curlcheck_ssh_hostkey_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_sshhostkeycallback))
|
||||
|
||||
/* evaluates to true if expr is of type curl_sshkeycallback */
|
||||
#define curlcheck_ssh_key_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_sshkeycallback))
|
||||
|
||||
/* evaluates to true if expr is of type curl_interleave_callback */
|
||||
#define curlcheck_interleave_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), _curl_interleave_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_interleave_callback2))
|
||||
typedef size_t (*_curl_interleave_callback1)(void *p, size_t s,
|
||||
size_t n, void *u);
|
||||
typedef size_t (*_curl_interleave_callback2)(char *p, size_t s,
|
||||
size_t n, void *u);
|
||||
|
||||
/* evaluates to true if expr is of type curl_prereq_callback */
|
||||
#define curlcheck_prereq_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_prereq_callback))
|
||||
|
||||
/* evaluates to true if expr is of type curl_trailer_callback */
|
||||
#define curlcheck_trailer_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_trailer_callback))
|
||||
|
||||
#endif /* CURLINC_TYPECHECK_GCC_H */
|
||||
@@ -0,0 +1,155 @@
|
||||
#ifndef CURLINC_URLAPI_H
|
||||
#define CURLINC_URLAPI_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* the error codes for the URL API */
|
||||
typedef enum {
|
||||
CURLUE_OK,
|
||||
CURLUE_BAD_HANDLE, /* 1 */
|
||||
CURLUE_BAD_PARTPOINTER, /* 2 */
|
||||
CURLUE_MALFORMED_INPUT, /* 3 */
|
||||
CURLUE_BAD_PORT_NUMBER, /* 4 */
|
||||
CURLUE_UNSUPPORTED_SCHEME, /* 5 */
|
||||
CURLUE_URLDECODE, /* 6 */
|
||||
CURLUE_OUT_OF_MEMORY, /* 7 */
|
||||
CURLUE_USER_NOT_ALLOWED, /* 8 */
|
||||
CURLUE_UNKNOWN_PART, /* 9 */
|
||||
CURLUE_NO_SCHEME, /* 10 */
|
||||
CURLUE_NO_USER, /* 11 */
|
||||
CURLUE_NO_PASSWORD, /* 12 */
|
||||
CURLUE_NO_OPTIONS, /* 13 */
|
||||
CURLUE_NO_HOST, /* 14 */
|
||||
CURLUE_NO_PORT, /* 15 */
|
||||
CURLUE_NO_QUERY, /* 16 */
|
||||
CURLUE_NO_FRAGMENT, /* 17 */
|
||||
CURLUE_NO_ZONEID, /* 18 */
|
||||
CURLUE_BAD_FILE_URL, /* 19 */
|
||||
CURLUE_BAD_FRAGMENT, /* 20 */
|
||||
CURLUE_BAD_HOSTNAME, /* 21 */
|
||||
CURLUE_BAD_IPV6, /* 22 */
|
||||
CURLUE_BAD_LOGIN, /* 23 */
|
||||
CURLUE_BAD_PASSWORD, /* 24 */
|
||||
CURLUE_BAD_PATH, /* 25 */
|
||||
CURLUE_BAD_QUERY, /* 26 */
|
||||
CURLUE_BAD_SCHEME, /* 27 */
|
||||
CURLUE_BAD_SLASHES, /* 28 */
|
||||
CURLUE_BAD_USER, /* 29 */
|
||||
CURLUE_LACKS_IDN, /* 30 */
|
||||
CURLUE_TOO_LARGE, /* 31 */
|
||||
CURLUE_LAST
|
||||
} CURLUcode;
|
||||
|
||||
typedef enum {
|
||||
CURLUPART_URL,
|
||||
CURLUPART_SCHEME,
|
||||
CURLUPART_USER,
|
||||
CURLUPART_PASSWORD,
|
||||
CURLUPART_OPTIONS,
|
||||
CURLUPART_HOST,
|
||||
CURLUPART_PORT,
|
||||
CURLUPART_PATH,
|
||||
CURLUPART_QUERY,
|
||||
CURLUPART_FRAGMENT,
|
||||
CURLUPART_ZONEID /* added in 7.65.0 */
|
||||
} CURLUPart;
|
||||
|
||||
#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */
|
||||
#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set,
|
||||
if the port number matches the
|
||||
default for the scheme */
|
||||
#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if
|
||||
missing */
|
||||
#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */
|
||||
#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */
|
||||
#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */
|
||||
#define CURLU_URLDECODE (1<<6) /* URL decode on get */
|
||||
#define CURLU_URLENCODE (1<<7) /* URL encode on set */
|
||||
#define CURLU_APPENDQUERY (1<<8) /* append a form style part */
|
||||
#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */
|
||||
#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the
|
||||
scheme is unknown. */
|
||||
#define CURLU_ALLOW_SPACE (1<<11) /* Allow spaces in the URL */
|
||||
#define CURLU_PUNYCODE (1<<12) /* get the hostname in punycode */
|
||||
#define CURLU_PUNY2IDN (1<<13) /* punycode => IDN conversion */
|
||||
#define CURLU_GET_EMPTY (1<<14) /* allow empty queries and fragments
|
||||
when extracting the URL or the
|
||||
components */
|
||||
#define CURLU_NO_GUESS_SCHEME (1<<15) /* for get, do not accept a guess */
|
||||
|
||||
typedef struct Curl_URL CURLU;
|
||||
|
||||
/*
|
||||
* curl_url() creates a new CURLU handle and returns a pointer to it.
|
||||
* Must be freed with curl_url_cleanup().
|
||||
*/
|
||||
CURL_EXTERN CURLU *curl_url(void);
|
||||
|
||||
/*
|
||||
* curl_url_cleanup() frees the CURLU handle and related resources used for
|
||||
* the URL parsing. It will not free strings previously returned with the URL
|
||||
* API.
|
||||
*/
|
||||
CURL_EXTERN void curl_url_cleanup(CURLU *handle);
|
||||
|
||||
/*
|
||||
* curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
|
||||
* handle must also be freed with curl_url_cleanup().
|
||||
*/
|
||||
CURL_EXTERN CURLU *curl_url_dup(const CURLU *in);
|
||||
|
||||
/*
|
||||
* curl_url_get() extracts a specific part of the URL from a CURLU
|
||||
* handle. Returns error code. The returned pointer MUST be freed with
|
||||
* curl_free() afterwards.
|
||||
*/
|
||||
CURL_EXTERN CURLUcode curl_url_get(const CURLU *handle, CURLUPart what,
|
||||
char **part, unsigned int flags);
|
||||
|
||||
/*
|
||||
* curl_url_set() sets a specific part of the URL in a CURLU handle. Returns
|
||||
* error code. The passed in string will be copied. Passing a NULL instead of
|
||||
* a part string, clears that part.
|
||||
*/
|
||||
CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what,
|
||||
const char *part, unsigned int flags);
|
||||
|
||||
/*
|
||||
* curl_url_strerror() turns a CURLUcode value into the equivalent human
|
||||
* readable error string. This is useful for printing meaningful error
|
||||
* messages.
|
||||
*/
|
||||
CURL_EXTERN const char *curl_url_strerror(CURLUcode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* CURLINC_URLAPI_H */
|
||||
@@ -0,0 +1,85 @@
|
||||
#ifndef CURLINC_WEBSOCKETS_H
|
||||
#define CURLINC_WEBSOCKETS_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct curl_ws_frame {
|
||||
int age; /* zero */
|
||||
int flags; /* See the CURLWS_* defines */
|
||||
curl_off_t offset; /* the offset of this data into the frame */
|
||||
curl_off_t bytesleft; /* number of pending bytes left of the payload */
|
||||
size_t len; /* size of the current data chunk */
|
||||
};
|
||||
|
||||
/* flag bits */
|
||||
#define CURLWS_TEXT (1<<0)
|
||||
#define CURLWS_BINARY (1<<1)
|
||||
#define CURLWS_CONT (1<<2)
|
||||
#define CURLWS_CLOSE (1<<3)
|
||||
#define CURLWS_PING (1<<4)
|
||||
#define CURLWS_OFFSET (1<<5)
|
||||
|
||||
/*
|
||||
* NAME curl_ws_recv()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Receives data from the websocket connection. Use after successful
|
||||
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
|
||||
size_t *recv,
|
||||
const struct curl_ws_frame **metap);
|
||||
|
||||
/* flags for curl_ws_send() */
|
||||
#define CURLWS_PONG (1<<6)
|
||||
|
||||
/*
|
||||
* NAME curl_ws_send()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Sends data over the websocket connection. Use after successful
|
||||
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_ws_send(CURL *curl, const void *buffer,
|
||||
size_t buflen, size_t *sent,
|
||||
curl_off_t fragsize,
|
||||
unsigned int flags);
|
||||
|
||||
/* bits for the CURLOPT_WS_OPTIONS bitmask: */
|
||||
#define CURLWS_RAW_MODE (1<<0)
|
||||
#define CURLWS_NOAUTOPONG (1<<1)
|
||||
|
||||
CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(CURL *curl);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CURLINC_WEBSOCKETS_H */
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
# libcurl.la - a libtool library file
|
||||
# Generated by libtool (GNU libtool) 2.4.7 Debian-2.4.7-7~deb12u1
|
||||
#
|
||||
# Please DO NOT delete this file!
|
||||
# It is necessary for linking the library.
|
||||
|
||||
# The name that we can dlopen(3).
|
||||
dlname=''
|
||||
|
||||
# Names of this library.
|
||||
library_names=''
|
||||
|
||||
# The name of the static archive.
|
||||
old_library='libcurl.a'
|
||||
|
||||
# Linker flags that cannot go in dependency_libs.
|
||||
inherited_linker_flags=''
|
||||
|
||||
# Libraries that this one depends upon.
|
||||
dependency_libs=' -lssl -lcrypto -lz -L/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/openssl-3.4.2/../openssl-install/lib64'
|
||||
|
||||
# Names of additional weak libraries provided by this library
|
||||
weak_library_names=''
|
||||
|
||||
# Version information for libcurl.
|
||||
current=12
|
||||
age=8
|
||||
revision=0
|
||||
|
||||
# Is this an already installed library?
|
||||
installed=yes
|
||||
|
||||
# Should we warn about portability when linking against -modules?
|
||||
shouldnotlink=no
|
||||
|
||||
# Files to dlopen/dlpreopen
|
||||
dlopen=''
|
||||
dlpreopen=''
|
||||
|
||||
# Directory that this library needs to be installed in:
|
||||
libdir='/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-install/lib'
|
||||
@@ -0,0 +1,41 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
prefix=/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-install
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
supported_protocols="FILE FTP FTPS HTTP HTTPS IPFS IPNS MQTT WS WSS"
|
||||
supported_features="alt-svc AsynchDNS HSTS IPv6 Largefile libz NTLM SSL threadsafe TLS-SRP UnixSockets"
|
||||
|
||||
Name: libcurl
|
||||
URL: https://curl.se/
|
||||
Description: Library to transfer files with HTTP, FTP, etc.
|
||||
Version: 8.15.0
|
||||
Requires: zlib,openssl
|
||||
Requires.private: zlib,openssl
|
||||
Libs: -L${libdir} -lcurl -lssl -lcrypto -lssl -lcrypto -lz
|
||||
Libs.private: -L/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/openssl-3.4.2/../openssl-install/lib64 -lssl -lcrypto -lssl -lcrypto -lz
|
||||
Cflags: -I${includedir} -DCURL_STATICLIB
|
||||
Cflags.private: -DCURL_STATICLIB
|
||||
@@ -0,0 +1,273 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) David Shaw <dshaw@jabberwocky.com>
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
# LIBCURL_CHECK_CONFIG([DEFAULT-ACTION], [MINIMUM-VERSION],
|
||||
# [ACTION-IF-YES], [ACTION-IF-NO])
|
||||
# ----------------------------------------------------------
|
||||
# David Shaw <dshaw@jabberwocky.com> May-09-2006
|
||||
#
|
||||
# Checks for libcurl. DEFAULT-ACTION is the string yes or no to
|
||||
# specify whether to default to --with-libcurl or --without-libcurl.
|
||||
# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the
|
||||
# minimum version of libcurl to accept. Pass the version as a regular
|
||||
# version number like 7.10.1. If not supplied, any version is
|
||||
# accepted. ACTION-IF-YES is a list of shell commands to run if
|
||||
# libcurl was successfully found and passed the various tests.
|
||||
# ACTION-IF-NO is a list of shell commands that are run otherwise.
|
||||
# Note that using --without-libcurl does run ACTION-IF-NO.
|
||||
#
|
||||
# This macro #defines HAVE_LIBCURL if a working libcurl setup is
|
||||
# found, and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary
|
||||
# values. Other useful defines are LIBCURL_FEATURE_xxx where xxx are
|
||||
# the various features supported by libcurl, and LIBCURL_PROTOCOL_yyy
|
||||
# where yyy are the various protocols supported by libcurl. Both xxx
|
||||
# and yyy are capitalized. See the list of AH_TEMPLATEs at the top of
|
||||
# the macro for the complete list of possible defines. Shell
|
||||
# variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also
|
||||
# defined to 'yes' for those features and protocols that were found.
|
||||
# Note that xxx and yyy keep the same capitalization as in the
|
||||
# curl-config list (e.g. it's "HTTP" and not "http").
|
||||
#
|
||||
# Users may override the detected values by doing something like:
|
||||
# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure
|
||||
#
|
||||
# For the sake of sanity, this macro assumes that any libcurl that is found is
|
||||
# after version 7.7.2, the first version that included the curl-config script.
|
||||
# Note that it is important for people packaging binary versions of libcurl to
|
||||
# include this script! Without curl-config, we can only guess what protocols
|
||||
# are available, or use curl_version_info to figure it out at runtime.
|
||||
|
||||
AC_DEFUN([LIBCURL_CHECK_CONFIG],
|
||||
[
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI])
|
||||
AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM])
|
||||
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_RTSP],[Defined if libcurl supports RTSP])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_POP3],[Defined if libcurl supports POP3])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_IMAP],[Defined if libcurl supports IMAP])
|
||||
AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP])
|
||||
|
||||
AC_ARG_WITH(libcurl,
|
||||
AS_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]),
|
||||
[_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])])
|
||||
|
||||
if test "$_libcurl_with" != "no"; then
|
||||
|
||||
AC_PROG_AWK
|
||||
|
||||
_libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'"
|
||||
|
||||
_libcurl_try_link=yes
|
||||
|
||||
if test -d "$_libcurl_with"; then
|
||||
LIBCURL_CPPFLAGS="-I$withval/include"
|
||||
_libcurl_ldflags="-L$withval/lib"
|
||||
AC_PATH_PROG([_libcurl_config],[curl-config],[],["$withval/bin"])
|
||||
else
|
||||
AC_PATH_PROG([_libcurl_config],[curl-config],[],[$PATH])
|
||||
fi
|
||||
|
||||
if test x$_libcurl_config != "x"; then
|
||||
AC_CACHE_CHECK([for the version of libcurl],
|
||||
[libcurl_cv_lib_curl_version],
|
||||
[libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`])
|
||||
|
||||
_libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse`
|
||||
_libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse`
|
||||
|
||||
if test $_libcurl_wanted -gt 0; then
|
||||
AC_CACHE_CHECK([for libcurl >= version $2],
|
||||
[libcurl_cv_lib_version_ok],
|
||||
[
|
||||
if test $_libcurl_version -ge $_libcurl_wanted; then
|
||||
libcurl_cv_lib_version_ok=yes
|
||||
else
|
||||
libcurl_cv_lib_version_ok=no
|
||||
fi
|
||||
])
|
||||
fi
|
||||
|
||||
if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes; then
|
||||
if test x"$LIBCURL_CPPFLAGS" = "x"; then
|
||||
LIBCURL_CPPFLAGS=`$_libcurl_config --cflags`
|
||||
fi
|
||||
if test x"$LIBCURL" = "x"; then
|
||||
LIBCURL=`$_libcurl_config --libs`
|
||||
|
||||
# This is so silly, but Apple actually has a bug in their
|
||||
# curl-config script. Fixed in Tiger, but there are still
|
||||
# lots of Panther installs around.
|
||||
case "${host}" in
|
||||
powerpc-apple-darwin7*)
|
||||
LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'`
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# All curl-config scripts support --feature
|
||||
_libcurl_features=`$_libcurl_config --feature`
|
||||
|
||||
# Is it modern enough to have --protocols? (7.12.4)
|
||||
if test $_libcurl_version -ge 461828; then
|
||||
_libcurl_protocols=`$_libcurl_config --protocols`
|
||||
fi
|
||||
else
|
||||
_libcurl_try_link=no
|
||||
fi
|
||||
|
||||
unset _libcurl_wanted
|
||||
fi
|
||||
|
||||
if test $_libcurl_try_link = yes; then
|
||||
|
||||
# we did not find curl-config, so let's see if the user-supplied
|
||||
# link line (or failing that, "-lcurl") is enough.
|
||||
LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"}
|
||||
|
||||
AC_CACHE_CHECK([whether libcurl is usable],
|
||||
[libcurl_cv_lib_curl_usable],
|
||||
[
|
||||
_libcurl_save_cppflags=$CPPFLAGS
|
||||
CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS"
|
||||
_libcurl_save_libs=$LIBS
|
||||
LIBS="$LIBCURL $LIBS"
|
||||
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <curl/curl.h>]],[[
|
||||
/* Try to use a few common options to force a failure if we are
|
||||
missing symbols or cannot link. */
|
||||
int x;
|
||||
curl_easy_setopt(NULL,CURLOPT_URL,NULL);
|
||||
x=CURL_ERROR_SIZE;
|
||||
x=CURLOPT_WRITEFUNCTION;
|
||||
x=CURLOPT_WRITEDATA;
|
||||
x=CURLOPT_ERRORBUFFER;
|
||||
x=CURLOPT_STDERR;
|
||||
x=CURLOPT_VERBOSE;
|
||||
if (x) {;}
|
||||
]])],libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no)
|
||||
|
||||
CPPFLAGS=$_libcurl_save_cppflags
|
||||
LIBS=$_libcurl_save_libs
|
||||
unset _libcurl_save_cppflags
|
||||
unset _libcurl_save_libs
|
||||
])
|
||||
|
||||
if test $libcurl_cv_lib_curl_usable = yes; then
|
||||
|
||||
# Does curl_free() exist in this version of libcurl?
|
||||
# If not, fake it with free()
|
||||
|
||||
_libcurl_save_cppflags=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS"
|
||||
_libcurl_save_libs=$LIBS
|
||||
LIBS="$LIBS $LIBCURL"
|
||||
|
||||
AC_CHECK_DECL([curl_free],[],
|
||||
[AC_DEFINE([curl_free],[free],
|
||||
[Define curl_free() as free() if our version of curl lacks curl_free.])],
|
||||
[[#include <curl/curl.h>]])
|
||||
|
||||
CPPFLAGS=$_libcurl_save_cppflags
|
||||
LIBS=$_libcurl_save_libs
|
||||
unset _libcurl_save_cppflags
|
||||
unset _libcurl_save_libs
|
||||
|
||||
AC_DEFINE(HAVE_LIBCURL,1,
|
||||
[Define to 1 if you have a functional curl library.])
|
||||
AC_SUBST(LIBCURL_CPPFLAGS)
|
||||
AC_SUBST(LIBCURL)
|
||||
|
||||
for _libcurl_feature in $_libcurl_features; do
|
||||
AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1])
|
||||
eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes
|
||||
done
|
||||
|
||||
if test "x$_libcurl_protocols" = "x"; then
|
||||
|
||||
# We do not have --protocols, so just assume that all
|
||||
# protocols are available
|
||||
_libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP"
|
||||
|
||||
if test x$libcurl_feature_SSL = xyes; then
|
||||
_libcurl_protocols="$_libcurl_protocols HTTPS"
|
||||
|
||||
# FTPS was not standards-compliant until version
|
||||
# 7.11.0 (0x070b00 == 461568)
|
||||
if test $_libcurl_version -ge 461568; then
|
||||
_libcurl_protocols="$_libcurl_protocols FTPS"
|
||||
fi
|
||||
fi
|
||||
|
||||
# RTSP, IMAP, POP3 and SMTP were added in
|
||||
# 7.20.0 (0x071400 == 463872)
|
||||
if test $_libcurl_version -ge 463872; then
|
||||
_libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP"
|
||||
fi
|
||||
fi
|
||||
|
||||
for _libcurl_protocol in $_libcurl_protocols; do
|
||||
AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1])
|
||||
eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes
|
||||
done
|
||||
else
|
||||
unset LIBCURL
|
||||
unset LIBCURL_CPPFLAGS
|
||||
fi
|
||||
fi
|
||||
|
||||
unset _libcurl_try_link
|
||||
unset _libcurl_version_parse
|
||||
unset _libcurl_config
|
||||
unset _libcurl_feature
|
||||
unset _libcurl_features
|
||||
unset _libcurl_protocol
|
||||
unset _libcurl_protocols
|
||||
unset _libcurl_version
|
||||
unset _libcurl_ldflags
|
||||
fi
|
||||
|
||||
if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes; then
|
||||
# This is the IF-NO path
|
||||
ifelse([$4],,:,[$4])
|
||||
else
|
||||
# This is the IF-YES path
|
||||
ifelse([$3],,:,[$3])
|
||||
fi
|
||||
|
||||
unset _libcurl_with
|
||||
])
|
||||
@@ -0,0 +1,90 @@
|
||||
.\" generated by cd2nroff 0.1 from curl-config.md
|
||||
.TH curl-config 1 "2025-08-14" curl-config
|
||||
.SH NAME
|
||||
curl\-config \- Get information about a libcurl installation
|
||||
.SH SYNOPSIS
|
||||
\fBcurl\-config [options]\fP
|
||||
.SH DESCRIPTION
|
||||
\fBcurl\-config\fP
|
||||
displays information about the curl and libcurl installation.
|
||||
.SH OPTIONS
|
||||
.IP --ca
|
||||
Displays the built\-in path to the CA cert bundle this libcurl uses.
|
||||
.IP --cc
|
||||
Displays the compiler used to build libcurl.
|
||||
.IP --cflags
|
||||
Set of compiler options (CFLAGS) to use when compiling files that use
|
||||
libcurl. Currently that is only the include path to the curl include files.
|
||||
.IP "--checkfor [version]"
|
||||
Specify the oldest possible libcurl version string you want, and this script
|
||||
returns 0 if the current installation is new enough or it returns 1 and
|
||||
outputs a text saying that the current version is not new enough. (Added in
|
||||
7.15.4)
|
||||
.IP --configure
|
||||
Displays the arguments given to configure when building curl.
|
||||
.IP --feature
|
||||
Lists what particular main features the installed libcurl was built with. At
|
||||
the time of writing, this list may include SSL, KRB4 or IPv6. Do not assume
|
||||
any particular order. The keywords are separated by newlines. There may be
|
||||
none, one, or several keywords in the list.
|
||||
.IP --help
|
||||
Displays the available options.
|
||||
.IP --libs
|
||||
Shows the complete set of libs and other linker options you need in order to
|
||||
link your application with libcurl.
|
||||
.IP --prefix
|
||||
This is the prefix used when libcurl was installed. libcurl is then installed
|
||||
in $prefix/lib and its header files are installed in $prefix/include and so
|
||||
on. The prefix is set with \fIconfigure \--prefix\fP.
|
||||
.IP --protocols
|
||||
Lists what particular protocols the installed libcurl was built to support. At
|
||||
the time of writing, this list may include HTTP, HTTPS, FTP, FTPS, FILE,
|
||||
TELNET, LDAP, DICT and many more. Do not assume any particular order. The
|
||||
protocols are listed using uppercase and are separated by newlines. There may
|
||||
be none, one, or several protocols in the list. (Added in 7.13.0)
|
||||
.IP --ssl-backends
|
||||
Lists the SSL backends that were enabled when libcurl was built. It might be
|
||||
no, one or several names. If more than one name, they appear comma\-separated.
|
||||
(Added in 7.58.0)
|
||||
.IP --static-libs
|
||||
Shows the complete set of libs and other linker options you need in order to
|
||||
link your application with libcurl statically. (Added in 7.17.1)
|
||||
.IP --version
|
||||
Outputs version information about the installed libcurl.
|
||||
.IP --vernum
|
||||
Outputs version information about the installed libcurl, in numerical mode.
|
||||
This shows the version number, in hexadecimal, using 8 bits for each part:
|
||||
major, minor, and patch numbers. This makes libcurl 7.7.4 appear as 070704 and
|
||||
libcurl 12.13.14 appear as 0c0d0e... Note that the initial zero might be
|
||||
omitted. (This option was broken in the 7.15.0 release.)
|
||||
.SH EXAMPLES
|
||||
What linker options do I need when I link with libcurl?
|
||||
|
||||
.nf
|
||||
$ curl-config --libs
|
||||
.fi
|
||||
|
||||
What compiler options do I need when I compile using libcurl functions?
|
||||
|
||||
.nf
|
||||
$ curl-config --cflags
|
||||
.fi
|
||||
|
||||
How do I know if libcurl was built with SSL support?
|
||||
|
||||
.nf
|
||||
$ curl-config --feature | grep SSL
|
||||
.fi
|
||||
|
||||
What\(aqs the installed libcurl version?
|
||||
|
||||
.nf
|
||||
$ curl-config --version
|
||||
.fi
|
||||
|
||||
How do I build a single file with a one\-line command?
|
||||
|
||||
.nf
|
||||
$ `curl-config --cc --cflags` -o example source.c `curl-config --libs`
|
||||
.SH SEE ALSO
|
||||
.BR curl (1)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,111 @@
|
||||
.\" generated by cd2nroff 0.1 from wcurl.md
|
||||
.TH wcurl 1 "2025-08-14" wcurl
|
||||
.SH NAME
|
||||
\fBwcurl\fP \- a simple wrapper around curl to easily download files.
|
||||
.SH SYNOPSIS
|
||||
\fBwcurl <URL>...\fP
|
||||
|
||||
\fBwcurl [\--curl\-options <CURL_OPTIONS>]... [\--dry\-run] [\--no\-decode\-filename] [\-o|\-O|\--output <PATH>] [\--] <URL>...\fP
|
||||
|
||||
\fBwcurl [\--curl\-options=<CURL_OPTIONS>]... [\--dry\-run] [\--no\-decode\-filename] [\--output=<PATH>] [\--] <URL>...\fP
|
||||
|
||||
\fBwcurl \-V|\--version\fP
|
||||
|
||||
\fBwcurl \-h|\--help\fP
|
||||
.SH DESCRIPTION
|
||||
\fBwcurl\fP is a simple curl wrapper which lets you use curl to download files
|
||||
without having to remember any parameters.
|
||||
|
||||
Simply call \fBwcurl\fP with a list of URLs you want to download and \fBwcurl\fP
|
||||
picks sane defaults.
|
||||
|
||||
If you need anything more complex, you can provide any of curl\(aqs supported
|
||||
parameters via the \fB\--curl\-options\fP option. Just beware that you likely
|
||||
should be using curl directly if your use case is not covered.
|
||||
|
||||
By default, \fBwcurl\fP does:
|
||||
.IP "* Percent-encode whitespaces in URLs;"
|
||||
.IP "* Download multiple URLs in parallel"
|
||||
.nf
|
||||
if the installed curl's version is \>= 7.66.0 (--parallel);
|
||||
.fi
|
||||
.IP "* Follow redirects;"
|
||||
.IP "* Automatically choose a filename as output;"
|
||||
.IP "* Avoid overwriting files"
|
||||
.nf
|
||||
if the installed curl's version is \>= 7.83.0 (--no-clobber);
|
||||
.fi
|
||||
.IP "* Perform retries;"
|
||||
.IP "* Set the downloaded file timestamp"
|
||||
.nf
|
||||
to the value provided by the server, if available;
|
||||
.fi
|
||||
.IP "* Default to https"
|
||||
.nf
|
||||
if the URL does not contain any scheme;
|
||||
.fi
|
||||
.IP "* Disable curl's URL globbing parser"
|
||||
.nf
|
||||
so {} and [] characters in URLs are not treated specially;
|
||||
.fi
|
||||
.IP "* Percent-decode the resulting filename;"
|
||||
.IP "* Use 'index.html' as the default filename"
|
||||
.nf
|
||||
if there is none in the URL.
|
||||
.fi
|
||||
.SH OPTIONS
|
||||
.IP "--curl-options, --curl-options=\<CURL_OPTIONS\>..."
|
||||
Specify extra options to be passed when invoking curl. May be specified more
|
||||
than once.
|
||||
.IP "-o, -O, --output, --output=\<PATH\>"
|
||||
Use the provided output path instead of getting it from the URL. If multiple
|
||||
URLs are provided, resulting files share the same name with a number appended to
|
||||
the end (curl >= 7.83.0). If this option is provided multiple times, only the
|
||||
last value is considered.
|
||||
.IP --no-decode-filename
|
||||
Don\(aqt percent\-decode the output filename, even if the percent\-encoding in the
|
||||
URL was done by \fBwcurl\fP, e.g.: The URL contained whitespaces.
|
||||
.IP --dry-run
|
||||
Do not actually execute curl, just print what would be invoked.
|
||||
.IP "-V, \--version"
|
||||
Print version information.
|
||||
.IP "-h, \--help"
|
||||
Print help message.
|
||||
.SH CURL_OPTIONS
|
||||
Any option supported by curl can be set here. This is not used by \fBwcurl\fP; it
|
||||
is instead forwarded to the curl invocation.
|
||||
.SH URL
|
||||
URL to be downloaded. Anything that is not a parameter is considered
|
||||
an URL. Whitespaces are percent\-encoded and the URL is passed to curl, which
|
||||
then performs the parsing. May be specified more than once.
|
||||
.SH EXAMPLES
|
||||
Download a single file:
|
||||
|
||||
\fBwcurl example.com/filename.txt\fP
|
||||
|
||||
Download two files in parallel:
|
||||
|
||||
\fBwcurl example.com/filename1.txt example.com/filename2.txt\fP
|
||||
|
||||
Download a file passing the \fB\--progress\-bar\fP and \fB\--http2\fP flags to curl:
|
||||
|
||||
\fBwcurl \--curl\-options="\--progress\-bar \--http2" example.com/filename.txt\fP
|
||||
|
||||
Resume from an interrupted download (if more options are used, this needs to
|
||||
be the last one in the list):
|
||||
|
||||
\fBwcurl \--curl\-options="\--continue\-at \-" example.com/filename.txt\fP
|
||||
.SH AUTHORS
|
||||
.nf
|
||||
Samuel Henrique \<samueloph@debian.org\>
|
||||
Sergio Durigan Junior \<sergiodj@debian.org\>
|
||||
and many contributors, see the AUTHORS file.
|
||||
.fi
|
||||
.SH REPORTING BUGS
|
||||
If you experience any problems with \fBwcurl\fP that you do not experience with
|
||||
curl, submit an issue on Github: https://github.com/curl/wcurl
|
||||
.SH COPYRIGHT
|
||||
\fBwcurl\fP is licensed under the curl license
|
||||
.SH SEE ALSO
|
||||
.BR curl (1),
|
||||
.BR trurl (1)
|
||||
@@ -0,0 +1,66 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_ACTIVESOCKET.md
|
||||
.TH CURLINFO_ACTIVESOCKET 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_ACTIVESOCKET \- get the active socket
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_ACTIVESOCKET,
|
||||
curl_socket_t *socket);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a curl_socket_t to receive the most recently active socket
|
||||
used for the transfer connection by this curl session. If the socket is no
|
||||
longer valid, \fICURL_SOCKET_BAD\fP is returned. When you are finished working
|
||||
with the socket, you must call \fIcurl_easy_cleanup(3)\fP as usual on the easy
|
||||
handle and let libcurl close the socket and cleanup other resources associated
|
||||
with the handle. This option returns the active socket only after the transfer
|
||||
is complete, and is typically used in combination with
|
||||
\fICURLOPT_CONNECT_ONLY(3)\fP, which skips the transfer phase.
|
||||
|
||||
\fICURLINFO_ACTIVESOCKET(3)\fP was added as a replacement for
|
||||
\fICURLINFO_LASTSOCKET(3)\fP since that one is not working on all platforms.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_socket_t sockfd;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Do not do the transfer - only connect to host */
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
|
||||
res = curl_easy_perform(curl);
|
||||
if(res != CURLE_OK) {
|
||||
printf("Error: %s\\n", curl_easy_strerror(res));
|
||||
curl_easy_cleanup(curl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Extract the socket from the curl handle */
|
||||
res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd);
|
||||
if(!res && sockfd != CURL_SOCKET_BAD) {
|
||||
/* operate on sockfd */
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.45.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_LASTSOCKET (3),
|
||||
.BR CURLOPT_CONNECT_ONLY (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,55 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_APPCONNECT_TIME.md
|
||||
.TH CURLINFO_APPCONNECT_TIME 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_APPCONNECT_TIME \- get the time until the SSL/SSH handshake is completed
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_APPCONNECT_TIME,
|
||||
double *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a double to receive the time, in seconds, it took from the
|
||||
start until the SSL/SSH connect/handshake to the remote host was completed.
|
||||
This time is most often close to the \fICURLINFO_PRETRANSFER_TIME(3)\fP time, except
|
||||
for cases such as HTTP multiplexing where the pretransfer time can be delayed
|
||||
due to waits in line for the stream and more.
|
||||
|
||||
When a redirect is followed, the time from each request is added together.
|
||||
|
||||
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
double connect;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
res = curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &connect);
|
||||
if(CURLE_OK == res) {
|
||||
printf("Time: %.1f", connect);
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.19.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_APPCONNECT_TIME_T (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,56 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_APPCONNECT_TIME_T.md
|
||||
.TH CURLINFO_APPCONNECT_TIME_T 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_APPCONNECT_TIME_T \- time until the SSL/SSH handshake completed
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_APPCONNECT_TIME_T,
|
||||
curl_off_t *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a curl_off_t to receive the time, in microseconds, it took
|
||||
from the start until the SSL/SSH connect/handshake to the remote host was
|
||||
completed. This time is most often close to the \fICURLINFO_PRETRANSFER_TIME_T(3)\fP
|
||||
time, except for cases such as HTTP multiplexing where the pretransfer time
|
||||
can be delayed due to waits in line for the stream and more.
|
||||
|
||||
When a redirect is followed, the time from each request is added together.
|
||||
|
||||
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_off_t connect;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
res = curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME_T, &connect);
|
||||
if(CURLE_OK == res) {
|
||||
printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", connect / 1000000,
|
||||
(long)(connect % 1000000));
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.61.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_APPCONNECT_TIME (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,52 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_CAINFO.md
|
||||
.TH CURLINFO_CAINFO 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_CAINFO \- get the default built\-in CA certificate path
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CAINFO, char **path);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a char pointer to receive the pointer to a null\-terminated
|
||||
string holding the default built\-in path used for the \fICURLOPT_CAINFO(3)\fP
|
||||
option unless set by the user.
|
||||
|
||||
Note that in a situation where libcurl has been built to support multiple TLS
|
||||
libraries, this option might return a string even if the specific TLS library
|
||||
currently set to be used does not support \fICURLOPT_CAINFO(3)\fP.
|
||||
|
||||
This is a path identifying a single file containing CA certificates.
|
||||
|
||||
The \fBpath\fP pointer is set to NULL if there is no default path.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
|
||||
|
||||
All TLS backends support this option.
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
char *cainfo = NULL;
|
||||
curl_easy_getinfo(curl, CURLINFO_CAINFO, &cainfo);
|
||||
if(cainfo) {
|
||||
printf("default ca info path: %s\\n", cainfo);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.84.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_CAPATH (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,53 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_CAPATH.md
|
||||
.TH CURLINFO_CAPATH 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_CAPATH \- get the default built\-in CA path string
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CAPATH, char **path);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a char pointer to receive the pointer to a null\-terminated
|
||||
string holding the default built\-in path used for the \fICURLOPT_CAPATH(3)\fP
|
||||
option unless set by the user.
|
||||
|
||||
Note that in a situation where libcurl has been built to support multiple TLS
|
||||
libraries, this option might return a string even if the specific TLS library
|
||||
currently set to be used does not support \fICURLOPT_CAPATH(3)\fP.
|
||||
|
||||
This is a path identifying a directory.
|
||||
|
||||
The \fBpath\fP pointer is set to NULL if there is no default path.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
|
||||
|
||||
This option works only with the following TLS backends:
|
||||
GnuTLS, OpenSSL, mbedTLS and wolfSSL
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
char *capath = NULL;
|
||||
curl_easy_getinfo(curl, CURLINFO_CAPATH, &capath);
|
||||
if(capath) {
|
||||
printf("default ca path: %s\\n", capath);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.84.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_CAINFO (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,87 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_CERTINFO.md
|
||||
.TH CURLINFO_CERTINFO 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_CERTINFO \- get the TLS certificate chain
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CERTINFO,
|
||||
struct curl_certinfo **chainp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a \fIstruct curl_certinfo \fP* and it is set to point to a
|
||||
struct that holds info about the server\(aqs certificate chain, assuming you had
|
||||
\fICURLOPT_CERTINFO(3)\fP enabled when the request was made.
|
||||
|
||||
.nf
|
||||
struct curl_certinfo {
|
||||
int num_of_certs;
|
||||
struct curl_slist **certinfo;
|
||||
};
|
||||
.fi
|
||||
|
||||
The \fIcertinfo\fP struct member is an array of linked lists of certificate
|
||||
information. The \fInum_of_certs\fP struct member is the number of certificates
|
||||
which is the number of elements in the array. Each certificate\(aqs list has
|
||||
items with textual information in the format "name:content" such as
|
||||
\&"Subject:Foo", "Issuer:Bar", etc. The items in each list varies depending on
|
||||
the SSL backend and the certificate.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
|
||||
|
||||
This option works only with the following TLS backends:
|
||||
GnuTLS, OpenSSL, Schannel and rustls
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");
|
||||
|
||||
/* connect to any HTTPS site, trusted or not */
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
int i;
|
||||
struct curl_certinfo *ci;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &ci);
|
||||
|
||||
if(!res) {
|
||||
printf("%d certs!\\n", ci->num_of_certs);
|
||||
|
||||
for(i = 0; i < ci->num_of_certs; i++) {
|
||||
struct curl_slist *slist;
|
||||
|
||||
for(slist = ci->certinfo[i]; slist; slist = slist->next)
|
||||
printf("%s\\n", slist->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
|
||||
See also the \fIcertinfo.c\fP example.
|
||||
.SH HISTORY
|
||||
GnuTLS support added in 7.42.0. Schannel support added in 7.50.0. mbedTLS
|
||||
support added in 8.9.0.
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.19.1
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_CAPATH (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,64 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_CONDITION_UNMET.md
|
||||
.TH CURLINFO_CONDITION_UNMET 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_CONDITION_UNMET \- get info on unmet time conditional or 304 HTTP response.
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONDITION_UNMET,
|
||||
long *unmet);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the number 1 if the condition provided in
|
||||
the previous request did not match (see \fICURLOPT_TIMECONDITION(3)\fP). Alas,
|
||||
if this returns a 1 you know that the reason you did not get data in return is
|
||||
because it did not fulfill the condition. The long this argument points to
|
||||
gets a zero stored if the condition instead was met. This can also return 1 if
|
||||
the server responded with a 304 HTTP status code, for example after sending a
|
||||
custom "If\-Match\-*" header.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* January 1, 2020 is 1577833200 */
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEVALUE, 1577833200L);
|
||||
|
||||
/* If-Modified-Since the above time stamp */
|
||||
curl_easy_setopt(curl, CURLOPT_TIMECONDITION,
|
||||
(long)CURL_TIMECOND_IFMODSINCE);
|
||||
|
||||
/* Perform the request */
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
/* check the time condition */
|
||||
long unmet;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &unmet);
|
||||
if(!res) {
|
||||
printf("The time condition was %sfulfilled\\n", unmet?"NOT":"");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.19.4
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLOPT_TIMECONDITION (3),
|
||||
.BR CURLOPT_TIMEVALUE (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,51 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_CONNECT_TIME.md
|
||||
.TH CURLINFO_CONNECT_TIME 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_CONNECT_TIME \- get the time until connect
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONNECT_TIME, double *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a double to receive the total time in seconds from the start
|
||||
until the connection to the remote host (or proxy) was completed.
|
||||
|
||||
When a redirect is followed, the time from each request is added together.
|
||||
|
||||
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
double connect;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
res = curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &connect);
|
||||
if(CURLE_OK == res) {
|
||||
printf("Time: %.1f", connect);
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.4.1
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_CONNECT_TIME_T (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,54 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_CONNECT_TIME_T.md
|
||||
.TH CURLINFO_CONNECT_TIME_T 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_CONNECT_TIME_T \- get the time until connect
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONNECT_TIME_T,
|
||||
curl_off_t *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a curl_off_t to receive the total time in microseconds from
|
||||
the start until the connection to the remote host (or proxy) was completed.
|
||||
|
||||
When a redirect is followed, the time from each request is added together.
|
||||
|
||||
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_off_t connect;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
res = curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME_T, &connect);
|
||||
if(CURLE_OK == res) {
|
||||
printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", connect / 1000000,
|
||||
(long)(connect % 1000000));
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.61.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_CONNECT_TIME (3),
|
||||
.BR CURLOPT_CONNECTTIMEOUT (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,54 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_CONN_ID.md
|
||||
.TH CURLINFO_CONN_ID 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_CONN_ID \- get the ID of the last connection used by the handle
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONN_ID,
|
||||
curl_off_t *conn_id);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a \fIcurl_off_t\fP to receive the connection identifier last
|
||||
used by the handle. Stores \-1 if there was no connection used.
|
||||
|
||||
The connection id is unique among all connections using the same
|
||||
connection cache. This is implicitly the case for all connections in the
|
||||
same multi handle.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Perform the request */
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
curl_off_t conn_id;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_CONN_ID, &conn_id);
|
||||
if(!res) {
|
||||
printf("Connection used: %" CURL_FORMAT_CURL_OFF_T "\\n", conn_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 8.2.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_XFER_ID (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,56 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_CONTENT_LENGTH_DOWNLOAD.md
|
||||
.TH CURLINFO_CONTENT_LENGTH_DOWNLOAD 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_CONTENT_LENGTH_DOWNLOAD \- get content\-length of download
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
|
||||
double *content_length);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a double to receive the content\-length of the download. This
|
||||
is the value read from the Content\-Length: field. Since 7.19.4, this returns
|
||||
-1 if the size is not known.
|
||||
|
||||
\fICURLINFO_CONTENT_LENGTH_DOWNLOAD_T(3)\fP is a newer replacement that returns a more
|
||||
sensible variable type.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Perform the request */
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
/* check the size */
|
||||
double cl;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl);
|
||||
if(!res) {
|
||||
printf("Size: %.0f\\n", cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH DEPRECATED
|
||||
Deprecated since 7.55.0.
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.6.1
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_CONTENT_LENGTH_UPLOAD (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,51 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md
|
||||
.TH CURLINFO_CONTENT_LENGTH_DOWNLOAD_T 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_CONTENT_LENGTH_DOWNLOAD_T \- get content\-length of download
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,
|
||||
curl_off_t *content_length);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a \fIcurl_off_t\fP to receive the content\-length of the
|
||||
download. This is the value read from the Content\-Length: field. Stores \-1 if
|
||||
the size is not known.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Perform the request */
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
/* check the size */
|
||||
curl_off_t cl;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &cl);
|
||||
if(!res) {
|
||||
printf("Download size: %" CURL_FORMAT_CURL_OFF_T "\\n", cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.55.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_CONTENT_LENGTH_UPLOAD_T (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,55 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_CONTENT_LENGTH_UPLOAD.md
|
||||
.TH CURLINFO_CONTENT_LENGTH_UPLOAD 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_CONTENT_LENGTH_UPLOAD \- get the specified size of the upload
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_UPLOAD,
|
||||
double *content_length);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a double to receive the specified size of the upload. Since
|
||||
7.19.4, this returns \-1 if the size is not known.
|
||||
|
||||
\fICURLINFO_CONTENT_LENGTH_UPLOAD_T(3)\fP is a newer replacement that returns a
|
||||
more sensible variable type.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Perform the upload */
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
/* check the size */
|
||||
double cl;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_UPLOAD, &cl);
|
||||
if(!res) {
|
||||
printf("Size: %.0f\\n", cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH DEPRECATED
|
||||
Deprecated since 7.55.0.
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.6.1
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_CONTENT_LENGTH_DOWNLOAD_T (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,50 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_CONTENT_LENGTH_UPLOAD_T.md
|
||||
.TH CURLINFO_CONTENT_LENGTH_UPLOAD_T 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_CONTENT_LENGTH_UPLOAD_T \- get the specified size of the upload
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_UPLOAD_T,
|
||||
curl_off_t *content_length);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a \fIcurl_off_t\fP to receive the specified size of the
|
||||
upload. Stores \-1 if the size is not known.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Perform the upload */
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
/* check the size */
|
||||
curl_off_t cl;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_UPLOAD_T, &cl);
|
||||
if(!res) {
|
||||
printf("Upload size: %" CURL_FORMAT_CURL_OFF_T "\\n", cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.55.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_CONTENT_LENGTH_DOWNLOAD_T (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,59 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_CONTENT_TYPE.md
|
||||
.TH CURLINFO_CONTENT_TYPE 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_CONTENT_TYPE \- get Content\-Type
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_TYPE, char **ct);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a char pointer to receive the content\-type of the downloaded
|
||||
object. This is the value read from the Content\-Type: field. If you get NULL,
|
||||
it means that the server did not send a valid Content\-Type header or that the
|
||||
protocol used does not support this.
|
||||
|
||||
The \fBct\fP pointer is set to NULL or pointing to private memory. You MUST
|
||||
NOT free it \- it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the
|
||||
corresponding curl handle.
|
||||
|
||||
The modern way to get this header from a response is to instead use the
|
||||
\fIcurl_easy_header(3)\fP function.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
/* extract the content-type */
|
||||
char *ct = NULL;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
|
||||
if(!res && ct) {
|
||||
printf("Content-Type: %s\\n", ct);
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.9.4
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLOPT_HEADERFUNCTION (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_header (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,66 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_COOKIELIST.md
|
||||
.TH CURLINFO_COOKIELIST 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_COOKIELIST \- get all known cookies
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_COOKIELIST,
|
||||
struct curl_slist **cookies);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a \(aqstruct curl_slist *\(aq to receive a linked\-list of all
|
||||
cookies curl knows (expired ones, too). Do not forget to call
|
||||
\fIcurl_slist_free_all(3)\fP on the list after it has been used. If there are no
|
||||
cookies (cookies for the handle have not been enabled or simply none have been
|
||||
received) the \(aqstruct curl_slist *\(aq is made a NULL pointer.
|
||||
|
||||
Since 7.43.0 cookies that were imported in the Set\-Cookie format without a
|
||||
domain name are not exported by this option.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* enable the cookie engine */
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
/* extract all known cookies */
|
||||
struct curl_slist *cookies = NULL;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
|
||||
if(!res && cookies) {
|
||||
/* a linked list of cookies in cookie file format */
|
||||
struct curl_slist *each = cookies;
|
||||
while(each) {
|
||||
printf("%s\\n", each->data);
|
||||
each = each->next;
|
||||
}
|
||||
/* we must free these cookies when we are done */
|
||||
curl_slist_free_all(cookies);
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.14.1
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLOPT_COOKIELIST (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,61 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_EARLYDATA_SENT_T.md
|
||||
.TH CURLINFO_EARLYDATA_SENT_T 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_EARLYDATA_SENT_T \- get the number of bytes sent as TLS early data
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_EARLYDATA_SENT_T,
|
||||
curl_off_t *amount);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to an \fIcurl_off_t\fP to receive the total amount of bytes that
|
||||
were sent to the server as TLSv1.3 early data. When no TLS early
|
||||
data is used, this reports 0.
|
||||
|
||||
TLS early data is only attempted when CURLSSLOPT_EARLYDATA is set for the
|
||||
transfer. In addition, it is only used by libcurl when a TLS session exists
|
||||
that announces support.
|
||||
|
||||
The amount is \fBnegative\fP when the sent data was rejected
|
||||
by the server. TLS allows a server that announces support for early data to
|
||||
reject any attempt to use it at its own discretion. When for example 127
|
||||
bytes had been sent, but were rejected, it reports \-127 as the amount "sent".
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
|
||||
|
||||
This option works only with the following TLS backends:
|
||||
GnuTLS
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Perform the request */
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
curl_off_t amount;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_EARLYDATA_SENT_T, &amount);
|
||||
if(!res) {
|
||||
printf("TLS earlydata: %" CURL_FORMAT_CURL_OFF_T " bytes\\n", amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 8.11.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,56 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_EFFECTIVE_METHOD.md
|
||||
.TH CURLINFO_EFFECTIVE_METHOD 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_EFFECTIVE_METHOD \- get the last used HTTP method
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_EFFECTIVE_METHOD,
|
||||
char **methodp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass in a pointer to a char pointer and get the last used effective HTTP
|
||||
method.
|
||||
|
||||
In cases when you have asked libcurl to follow redirects, the method may not be
|
||||
the same method the first request would use.
|
||||
|
||||
The \fBmethodp\fP pointer is NULL or points to private memory. You MUST NOT
|
||||
free \- it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the
|
||||
corresponding curl handle.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "data");
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
char *method = NULL;
|
||||
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_METHOD, &method);
|
||||
if(method)
|
||||
printf("Redirected to method: %s\\n", method);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.72.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLOPT_CUSTOMREQUEST (3),
|
||||
.BR CURLOPT_FOLLOWLOCATION (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,52 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_EFFECTIVE_URL.md
|
||||
.TH CURLINFO_EFFECTIVE_URL 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_EFFECTIVE_URL \- get the last used URL
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_EFFECTIVE_URL, char **urlp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass in a pointer to a char pointer and get the last used effective URL.
|
||||
|
||||
In cases when you have asked libcurl to follow redirects, it may not be the same
|
||||
value you set with \fICURLOPT_URL(3)\fP.
|
||||
|
||||
The \fBurlp\fP pointer is NULL or points to private memory. You MUST NOT free
|
||||
- it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding curl
|
||||
handle.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
char *url = NULL;
|
||||
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
|
||||
if(url)
|
||||
printf("Redirect to: %s\\n", url);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.4
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLOPT_FOLLOWLOCATION (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,59 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_FILETIME.md
|
||||
.TH CURLINFO_FILETIME 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_FILETIME \- get the remote time of the retrieved document
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FILETIME, long *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the remote time of the retrieved document
|
||||
in number of seconds since January 1 1970 in the GMT/UTC time zone. If you get
|
||||
-1, it can be because of many reasons (it might be unknown, the server might
|
||||
hide it or the server does not support the command that tells document time
|
||||
etc) and the time of the document is unknown.
|
||||
|
||||
You must ask libcurl to collect this information before the transfer is made,
|
||||
by using the \fICURLOPT_FILETIME(3)\fP option or you unconditionally get a \-1 back.
|
||||
|
||||
Consider \fICURLINFO_FILETIME_T(3)\fP instead to be able to extract dates beyond the
|
||||
year 2038 on systems using 32\-bit longs (Windows).
|
||||
.SH PROTOCOLS
|
||||
This functionality affects ftp, http and sftp
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
/* Ask for filetime */
|
||||
curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
long filetime = 0;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
|
||||
if((CURLE_OK == res) && (filetime >= 0)) {
|
||||
time_t file_time = (time_t)filetime;
|
||||
printf("filetime: %s", ctime(&file_time));
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.5
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLOPT_FILETIME (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,60 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_FILETIME_T.md
|
||||
.TH CURLINFO_FILETIME_T 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_FILETIME_T \- get the remote time of the retrieved document
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FILETIME_T,
|
||||
curl_off_t *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a curl_off_t to receive the remote time of the retrieved
|
||||
document in number of seconds since January 1 1970 in the GMT/UTC time zone.
|
||||
If you get \-1, it can be because of many reasons (it might be unknown, the
|
||||
server might hide it or the server does not support the command that tells
|
||||
document time etc) and the time of the document is unknown.
|
||||
|
||||
You must ask libcurl to collect this information before the transfer is made,
|
||||
by using the \fICURLOPT_FILETIME(3)\fP option or you unconditionally get a \-1 back.
|
||||
|
||||
This option is an alternative to \fICURLINFO_FILETIME(3)\fP to allow systems with 32
|
||||
bit long variables to extract dates outside of the 32\-bit timestamp range.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects ftp, http and sftp
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
|
||||
/* Ask for filetime */
|
||||
curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
curl_off_t filetime;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_FILETIME_T, &filetime);
|
||||
if((CURLE_OK == res) && (filetime >= 0)) {
|
||||
time_t file_time = (time_t)filetime;
|
||||
printf("filetime: %s", ctime(&file_time));
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.59.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLOPT_FILETIME (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,56 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_FTP_ENTRY_PATH.md
|
||||
.TH CURLINFO_FTP_ENTRY_PATH 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_FTP_ENTRY_PATH \- get entry path in FTP server
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FTP_ENTRY_PATH, char **path);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a char pointer to receive a pointer to a string holding the
|
||||
path of the entry path. That is the initial path libcurl ended up in when
|
||||
logging on to the remote FTP server. This stores a NULL as pointer if
|
||||
something is wrong.
|
||||
|
||||
The \fBpath\fP pointer is NULL or points to private memory. You MUST NOT free
|
||||
- it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding curl
|
||||
handle.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects ftp only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com");
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
/* extract the entry path */
|
||||
char *ep = NULL;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_FTP_ENTRY_PATH, &ep);
|
||||
if(!res && ep) {
|
||||
printf("Entry path was: %s\\n", ep);
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH HISTORY
|
||||
Works for SFTP since 7.21.4
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.15.4
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,49 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_HEADER_SIZE.md
|
||||
.TH CURLINFO_HEADER_SIZE 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_HEADER_SIZE \- get size of retrieved headers
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HEADER_SIZE, long *sizep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the total size of all the headers
|
||||
received. Measured in number of bytes.
|
||||
|
||||
The total includes the size of any received headers suppressed by
|
||||
\fICURLOPT_SUPPRESS_CONNECT_HEADERS(3)\fP.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
long size;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &size);
|
||||
if(!res)
|
||||
printf("Header size: %ld bytes\\n", size);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.4.1
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_REQUEST_SIZE (3),
|
||||
.BR CURLINFO_SIZE_DOWNLOAD (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,59 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_HTTPAUTH_AVAIL.md
|
||||
.TH CURLINFO_HTTPAUTH_AVAIL 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_HTTPAUTH_AVAIL \- get available HTTP authentication methods
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTPAUTH_AVAIL, long *authp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive a bitmask indicating the authentication
|
||||
method(s) available according to the previous response. The meaning of the
|
||||
bits is explained in the \fICURLOPT_HTTPAUTH(3)\fP option for \fIcurl_easy_setopt(3)\fP.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
/* extract the available authentication types */
|
||||
long auth;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_HTTPAUTH_AVAIL, &auth);
|
||||
if(!res) {
|
||||
if(!auth)
|
||||
printf("No auth available, perhaps no 401?\\n");
|
||||
else {
|
||||
printf("%s%s%s%s\\n",
|
||||
auth & CURLAUTH_BASIC ? "Basic ":"",
|
||||
auth & CURLAUTH_DIGEST ? "Digest ":"",
|
||||
auth & CURLAUTH_NEGOTIATE ? "Negotiate ":"",
|
||||
auth % CURLAUTH_NTLM ? "NTLM ":"");
|
||||
}
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.10.8
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_PROXYAUTH_AVAIL (3),
|
||||
.BR CURLOPT_HTTPAUTH (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,61 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_HTTPAUTH_USED.md
|
||||
.TH CURLINFO_HTTPAUTH_USED 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_HTTPAUTH_USED \- get used HTTP authentication method
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTPAUTH_USED, long *authp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive a bitmask indicating the authentication
|
||||
method that was used in the previous HTTP request. The meaning of the possible
|
||||
bits is explained in the \fICURLOPT_HTTPAUTH(3)\fP option for \fIcurl_easy_setopt(3)\fP.
|
||||
|
||||
The returned value has zero or one bit set.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST);
|
||||
curl_easy_setopt(curl, CURLOPT_USERNAME, "shrek");
|
||||
curl_easy_setopt(curl, CURLOPT_PASSWORD, "swamp");
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
long auth;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_HTTPAUTH_USED, &auth);
|
||||
if(!res) {
|
||||
if(!auth)
|
||||
printf("No auth used\\n");
|
||||
else {
|
||||
if(auth == CURLAUTH_DIGEST)
|
||||
printf("Used Digest authentication\\n");
|
||||
else
|
||||
printf("Used Basic authentication\\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 8.12.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_HTTPAUTH_AVAIL (3),
|
||||
.BR CURLINFO_PROXYAUTH_USED (3),
|
||||
.BR CURLOPT_HTTPAUTH (3)
|
||||
@@ -0,0 +1,49 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_HTTP_CONNECTCODE.md
|
||||
.TH CURLINFO_HTTP_CONNECTCODE 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_HTTP_CONNECTCODE \- get the CONNECT response code
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTP_CONNECTCODE, long *p);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the last received HTTP proxy response code
|
||||
to a CONNECT request. The returned value is zero if no such response code was
|
||||
available.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* typically CONNECT is used to do HTTPS over HTTP proxies */
|
||||
curl_easy_setopt(curl, CURLOPT_PROXY, "http://127.0.0.1");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
long code;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_HTTP_CONNECTCODE, &code);
|
||||
if(!res && code)
|
||||
printf("The CONNECT response code: %03ld\\n", code);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.10.7
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_RESPONSE_CODE (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,45 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_HTTP_VERSION.md
|
||||
.TH CURLINFO_HTTP_VERSION 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_HTTP_VERSION \- get the http version used in the connection
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTP_VERSION, long *p);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the version used in the last http
|
||||
connection done using this handle. The returned value is
|
||||
CURL_HTTP_VERSION_1_0, CURL_HTTP_VERSION_1_1, CURL_HTTP_VERSION_2_0,
|
||||
CURL_HTTP_VERSION_3 or 0 if the version cannot be determined.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
long http_version;
|
||||
curl_easy_getinfo(curl, CURLINFO_HTTP_VERSION, &http_version);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.50.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_RESPONSE_CODE (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,66 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_LASTSOCKET.md
|
||||
.TH CURLINFO_LASTSOCKET 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_LASTSOCKET \- get the last socket used
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LASTSOCKET, long *socket);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Deprecated since 7.45.0. Use \fICURLINFO_ACTIVESOCKET(3)\fP instead.
|
||||
|
||||
Pass a pointer to a long to receive the last socket used by this curl
|
||||
session. If the socket is no longer valid, \-1 is returned. When you finish
|
||||
working with the socket, you must call \fIcurl_easy_cleanup(3)\fP as usual and
|
||||
let libcurl close the socket and cleanup other resources associated with the
|
||||
handle. This is typically used in combination with
|
||||
\fICURLOPT_CONNECT_ONLY(3)\fP.
|
||||
|
||||
NOTE: this API is deprecated since it is not working on win64 where the SOCKET
|
||||
type is 64 bits large while its \(aqlong\(aq is 32 bits. Use the
|
||||
\fICURLINFO_ACTIVESOCKET(3)\fP instead, if possible.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
long sockfd; /* does not work on win64 */
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Do not do the transfer - only connect to host */
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
|
||||
res = curl_easy_perform(curl);
|
||||
if(res != CURLE_OK) {
|
||||
printf("Error: %s\\n", curl_easy_strerror(res));
|
||||
curl_easy_cleanup(curl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Extract the socket from the curl handle */
|
||||
res = curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, &sockfd);
|
||||
if(!res && sockfd != -1) {
|
||||
/* operate on sockfd */
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.15.2
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_ACTIVESOCKET (3),
|
||||
.BR CURLOPT_CONNECT_ONLY (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,56 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_LOCAL_IP.md
|
||||
.TH CURLINFO_LOCAL_IP 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_LOCAL_IP \- get local IP address of last connection
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LOCAL_IP, char **ip);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a char pointer to receive the pointer to a null\-terminated
|
||||
string holding the IP address of the local end of most recent connection done
|
||||
with this \fBcurl\fP handle. This string may be IPv6 when that is enabled. Note
|
||||
that you get a pointer to a memory area that is reused at next request so you
|
||||
need to copy the string if you want to keep the information.
|
||||
|
||||
The \fBip\fP pointer is NULL or points to private memory. You MUST NOT free \- it
|
||||
gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding CURL
|
||||
handle.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects quic and tcp
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
char *ip;
|
||||
CURLcode res;
|
||||
CURL *curl = curl_easy_init();
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Perform the transfer */
|
||||
res = curl_easy_perform(curl);
|
||||
/* Check for errors */
|
||||
if((res == CURLE_OK) &&
|
||||
!curl_easy_getinfo(curl, CURLINFO_LOCAL_IP, &ip) && ip) {
|
||||
printf("Local IP: %s\\n", ip);
|
||||
}
|
||||
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.21.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_LOCAL_PORT (3),
|
||||
.BR CURLINFO_PRIMARY_IP (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,55 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_LOCAL_PORT.md
|
||||
.TH CURLINFO_LOCAL_PORT 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_LOCAL_PORT \- get the latest local port number
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LOCAL_PORT, long *portp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the local port number of the most recent
|
||||
connection done with this \fBcurl\fP handle.
|
||||
|
||||
If the connection was done using QUIC, the port number is a UDP port number,
|
||||
otherwise it is a TCP port number.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects quic and tcp
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(CURLE_OK == res) {
|
||||
long port;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_LOCAL_PORT, &port);
|
||||
|
||||
if(CURLE_OK == res) {
|
||||
printf("We used local port: %ld\\n", port);
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.21.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_LOCAL_IP (3),
|
||||
.BR CURLINFO_PRIMARY_PORT (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,52 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_NAMELOOKUP_TIME.md
|
||||
.TH CURLINFO_NAMELOOKUP_TIME 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_NAMELOOKUP_TIME \- get the name lookup time
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NAMELOOKUP_TIME,
|
||||
double *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a double to receive the total time in seconds from the start
|
||||
until the name resolving was completed.
|
||||
|
||||
When a redirect is followed, the time from each request is added together.
|
||||
|
||||
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
double namelookup;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
res = curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME, &namelookup);
|
||||
if(CURLE_OK == res) {
|
||||
printf("Time: %.1f", namelookup);
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.4.1
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_NAMELOOKUP_TIME_T (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,53 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_NAMELOOKUP_TIME_T.md
|
||||
.TH CURLINFO_NAMELOOKUP_TIME_T 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_NAMELOOKUP_TIME_T \- get the name lookup time in microseconds
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NAMELOOKUP_TIME_T,
|
||||
curl_off_t *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a curl_off_t to receive the total time in microseconds
|
||||
from the start until the name resolving was completed.
|
||||
|
||||
When a redirect is followed, the time from each request is added together.
|
||||
|
||||
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_off_t namelookup;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
res = curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME_T, &namelookup);
|
||||
if(CURLE_OK == res) {
|
||||
printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", namelookup / 1000000,
|
||||
(long)(namelookup % 1000000));
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.61.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_NAMELOOKUP_TIME (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,49 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_NUM_CONNECTS.md
|
||||
.TH CURLINFO_NUM_CONNECTS 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_NUM_CONNECTS \- get number of created connections
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NUM_CONNECTS, long *nump);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive how many new connections libcurl had to
|
||||
create to achieve the previous transfer (only the successful connects are
|
||||
counted). Combined with \fICURLINFO_REDIRECT_COUNT(3)\fP you are able to know how
|
||||
many times libcurl successfully reused existing connection(s) or not. See the
|
||||
connection options of \fIcurl_easy_setopt(3)\fP to see how libcurl tries to make
|
||||
persistent connections to save time.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
long connects;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_NUM_CONNECTS, &connects);
|
||||
if(!res)
|
||||
printf("It needed %ld connects\\n", connects);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.12.3
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,54 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_OS_ERRNO.md
|
||||
.TH CURLINFO_OS_ERRNO 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_OS_ERRNO \- get errno number from last connect failure
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_OS_ERRNO, long *errnop);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the errno variable from a connect failure.
|
||||
Note that the value is only set on failure, it is not reset upon a successful
|
||||
operation. The number is OS and system specific.
|
||||
|
||||
libcurl network\-related errors that may have a saved errno are:
|
||||
CURLE_COULDNT_CONNECT, CURLE_FAILED_INIT, CURLE_INTERFACE_FAILED,
|
||||
CURLE_OPERATION_TIMEDOUT, CURLE_RECV_ERROR, CURLE_SEND_ERROR.
|
||||
|
||||
Since 8.8.0 libcurl clears the easy handle\(aqs saved errno before performing the
|
||||
transfer. Prior versions did not clear the saved errno, which means if a saved
|
||||
errno is retrieved it could be from a previous transfer on the same handle.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res != CURLE_OK) {
|
||||
long error;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_OS_ERRNO, &error);
|
||||
if(!res && error) {
|
||||
printf("Errno: %ld\\n", error);
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.12.2
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,55 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_POSTTRANSFER_TIME_T.md
|
||||
.TH CURLINFO_POSTTRANSFER_TIME_T 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_POSTTRANSFER_TIME_T \- get the time until the last byte is sent
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_POSTTRANSFER_TIME_T,
|
||||
curl_off_t *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a curl_off_t to receive the time, in microseconds,
|
||||
it took from the start until the last byte is sent by libcurl.
|
||||
|
||||
When a redirect is followed, the time from each request is added together.
|
||||
|
||||
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
curl_off_t posttransfer;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_POSTTRANSFER_TIME_T,
|
||||
&posttransfer);
|
||||
if(CURLE_OK == res) {
|
||||
printf("Request sent after: %" CURL_FORMAT_CURL_OFF_T ".%06ld us",
|
||||
posttransfer / 1000000, (long)(posttransfer % 1000000));
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 8.10.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_PRETRANSFER_TIME_T (3),
|
||||
.BR CURLOPT_TIMEOUT (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,57 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_PRETRANSFER_TIME.md
|
||||
.TH CURLINFO_PRETRANSFER_TIME 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_PRETRANSFER_TIME \- get the time until the file transfer start
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRETRANSFER_TIME,
|
||||
double *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a double to receive the time, in seconds, it took from the
|
||||
start until the file transfer is just about to begin.
|
||||
|
||||
This time\-stamp includes all pre\-transfer commands and negotiations that are
|
||||
specific to the particular protocol(s) involved. It includes the sending of
|
||||
the protocol\-specific instructions that trigger a transfer.
|
||||
|
||||
When a redirect is followed, the time from each request is added together.
|
||||
|
||||
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
double pretransfer;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
res = curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &pretransfer);
|
||||
if(CURLE_OK == res) {
|
||||
printf("Time: %.1f", pretransfer);
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.4.1
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_CONNECT_TIME_T (3),
|
||||
.BR CURLINFO_PRETRANSFER_TIME_T (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,59 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_PRETRANSFER_TIME_T.md
|
||||
.TH CURLINFO_PRETRANSFER_TIME_T 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_PRETRANSFER_TIME_T \- get the time until the file transfer start
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRETRANSFER_TIME_T,
|
||||
curl_off_t *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a curl_off_t to receive the time, in microseconds, it took
|
||||
from the start until the file transfer is just about to begin.
|
||||
|
||||
This time\-stamp includes all pre\-transfer commands and negotiations that are
|
||||
specific to the particular protocol(s) involved. It includes the sending of
|
||||
the protocol\-specific instructions that trigger a transfer.
|
||||
|
||||
When a redirect is followed, the time from each request is added together.
|
||||
|
||||
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_off_t pretransfer;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
res = curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME_T, &pretransfer);
|
||||
if(CURLE_OK == res) {
|
||||
printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld\\n",
|
||||
pretransfer / 1000000,
|
||||
(long)(pretransfer % 1000000));
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.61.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_CONNECT_TIME (3),
|
||||
.BR CURLINFO_PRETRANSFER_TIME_T (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,57 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_PRIMARY_IP.md
|
||||
.TH CURLINFO_PRIMARY_IP 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_PRIMARY_IP \- get IP address of last connection
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIMARY_IP, char **ip);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a char pointer to receive the pointer to a null\-terminated
|
||||
string holding the IP address of the most recent connection done with this
|
||||
\fBcurl\fP handle. This string may be IPv6 when that is enabled. Note that you
|
||||
get a pointer to a memory area that is reused at next request so you need to
|
||||
copy the string if you want to keep the information.
|
||||
|
||||
The \fBip\fP pointer is NULL or points to private memory. You MUST NOT free \- it
|
||||
gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding curl
|
||||
handle.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
char *ip;
|
||||
CURLcode res;
|
||||
CURL *curl = curl_easy_init();
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Perform the transfer */
|
||||
res = curl_easy_perform(curl);
|
||||
/* Check for errors */
|
||||
if((res == CURLE_OK) &&
|
||||
!curl_easy_getinfo(curl, CURLINFO_PRIMARY_IP, &ip) && ip) {
|
||||
printf("IP: %s\\n", ip);
|
||||
}
|
||||
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.19.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_LOCAL_IP (3),
|
||||
.BR CURLINFO_LOCAL_PORT (3),
|
||||
.BR CURLINFO_PRIMARY_PORT (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,51 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_PRIMARY_PORT.md
|
||||
.TH CURLINFO_PRIMARY_PORT 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_PRIMARY_PORT \- get the latest destination port number
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIMARY_PORT, long *portp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the destination port of the most recent
|
||||
connection done with this \fBcurl\fP handle.
|
||||
|
||||
This is the destination port of the actual TCP or UDP connection libcurl used.
|
||||
If a proxy was used for the most recent transfer, this is the port number of
|
||||
the proxy, if no proxy was used it is the port number of the most recently
|
||||
accessed URL.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
long port;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_PRIMARY_PORT, &port);
|
||||
if(!res)
|
||||
printf("Connected to remote port: %ld\\n", port);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.21.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_LOCAL_PORT (3),
|
||||
.BR CURLINFO_PRIMARY_IP (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,52 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_PRIVATE.md
|
||||
.TH CURLINFO_PRIVATE 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_PRIVATE \- get the private pointer
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIVATE, char **private);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a char pointer to receive the pointer to the private data
|
||||
associated with the curl handle (set with the \fICURLOPT_PRIVATE(3)\fP).
|
||||
Please note that for internal reasons, the value is returned as a char
|
||||
pointer, although effectively being a \(aqvoid *\(aq.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
void *pointer = (void *)0x2345454;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
|
||||
|
||||
/* set the private pointer */
|
||||
curl_easy_setopt(curl, CURLOPT_PRIVATE, pointer);
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
/* extract the private pointer again */
|
||||
res = curl_easy_getinfo(curl, CURLINFO_PRIVATE, &pointer);
|
||||
|
||||
if(res)
|
||||
printf("error: %s\\n", curl_easy_strerror(res));
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.10.3
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLOPT_PRIVATE (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,59 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_PROTOCOL.md
|
||||
.TH CURLINFO_PROTOCOL 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_PROTOCOL \- get the protocol used in the connection
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROTOCOL, long *p);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
This option is deprecated. We strongly recommend using
|
||||
\fICURLINFO_SCHEME(3)\fP instead, because this option cannot return all
|
||||
possible protocols.
|
||||
|
||||
Pass a pointer to a long to receive the version used in the last http
|
||||
connection. The returned value is set to one of these values:
|
||||
|
||||
.nf
|
||||
CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_FTP, CURLPROTO_FTPS,
|
||||
CURLPROTO_GOPHER, CURLPROTO_HTTP, CURLPROTO_HTTPS, CURLPROTO_IMAP,
|
||||
CURLPROTO_IMAPS, CURLPROTO_LDAP, CURLPROTO_LDAPS, CURLPROTO_POP3,
|
||||
CURLPROTO_POP3S, CURLPROTO_RTMP, CURLPROTO_RTMPE, CURLPROTO_RTMPS,
|
||||
CURLPROTO_RTMPT, CURLPROTO_RTMPTE, CURLPROTO_RTMPTS, CURLPROTO_RTSP,
|
||||
CURLPROTO_SCP, CURLPROTO_SFTP, CURLPROTO_SMB, CURLPROTO_SMBS, CURLPROTO_SMTP,
|
||||
CURLPROTO_SMTPS, CURLPROTO_TELNET, CURLPROTO_TFTP, CURLPROTO_MQTT
|
||||
.fi
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
long protocol;
|
||||
curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH DEPRECATED
|
||||
Deprecated since 7.85.0.
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.52.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_RESPONSE_CODE (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,60 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_PROXYAUTH_AVAIL.md
|
||||
.TH CURLINFO_PROXYAUTH_AVAIL 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_PROXYAUTH_AVAIL \- get available HTTP proxy authentication methods
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXYAUTH_AVAIL,
|
||||
long *authp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive a bitmask indicating the authentication
|
||||
method(s) available according to the previous response. The meaning of the
|
||||
bits is explained in the \fICURLOPT_PROXYAUTH(3)\fP option for \fIcurl_easy_setopt(3)\fP.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
curl_easy_setopt(curl, CURLOPT_PROXY, "http://127.0.0.1:80");
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
/* extract the available proxy authentication types */
|
||||
long auth;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_PROXYAUTH_AVAIL, &auth);
|
||||
if(!res) {
|
||||
if(!auth)
|
||||
printf("No proxy auth available, perhaps no 407?\\n");
|
||||
else {
|
||||
printf("%s%s%s%s\\n",
|
||||
auth & CURLAUTH_BASIC ? "Basic ":"",
|
||||
auth & CURLAUTH_DIGEST ? "Digest ":"",
|
||||
auth & CURLAUTH_NEGOTIATE ? "Negotiate ":"",
|
||||
auth % CURLAUTH_NTLM ? "NTLM ":"");
|
||||
}
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.10.8
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_HTTPAUTH_AVAIL (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,64 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_PROXYAUTH_USED.md
|
||||
.TH CURLINFO_PROXYAUTH_USED 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_PROXYAUTH_USED \- get used HTTP proxy authentication method
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXYAUTH_USED, long *authp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive a bitmask indicating the authentication
|
||||
method that was used in the previous request done over an HTTP proxy. The
|
||||
meaning of the possible bits is explained in the \fICURLOPT_HTTPAUTH(3)\fP option
|
||||
for \fIcurl_easy_setopt(3)\fP.
|
||||
|
||||
The returned value has zero or one bit set.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.example.com");
|
||||
curl_easy_setopt(curl, CURLOPT_PROXYAUTH,
|
||||
CURLAUTH_BASIC | CURLAUTH_DIGEST);
|
||||
curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, "shrek");
|
||||
curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, "swamp");
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
long auth;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_PROXYAUTH_USED, &auth);
|
||||
if(!res) {
|
||||
if(!auth)
|
||||
printf("No auth used\\n");
|
||||
else {
|
||||
if(auth == CURLAUTH_DIGEST)
|
||||
printf("Used Digest proxy authentication\\n");
|
||||
else
|
||||
printf("Used Basic proxy authentication\\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 8.12.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_HTTPAUTH_USED (3),
|
||||
.BR CURLINFO_PROXYAUTH_AVAIL (3),
|
||||
.BR CURLOPT_HTTPAUTH (3)
|
||||
@@ -0,0 +1,89 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_PROXY_ERROR.md
|
||||
.TH CURLINFO_PROXY_ERROR 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_PROXY_ERROR \- get the detailed (SOCKS) proxy error
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
typedef enum {
|
||||
CURLPX_OK,
|
||||
CURLPX_BAD_ADDRESS_TYPE,
|
||||
CURLPX_BAD_VERSION,
|
||||
CURLPX_CLOSED,
|
||||
CURLPX_GSSAPI,
|
||||
CURLPX_GSSAPI_PERMSG,
|
||||
CURLPX_GSSAPI_PROTECTION,
|
||||
CURLPX_IDENTD,
|
||||
CURLPX_IDENTD_DIFFER,
|
||||
CURLPX_LONG_HOSTNAME,
|
||||
CURLPX_LONG_PASSWD,
|
||||
CURLPX_LONG_USER,
|
||||
CURLPX_NO_AUTH,
|
||||
CURLPX_RECV_ADDRESS,
|
||||
CURLPX_RECV_AUTH,
|
||||
CURLPX_RECV_CONNECT,
|
||||
CURLPX_RECV_REQACK,
|
||||
CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED,
|
||||
CURLPX_REPLY_COMMAND_NOT_SUPPORTED,
|
||||
CURLPX_REPLY_CONNECTION_REFUSED,
|
||||
CURLPX_REPLY_GENERAL_SERVER_FAILURE,
|
||||
CURLPX_REPLY_HOST_UNREACHABLE,
|
||||
CURLPX_REPLY_NETWORK_UNREACHABLE,
|
||||
CURLPX_REPLY_NOT_ALLOWED,
|
||||
CURLPX_REPLY_TTL_EXPIRED,
|
||||
CURLPX_REPLY_UNASSIGNED,
|
||||
CURLPX_REQUEST_FAILED,
|
||||
CURLPX_RESOLVE_HOST,
|
||||
CURLPX_SEND_AUTH,
|
||||
CURLPX_SEND_CONNECT,
|
||||
CURLPX_SEND_REQUEST,
|
||||
CURLPX_UNKNOWN_FAIL,
|
||||
CURLPX_UNKNOWN_MODE,
|
||||
CURLPX_USER_REJECTED,
|
||||
CURLPX_LAST /* never use */
|
||||
} CURLproxycode;
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXY_ERROR, long *detail);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive a detailed error code when the most recent
|
||||
transfer returned a \fBCURLE_PROXY\fP error. That error code matches the
|
||||
\fBCURLproxycode\fP set.
|
||||
|
||||
The error code is zero (\fBCURLPX_OK\fP) if no response code was available.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://127.0.0.1");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_PROXY) {
|
||||
long proxycode;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_PROXY_ERROR, &proxycode);
|
||||
if(!res && proxycode)
|
||||
printf("The detailed proxy error: %ld\\n", proxycode);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.73.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_RESPONSE_CODE (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3),
|
||||
.BR libcurl-errors (3)
|
||||
@@ -0,0 +1,62 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_PROXY_SSL_VERIFYRESULT.md
|
||||
.TH CURLINFO_PROXY_SSL_VERIFYRESULT 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_PROXY_SSL_VERIFYRESULT \- get the result of the proxy certificate verification
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXY_SSL_VERIFYRESULT,
|
||||
long *result);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the result of the certificate verification
|
||||
that was requested (using the \fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP
|
||||
option. This is only used for HTTPS proxies.
|
||||
|
||||
0 is a positive result. Non\-zero is an error.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
|
||||
|
||||
This option works only with the following TLS backends:
|
||||
GnuTLS and OpenSSL
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
long verifyresult;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy:443");
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
if(res) {
|
||||
printf("error: %s\\n", curl_easy_strerror(res));
|
||||
curl_easy_cleanup(curl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = curl_easy_getinfo(curl, CURLINFO_PROXY_SSL_VERIFYRESULT,
|
||||
&verifyresult);
|
||||
if(!res) {
|
||||
printf("The peer verification said %s\\n",
|
||||
(verifyresult ? "bad" : "fine"));
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.52.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_SSL_VERIFYRESULT (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,54 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_QUEUE_TIME_T.md
|
||||
.TH CURLINFO_QUEUE_TIME_T 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_QUEUE_TIME_T \- time this transfer was queued
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_QUEUE_TIME_T,
|
||||
curl_off_t *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a curl_off_t to receive the time, in microseconds, this
|
||||
transfer was held in a waiting queue before it started "for real". A transfer
|
||||
might be put in a queue if after getting started, it cannot create a new
|
||||
connection etc due to set conditions and limits imposed by the application.
|
||||
|
||||
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_off_t queue;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
res = curl_easy_getinfo(curl, CURLINFO_QUEUE_TIME_T, &queue);
|
||||
if(CURLE_OK == res) {
|
||||
printf("Queued: %" CURL_FORMAT_CURL_OFF_T ".%06ld us", queue / 1000000,
|
||||
(long)(queue % 1000000));
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 8.6.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_STARTTRANSFER_TIME_T (3),
|
||||
.BR CURLOPT_TIMEOUT (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,46 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_REDIRECT_COUNT.md
|
||||
.TH CURLINFO_REDIRECT_COUNT 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_REDIRECT_COUNT \- get the number of redirects
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_COUNT,
|
||||
long *countp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the total number of redirections that were
|
||||
actually followed.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
long redirects;
|
||||
curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &redirects);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.9.7
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_REDIRECT_URL (3),
|
||||
.BR CURLOPT_FOLLOWLOCATION (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,54 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_REDIRECT_TIME.md
|
||||
.TH CURLINFO_REDIRECT_TIME 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_REDIRECT_TIME \- get the time for all redirection steps
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_TIME,
|
||||
double *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a double to receive the total time, in seconds, it took for
|
||||
all redirection steps include name lookup, connect, pretransfer and transfer
|
||||
before final transaction was started. \fICURLINFO_REDIRECT_TIME(3)\fP contains
|
||||
the complete execution time for multiple redirections.
|
||||
|
||||
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
double redirect;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
res = curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME, &redirect);
|
||||
if(CURLE_OK == res) {
|
||||
printf("Time: %.1f", redirect);
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.9.7
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_REDIRECT_COUNT (3),
|
||||
.BR CURLINFO_REDIRECT_TIME_T (3),
|
||||
.BR CURLINFO_REDIRECT_URL (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,56 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_REDIRECT_TIME_T.md
|
||||
.TH CURLINFO_REDIRECT_TIME_T 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_REDIRECT_TIME_T \- get the time for all redirection steps
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_TIME_T,
|
||||
curl_off_t *timep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a curl_off_t to receive the total time, in microseconds, it
|
||||
took for all redirection steps include name lookup, connect, pretransfer and
|
||||
transfer before final transaction was started.
|
||||
\fICURLINFO_REDIRECT_TIME_T(3)\fP holds the complete execution time for
|
||||
multiple redirections.
|
||||
|
||||
See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_off_t redirect;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(CURLE_OK == res) {
|
||||
res = curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME_T, &redirect);
|
||||
if(CURLE_OK == res) {
|
||||
printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", redirect / 1000000,
|
||||
(long)(redirect % 1000000));
|
||||
}
|
||||
}
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.61.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_REDIRECT_COUNT (3),
|
||||
.BR CURLINFO_REDIRECT_TIME (3),
|
||||
.BR CURLINFO_REDIRECT_URL (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,53 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_REDIRECT_URL.md
|
||||
.TH CURLINFO_REDIRECT_URL 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_REDIRECT_URL \- get the URL a redirect would go to
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_URL, char **urlp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a char pointer to receive the URL a redirect \fIwould\fP take
|
||||
you to if you would enable \fICURLOPT_FOLLOWLOCATION(3)\fP. This can come handy if
|
||||
you think using the built\-in libcurl redirect logic is not good enough for you
|
||||
but you would still prefer to avoid implementing all the magic of figuring out
|
||||
the new URL.
|
||||
|
||||
This URL is also set if the \fICURLOPT_MAXREDIRS(3)\fP limit prevented a redirect to
|
||||
happen (since 7.54.1).
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
char *url = NULL;
|
||||
curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &url);
|
||||
if(url)
|
||||
printf("Redirect to: %s\\n", url);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.18.2
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_REDIRECT_COUNT (3),
|
||||
.BR CURLINFO_REDIRECT_TIME_T (3),
|
||||
.BR CURLOPT_FOLLOWLOCATION (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,51 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_REFERER.md
|
||||
.TH CURLINFO_REFERER 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_REFERER \- get the used referrer request header
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REFERER, char **hdrp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass in a pointer to a char pointer and get the referrer header used in the
|
||||
most recent request.
|
||||
|
||||
The \fBhdrp\fP pointer is NULL or points to private memory you MUST NOT free \-
|
||||
it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding curl
|
||||
handle.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects http only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
curl_easy_setopt(curl, CURLOPT_REFERER, "https://example.org/referrer");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
char *hdr = NULL;
|
||||
curl_easy_getinfo(curl, CURLINFO_REFERER, &hdr);
|
||||
if(hdr)
|
||||
printf("Referrer header: %s\\n", hdr);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.76.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLOPT_REFERER (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_header (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,47 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_REQUEST_SIZE.md
|
||||
.TH CURLINFO_REQUEST_SIZE 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_REQUEST_SIZE \- get size of sent request
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REQUEST_SIZE, long *sizep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the total size of the issued
|
||||
requests. This is so far only for HTTP requests. Note that this may be more
|
||||
than one request if \fICURLOPT_FOLLOWLOCATION(3)\fP is enabled.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
long req;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &req);
|
||||
if(!res)
|
||||
printf("Request size: %ld bytes\\n", req);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.4.1
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_HEADER_SIZE (3),
|
||||
.BR CURLINFO_SIZE_DOWNLOAD_T (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,51 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_RESPONSE_CODE.md
|
||||
.TH CURLINFO_RESPONSE_CODE 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_RESPONSE_CODE \- get the last response code
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RESPONSE_CODE, long *codep);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the last received HTTP, FTP, SMTP or LDAP
|
||||
(OpenLDAP only) response code. This option was previously known as
|
||||
CURLINFO_HTTP_CODE in libcurl 7.10.7 and earlier. The stored value is zero if
|
||||
no server response code has been received.
|
||||
|
||||
Note that a proxy\(aqs CONNECT response should be read with
|
||||
\fICURLINFO_HTTP_CONNECTCODE(3)\fP and not this.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects ftp, http, ldap and smtp
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
long response_code;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH NOTES
|
||||
The former name, CURLINFO_HTTP_CODE, was added in 7.4.1. Support for SMTP
|
||||
responses added in 7.25.0, for OpenLDAP in 7.81.0.
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.10.8
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_HTTP_CONNECTCODE (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,58 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_RETRY_AFTER.md
|
||||
.TH CURLINFO_RETRY_AFTER 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_RETRY_AFTER \- returns the Retry\-After retry delay
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RETRY_AFTER,
|
||||
curl_off_t *retry);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a curl_off_t variable to receive the number of seconds the
|
||||
HTTP server suggests the client should wait until the next request is
|
||||
issued. The information from the "Retry\-After:" header.
|
||||
|
||||
While the HTTP header might contain a fixed date string, the
|
||||
\fICURLINFO_RETRY_AFTER(3)\fP always returns the number of seconds to wait \-
|
||||
or zero if there was no header or the header could not be parsed.
|
||||
|
||||
This option used to return a negative wait time if the server provided a date
|
||||
in the past. Since 8.12.0, a negative wait time is returned as zero. In any
|
||||
case we recommend checking that the wait time is within an acceptable range for
|
||||
your circumstance.
|
||||
.SH DEFAULT
|
||||
Zero if there was no header.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
curl_off_t wait = 0;
|
||||
curl_easy_getinfo(curl, CURLINFO_RETRY_AFTER, &wait);
|
||||
if(wait)
|
||||
printf("Wait for %" CURL_FORMAT_CURL_OFF_T " seconds\\n", wait);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.66.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLOPT_HEADERFUNCTION (3),
|
||||
.BR CURLOPT_STDERR (3),
|
||||
.BR curl_easy_header (3)
|
||||
@@ -0,0 +1,45 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_RTSP_CLIENT_CSEQ.md
|
||||
.TH CURLINFO_RTSP_CLIENT_CSEQ 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_RTSP_CLIENT_CSEQ \- get the next RTSP client CSeq
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_CLIENT_CSEQ,
|
||||
long *cseq);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the next CSeq that is expected to be used
|
||||
by the application.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects rtsp only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
long cseq;
|
||||
curl_easy_getinfo(curl, CURLINFO_RTSP_CLIENT_CSEQ, &cseq);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.20.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_RTSP_CSEQ_RECV (3),
|
||||
.BR CURLINFO_RTSP_SERVER_CSEQ (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,45 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_RTSP_CSEQ_RECV.md
|
||||
.TH CURLINFO_RTSP_CSEQ_RECV 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_RTSP_CSEQ_RECV \- get the recently received CSeq
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_CSEQ_RECV, long *cseq);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the most recently received CSeq from the
|
||||
server. If your application encounters a \fICURLE_RTSP_CSEQ_ERROR\fP then you
|
||||
may wish to troubleshoot and/or fix the CSeq mismatch by peeking at this
|
||||
value.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects rtsp only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
long cseq;
|
||||
curl_easy_getinfo(curl, CURLINFO_RTSP_CSEQ_RECV, &cseq);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.20.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_RTSP_SERVER_CSEQ (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,49 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_RTSP_SERVER_CSEQ.md
|
||||
.TH CURLINFO_RTSP_SERVER_CSEQ 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_RTSP_SERVER_CSEQ \- get the next RTSP server CSeq
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_SERVER_CSEQ,
|
||||
long *cseq);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a long to receive the next CSeq that is expected to be used
|
||||
by the application.
|
||||
|
||||
Listening for server initiated requests is not implemented.
|
||||
|
||||
Applications wishing to resume an RTSP session on another connection should
|
||||
retrieve this info before closing the active connection.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects rtsp only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
long cseq;
|
||||
curl_easy_getinfo(curl, CURLINFO_RTSP_SERVER_CSEQ, &cseq);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.20.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_RTSP_CSEQ_RECV (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,50 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_RTSP_SESSION_ID.md
|
||||
.TH CURLINFO_RTSP_SESSION_ID 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_RTSP_SESSION_ID \- get RTSP session ID
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_SESSION_ID, char **id);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a char pointer to receive a pointer to a string holding the
|
||||
most recent RTSP Session ID.
|
||||
|
||||
Applications wishing to resume an RTSP session on another connection should
|
||||
retrieve this info before closing the active connection.
|
||||
|
||||
The \fBid\fP pointer is NULL or points to private memory. You MUST NOT free \- it
|
||||
gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding curl
|
||||
handle.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects rtsp only
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
char *id;
|
||||
curl_easy_getinfo(curl, CURLINFO_RTSP_SESSION_ID, &id);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.20.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_RTSP_CSEQ_RECV (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,55 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_SCHEME.md
|
||||
.TH CURLINFO_SCHEME 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_SCHEME \- get the URL scheme (sometimes called protocol) used in the connection
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SCHEME, char **scheme);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a char pointer to receive the pointer to a null\-terminated
|
||||
string holding the URL scheme used for the most recent connection done with
|
||||
this CURL \fBhandle\fP.
|
||||
|
||||
The \fBscheme\fP pointer is NULL or points to private memory. You MUST NOT
|
||||
free \- it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding
|
||||
curl handle.
|
||||
|
||||
The returned scheme might be upper or lowercase. Do comparisons case
|
||||
insensitively.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
res = curl_easy_perform(curl);
|
||||
if(res == CURLE_OK) {
|
||||
char *scheme = NULL;
|
||||
curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme);
|
||||
if(scheme)
|
||||
printf("scheme: %s\\n", scheme); /* scheme: HTTP */
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.52.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_EFFECTIVE_URL (3),
|
||||
.BR CURLINFO_PROTOCOL (3),
|
||||
.BR CURLINFO_RESPONSE_CODE (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,59 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_SIZE_DOWNLOAD.md
|
||||
.TH CURLINFO_SIZE_DOWNLOAD 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_SIZE_DOWNLOAD \- get the number of downloaded bytes
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DOWNLOAD, double *dlp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a double to receive the total amount of bytes that were
|
||||
downloaded. The amount is only for the latest transfer and gets reset again
|
||||
for each new transfer. This counts actual payload data, what\(aqs also commonly
|
||||
called body. All meta and header data is excluded and not included in this
|
||||
number.
|
||||
|
||||
\fICURLINFO_SIZE_DOWNLOAD_T(3)\fP is a newer replacement that returns a more
|
||||
sensible variable type.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Perform the request */
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
/* check the size */
|
||||
double dl;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &dl);
|
||||
if(!res) {
|
||||
printf("Downloaded %.0f bytes\\n", dl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH DEPRECATED
|
||||
Deprecated since 7.55.0.
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.4.1
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_setopt(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_SIZE_DOWNLOAD_T (3),
|
||||
.BR CURLINFO_SIZE_UPLOAD_T (3),
|
||||
.BR CURLOPT_MAXFILESIZE (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,54 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_SIZE_DOWNLOAD_T.md
|
||||
.TH CURLINFO_SIZE_DOWNLOAD_T 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_SIZE_DOWNLOAD_T \- get the number of downloaded bytes
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DOWNLOAD_T,
|
||||
curl_off_t *dlp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a \fIcurl_off_t\fP to receive the total amount of bytes that
|
||||
were downloaded. The amount is only for the latest transfer and gets reset
|
||||
again for each new transfer. This counts actual payload data, what\(aqs also
|
||||
commonly called body. All meta and header data is excluded from this amount.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Perform the request */
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
/* check the size */
|
||||
curl_off_t dl;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD_T, &dl);
|
||||
if(!res) {
|
||||
printf("Downloaded %" CURL_FORMAT_CURL_OFF_T " bytes\\n", dl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.55.0
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_setopt(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_SIZE_DOWNLOAD (3),
|
||||
.BR CURLINFO_SIZE_UPLOAD_T (3),
|
||||
.BR CURLOPT_MAXFILESIZE (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
@@ -0,0 +1,55 @@
|
||||
.\" generated by cd2nroff 0.1 from CURLINFO_SIZE_UPLOAD.md
|
||||
.TH CURLINFO_SIZE_UPLOAD 3 "2025-08-14" libcurl
|
||||
.SH NAME
|
||||
CURLINFO_SIZE_UPLOAD \- get the number of uploaded bytes
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_UPLOAD,
|
||||
double *uploadp);
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Pass a pointer to a double to receive the total amount of bytes that were
|
||||
uploaded.
|
||||
|
||||
\fICURLINFO_SIZE_UPLOAD_T(3)\fP is a newer replacement that returns a more
|
||||
sensible variable type.
|
||||
.SH PROTOCOLS
|
||||
This functionality affects all supported protocols
|
||||
.SH EXAMPLE
|
||||
.nf
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl = curl_easy_init();
|
||||
if(curl) {
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* Perform the request */
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(!res) {
|
||||
double ul;
|
||||
res = curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &ul);
|
||||
if(!res) {
|
||||
printf("Uploaded %.0f bytes\\n", ul);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.fi
|
||||
.SH DEPRECATED
|
||||
Deprecated since 7.55.0.
|
||||
.SH AVAILABILITY
|
||||
Added in curl 7.4.1
|
||||
.SH RETURN VALUE
|
||||
\fIcurl_easy_getinfo(3)\fP returns a CURLcode indicating success or error.
|
||||
|
||||
CURLE_OK (0) means everything was OK, non\-zero means an error occurred, see
|
||||
\fIlibcurl\-errors(3)\fP.
|
||||
.SH SEE ALSO
|
||||
.BR CURLINFO_SIZE_DOWNLOAD_T (3),
|
||||
.BR CURLINFO_SIZE_UPLOAD_T (3),
|
||||
.BR curl_easy_getinfo (3),
|
||||
.BR curl_easy_setopt (3)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user