Skip to content

Conversation

@kraman-msft-eng
Copy link

Pull Request Checklist

Added Callback to support implementing multi-nic delegation from client.

…guration

This change adds a new optional callback function to CurlTransportOptions that allows
users to customize the CURL handle with additional options before request execution.

Key changes:
- Added CurlOptionsCallback field to CurlTransportOptions struct in curl_transport.hpp
- Callback receives the CURL* handle (as void*) for setting custom options
- Invoked just before curl_easy_perform() in CurlConnection constructor
- Enables use cases like network interface binding via CURLOPT_INTERFACE

This provides flexibility for advanced scenarios requiring per-request CURL customization
while maintaining backward compatibility.
This change adds a CurlOptionsCallback member to CurlTransportOptions that allows
applications to customize CURL handles before requests are sent. This enables
scenarios like:
- Network interface binding (CURLOPT_INTERFACE) for multi-NIC environments
- Custom DNS server configuration
- Request-specific CURL option overrides

Key changes:
- Added CurlOptionsCallback field to CurlTransportOptions struct
- Callback is invoked BEFORE URL setup to prevent CURL from reprocessing the URL
- Added comprehensive error handling and logging around callback invocation
- Added unit test to verify callback functionality

The callback timing is critical - it must be invoked before CURLOPT_URL is set
to ensure options like CURLOPT_INTERFACE work correctly without URL corruption.

Fixes Azure/azure-sdk-for-cpp#XXXX
- Move callback invocation to BEFORE CURLOPT_URL setup (critical fix)
- Add CURLINFO_LOCAL_IP query to verify interface binding
- Add comprehensive error handling around callback
- Add detailed logging for debugging multi-NIC scenarios

This ensures CURLOPT_INTERFACE is set before CURL processes the URL,
preventing URL corruption and InvalidUri errors.
Keep implementation clean and minimal - remove debug logging and
exception handling wrapper to keep the code simple and maintainable.
@github-actions github-actions bot added Azure.Core Community Contribution Community members are working on the issue customer-reported Issues that are reported by GitHub users external to the Azure organization. labels Nov 15, 2025
@github-actions
Copy link

Thank you for your contribution @kraman-msft-eng! We will review the pull request and get back to you soon.


// Apply custom CURL options callback BEFORE setting URL
// This allows the callback to set options like CURLOPT_INTERFACE before CURL processes the URL
if (options.CurlOptionsCallback)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have an options callback, you need to either:

  1. Apply the option to every curl connection created equally
  2. Exempt the connection from the connection pool or
  3. Come up with a way to distinguish between curl connection options in the connection pool.

Otherwise, the connection pool will re-use a custom configured curl handle in an environment that doesn't expect that configuration.

…optimizations

This commit introduces comprehensive enhancements to the Azure SDK C++ CURL transport
for multi-NIC environments with connection tracking and performance optimizations.

## Core Features

### 1. Connection Reuse Tracking (UpdateSocketReuse)
- Added UpdateSocketReuse() method to track socket lifecycle
- Logs three connection states: first request, connection reused, new connection
- Called before each HTTP request in SendRawHttp()
- Uses CURLINFO_ACTIVESOCKET to monitor socket handles

### 2. Global CURL Handle Pool
- Implemented GlobalCurlHandlePool singleton for handle reuse across hosts
- Pool size: 100 pre-initialized CURL* handles
- Eliminates curl_easy_init() overhead for new connections
- Handles returned to pool on CurlConnection destruction

### 3. Shared DNS and SSL Cache
- Added GlobalCurlShareObject for DNS and SSL session sharing
- Enables CURLSH_LOCK_DATA_DNS and CURLSH_LOCK_DATA_SSL_SESSION
- Reduces DNS lookups and SSL handshakes across connections

