184 lines
7.4 KiB
Markdown
184 lines
7.4 KiB
Markdown
# 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
|