Files
2026-03-05 02:44:43 +08:00

184 lines
7.4 KiB
Markdown
Raw Permalink Blame History

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Build & Test Commands
```bash
# Install dependencies
pod install
# Build SDK (Release configuration)
xcodebuild -workspace NewHttpDNS.xcworkspace -scheme NewHttpDNS -configuration Release build
# Run all unit tests
xcodebuild test -workspace NewHttpDNS.xcworkspace -scheme NewHttpDNSTests -destination 'platform=iOS Simulator,name=iPhone 15'
# Build distributable XCFramework
sh build_xc_framework.sh
```
**Note:** After creating new Xcode files, wait for the user to add them to the appropriate target before running builds or tests.
## Architecture Overview
This is an iOS HTTPDNS SDK with a multi-layered architecture designed for secure, cached, and resilient DNS resolution over HTTP/HTTPS.
### Core Architecture Layers
**1. Public API Layer (`HttpdnsService`)**
- Singleton facade providing three resolution modes:
- `resolveHostSync:` - Blocking with timeout
- `resolveHostAsync:` - Non-blocking with callbacks
- `resolveHostSyncNonBlocking:` - Returns cache immediately, refreshes async
- Manages multi-account instances (one per account ID)
- Configuration entry point for all SDK features
**2. Request Management Layer (`HttpdnsRequestManager`)**
- Orchestrates cache lookups before triggering network requests
- Manages two-tier caching:
- Memory cache (`HttpdnsHostObjectInMemoryCache`)
- Persistent SQLite cache (`HttpdnsDB`)
- Handles TTL validation and expired IP reuse policy
- Coordinates retry logic and degradation to local DNS
**3. Network Transport Layer (`HttpdnsNWHTTPClient`)**
- Low-level HTTP/HTTPS transport using Apple's Network framework
- Singleton with persistent connection pooling (max 4 idle connections per host:port:scheme)
- Manages reusable connections (`HttpdnsNWReusableConnection`) with automatic idle timeout (30s)
- Thread-safe concurrent request handling via serial pool queue
- Custom HTTP header parser supporting chunked transfer encoding
- TLS certificate validation with configurable trust evaluation
- Exposed by `HttpdnsRemoteResolver` for DNS resolution requests
**4. DNS Resolution Layer**
- **`HttpdnsRemoteResolver`**: HTTPS/HTTP requests to New servers
- Builds authenticated requests with HMAC-SHA256 signatures
- Optional AES-CBC encryption for sensitive parameters
- Parses JSON responses into `HttpdnsHostObject` (IPv4/IPv6)
- Uses `HttpdnsNWHTTPClient` for actual HTTP transport
- **`HttpdnsLocalResolver`**: Fallback to system DNS when remote fails
**5. Scheduling & Service Discovery (`HttpdnsScheduleCenter`)**
- Maintains regional service endpoint pools (CN, HK, SG, US, DE)
- Rotates between endpoints on failure for load balancing
- Separates IPv4 and IPv6 endpoint lists
- Per-account endpoint isolation
**6. Data Flow (Synchronous Resolution)**
```
User Request
<20><>?Validate & wrap in HttpdnsRequest
<20><>?Check memory cache (valid? return)
<20><>?Load from SQLite DB (valid? return)
<20><>?HttpdnsRemoteResolver
- Build URL with auth (HMAC-SHA256)
- Encrypt params if enabled (AES-CBC)
- Send to service endpoint
- Parse JSON response
- Decrypt if needed
<20><>?Cache in memory + DB
<20><>?Return HttpdnsResult
On Failure:
<20><>?Retry with different endpoint (max 1 retry)
<20><>?Return expired IP (if setReuseExpiredIPEnabled:YES)
<20><>?Fall back to local DNS (if setDegradeToLocalDNSEnabled:YES)
<20><>?Return nil
```
### Authentication & Encryption
**Request Signing:**
- All sensitive params signed with HMAC-SHA256
- Signature includes: account ID, expiration timestamp, domain, query type
- Params sorted alphabetically before signing
- Expiration: current_time + 10 minutes
**Request Encryption (Optional):**
- Domain name, query type, and SDNS params encrypted with AES-CBC
- Encrypted blob included as `enc` parameter
- Only encrypted when `aesSecretKey` provided at init
### Key Internal Components
- **`HttpdnsHostObject`**: Internal model with separate IPv4/IPv6 arrays, TTLs, timestamps
- **`HttpdnsResult`**: Public-facing result model (simplified view)
- **`HttpdnsHostRecord`**: Serializable model for SQLite persistence
- **`HttpdnsNWHTTPClient`**: Singleton HTTP transport layer with connection pooling
- **`HttpdnsNWReusableConnection`**: Wrapper for Network framework connections with idle timeout tracking
- **`HttpdnsIpStackDetector`**: Detects network stack type (IPv4/IPv6 capability)
- **`HttpdnsReachability`**: Monitors network changes, triggers pre-resolution
- **`HttpdnsUtil`**: Crypto utilities (HMAC, AES), IP validation, encoding
### Concurrency Model
- Concurrent queues for async user requests and DNS resolution
- Serial pool queue in `HttpdnsNWHTTPClient` for connection pool management
- `dispatch_semaphore_t` for blocking synchronous calls
- `HttpDnsLocker` prevents duplicate concurrent resolution of same domain
- Network framework handles underlying I/O asynchronously
## Coding Conventions
**Style:**
- 4-space indentation, no trailing whitespace
- Braces on same line as control statements; body starts on next line
- Always use braces for control statement bodies, even single statements
- Comments in Chinese, only for complex logic explaining WHY
**Naming:**
- Types/files: `UpperCamelCase` (e.g., `NewHttpDNSClient.h`)
- Methods/variables: `lowerCamelCase`
- Constants: `kAC...` prefix
- Internal headers: `+Internal.h` suffix
**Commit Messages:**
- Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`, `config:`
- Write in Chinese
- After `git add`, run: `/Users/xuyecan/.macconfig/script/strip-trailing-ws-in-diff --staged`
## Testing Notes
- Test target: `NewHttpDNSTests`
- OCMock-based tests may have memory issues when run in batch - run individually if needed
- Non-mock tests use predefined credentials:
- Account ID: `1000000`
- Test domains: `*.onlyforhttpdnstest.run.place` (renewed annually)
- Never commit real production Account IDs or Secret Keys
- Test file naming mirrors class under test (e.g., `NewHttpDNSClientTests.m`)
- Network layer integration tests organized into 5 focused modules:
- `HttpdnsNWHTTPClient_BasicIntegrationTests.m`: Basic HTTP/HTTPS requests
- `HttpdnsNWHTTPClient_ConcurrencyTests.m`: Thread safety and concurrent access
- `HttpdnsNWHTTPClient_PoolManagementTests.m`: Connection pooling and reuse
- `HttpdnsNWHTTPClient_EdgeCasesAndTimeoutTests.m`: Timeout and error handling
- `HttpdnsNWHTTPClient_StateMachineTests.m`: Connection lifecycle state transitions
## SDK-Specific Notes
**Multi-Account Support:**
- Each account ID gets isolated singleton instance
- Separate endpoint pools, caches, and configurations per account
**Public vs Internal Headers:**
- Public headers listed in `NewHTTPDNS.podspec` under `public_header_files`
- Internal headers use `+Internal.h` suffix and are not exposed
- Umbrella header: `NewHttpDNS.h` imports all public APIs
**Required System Frameworks:**
- `CoreTelephony`, `SystemConfiguration`, `Network` (for HTTP transport)
- Libraries: `sqlite3.0`, `resolv`, `z`
- Linker flags: `-ObjC -lz`
- Minimum deployment target: iOS 12.0+ (required for Network framework)
**Pre-Resolution Strategy:**
- Call `setPreResolveHosts:byIPType:` at app startup for hot domains
- Automatically re-triggered on network changes (WiFi <20><>?cellular)
- Batch requests combine multiple hosts in single HTTP call
**Persistence & Cache:**
- SQLite DB per account in isolated directory
- Enable with `setPersistentCacheIPEnabled:YES`
- Automatic expiration cleanup
- Speeds up cold starts with pre-cached DNS results