### 4. Performance Optimizations
- Poll interval: 1000ms → 10ms (100x latency reduction)
- Buffer size: 16KB → 512KB (download/upload)
- Connection cache: 5 → 100 connections
- DNS cache: 60 seconds (configurable)
- TCP_NODELAY: enabled by default (disables Nagle's algorithm)
- HTTP/2: opt-in support for connection multiplexing

### 5. CurlOptionsCallback
- Added callback for per-request CURL customization
- Allows setting CURLOPT_INTERFACE for network interface binding
- Invoked before request execution

## API Changes

### CurlTransportOptions (curl_transport.hpp)
```cpp
std::function<void(void*)> CurlOptionsCallback;
long MaxConnectionsCache = 100;
long DnsCacheTimeout = 60;
bool EnableHttp2 = false;
long BufferSize = 524288;       // 512KB
long UploadBufferSize = 524288; // 512KB
bool TcpNoDelay = true;
long PollIntervalMs = 10;
```

### CurlConnection (curl_connection_private.hpp)
```cpp
virtual void UpdateSocketReuse() = 0;
bool m_handleFromGlobalPool;
long m_pollIntervalMs;
curl_socket_t m_previousSocket;
```

## Build Configuration

### Prerequisites
- Visual Studio 2022 (or 2019)
- CMake 3.20+
- vcpkg for dependencies

### Build Commands
```powershell
# Automated build with VS auto-detection
.\build-sdk.ps1 -Config Release -CleanBuild

# Manual build
cmake -B build -G "NMake Makefiles" ^
  -DCMAKE_BUILD_TYPE=Release ^
  -DBUILD_TRANSPORT_CURL=ON ^
  -DBUILD_TRANSPORT_WINHTTP=ON ^
  -DMSVC_USE_STATIC_CRT=ON ^
  -DCMAKE_CXX_FLAGS="/DCURL_STATICLIB /DWIL_ENABLE_EXCEPTIONS" ^
  -DDISABLE_RUST_IN_BUILD=ON ^
  -DDISABLE_AMQP=ON

cmake --build build --target azure-core
cmake --install build --prefix C:\Users\kraman\azure-sdk-local
```

## Technical Details

### Static CURL Linkage
- CURL_STATICLIB defined as preprocessor macro
- Verified via dumpbin: curl_easy_* symbols (not __imp_curl_*)
- Linked with /MT static runtime

### WinHTTP Transport Support
- WIL_ENABLE_EXCEPTIONS preprocessor define required
- Both CURL and WinHTTP transports available

### Connection Pool Architecture
- Host-specific keys: (host, proxy, TLS settings, timeout)
- Connection reuse within same host configuration
- Global handle pool reuses handles across different hosts

## Documentation
- BUILD_AND_USE.md: Integration guide for consuming projects
- REBUILD-GUIDE.md: Detailed build instructions
- QUICK_START.md: Quick testing guide
- BUILD-SUMMARY.md: Build configuration summary
- VERIFICATION.md: Feature verification steps
- WINHTTP-BUILD-FIX.md: WIL compatibility solution

## Testing
Verified with dumpbin symbol inspection:
- ✅ UpdateSocketReuse symbol present
- ✅ Static CURL linkage confirmed
- ✅ WinHTTP transport symbols present
- ✅ Both transports functional

Installed to: C:\Users\kraman\azure-sdk-local
@github-actions
Copy link

Hi @kraman-msft-eng. Thank you for your interest in helping to improve the Azure SDK experience and for your contribution. We've noticed that there hasn't been recent engagement on this pull request. If this is still an active work stream, please let us know by pushing some changes or leaving a comment. Otherwise, we'll close this out in 7 days.

@github-actions github-actions bot added the no-recent-activity There has been no recent activity on this issue. label Jan 23, 2026
@github-actions
Copy link

Hi @kraman-msft-eng. Thank you for your contribution. Since there hasn't been recent engagement, we're going to close this out. Feel free to respond with a comment containing /reopen if you'd like to continue working on these changes. Please be sure to use the command to reopen or remove the no-recent-activity label; otherwise, this is likely to be closed again with the next cleanup pass.

@github-actions github-actions bot closed this Jan 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Azure.Core Community Contribution Community members are working on the issue customer-reported Issues that are reported by GitHub users external to the Azure organization. no-recent-activity There has been no recent activity on this issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants