mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 19:45:22 +00:00
Compare commits
74
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53826d5145 | ||
|
|
f58955f194 | ||
|
|
537737f521 | ||
|
|
b58c71f777 | ||
|
|
b4e2746be6 | ||
|
|
91040f7ed4 | ||
|
|
588d8fef0d | ||
|
|
8cd5a09a86 | ||
|
|
121e1d246a | ||
|
|
e5028e5e86 | ||
|
|
6681ca11c3 | ||
|
|
81b5dd15c1 | ||
|
|
098f223906 | ||
|
|
d31dd8300f | ||
|
|
85b627945d | ||
|
|
035ad175a7 | ||
|
|
b995a3fe4f | ||
|
|
fb26db3bf0 | ||
|
|
de4bf0a471 | ||
|
|
f493b50163 | ||
|
|
4aa12c08e7 | ||
|
|
c2a0c86542 | ||
|
|
073e22e126 | ||
|
|
6533293f75 | ||
|
|
757acef8d1 | ||
|
|
db52c9463b | ||
|
|
b179d99cf8 | ||
|
|
73d0867c18 | ||
|
|
97f822b88d | ||
|
|
3f91d6510b | ||
|
|
2bb55cbe1a | ||
|
|
7fb93eb522 | ||
|
|
cb8b34f8ea | ||
|
|
b872113a4b | ||
|
|
de3795289d | ||
|
|
bd37cc69a0 | ||
|
|
788e21c4ea | ||
|
|
c179e34c43 | ||
|
|
aa8b257e68 | ||
|
|
7b4aeb506e | ||
|
|
5d5ed94952 | ||
|
|
4945688eca | ||
|
|
22bd975059 | ||
|
|
d28b58ecb2 | ||
|
|
e17163b3da | ||
|
|
9346e62971 | ||
|
|
a89fd153ee | ||
|
|
25bc737919 | ||
|
|
8218c12f69 | ||
|
|
60c2263a46 | ||
|
|
e2fcb44982 | ||
|
|
ebbb7b356f | ||
|
|
2d0f55ae84 | ||
|
|
51e8e4e51a | ||
|
|
fb251a3fa8 | ||
|
|
4052ba581a | ||
|
|
235fefe4ab | ||
|
|
8389961269 | ||
|
|
a244c4084f | ||
|
|
ed320fb0ad | ||
|
|
2bdc1535c7 | ||
|
|
60a375469a | ||
|
|
640567b7e4 | ||
|
|
f58bcaf615 | ||
|
|
6e19995de2 | ||
|
|
78d72f5814 | ||
|
|
f145d13992 | ||
|
|
f607413caf | ||
|
|
47db836a22 | ||
|
|
aa7a5efe6a | ||
|
|
c8d196f106 | ||
|
|
2cd90ff813 | ||
|
|
5267489fa2 | ||
|
|
790dcda8e5 |
@@ -7,7 +7,6 @@ on:
|
|||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update-relay-data:
|
update-relay-data:
|
||||||
@@ -18,54 +17,24 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Fetch GeoRelays
|
- name: Fetch GeoRelays
|
||||||
run: |
|
run: |
|
||||||
wget -q https://raw.githubusercontent.com/permissionlesstech/georelays/refs/heads/main/nostr_relays.csv
|
wget https://raw.githubusercontent.com/permissionlesstech/georelays/refs/heads/main/nostr_relays.csv
|
||||||
mv nostr_relays.csv ./relays/online_relays_gps.csv
|
mv nostr_relays.csv ./relays/online_relays_gps.csv
|
||||||
|
|
||||||
- name: Configure git
|
- name: Check for changes
|
||||||
|
id: git-check
|
||||||
run: |
|
run: |
|
||||||
git config user.email "action@github.com"
|
git diff --exit-code || echo "changes=true" >> $GITHUB_OUTPUT
|
||||||
git config user.name "GitHub Action"
|
|
||||||
|
|
||||||
- name: Create update branch if changes
|
- name: Commit and push changes
|
||||||
id: create_branch
|
if: steps.git-check.outputs.changes == 'true'
|
||||||
run: |
|
run: |
|
||||||
# exit early if no changes
|
git config --local user.email "action@github.com"
|
||||||
if git diff --quiet --relays/online_relays_gps.csv; then
|
git config --local user.name "GitHub Action"
|
||||||
echo "changed=false" >> $GITHUB_OUTPUT
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# branch name with timestamp
|
|
||||||
BRANCH="update-georelays-$(date -u +%Y%m%dT%H%M%SZ)"
|
|
||||||
git checkout -b "$BRANCH"
|
|
||||||
|
|
||||||
git add relays/online_relays_gps.csv
|
git add relays/online_relays_gps.csv
|
||||||
git commit -m "Automated update of relay data - $(date -u --rfc-3339=seconds)"
|
git commit -m "Automated update of relay data - $(date -u)"
|
||||||
echo "changed=true" >> $GITHUB_OUTPUT
|
git push
|
||||||
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Push branch
|
|
||||||
if: steps.create_branch.outputs.changed == 'true'
|
|
||||||
run: |
|
|
||||||
git push --set-upstream origin "${{ steps.create_branch.outputs.branch }}"
|
|
||||||
|
|
||||||
- name: Create pull request
|
|
||||||
if: steps.create_branch.outputs.changed == 'true'
|
|
||||||
uses: peter-evans/create-pull-request@v5
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
commit-message: Automated update of relay data
|
|
||||||
branch: ${{ steps.create_branch.outputs.branch }}
|
|
||||||
base: main
|
|
||||||
title: Automated update of relay data
|
|
||||||
body: |
|
|
||||||
This PR was created automatically by the scheduled workflow. It updates relays/online_relays_gps.csv from the GeoRelays source.
|
|
||||||
labels: automated, georelays
|
|
||||||
|
|
||||||
- name: No changes
|
|
||||||
if: steps.create_branch.outputs.changed != 'true'
|
|
||||||
run: echo "No changes to relays/online_relays_gps.csv"
|
|
||||||
@@ -14,11 +14,8 @@ default:
|
|||||||
# Check prerequisites
|
# Check prerequisites
|
||||||
check:
|
check:
|
||||||
@echo "Checking prerequisites..."
|
@echo "Checking prerequisites..."
|
||||||
@command -v xcodebuild >/dev/null 2>&1 || (echo "❌ xcodebuild not found. Install Xcode from App Store" && exit 1)
|
@command -v xcodebuild >/dev/null 2>&1 || (echo "❌ Xcode not found. Install Xcode from App Store" && exit 1)
|
||||||
@xcode-select -p | grep -q "Xcode.app" || (echo "❌ Full Xcode required, not just command line tools. Install from App Store and run:\n sudo xcode-select -s /Applications/Xcode.app/Contents/Developer" && exit 1)
|
@security find-identity -v -p codesigning | grep -q "Developer ID" || (echo "⚠️ No Developer ID found - code signing may fail" && exit 0)
|
||||||
@test -d "/Applications/Xcode.app" || (echo "❌ Xcode.app not found in Applications folder. Install from App Store" && exit 1)
|
|
||||||
@xcodebuild -version >/dev/null 2>&1 || (echo "❌ Xcode not properly configured. Try:\n sudo xcode-select -s /Applications/Xcode.app/Contents/Developer" && exit 1)
|
|
||||||
@security find-identity -v -p codesigning | grep -q "Apple Development\|Developer ID" || (echo "⚠️ No Developer ID found - code signing may fail" && exit 0)
|
|
||||||
@echo "✅ All prerequisites met"
|
@echo "✅ All prerequisites met"
|
||||||
|
|
||||||
# Backup original files
|
# Backup original files
|
||||||
|
|||||||
@@ -98,8 +98,8 @@
|
|||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
<EnvironmentVariables>
|
<EnvironmentVariables>
|
||||||
<EnvironmentVariable
|
<EnvironmentVariable
|
||||||
key = "BITCHAT_LOG_LEVEL"
|
key = "-DBITCHAT_DEV_ALLOW_CLEARNET"
|
||||||
value = "debug"
|
value = ""
|
||||||
isEnabled = "YES">
|
isEnabled = "YES">
|
||||||
</EnvironmentVariable>
|
</EnvironmentVariable>
|
||||||
</EnvironmentVariables>
|
</EnvironmentVariables>
|
||||||
|
|||||||
@@ -57,9 +57,11 @@ struct BitchatApp: App {
|
|||||||
let npub = try? idBridge.getCurrentNostrIdentity()?.npub
|
let npub = try? idBridge.getCurrentNostrIdentity()?.npub
|
||||||
_ = VerificationService.shared.buildMyQRString(nickname: chatViewModel.nickname, npub: npub)
|
_ = VerificationService.shared.buildMyQRString(nickname: chatViewModel.nickname, npub: npub)
|
||||||
}
|
}
|
||||||
|
#if os(iOS)
|
||||||
appDelegate.chatViewModel = chatViewModel
|
appDelegate.chatViewModel = chatViewModel
|
||||||
|
#elseif os(macOS)
|
||||||
|
appDelegate.chatViewModel = chatViewModel
|
||||||
|
#endif
|
||||||
// Initialize network activation policy; will start Tor/Nostr only when allowed
|
// Initialize network activation policy; will start Tor/Nostr only when allowed
|
||||||
NetworkActivationService.shared.start()
|
NetworkActivationService.shared.start()
|
||||||
// Check for shared content
|
// Check for shared content
|
||||||
@@ -187,10 +189,6 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
|
|||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationWillTerminate(_ application: UIApplication) {
|
|
||||||
chatViewModel?.applicationWillTerminate()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -248,7 +246,7 @@ final class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
|
|||||||
// Get peer ID from userInfo
|
// Get peer ID from userInfo
|
||||||
if let peerID = userInfo["peerID"] as? String {
|
if let peerID = userInfo["peerID"] as? String {
|
||||||
// Don't show notification if the private chat is already open
|
// Don't show notification if the private chat is already open
|
||||||
if chatViewModel?.selectedPrivateChatPeer == PeerID(str: peerID) {
|
if chatViewModel?.selectedPrivateChatPeer == peerID {
|
||||||
completionHandler([])
|
completionHandler([])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import ImageIO
|
|
||||||
import UniformTypeIdentifiers
|
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
import UIKit
|
import UIKit
|
||||||
#else
|
#else
|
||||||
import AppKit
|
import AppKit
|
||||||
|
import ImageIO
|
||||||
|
import UniformTypeIdentifiers
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum ImageUtilsError: Error {
|
enum ImageUtilsError: Error {
|
||||||
@@ -13,10 +13,10 @@ enum ImageUtilsError: Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum ImageUtils {
|
enum ImageUtils {
|
||||||
private static let compressionQuality: CGFloat = 0.82
|
private static let compressionQuality: CGFloat = 0.85
|
||||||
private static let targetImageBytes: Int = 45_000
|
private static let targetImageBytes: Int = 60_000
|
||||||
|
|
||||||
static func processImage(at url: URL, maxDimension: CGFloat = 448) throws -> URL {
|
static func processImage(at url: URL, maxDimension: CGFloat = 512) throws -> URL {
|
||||||
// Security H1: Check file size BEFORE reading into memory
|
// Security H1: Check file size BEFORE reading into memory
|
||||||
let attrs = try FileManager.default.attributesOfItem(atPath: url.path)
|
let attrs = try FileManager.default.attributesOfItem(atPath: url.path)
|
||||||
guard let fileSize = attrs[.size] as? Int else {
|
guard let fileSize = attrs[.size] as? Int else {
|
||||||
@@ -38,32 +38,21 @@ enum ImageUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
static func processImage(_ image: UIImage, maxDimension: CGFloat = 448) throws -> URL {
|
static func processImage(_ image: UIImage, maxDimension: CGFloat = 512) throws -> URL {
|
||||||
return try autoreleasepool {
|
return try autoreleasepool {
|
||||||
// Scale the image first
|
|
||||||
let scaled = scaledImage(image, maxDimension: maxDimension)
|
let scaled = scaledImage(image, maxDimension: maxDimension)
|
||||||
|
|
||||||
// Get CGImage from UIImage - this is the key to stripping metadata
|
|
||||||
guard let cgImage = scaled.cgImage else {
|
|
||||||
throw ImageUtilsError.encodingFailed
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use CGImageDestination to encode without metadata (same as macOS)
|
|
||||||
var quality = compressionQuality
|
var quality = compressionQuality
|
||||||
guard var jpegData = encodeJPEG(from: cgImage, quality: quality) else {
|
guard var jpegData = scaled.jpegData(compressionQuality: quality) else {
|
||||||
throw ImageUtilsError.encodingFailed
|
throw ImageUtilsError.encodingFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compress to target size
|
|
||||||
while jpegData.count > targetImageBytes && quality > 0.3 {
|
while jpegData.count > targetImageBytes && quality > 0.3 {
|
||||||
quality -= 0.1
|
quality -= 0.1
|
||||||
autoreleasepool {
|
autoreleasepool {
|
||||||
if let next = encodeJPEG(from: cgImage, quality: quality) {
|
if let next = scaled.jpegData(compressionQuality: quality) {
|
||||||
jpegData = next
|
jpegData = next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let outputURL = try makeOutputURL()
|
let outputURL = try makeOutputURL()
|
||||||
try jpegData.write(to: outputURL, options: .atomic)
|
try jpegData.write(to: outputURL, options: .atomic)
|
||||||
return outputURL
|
return outputURL
|
||||||
@@ -76,37 +65,14 @@ enum ImageUtils {
|
|||||||
guard maxSide > maxDimension else { return image }
|
guard maxSide > maxDimension else { return image }
|
||||||
let scale = maxDimension / maxSide
|
let scale = maxDimension / maxSide
|
||||||
let newSize = CGSize(width: size.width * scale, height: size.height * scale)
|
let newSize = CGSize(width: size.width * scale, height: size.height * scale)
|
||||||
|
|
||||||
// Draw into a new context to get a clean CGImage without metadata
|
|
||||||
UIGraphicsBeginImageContextWithOptions(newSize, true, 1.0)
|
UIGraphicsBeginImageContextWithOptions(newSize, true, 1.0)
|
||||||
image.draw(in: CGRect(origin: .zero, size: newSize))
|
image.draw(in: CGRect(origin: .zero, size: newSize))
|
||||||
let rendered = UIGraphicsGetImageFromCurrentImageContext()
|
let rendered = UIGraphicsGetImageFromCurrentImageContext()
|
||||||
UIGraphicsEndImageContext()
|
UIGraphicsEndImageContext()
|
||||||
return rendered ?? image
|
return rendered ?? image
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shared EXIF-stripping JPEG encoder for both iOS and macOS
|
|
||||||
private static func encodeJPEG(from cgImage: CGImage, quality: CGFloat) -> Data? {
|
|
||||||
guard let data = CFDataCreateMutable(nil, 0) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
guard let destination = CGImageDestinationCreateWithData(data, UTType.jpeg.identifier as CFString, 1, nil) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Security: Strip ALL metadata (EXIF, GPS, TIFF, IPTC, XMP)
|
|
||||||
// By only specifying compression quality and no metadata keys,
|
|
||||||
// we ensure a clean JPEG with no privacy-leaking information
|
|
||||||
let options: [CFString: Any] = [
|
|
||||||
kCGImageDestinationLossyCompressionQuality: quality
|
|
||||||
]
|
|
||||||
CGImageDestinationAddImage(destination, cgImage, options as CFDictionary)
|
|
||||||
guard CGImageDestinationFinalize(destination) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return data as Data
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
static func processImage(_ image: NSImage, maxDimension: CGFloat = 448) throws -> URL {
|
static func processImage(_ image: NSImage, maxDimension: CGFloat = 512) throws -> URL {
|
||||||
return try autoreleasepool {
|
return try autoreleasepool {
|
||||||
let scaled = scaledImage(image, maxDimension: maxDimension)
|
let scaled = scaledImage(image, maxDimension: maxDimension)
|
||||||
guard let inputCG = scaled.cgImage(forProposedRect: nil, context: nil, hints: nil) else {
|
guard let inputCG = scaled.cgImage(forProposedRect: nil, context: nil, hints: nil) else {
|
||||||
@@ -164,7 +130,6 @@ enum ImageUtils {
|
|||||||
return scaledImage
|
return scaledImage
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shared EXIF-stripping JPEG encoder for both iOS and macOS
|
|
||||||
private static func encodeJPEG(from cgImage: CGImage, quality: CGFloat) -> Data? {
|
private static func encodeJPEG(from cgImage: CGImage, quality: CGFloat) -> Data? {
|
||||||
guard let data = CFDataCreateMutable(nil, 0) else {
|
guard let data = CFDataCreateMutable(nil, 0) else {
|
||||||
return nil
|
return nil
|
||||||
@@ -172,9 +137,8 @@ enum ImageUtils {
|
|||||||
guard let destination = CGImageDestinationCreateWithData(data, UTType.jpeg.identifier as CFString, 1, nil) else {
|
guard let destination = CGImageDestinationCreateWithData(data, UTType.jpeg.identifier as CFString, 1, nil) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Security: Strip ALL metadata (EXIF, GPS, TIFF, IPTC, XMP)
|
// Security H2: Strip ALL metadata (EXIF, GPS, TIFF, IPTC, XMP)
|
||||||
// By only specifying compression quality and no metadata keys,
|
// Don't add any metadata dictionary keys - fresh CGContext ensures clean image
|
||||||
// we ensure a clean JPEG with no privacy-leaking information
|
|
||||||
let options: [CFString: Any] = [
|
let options: [CFString: Any] = [
|
||||||
kCGImageDestinationLossyCompressionQuality: quality
|
kCGImageDestinationLossyCompressionQuality: quality
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ final class VoiceRecorder: NSObject, AVAudioRecorderDelegate {
|
|||||||
|
|
||||||
private let queue = DispatchQueue(label: "com.bitchat.voice-recorder")
|
private let queue = DispatchQueue(label: "com.bitchat.voice-recorder")
|
||||||
private let paddingInterval: TimeInterval = 0.5
|
private let paddingInterval: TimeInterval = 0.5
|
||||||
private let maxRecordingDuration: TimeInterval = 120
|
|
||||||
|
|
||||||
private var recorder: AVAudioRecorder?
|
private var recorder: AVAudioRecorder?
|
||||||
private var currentURL: URL?
|
private var currentURL: URL?
|
||||||
@@ -76,14 +75,14 @@ final class VoiceRecorder: NSObject, AVAudioRecorderDelegate {
|
|||||||
AVFormatIDKey: kAudioFormatMPEG4AAC,
|
AVFormatIDKey: kAudioFormatMPEG4AAC,
|
||||||
AVSampleRateKey: 16_000,
|
AVSampleRateKey: 16_000,
|
||||||
AVNumberOfChannelsKey: 1,
|
AVNumberOfChannelsKey: 1,
|
||||||
AVEncoderBitRateKey: 16_000
|
AVEncoderBitRateKey: 20_000
|
||||||
]
|
]
|
||||||
|
|
||||||
let audioRecorder = try AVAudioRecorder(url: outputURL, settings: settings)
|
let audioRecorder = try AVAudioRecorder(url: outputURL, settings: settings)
|
||||||
audioRecorder.delegate = self
|
audioRecorder.delegate = self
|
||||||
audioRecorder.isMeteringEnabled = true
|
audioRecorder.isMeteringEnabled = true
|
||||||
audioRecorder.prepareToRecord()
|
audioRecorder.prepareToRecord()
|
||||||
audioRecorder.record(forDuration: maxRecordingDuration)
|
audioRecorder.record()
|
||||||
|
|
||||||
recorder = audioRecorder
|
recorder = audioRecorder
|
||||||
currentURL = outputURL
|
currentURL = outputURL
|
||||||
|
|||||||
+23866
-24188
File diff suppressed because it is too large
Load Diff
@@ -21,9 +21,8 @@ struct BitchatPacket: Codable {
|
|||||||
let payload: Data
|
let payload: Data
|
||||||
var signature: Data?
|
var signature: Data?
|
||||||
var ttl: UInt8
|
var ttl: UInt8
|
||||||
var route: [Data]?
|
|
||||||
|
|
||||||
init(type: UInt8, senderID: Data, recipientID: Data?, timestamp: UInt64, payload: Data, signature: Data?, ttl: UInt8, version: UInt8 = 1, route: [Data]? = nil) {
|
init(type: UInt8, senderID: Data, recipientID: Data?, timestamp: UInt64, payload: Data, signature: Data?, ttl: UInt8, version: UInt8 = 1) {
|
||||||
self.version = version
|
self.version = version
|
||||||
self.type = type
|
self.type = type
|
||||||
self.senderID = senderID
|
self.senderID = senderID
|
||||||
@@ -32,7 +31,6 @@ struct BitchatPacket: Codable {
|
|||||||
self.payload = payload
|
self.payload = payload
|
||||||
self.signature = signature
|
self.signature = signature
|
||||||
self.ttl = ttl
|
self.ttl = ttl
|
||||||
self.route = route
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience initializer for new binary format
|
// Convenience initializer for new binary format
|
||||||
@@ -55,7 +53,6 @@ struct BitchatPacket: Codable {
|
|||||||
self.payload = payload
|
self.payload = payload
|
||||||
self.signature = nil
|
self.signature = nil
|
||||||
self.ttl = ttl
|
self.ttl = ttl
|
||||||
self.route = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var data: Data? {
|
var data: Data? {
|
||||||
@@ -84,8 +81,7 @@ struct BitchatPacket: Codable {
|
|||||||
payload: payload,
|
payload: payload,
|
||||||
signature: nil, // Remove signature for signing
|
signature: nil, // Remove signature for signing
|
||||||
ttl: 0, // Use fixed TTL=0 for signing to ensure relay compatibility
|
ttl: 0, // Use fixed TTL=0 for signing to ensure relay compatibility
|
||||||
version: version,
|
version: version
|
||||||
route: route
|
|
||||||
)
|
)
|
||||||
return BinaryProtocol.encode(unsignedPacket)
|
return BinaryProtocol.encode(unsignedPacket)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
//
|
|
||||||
// CommandsInfo.swift
|
|
||||||
// bitchat
|
|
||||||
//
|
|
||||||
// This is free and unencumbered software released into the public domain.
|
|
||||||
// For more information, see <https://unlicense.org>
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
// MARK: - CommandInfo Enum
|
|
||||||
|
|
||||||
enum CommandInfo: String, Identifiable {
|
|
||||||
case block
|
|
||||||
case clear
|
|
||||||
case hug
|
|
||||||
case message = "dm"
|
|
||||||
case slap
|
|
||||||
case unblock
|
|
||||||
case who
|
|
||||||
case favorite
|
|
||||||
case unfavorite
|
|
||||||
|
|
||||||
var id: String { rawValue }
|
|
||||||
|
|
||||||
var alias: String { "/" + rawValue }
|
|
||||||
|
|
||||||
var placeholder: String? {
|
|
||||||
switch self {
|
|
||||||
case .block, .hug, .message, .slap, .unblock, .favorite, .unfavorite:
|
|
||||||
return "<" + String(localized: "content.input.nickname_placeholder") + ">"
|
|
||||||
case .clear, .who:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var description: String {
|
|
||||||
switch self {
|
|
||||||
case .block: String(localized: "content.commands.block")
|
|
||||||
case .clear: String(localized: "content.commands.clear")
|
|
||||||
case .hug: String(localized: "content.commands.hug")
|
|
||||||
case .message: String(localized: "content.commands.message")
|
|
||||||
case .slap: String(localized: "content.commands.slap")
|
|
||||||
case .unblock: String(localized: "content.commands.unblock")
|
|
||||||
case .who: String(localized: "content.commands.who")
|
|
||||||
case .favorite: String(localized: "content.commands.favorite")
|
|
||||||
case .unfavorite: String(localized: "content.commands.unfavorite")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static func all(isGeoPublic: Bool, isGeoDM: Bool) -> [CommandInfo] {
|
|
||||||
let baseCommands: [CommandInfo] = [.block, .unblock, .clear, .hug, .message, .slap, .who]
|
|
||||||
if isGeoPublic || isGeoDM {
|
|
||||||
return baseCommands + [.favorite, .unfavorite]
|
|
||||||
}
|
|
||||||
return baseCommands
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+18
-22
@@ -35,7 +35,7 @@ struct PeerID: Equatable, Hashable {
|
|||||||
// Private so the callers have to go through a convenience init
|
// Private so the callers have to go through a convenience init
|
||||||
private init(prefix: Prefix, bare: any StringProtocol) {
|
private init(prefix: Prefix, bare: any StringProtocol) {
|
||||||
self.prefix = prefix
|
self.prefix = prefix
|
||||||
self.bare = String(bare).lowercased()
|
self.bare = String(bare)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,12 +76,6 @@ extension PeerID {
|
|||||||
init(hexData: Data) {
|
init(hexData: Data) {
|
||||||
self.init(str: hexData.hexEncodedString())
|
self.init(str: hexData.hexEncodedString())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience init to "hide" hex-encoding implementation detail
|
|
||||||
init?(hexData: Data?) {
|
|
||||||
guard let hexData else { return nil }
|
|
||||||
self.init(hexData: hexData)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Noise Public Key Helpers
|
// MARK: - Noise Public Key Helpers
|
||||||
@@ -136,20 +130,6 @@ extension PeerID {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension PeerID {
|
|
||||||
var routingData: Data? {
|
|
||||||
if let direct = Data(hexString: id), direct.count == 8 { return direct }
|
|
||||||
if let bareData = Data(hexString: bare), bareData.count == 8 { return bareData }
|
|
||||||
let short = toShort()
|
|
||||||
return Data(hexString: short.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
init?(routingData: Data) {
|
|
||||||
guard routingData.count == 8 else { return nil }
|
|
||||||
self.init(hexData: routingData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Validation
|
// MARK: - Validation
|
||||||
|
|
||||||
extension PeerID {
|
extension PeerID {
|
||||||
@@ -211,7 +191,9 @@ extension PeerID: Comparable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - CustomStringConvertible
|
// MARK: - String Interop Helpers
|
||||||
|
|
||||||
|
// MARK: CustomStringConvertible
|
||||||
|
|
||||||
extension PeerID: CustomStringConvertible {
|
extension PeerID: CustomStringConvertible {
|
||||||
/// So it returns the actual `id` like before even inside another String
|
/// So it returns the actual `id` like before even inside another String
|
||||||
@@ -219,3 +201,17 @@ extension PeerID: CustomStringConvertible {
|
|||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Custom Equatable w/ String & Optionality
|
||||||
|
|
||||||
|
// PeerID <> String
|
||||||
|
extension Optional where Wrapped == PeerID {
|
||||||
|
static func ==(lhs: Optional<Wrapped>, rhs: Optional<String>) -> Bool { lhs?.id == rhs }
|
||||||
|
static func !=(lhs: Optional<Wrapped>, rhs: Optional<String>) -> Bool { lhs?.id != rhs }
|
||||||
|
}
|
||||||
|
|
||||||
|
// String <> PeerID
|
||||||
|
extension Optional where Wrapped == String {
|
||||||
|
static func ==(lhs: Optional<Wrapped>, rhs: Optional<PeerID>) -> Bool { lhs == rhs?.id }
|
||||||
|
static func !=(lhs: Optional<Wrapped>, rhs: Optional<PeerID>) -> Bool { lhs != rhs?.id }
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import Foundation
|
|||||||
struct ReadReceipt: Codable {
|
struct ReadReceipt: Codable {
|
||||||
let originalMessageID: String
|
let originalMessageID: String
|
||||||
let receiptID: String
|
let receiptID: String
|
||||||
var readerID: PeerID // Who read it
|
var readerID: String // Who read it
|
||||||
let readerNickname: String
|
let readerNickname: String
|
||||||
let timestamp: Date
|
let timestamp: Date
|
||||||
|
|
||||||
init(originalMessageID: String, readerID: PeerID, readerNickname: String) {
|
init(originalMessageID: String, readerID: String, readerNickname: String) {
|
||||||
self.originalMessageID = originalMessageID
|
self.originalMessageID = originalMessageID
|
||||||
self.receiptID = UUID().uuidString
|
self.receiptID = UUID().uuidString
|
||||||
self.readerID = readerID
|
self.readerID = readerID
|
||||||
@@ -24,7 +24,7 @@ struct ReadReceipt: Codable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For binary decoding
|
// For binary decoding
|
||||||
private init(originalMessageID: String, receiptID: String, readerID: PeerID, readerNickname: String, timestamp: Date) {
|
private init(originalMessageID: String, receiptID: String, readerID: String, readerNickname: String, timestamp: Date) {
|
||||||
self.originalMessageID = originalMessageID
|
self.originalMessageID = originalMessageID
|
||||||
self.receiptID = receiptID
|
self.receiptID = receiptID
|
||||||
self.readerID = readerID
|
self.readerID = readerID
|
||||||
@@ -48,7 +48,7 @@ struct ReadReceipt: Codable {
|
|||||||
data.appendUUID(receiptID)
|
data.appendUUID(receiptID)
|
||||||
// ReaderID as 8-byte hex string
|
// ReaderID as 8-byte hex string
|
||||||
var readerData = Data()
|
var readerData = Data()
|
||||||
var tempID = readerID.id
|
var tempID = readerID
|
||||||
while tempID.count >= 2 && readerData.count < 8 {
|
while tempID.count >= 2 && readerData.count < 8 {
|
||||||
let hexByte = String(tempID.prefix(2))
|
let hexByte = String(tempID.prefix(2))
|
||||||
if let byte = UInt8(hexByte, radix: 16) {
|
if let byte = UInt8(hexByte, radix: 16) {
|
||||||
@@ -78,8 +78,8 @@ struct ReadReceipt: Codable {
|
|||||||
let receiptID = dataCopy.readUUID(at: &offset) else { return nil }
|
let receiptID = dataCopy.readUUID(at: &offset) else { return nil }
|
||||||
|
|
||||||
guard let readerIDData = dataCopy.readFixedBytes(at: &offset, count: 8) else { return nil }
|
guard let readerIDData = dataCopy.readFixedBytes(at: &offset, count: 8) else { return nil }
|
||||||
let readerID = PeerID(hexData: readerIDData)
|
let readerID = readerIDData.hexEncodedString()
|
||||||
guard readerID.isValid else { return nil }
|
guard PeerID(str: readerID).isValid else { return nil }
|
||||||
|
|
||||||
guard let timestamp = dataCopy.readDate(at: &offset),
|
guard let timestamp = dataCopy.readDate(at: &offset),
|
||||||
InputValidator.validateTimestamp(timestamp),
|
InputValidator.validateTimestamp(timestamp),
|
||||||
|
|||||||
@@ -8,14 +8,6 @@ struct RequestSyncPacket {
|
|||||||
let p: Int
|
let p: Int
|
||||||
let m: UInt32
|
let m: UInt32
|
||||||
let data: Data
|
let data: Data
|
||||||
let types: SyncTypeFlags?
|
|
||||||
|
|
||||||
init(p: Int, m: UInt32, data: Data, types: SyncTypeFlags? = nil) {
|
|
||||||
self.p = p
|
|
||||||
self.m = m
|
|
||||||
self.data = data
|
|
||||||
self.types = types
|
|
||||||
}
|
|
||||||
|
|
||||||
func encode() -> Data {
|
func encode() -> Data {
|
||||||
var out = Data()
|
var out = Data()
|
||||||
@@ -33,9 +25,6 @@ struct RequestSyncPacket {
|
|||||||
putTLV(0x02, withUnsafeBytes(of: &mBE) { Data($0) })
|
putTLV(0x02, withUnsafeBytes(of: &mBE) { Data($0) })
|
||||||
// data
|
// data
|
||||||
putTLV(0x03, data)
|
putTLV(0x03, data)
|
||||||
if let typesData = types?.toData() {
|
|
||||||
putTLV(0x04, typesData)
|
|
||||||
}
|
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +33,6 @@ struct RequestSyncPacket {
|
|||||||
var p: Int? = nil
|
var p: Int? = nil
|
||||||
var m: UInt32? = nil
|
var m: UInt32? = nil
|
||||||
var payload: Data? = nil
|
var payload: Data? = nil
|
||||||
var types: SyncTypeFlags? = nil
|
|
||||||
|
|
||||||
while off + 3 <= data.count {
|
while off + 3 <= data.count {
|
||||||
let t = Int(data[off]); off += 1
|
let t = Int(data[off]); off += 1
|
||||||
@@ -64,16 +52,12 @@ struct RequestSyncPacket {
|
|||||||
case 0x03:
|
case 0x03:
|
||||||
if v.count > maxAcceptBytes { return nil }
|
if v.count > maxAcceptBytes { return nil }
|
||||||
payload = v
|
payload = v
|
||||||
case 0x04:
|
|
||||||
if let decoded = SyncTypeFlags.decode(v) {
|
|
||||||
types = decoded
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
break // forward compatible; ignore unknown TLVs
|
break // forward compatible; ignore unknown TLVs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let pp = p, let mm = m, let dd = payload, pp >= 1, mm > 0 else { return nil }
|
guard let pp = p, let mm = m, let dd = payload, pp >= 1, mm > 0 else { return nil }
|
||||||
return RequestSyncPacket(p: pp, m: mm, data: dd, types: types)
|
return RequestSyncPacket(p: pp, m: mm, data: dd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
import BitLogger
|
import BitLogger
|
||||||
import Foundation
|
import Foundation
|
||||||
import Tor
|
import Tor
|
||||||
#if os(iOS)
|
|
||||||
import UIKit
|
|
||||||
#elseif os(macOS)
|
|
||||||
import AppKit
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Directory of online Nostr relays with approximate GPS locations, used for geohash routing.
|
/// Directory of online Nostr relays with approximate GPS locations, used for geohash routing.
|
||||||
@MainActor
|
@MainActor
|
||||||
@@ -17,32 +12,19 @@ final class GeoRelayDirectory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static let shared = GeoRelayDirectory()
|
static let shared = GeoRelayDirectory()
|
||||||
|
|
||||||
private(set) var entries: [Entry] = []
|
private(set) var entries: [Entry] = []
|
||||||
private let cacheFileName = "georelays_cache.csv"
|
private let cacheFileName = "georelays_cache.csv"
|
||||||
private let lastFetchKey = "georelay.lastFetchAt"
|
private let lastFetchKey = "georelay.lastFetchAt"
|
||||||
private let remoteURL = URL(string: "https://raw.githubusercontent.com/permissionlesstech/georelays/refs/heads/main/nostr_relays.csv")!
|
private let remoteURL = URL(string: "https://raw.githubusercontent.com/permissionlesstech/georelays/refs/heads/main/nostr_relays.csv")!
|
||||||
private let fetchInterval: TimeInterval = TransportConfig.geoRelayFetchIntervalSeconds
|
private let fetchInterval: TimeInterval = TransportConfig.geoRelayFetchIntervalSeconds // 24h
|
||||||
|
|
||||||
private var refreshTimer: Timer?
|
|
||||||
private var retryTask: Task<Void, Never>?
|
|
||||||
private var retryAttempt: Int = 0
|
|
||||||
private var isFetching: Bool = false
|
|
||||||
private var observers: [NSObjectProtocol] = []
|
|
||||||
|
|
||||||
private init() {
|
private init() {
|
||||||
entries = loadLocalEntries()
|
// Load cached or bundled data synchronously
|
||||||
registerObservers()
|
self.entries = self.loadLocalEntries()
|
||||||
startRefreshTimer()
|
// Fire-and-forget remote refresh if stale
|
||||||
prefetchIfNeeded()
|
prefetchIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
|
||||||
observers.forEach { NotificationCenter.default.removeObserver($0) }
|
|
||||||
refreshTimer?.invalidate()
|
|
||||||
retryTask?.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns up to `count` relay URLs (wss://) closest to the geohash center.
|
/// Returns up to `count` relay URLs (wss://) closest to the geohash center.
|
||||||
func closestRelays(toGeohash geohash: String, count: Int = 5) -> [String] {
|
func closestRelays(toGeohash geohash: String, count: Int = 5) -> [String] {
|
||||||
let center = Geohash.decodeCenter(geohash)
|
let center = Geohash.decodeCenter(geohash)
|
||||||
@@ -51,146 +33,50 @@ final class GeoRelayDirectory {
|
|||||||
|
|
||||||
/// Returns up to `count` relay URLs (wss://) closest to the given coordinate.
|
/// Returns up to `count` relay URLs (wss://) closest to the given coordinate.
|
||||||
func closestRelays(toLat lat: Double, lon: Double, count: Int = 5) -> [String] {
|
func closestRelays(toLat lat: Double, lon: Double, count: Int = 5) -> [String] {
|
||||||
guard !entries.isEmpty, count > 0 else { return [] }
|
guard !entries.isEmpty else { return [] }
|
||||||
|
let sorted = entries
|
||||||
if entries.count <= count {
|
|
||||||
return entries
|
|
||||||
.sorted { a, b in
|
.sorted { a, b in
|
||||||
haversineKm(lat, lon, a.lat, a.lon) < haversineKm(lat, lon, b.lat, b.lon)
|
haversineKm(lat, lon, a.lat, a.lon) < haversineKm(lat, lon, b.lat, b.lon)
|
||||||
}
|
}
|
||||||
.map { "wss://\($0.host)" }
|
.prefix(count)
|
||||||
}
|
return sorted.map { "wss://\($0.host)" }
|
||||||
|
|
||||||
var best: [(entry: Entry, distance: Double)] = []
|
|
||||||
best.reserveCapacity(count)
|
|
||||||
|
|
||||||
for entry in entries {
|
|
||||||
let distance = haversineKm(lat, lon, entry.lat, entry.lon)
|
|
||||||
if best.count < count {
|
|
||||||
let idx = best.firstIndex { $0.distance > distance } ?? best.count
|
|
||||||
best.insert((entry, distance), at: idx)
|
|
||||||
} else if let worstDistance = best.last?.distance, distance < worstDistance {
|
|
||||||
let idx = best.firstIndex { $0.distance > distance } ?? best.count
|
|
||||||
best.insert((entry, distance), at: idx)
|
|
||||||
best.removeLast()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return best.map { "wss://\($0.entry.host)" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Remote Fetch
|
// MARK: - Remote Fetch
|
||||||
func prefetchIfNeeded(force: Bool = false) {
|
func prefetchIfNeeded() {
|
||||||
guard !isFetching else { return }
|
|
||||||
|
|
||||||
let now = Date()
|
let now = Date()
|
||||||
let last = UserDefaults.standard.object(forKey: lastFetchKey) as? Date ?? .distantPast
|
let last = UserDefaults.standard.object(forKey: lastFetchKey) as? Date ?? .distantPast
|
||||||
|
|
||||||
if !force {
|
|
||||||
guard now.timeIntervalSince(last) >= fetchInterval else { return }
|
guard now.timeIntervalSince(last) >= fetchInterval else { return }
|
||||||
} else if last != .distantPast,
|
|
||||||
now.timeIntervalSince(last) < TransportConfig.geoRelayRetryInitialSeconds {
|
|
||||||
// Skip forced fetches if we just refreshed moments ago.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelRetry()
|
|
||||||
fetchRemote()
|
fetchRemote()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func fetchRemote() {
|
private func fetchRemote() {
|
||||||
guard !isFetching else { return }
|
let req = URLRequest(url: remoteURL, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 15)
|
||||||
isFetching = true
|
// Ensure Tor readiness before fetching (fail-closed by default)
|
||||||
|
Task.detached {
|
||||||
let request = URLRequest(
|
|
||||||
url: remoteURL,
|
|
||||||
cachePolicy: .reloadIgnoringLocalCacheData,
|
|
||||||
timeoutInterval: 15
|
|
||||||
)
|
|
||||||
|
|
||||||
Task.detached { [weak self] in
|
|
||||||
guard let self else { return }
|
|
||||||
|
|
||||||
let ready = await TorManager.shared.awaitReady()
|
let ready = await TorManager.shared.awaitReady()
|
||||||
if !ready {
|
if !ready {
|
||||||
await self.handleFetchFailure(.torNotReady)
|
SecureLogger.warning("GeoRelayDirectory: Tor not ready; skipping remote fetch (fail-closed)", category: .session)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
let task = TorURLSession.shared.session.dataTask(with: req) { [weak self] data, _, error in
|
||||||
do {
|
guard let self = self else { return }
|
||||||
let (data, _) = try await TorURLSession.shared.session.data(for: request)
|
if let data = data, error == nil, let text = String(data: data, encoding: .utf8) {
|
||||||
guard let text = String(data: data, encoding: .utf8) else {
|
|
||||||
await self.handleFetchFailure(.invalidData)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let parsed = GeoRelayDirectory.parseCSV(text)
|
let parsed = GeoRelayDirectory.parseCSV(text)
|
||||||
guard !parsed.isEmpty else {
|
if !parsed.isEmpty {
|
||||||
await self.handleFetchFailure(.invalidData)
|
Task { @MainActor in
|
||||||
|
self.entries = parsed
|
||||||
|
self.persistCache(text)
|
||||||
|
UserDefaults.standard.set(Date(), forKey: self.lastFetchKey)
|
||||||
|
SecureLogger.info("GeoRelayDirectory: refreshed \(parsed.count) relays from remote", category: .session)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await self.handleFetchSuccess(entries: parsed, csv: text)
|
|
||||||
} catch {
|
|
||||||
await self.handleFetchFailure(.network(error))
|
|
||||||
}
|
}
|
||||||
|
SecureLogger.warning("GeoRelayDirectory: remote fetch failed; keeping local entries", category: .session)
|
||||||
}
|
}
|
||||||
|
task.resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum FetchFailure {
|
|
||||||
case torNotReady
|
|
||||||
case invalidData
|
|
||||||
case network(Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
private func handleFetchSuccess(entries parsed: [Entry], csv: String) {
|
|
||||||
entries = parsed
|
|
||||||
persistCache(csv)
|
|
||||||
UserDefaults.standard.set(Date(), forKey: lastFetchKey)
|
|
||||||
SecureLogger.info("GeoRelayDirectory: refreshed \(parsed.count) relays from remote", category: .session)
|
|
||||||
isFetching = false
|
|
||||||
retryAttempt = 0
|
|
||||||
cancelRetry()
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
private func handleFetchFailure(_ reason: FetchFailure) {
|
|
||||||
switch reason {
|
|
||||||
case .torNotReady:
|
|
||||||
SecureLogger.warning("GeoRelayDirectory: Tor not ready; scheduling retry", category: .session)
|
|
||||||
case .invalidData:
|
|
||||||
SecureLogger.warning("GeoRelayDirectory: remote fetch returned invalid data; scheduling retry", category: .session)
|
|
||||||
case .network(let error):
|
|
||||||
SecureLogger.warning("GeoRelayDirectory: remote fetch failed with error: \(error.localizedDescription)", category: .session)
|
|
||||||
}
|
|
||||||
isFetching = false
|
|
||||||
scheduleRetry()
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
private func scheduleRetry() {
|
|
||||||
retryAttempt = min(retryAttempt + 1, 10)
|
|
||||||
let base = TransportConfig.geoRelayRetryInitialSeconds
|
|
||||||
let maxDelay = TransportConfig.geoRelayRetryMaxSeconds
|
|
||||||
let multiplier = pow(2.0, Double(max(retryAttempt - 1, 0)))
|
|
||||||
let calculated = base * multiplier
|
|
||||||
let delay = min(maxDelay, max(base, calculated))
|
|
||||||
|
|
||||||
cancelRetry()
|
|
||||||
retryTask = Task { [weak self] in
|
|
||||||
let nanoseconds = UInt64(delay * 1_000_000_000)
|
|
||||||
try? await Task.sleep(nanoseconds: nanoseconds)
|
|
||||||
await MainActor.run {
|
|
||||||
self?.prefetchIfNeeded(force: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
private func cancelRetry() {
|
|
||||||
retryTask?.cancel()
|
|
||||||
retryTask = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func persistCache(_ text: String) {
|
private func persistCache(_ text: String) {
|
||||||
@@ -205,35 +91,30 @@ final class GeoRelayDirectory {
|
|||||||
// MARK: - Loading
|
// MARK: - Loading
|
||||||
private func loadLocalEntries() -> [Entry] {
|
private func loadLocalEntries() -> [Entry] {
|
||||||
// Prefer cached file if present
|
// Prefer cached file if present
|
||||||
if let cache = cacheURL(),
|
if let cache = self.cacheURL(),
|
||||||
let data = try? Data(contentsOf: cache),
|
let data = try? Data(contentsOf: cache),
|
||||||
let text = String(data: data, encoding: .utf8) {
|
let text = String(data: data, encoding: .utf8) {
|
||||||
let arr = Self.parseCSV(text)
|
let arr = Self.parseCSV(text)
|
||||||
if !arr.isEmpty { return arr }
|
if !arr.isEmpty { return arr }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try bundled resource(s)
|
// Try bundled resource(s)
|
||||||
let bundleCandidates = [
|
let bundleCandidates = [
|
||||||
Bundle.main.url(forResource: "nostr_relays", withExtension: "csv"),
|
Bundle.main.url(forResource: "nostr_relays", withExtension: "csv"),
|
||||||
Bundle.main.url(forResource: "online_relays_gps", withExtension: "csv"),
|
Bundle.main.url(forResource: "online_relays_gps", withExtension: "csv"),
|
||||||
Bundle.main.url(forResource: "online_relays_gps", withExtension: "csv", subdirectory: "relays")
|
Bundle.main.url(forResource: "online_relays_gps", withExtension: "csv", subdirectory: "relays")
|
||||||
].compactMap { $0 }
|
].compactMap { $0 }
|
||||||
|
|
||||||
for url in bundleCandidates {
|
for url in bundleCandidates {
|
||||||
if let data = try? Data(contentsOf: url),
|
if let data = try? Data(contentsOf: url), let text = String(data: data, encoding: .utf8) {
|
||||||
let text = String(data: data, encoding: .utf8) {
|
|
||||||
let arr = Self.parseCSV(text)
|
let arr = Self.parseCSV(text)
|
||||||
if !arr.isEmpty { return arr }
|
if !arr.isEmpty { return arr }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try filesystem path (development/test)
|
// Try filesystem path (development/test)
|
||||||
if let cwd = FileManager.default.currentDirectoryPath as String?,
|
if let cwd = FileManager.default.currentDirectoryPath as String?,
|
||||||
let data = try? Data(contentsOf: URL(fileURLWithPath: cwd).appendingPathComponent("relays/online_relays_gps.csv")),
|
let data = try? Data(contentsOf: URL(fileURLWithPath: cwd).appendingPathComponent("relays/online_relays_gps.csv")),
|
||||||
let text = String(data: data, encoding: .utf8) {
|
let text = String(data: data, encoding: .utf8) {
|
||||||
return Self.parseCSV(text)
|
return Self.parseCSV(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
SecureLogger.warning("GeoRelayDirectory: no local CSV found; entries empty", category: .session)
|
SecureLogger.warning("GeoRelayDirectory: no local CSV found; entries empty", category: .session)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@@ -241,6 +122,7 @@ final class GeoRelayDirectory {
|
|||||||
nonisolated static func parseCSV(_ text: String) -> [Entry] {
|
nonisolated static func parseCSV(_ text: String) -> [Entry] {
|
||||||
var result: Set<Entry> = []
|
var result: Set<Entry> = []
|
||||||
let lines = text.split(whereSeparator: { $0.isNewline })
|
let lines = text.split(whereSeparator: { $0.isNewline })
|
||||||
|
// Skip header if present
|
||||||
for (idx, raw) in lines.enumerated() {
|
for (idx, raw) in lines.enumerated() {
|
||||||
let line = raw.trimmingCharacters(in: .whitespacesAndNewlines)
|
let line = raw.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
if line.isEmpty { continue }
|
if line.isEmpty { continue }
|
||||||
@@ -261,76 +143,11 @@ final class GeoRelayDirectory {
|
|||||||
|
|
||||||
private func cacheURL() -> URL? {
|
private func cacheURL() -> URL? {
|
||||||
do {
|
do {
|
||||||
let base = try FileManager.default.url(
|
let base = try FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
|
||||||
for: .applicationSupportDirectory,
|
|
||||||
in: .userDomainMask,
|
|
||||||
appropriateFor: nil,
|
|
||||||
create: true
|
|
||||||
)
|
|
||||||
let dir = base.appendingPathComponent("bitchat", isDirectory: true)
|
let dir = base.appendingPathComponent("bitchat", isDirectory: true)
|
||||||
try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
|
try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
|
||||||
return dir.appendingPathComponent(cacheFileName)
|
return dir.appendingPathComponent(cacheFileName)
|
||||||
} catch {
|
} catch { return nil }
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Observers & Timers
|
|
||||||
private func registerObservers() {
|
|
||||||
let center = NotificationCenter.default
|
|
||||||
|
|
||||||
let torReady = center.addObserver(
|
|
||||||
forName: .TorDidBecomeReady,
|
|
||||||
object: nil,
|
|
||||||
queue: .main
|
|
||||||
) { [weak self] _ in
|
|
||||||
guard let self else { return }
|
|
||||||
Task { @MainActor in
|
|
||||||
self.prefetchIfNeeded(force: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
observers.append(torReady)
|
|
||||||
|
|
||||||
#if os(iOS)
|
|
||||||
let didBecomeActive = center.addObserver(
|
|
||||||
forName: UIApplication.didBecomeActiveNotification,
|
|
||||||
object: nil,
|
|
||||||
queue: .main
|
|
||||||
) { [weak self] _ in
|
|
||||||
guard let self else { return }
|
|
||||||
Task { @MainActor in
|
|
||||||
self.prefetchIfNeeded()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
observers.append(didBecomeActive)
|
|
||||||
#elseif os(macOS)
|
|
||||||
let didBecomeActive = center.addObserver(
|
|
||||||
forName: NSApplication.didBecomeActiveNotification,
|
|
||||||
object: nil,
|
|
||||||
queue: .main
|
|
||||||
) { [weak self] _ in
|
|
||||||
guard let self else { return }
|
|
||||||
Task { @MainActor in
|
|
||||||
self.prefetchIfNeeded()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
observers.append(didBecomeActive)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private func startRefreshTimer() {
|
|
||||||
refreshTimer?.invalidate()
|
|
||||||
let interval = TransportConfig.geoRelayRefreshCheckIntervalSeconds
|
|
||||||
guard interval > 0 else { return }
|
|
||||||
|
|
||||||
let timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { [weak self] _ in
|
|
||||||
guard let self else { return }
|
|
||||||
Task { @MainActor in
|
|
||||||
self.prefetchIfNeeded()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
refreshTimer = timer
|
|
||||||
RunLoop.main.add(timer, forMode: .common)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Foundation
|
|||||||
|
|
||||||
struct NostrEmbeddedBitChat {
|
struct NostrEmbeddedBitChat {
|
||||||
/// Build a `bitchat1:` base64url-encoded BitChat packet carrying a private message for Nostr DMs.
|
/// Build a `bitchat1:` base64url-encoded BitChat packet carrying a private message for Nostr DMs.
|
||||||
static func encodePMForNostr(content: String, messageID: String, recipientPeerID: PeerID, senderPeerID: PeerID) -> String? {
|
static func encodePMForNostr(content: String, messageID: String, recipientPeerID: String, senderPeerID: String) -> String? {
|
||||||
// TLV-encode the private message
|
// TLV-encode the private message
|
||||||
let pm = PrivateMessagePacket(messageID: messageID, content: content)
|
let pm = PrivateMessagePacket(messageID: messageID, content: content)
|
||||||
guard let tlv = pm.encode() else { return nil }
|
guard let tlv = pm.encode() else { return nil }
|
||||||
@@ -14,12 +14,12 @@ struct NostrEmbeddedBitChat {
|
|||||||
payload.append(tlv)
|
payload.append(tlv)
|
||||||
|
|
||||||
// Determine 8-byte recipient ID to embed
|
// Determine 8-byte recipient ID to embed
|
||||||
let recipientID = normalizeRecipientPeerID(recipientPeerID)
|
let recipientIDHex: String = normalizeRecipientPeerID(recipientPeerID)
|
||||||
|
|
||||||
let packet = BitchatPacket(
|
let packet = BitchatPacket(
|
||||||
type: MessageType.noiseEncrypted.rawValue,
|
type: MessageType.noiseEncrypted.rawValue,
|
||||||
senderID: Data(hexString: senderPeerID.id) ?? Data(),
|
senderID: Data(hexString: senderPeerID) ?? Data(),
|
||||||
recipientID: Data(hexString: recipientID.id),
|
recipientID: Data(hexString: recipientIDHex),
|
||||||
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
||||||
payload: payload,
|
payload: payload,
|
||||||
signature: nil,
|
signature: nil,
|
||||||
@@ -31,18 +31,18 @@ struct NostrEmbeddedBitChat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Build a `bitchat1:` base64url-encoded BitChat packet carrying a delivery/read ack for Nostr DMs.
|
/// Build a `bitchat1:` base64url-encoded BitChat packet carrying a delivery/read ack for Nostr DMs.
|
||||||
static func encodeAckForNostr(type: NoisePayloadType, messageID: String, recipientPeerID: PeerID, senderPeerID: PeerID) -> String? {
|
static func encodeAckForNostr(type: NoisePayloadType, messageID: String, recipientPeerID: String, senderPeerID: String) -> String? {
|
||||||
guard type == .delivered || type == .readReceipt else { return nil }
|
guard type == .delivered || type == .readReceipt else { return nil }
|
||||||
|
|
||||||
var payload = Data([type.rawValue])
|
var payload = Data([type.rawValue])
|
||||||
payload.append(Data(messageID.utf8))
|
payload.append(Data(messageID.utf8))
|
||||||
|
|
||||||
let recipientID = normalizeRecipientPeerID(recipientPeerID)
|
let recipientIDHex: String = normalizeRecipientPeerID(recipientPeerID)
|
||||||
|
|
||||||
let packet = BitchatPacket(
|
let packet = BitchatPacket(
|
||||||
type: MessageType.noiseEncrypted.rawValue,
|
type: MessageType.noiseEncrypted.rawValue,
|
||||||
senderID: Data(hexString: senderPeerID.id) ?? Data(),
|
senderID: Data(hexString: senderPeerID) ?? Data(),
|
||||||
recipientID: Data(hexString: recipientID.id),
|
recipientID: Data(hexString: recipientIDHex),
|
||||||
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
||||||
payload: payload,
|
payload: payload,
|
||||||
signature: nil,
|
signature: nil,
|
||||||
@@ -54,7 +54,7 @@ struct NostrEmbeddedBitChat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Build a `bitchat1:` ACK (delivered/read) without an embedded recipient peer ID (geohash DMs).
|
/// Build a `bitchat1:` ACK (delivered/read) without an embedded recipient peer ID (geohash DMs).
|
||||||
static func encodeAckForNostrNoRecipient(type: NoisePayloadType, messageID: String, senderPeerID: PeerID) -> String? {
|
static func encodeAckForNostrNoRecipient(type: NoisePayloadType, messageID: String, senderPeerID: String) -> String? {
|
||||||
guard type == .delivered || type == .readReceipt else { return nil }
|
guard type == .delivered || type == .readReceipt else { return nil }
|
||||||
|
|
||||||
var payload = Data([type.rawValue])
|
var payload = Data([type.rawValue])
|
||||||
@@ -62,7 +62,7 @@ struct NostrEmbeddedBitChat {
|
|||||||
|
|
||||||
let packet = BitchatPacket(
|
let packet = BitchatPacket(
|
||||||
type: MessageType.noiseEncrypted.rawValue,
|
type: MessageType.noiseEncrypted.rawValue,
|
||||||
senderID: Data(hexString: senderPeerID.id) ?? Data(),
|
senderID: Data(hexString: senderPeerID) ?? Data(),
|
||||||
recipientID: nil,
|
recipientID: nil,
|
||||||
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
||||||
payload: payload,
|
payload: payload,
|
||||||
@@ -75,7 +75,7 @@ struct NostrEmbeddedBitChat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Build a `bitchat1:` payload without an embedded recipient peer ID (used for geohash DMs).
|
/// Build a `bitchat1:` payload without an embedded recipient peer ID (used for geohash DMs).
|
||||||
static func encodePMForNostrNoRecipient(content: String, messageID: String, senderPeerID: PeerID) -> String? {
|
static func encodePMForNostrNoRecipient(content: String, messageID: String, senderPeerID: String) -> String? {
|
||||||
let pm = PrivateMessagePacket(messageID: messageID, content: content)
|
let pm = PrivateMessagePacket(messageID: messageID, content: content)
|
||||||
guard let tlv = pm.encode() else { return nil }
|
guard let tlv = pm.encode() else { return nil }
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ struct NostrEmbeddedBitChat {
|
|||||||
|
|
||||||
let packet = BitchatPacket(
|
let packet = BitchatPacket(
|
||||||
type: MessageType.noiseEncrypted.rawValue,
|
type: MessageType.noiseEncrypted.rawValue,
|
||||||
senderID: Data(hexString: senderPeerID.id) ?? Data(),
|
senderID: Data(hexString: senderPeerID) ?? Data(),
|
||||||
recipientID: nil,
|
recipientID: nil,
|
||||||
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
||||||
payload: payload,
|
payload: payload,
|
||||||
@@ -96,11 +96,11 @@ struct NostrEmbeddedBitChat {
|
|||||||
return "bitchat1:" + base64URLEncode(data)
|
return "bitchat1:" + base64URLEncode(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func normalizeRecipientPeerID(_ recipientPeerID: PeerID) -> PeerID {
|
private static func normalizeRecipientPeerID(_ recipientPeerID: String) -> String {
|
||||||
if let maybeData = Data(hexString: recipientPeerID.id) {
|
if let maybeData = Data(hexString: recipientPeerID) {
|
||||||
if maybeData.count == 32 {
|
if maybeData.count == 32 {
|
||||||
// Treat as Noise static public key; derive peerID from fingerprint
|
// Treat as Noise static public key; derive peerID from fingerprint
|
||||||
return PeerID(publicKey: maybeData)
|
return PeerID(publicKey: maybeData).id
|
||||||
} else if maybeData.count == 8 {
|
} else if maybeData.count == 8 {
|
||||||
// Already an 8-byte peer ID
|
// Already an 8-byte peer ID
|
||||||
return recipientPeerID
|
return recipientPeerID
|
||||||
|
|||||||
@@ -906,16 +906,6 @@ struct NostrFilter: Encodable {
|
|||||||
filter.limit = limit
|
filter.limit = limit
|
||||||
return filter
|
return filter
|
||||||
}
|
}
|
||||||
|
|
||||||
// For location notes with neighbors: subscribe to multiple geohashes (center + neighbors)
|
|
||||||
static func geohashNotes(_ geohashes: [String], since: Date? = nil, limit: Int = 200) -> NostrFilter {
|
|
||||||
var filter = NostrFilter()
|
|
||||||
filter.kinds = [1]
|
|
||||||
filter.since = since?.timeIntervalSince1970.toInt()
|
|
||||||
filter.tagFilters = ["g": geohashes]
|
|
||||||
filter.limit = limit
|
|
||||||
return filter
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic coding key for tag filters
|
// Dynamic coding key for tag filters
|
||||||
|
|||||||
@@ -137,7 +137,6 @@ struct BinaryProtocol {
|
|||||||
static let hasRecipient: UInt8 = 0x01
|
static let hasRecipient: UInt8 = 0x01
|
||||||
static let hasSignature: UInt8 = 0x02
|
static let hasSignature: UInt8 = 0x02
|
||||||
static let isCompressed: UInt8 = 0x04
|
static let isCompressed: UInt8 = 0x04
|
||||||
static let hasRoute: UInt8 = 0x08
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode BitchatPacket to binary format
|
// Encode BitchatPacket to binary format
|
||||||
@@ -161,21 +160,8 @@ struct BinaryProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let lengthFieldBytes = lengthFieldSize(for: version)
|
let lengthFieldBytes = lengthFieldSize(for: version)
|
||||||
let originalRoute = packet.route ?? []
|
|
||||||
if originalRoute.contains(where: { $0.isEmpty }) { return nil }
|
|
||||||
let sanitizedRoute: [Data] = originalRoute.map { hop in
|
|
||||||
if hop.count == senderIDSize { return hop }
|
|
||||||
if hop.count > senderIDSize { return Data(hop.prefix(senderIDSize)) }
|
|
||||||
var padded = hop
|
|
||||||
padded.append(Data(repeating: 0, count: senderIDSize - hop.count))
|
|
||||||
return padded
|
|
||||||
}
|
|
||||||
guard sanitizedRoute.count <= 255 else { return nil }
|
|
||||||
|
|
||||||
let hasRoute = !sanitizedRoute.isEmpty
|
|
||||||
let routeLength = hasRoute ? 1 + sanitizedRoute.count * senderIDSize : 0
|
|
||||||
let originalSizeFieldBytes = isCompressed ? lengthFieldBytes : 0
|
let originalSizeFieldBytes = isCompressed ? lengthFieldBytes : 0
|
||||||
let payloadDataSize = routeLength + payload.count + originalSizeFieldBytes
|
let payloadDataSize = payload.count + originalSizeFieldBytes
|
||||||
|
|
||||||
if version == 1 && payloadDataSize > Int(UInt16.max) { return nil }
|
if version == 1 && payloadDataSize > Int(UInt16.max) { return nil }
|
||||||
if version == 2 && payloadDataSize > Int(UInt32.max) { return nil }
|
if version == 2 && payloadDataSize > Int(UInt32.max) { return nil }
|
||||||
@@ -199,7 +185,6 @@ struct BinaryProtocol {
|
|||||||
if packet.recipientID != nil { flags |= Flags.hasRecipient }
|
if packet.recipientID != nil { flags |= Flags.hasRecipient }
|
||||||
if packet.signature != nil { flags |= Flags.hasSignature }
|
if packet.signature != nil { flags |= Flags.hasSignature }
|
||||||
if isCompressed { flags |= Flags.isCompressed }
|
if isCompressed { flags |= Flags.isCompressed }
|
||||||
if hasRoute { flags |= Flags.hasRoute }
|
|
||||||
data.append(flags)
|
data.append(flags)
|
||||||
|
|
||||||
if version == 2 {
|
if version == 2 {
|
||||||
@@ -227,13 +212,6 @@ struct BinaryProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasRoute {
|
|
||||||
data.append(UInt8(sanitizedRoute.count))
|
|
||||||
for hop in sanitizedRoute {
|
|
||||||
data.append(hop)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if isCompressed, let originalSize = originalPayloadSize {
|
if isCompressed, let originalSize = originalPayloadSize {
|
||||||
if version == 2 {
|
if version == 2 {
|
||||||
let value = UInt32(originalSize)
|
let value = UInt32(originalSize)
|
||||||
@@ -343,27 +321,9 @@ struct BinaryProtocol {
|
|||||||
if recipientID == nil { return nil }
|
if recipientID == nil { return nil }
|
||||||
}
|
}
|
||||||
|
|
||||||
var route: [Data]? = nil
|
|
||||||
var remainingPayloadBytes = payloadLength
|
|
||||||
|
|
||||||
if (flags & Flags.hasRoute) != 0 {
|
|
||||||
guard remainingPayloadBytes >= 1, let routeCount = read8() else { return nil }
|
|
||||||
remainingPayloadBytes -= 1
|
|
||||||
if routeCount > 0 {
|
|
||||||
var hops: [Data] = []
|
|
||||||
for _ in 0..<Int(routeCount) {
|
|
||||||
guard remainingPayloadBytes >= senderIDSize,
|
|
||||||
let hop = readData(senderIDSize) else { return nil }
|
|
||||||
remainingPayloadBytes -= senderIDSize
|
|
||||||
hops.append(hop)
|
|
||||||
}
|
|
||||||
route = hops
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let payload: Data
|
let payload: Data
|
||||||
if isCompressed {
|
if isCompressed {
|
||||||
guard remainingPayloadBytes >= lengthFieldBytes else { return nil }
|
guard payloadLength >= lengthFieldBytes else { return nil }
|
||||||
let originalSize: Int
|
let originalSize: Int
|
||||||
if version == 2 {
|
if version == 2 {
|
||||||
guard let rawSize = read32() else { return nil }
|
guard let rawSize = read32() else { return nil }
|
||||||
@@ -372,12 +332,15 @@ struct BinaryProtocol {
|
|||||||
guard let rawSize = read16() else { return nil }
|
guard let rawSize = read16() else { return nil }
|
||||||
originalSize = Int(rawSize)
|
originalSize = Int(rawSize)
|
||||||
}
|
}
|
||||||
remainingPayloadBytes -= lengthFieldBytes
|
// Guard to keep decompression bounded to sane BLE payload limits
|
||||||
guard originalSize >= 0 && originalSize <= FileTransferLimits.maxFramedFileBytes else { return nil }
|
guard originalSize >= 0 && originalSize <= FileTransferLimits.maxPayloadBytes else { return nil }
|
||||||
let compressedSize = remainingPayloadBytes
|
let compressedSize = payloadLength - lengthFieldBytes
|
||||||
guard compressedSize > 0, let compressed = readData(compressedSize) else { return nil }
|
guard compressedSize >= 0, let compressed = readData(compressedSize) else { return nil }
|
||||||
remainingPayloadBytes = 0
|
|
||||||
|
|
||||||
|
// Validate compression ratio to prevent zip bomb attacks
|
||||||
|
// Primary protection: originalSize capped at 1MB (line 336)
|
||||||
|
// Defense-in-depth: reject extreme ratios (prevents DoS via memory allocation)
|
||||||
|
guard compressedSize > 0 else { return nil }
|
||||||
let compressionRatio = Double(originalSize) / Double(compressedSize)
|
let compressionRatio = Double(originalSize) / Double(compressedSize)
|
||||||
guard compressionRatio <= 50_000.0 else {
|
guard compressionRatio <= 50_000.0 else {
|
||||||
SecureLogger.warning("🚫 Suspicious compression ratio: \(String(format: "%.0f", compressionRatio)):1", category: .security)
|
SecureLogger.warning("🚫 Suspicious compression ratio: \(String(format: "%.0f", compressionRatio)):1", category: .security)
|
||||||
@@ -388,9 +351,7 @@ struct BinaryProtocol {
|
|||||||
decompressed.count == originalSize else { return nil }
|
decompressed.count == originalSize else { return nil }
|
||||||
payload = decompressed
|
payload = decompressed
|
||||||
} else {
|
} else {
|
||||||
guard remainingPayloadBytes >= 0,
|
guard let rawPayload = readData(payloadLength) else { return nil }
|
||||||
let rawPayload = readData(remainingPayloadBytes) else { return nil }
|
|
||||||
remainingPayloadBytes = 0
|
|
||||||
payload = rawPayload
|
payload = rawPayload
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,8 +371,7 @@ struct BinaryProtocol {
|
|||||||
payload: payload,
|
payload: payload,
|
||||||
signature: signature,
|
signature: signature,
|
||||||
ttl: ttl,
|
ttl: ttl,
|
||||||
version: version,
|
version: version
|
||||||
route: route
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ protocol BitchatDelegate: AnyObject {
|
|||||||
|
|
||||||
// Bluetooth state updates for user notifications
|
// Bluetooth state updates for user notifications
|
||||||
func didUpdateBluetoothState(_ state: CBManagerState)
|
func didUpdateBluetoothState(_ state: CBManagerState)
|
||||||
func didReceivePublicMessage(from peerID: PeerID, nickname: String, content: String, timestamp: Date, messageID: String?)
|
func didReceivePublicMessage(from peerID: PeerID, nickname: String, content: String, timestamp: Date)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide default implementation to make it effectively optional
|
// Provide default implementation to make it effectively optional
|
||||||
@@ -195,7 +195,7 @@ extension BitchatDelegate {
|
|||||||
// Default empty implementation
|
// Default empty implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
func didReceivePublicMessage(from peerID: PeerID, nickname: String, content: String, timestamp: Date, messageID: String?) {
|
func didReceivePublicMessage(from peerID: PeerID, nickname: String, content: String, timestamp: Date) {
|
||||||
// Default empty implementation
|
// Default empty implementation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,57 +119,4 @@ enum Geohash {
|
|||||||
}
|
}
|
||||||
return (latInterval.0, latInterval.1, lonInterval.0, lonInterval.1)
|
return (latInterval.0, latInterval.1, lonInterval.0, lonInterval.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all 8 neighboring geohash cells at the same precision.
|
|
||||||
/// - Parameter geohash: Base32 geohash string.
|
|
||||||
/// - Returns: Array of 8 neighboring geohashes (N, NE, E, SE, S, SW, W, NW order).
|
|
||||||
static func neighbors(of geohash: String) -> [String] {
|
|
||||||
guard !geohash.isEmpty else { return [] }
|
|
||||||
|
|
||||||
let precision = geohash.count
|
|
||||||
let bounds = decodeBounds(geohash)
|
|
||||||
let center = decodeCenter(geohash)
|
|
||||||
|
|
||||||
// Calculate cell dimensions
|
|
||||||
let latHeight = bounds.latMax - bounds.latMin
|
|
||||||
let lonWidth = bounds.lonMax - bounds.lonMin
|
|
||||||
|
|
||||||
// Helper to wrap longitude around ±180
|
|
||||||
func wrapLongitude(_ lon: Double) -> Double {
|
|
||||||
var wrapped = lon
|
|
||||||
while wrapped > 180.0 { wrapped -= 360.0 }
|
|
||||||
while wrapped < -180.0 { wrapped += 360.0 }
|
|
||||||
return wrapped
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper to clamp latitude to ±90
|
|
||||||
func clampLatitude(_ lat: Double) -> Double {
|
|
||||||
return max(-90.0, min(90.0, lat))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate 8 neighbor centers
|
|
||||||
let neighbors: [(lat: Double, lon: Double)] = [
|
|
||||||
(center.lat + latHeight, center.lon), // N
|
|
||||||
(center.lat + latHeight, center.lon + lonWidth), // NE
|
|
||||||
(center.lat, center.lon + lonWidth), // E
|
|
||||||
(center.lat - latHeight, center.lon + lonWidth), // SE
|
|
||||||
(center.lat - latHeight, center.lon), // S
|
|
||||||
(center.lat - latHeight, center.lon - lonWidth), // SW
|
|
||||||
(center.lat, center.lon - lonWidth), // W
|
|
||||||
(center.lat + latHeight, center.lon - lonWidth) // NW
|
|
||||||
]
|
|
||||||
|
|
||||||
// Encode each neighbor, handling boundary conditions
|
|
||||||
return neighbors.compactMap { neighbor in
|
|
||||||
let lat = clampLatitude(neighbor.lat)
|
|
||||||
let lon = wrapLongitude(neighbor.lon)
|
|
||||||
|
|
||||||
// Skip if we've crossed a pole (latitude clamped to boundary)
|
|
||||||
if (neighbor.lat > 90.0 || neighbor.lat < -90.0) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return encode(latitude: lat, longitude: lon, precision: precision)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,18 +116,4 @@ enum ChannelID: Equatable, Codable {
|
|||||||
case .location(let ch): return ch.geohash
|
case .location(let ch): return ch.geohash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isMesh: Bool {
|
|
||||||
switch self {
|
|
||||||
case .mesh: true
|
|
||||||
case .location: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var isLocation: Bool {
|
|
||||||
switch self {
|
|
||||||
case .mesh: false
|
|
||||||
case .location: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,11 @@ struct AnnouncementPacket {
|
|||||||
let nickname: String
|
let nickname: String
|
||||||
let noisePublicKey: Data // Noise static public key (Curve25519.KeyAgreement)
|
let noisePublicKey: Data // Noise static public key (Curve25519.KeyAgreement)
|
||||||
let signingPublicKey: Data // Ed25519 public key for signing
|
let signingPublicKey: Data // Ed25519 public key for signing
|
||||||
let directNeighbors: [Data]? // 8-byte peer IDs
|
|
||||||
|
|
||||||
private enum TLVType: UInt8 {
|
private enum TLVType: UInt8 {
|
||||||
case nickname = 0x01
|
case nickname = 0x01
|
||||||
case noisePublicKey = 0x02
|
case noisePublicKey = 0x02
|
||||||
case signingPublicKey = 0x03
|
case signingPublicKey = 0x03
|
||||||
case directNeighbors = 0x04
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode() -> Data? {
|
func encode() -> Data? {
|
||||||
@@ -38,16 +36,6 @@ struct AnnouncementPacket {
|
|||||||
data.append(UInt8(signingPublicKey.count))
|
data.append(UInt8(signingPublicKey.count))
|
||||||
data.append(signingPublicKey)
|
data.append(signingPublicKey)
|
||||||
|
|
||||||
// TLV for direct neighbors (optional)
|
|
||||||
if let neighbors = directNeighbors, !neighbors.isEmpty {
|
|
||||||
let neighborsData = neighbors.prefix(10).reduce(Data()) { $0 + $1 }
|
|
||||||
if !neighborsData.isEmpty && neighborsData.count % 8 == 0 {
|
|
||||||
data.append(TLVType.directNeighbors.rawValue)
|
|
||||||
data.append(UInt8(neighborsData.count))
|
|
||||||
data.append(neighborsData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +44,6 @@ struct AnnouncementPacket {
|
|||||||
var nickname: String?
|
var nickname: String?
|
||||||
var noisePublicKey: Data?
|
var noisePublicKey: Data?
|
||||||
var signingPublicKey: Data?
|
var signingPublicKey: Data?
|
||||||
var directNeighbors: [Data]?
|
|
||||||
|
|
||||||
while offset + 2 <= data.count {
|
while offset + 2 <= data.count {
|
||||||
let typeRaw = data[offset]
|
let typeRaw = data[offset]
|
||||||
@@ -76,17 +63,6 @@ struct AnnouncementPacket {
|
|||||||
noisePublicKey = Data(value)
|
noisePublicKey = Data(value)
|
||||||
case .signingPublicKey:
|
case .signingPublicKey:
|
||||||
signingPublicKey = Data(value)
|
signingPublicKey = Data(value)
|
||||||
case .directNeighbors:
|
|
||||||
if length > 0 && length % 8 == 0 {
|
|
||||||
var neighbors = [Data]()
|
|
||||||
let count = length / 8
|
|
||||||
for i in 0..<count {
|
|
||||||
let start = value.startIndex + i * 8
|
|
||||||
let end = start + 8
|
|
||||||
neighbors.append(Data(value[start..<end]))
|
|
||||||
}
|
|
||||||
directNeighbors = neighbors
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Unknown TLV; skip (tolerant decoder for forward compatibility)
|
// Unknown TLV; skip (tolerant decoder for forward compatibility)
|
||||||
@@ -98,8 +74,7 @@ struct AnnouncementPacket {
|
|||||||
return AnnouncementPacket(
|
return AnnouncementPacket(
|
||||||
nickname: nickname,
|
nickname: nickname,
|
||||||
noisePublicKey: noisePublicKey,
|
noisePublicKey: noisePublicKey,
|
||||||
signingPublicKey: signingPublicKey,
|
signingPublicKey: signingPublicKey
|
||||||
directNeighbors: directNeighbors
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,195 +0,0 @@
|
|||||||
//
|
|
||||||
// MimeType.swift
|
|
||||||
// bitchat
|
|
||||||
//
|
|
||||||
// This is free and unencumbered software released into the public domain.
|
|
||||||
// For more information, see <https://unlicense.org>
|
|
||||||
//
|
|
||||||
|
|
||||||
import UniformTypeIdentifiers
|
|
||||||
|
|
||||||
// MARK: - Extensions for missing UTTypes
|
|
||||||
|
|
||||||
extension UTType {
|
|
||||||
static let webP = UTType(importedAs: "image/webp")
|
|
||||||
static let aac = UTType(importedAs: "audio/aac")
|
|
||||||
static let m4a = UTType(importedAs: "audio/m4a")
|
|
||||||
static let ogg = UTType(importedAs: "audio/ogg")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - MimeType Enum
|
|
||||||
|
|
||||||
enum MimeType: CaseIterable, Hashable {
|
|
||||||
case jpeg
|
|
||||||
case jpg
|
|
||||||
case png
|
|
||||||
case gif
|
|
||||||
case webp
|
|
||||||
case mp4Audio
|
|
||||||
case m4a
|
|
||||||
case aac
|
|
||||||
case mpeg
|
|
||||||
case mp3
|
|
||||||
case wav
|
|
||||||
case xWav
|
|
||||||
case ogg
|
|
||||||
case pdf
|
|
||||||
case octetStream
|
|
||||||
|
|
||||||
var utType: UTType {
|
|
||||||
switch self {
|
|
||||||
case .jpeg, .jpg: .jpeg
|
|
||||||
case .png: .png
|
|
||||||
case .gif: .gif
|
|
||||||
case .webp: .webP
|
|
||||||
case .aac: .aac
|
|
||||||
case .m4a: .m4a
|
|
||||||
case .mp4Audio: .mpeg4Audio
|
|
||||||
case .mp3, .mpeg: .mp3
|
|
||||||
case .wav, .xWav: .wav
|
|
||||||
case .ogg: .ogg
|
|
||||||
case .pdf: .pdf
|
|
||||||
case .octetStream: .data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var category: Category {
|
|
||||||
switch self {
|
|
||||||
case .jpeg, .jpg, .png, .gif, .webp:
|
|
||||||
return .image
|
|
||||||
case .aac, .m4a, .mp4Audio, .mpeg, .mp3, .wav, .xWav, .ogg:
|
|
||||||
return .audio
|
|
||||||
case .pdf, .octetStream:
|
|
||||||
return .file
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var mimeString: String {
|
|
||||||
switch self {
|
|
||||||
case .jpeg, .jpg: "image/jpeg"
|
|
||||||
case .png: "image/png"
|
|
||||||
case .gif: "image/gif"
|
|
||||||
case .webp: "image/webp"
|
|
||||||
case .mp4Audio: "audio/mp4"
|
|
||||||
case .m4a: "audio/m4a"
|
|
||||||
case .aac: "audio/aac"
|
|
||||||
case .mpeg: "audio/mpeg"
|
|
||||||
case .mp3: "audio/mp3"
|
|
||||||
case .wav: "audio/wav"
|
|
||||||
case .xWav: "audio/x-wav"
|
|
||||||
case .ogg: "audio/ogg"
|
|
||||||
case .pdf: "application/pdf"
|
|
||||||
case .octetStream: "application/octet-stream"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultExtension: String {
|
|
||||||
switch self {
|
|
||||||
case .jpeg, .jpg: "jpg"
|
|
||||||
case .png: "png"
|
|
||||||
case .webp: "webp"
|
|
||||||
case .gif: "gif"
|
|
||||||
case .mp4Audio, .m4a, .aac: "m4a"
|
|
||||||
case .mpeg, .mp3: "mp3"
|
|
||||||
case .wav, .xWav: "wav"
|
|
||||||
case .ogg: "ogg"
|
|
||||||
case .pdf: "pdf"
|
|
||||||
case .octetStream: "bin"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static var allowed: Set<MimeType> = [
|
|
||||||
.jpeg, .jpg, .png, .gif, .webp,
|
|
||||||
.mp4Audio, .m4a, .aac, .mpeg, .mp3,
|
|
||||||
.wav, .xWav, .ogg,
|
|
||||||
.pdf, .octetStream
|
|
||||||
]
|
|
||||||
|
|
||||||
var isAllowed: Bool {
|
|
||||||
Self.allowed.contains(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Byte signature validation
|
|
||||||
func matches(data: Data) -> Bool {
|
|
||||||
guard !data.isEmpty else { return false }
|
|
||||||
|
|
||||||
// Generic type → skip validation
|
|
||||||
if self == .octetStream { return true }
|
|
||||||
|
|
||||||
switch self {
|
|
||||||
case .jpeg, .jpg:
|
|
||||||
return data.count >= 3 && data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF
|
|
||||||
|
|
||||||
case .png:
|
|
||||||
return data.count >= 8 &&
|
|
||||||
data[0] == 0x89 && data[1] == 0x50 && data[2] == 0x4E && data[3] == 0x47 &&
|
|
||||||
data[4] == 0x0D && data[5] == 0x0A && data[6] == 0x1A && data[7] == 0x0A
|
|
||||||
|
|
||||||
case .gif:
|
|
||||||
return data.count >= 6 && data[0] == 0x47 && data[1] == 0x49 && data[2] == 0x46 &&
|
|
||||||
data[3] == 0x38 && (data[4] == 0x37 || data[4] == 0x39) && data[5] == 0x61
|
|
||||||
|
|
||||||
case .webp:
|
|
||||||
return data.count >= 12 &&
|
|
||||||
data[0] == 0x52 && data[1] == 0x49 && data[2] == 0x46 && data[3] == 0x46 &&
|
|
||||||
data[8] == 0x57 && data[9] == 0x45 && data[10] == 0x42 && data[11] == 0x50
|
|
||||||
|
|
||||||
case .m4a, .mp4Audio, .aac:
|
|
||||||
// AVAudioRecorder output varies by platform - be lenient
|
|
||||||
// Security: size already capped + sandboxed execution
|
|
||||||
return data.count > 100
|
|
||||||
|
|
||||||
case .mpeg, .mp3:
|
|
||||||
if data.count >= 3 && data[0] == 0x49 && data[1] == 0x44 && data[2] == 0x33 {
|
|
||||||
return true // ID3 header
|
|
||||||
}
|
|
||||||
return data.count >= 2 && data[0] == 0xFF && (data[1] & 0xE0) == 0xE0
|
|
||||||
|
|
||||||
case .wav, .xWav:
|
|
||||||
return data.count >= 12 &&
|
|
||||||
data[0] == 0x52 && data[1] == 0x49 && data[2] == 0x46 && data[3] == 0x46 &&
|
|
||||||
data[8] == 0x57 && data[9] == 0x41 && data[10] == 0x56 && data[11] == 0x45
|
|
||||||
|
|
||||||
case .ogg:
|
|
||||||
return data.count >= 4 &&
|
|
||||||
data[0] == 0x4F && data[1] == 0x67 && data[2] == 0x67 && data[3] == 0x53
|
|
||||||
|
|
||||||
case .pdf:
|
|
||||||
return data.count >= 4 &&
|
|
||||||
data[0] == 0x25 && data[1] == 0x50 && data[2] == 0x44 && data[3] == 0x46
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Convenience Initializers
|
|
||||||
|
|
||||||
init?(_ mimeString: String?) {
|
|
||||||
guard let mimeString else { return nil }
|
|
||||||
|
|
||||||
let normalized = mimeString.lowercased()
|
|
||||||
|
|
||||||
// Direct match with our canonical list
|
|
||||||
if let match = MimeType.allCases.first(where: { $0.mimeString == normalized }) {
|
|
||||||
self = match
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let UTType normalize aliases like "image/jpg", "audio/x-wav", etc.
|
|
||||||
if let type = UTType(mimeType: normalized),
|
|
||||||
let match = MimeType.allCases.first(where: { type.conforms(to: $0.utType) }) {
|
|
||||||
self = match
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension MimeType {
|
|
||||||
enum Category: String {
|
|
||||||
case audio, image, file
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -65,6 +65,9 @@ final class CommandProcessor {
|
|||||||
case "/unfav":
|
case "/unfav":
|
||||||
if inGeoPublic || inGeoDM { return .error(message: "favorites are only for mesh peers in #mesh") }
|
if inGeoPublic || inGeoDM { return .error(message: "favorites are only for mesh peers in #mesh") }
|
||||||
return handleFavorite(args, add: false)
|
return handleFavorite(args, add: false)
|
||||||
|
//
|
||||||
|
case "/help", "/h":
|
||||||
|
return .error(message: "unknown command: \(cmd)")
|
||||||
default:
|
default:
|
||||||
return .error(message: "unknown command: \(cmd)")
|
return .error(message: "unknown command: \(cmd)")
|
||||||
}
|
}
|
||||||
@@ -308,4 +311,19 @@ final class CommandProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func handleHelp() -> CommandResult {
|
||||||
|
let helpText = """
|
||||||
|
commands:
|
||||||
|
/msg @name - start private chat
|
||||||
|
/who - list who's online
|
||||||
|
/clear - clear messages
|
||||||
|
/hug @name - send a hug
|
||||||
|
/slap @name - slap with a trout
|
||||||
|
/fav @name - add to favorites
|
||||||
|
/unfav @name - remove from favorites
|
||||||
|
/block @name - block
|
||||||
|
/unblock @name - unblock
|
||||||
|
"""
|
||||||
|
return .success(message: helpText)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,34 @@ final class KeychainManager: KeychainManagerProtocol {
|
|||||||
private let service = BitchatApp.bundleID
|
private let service = BitchatApp.bundleID
|
||||||
private let appGroup = "group.\(BitchatApp.bundleID)"
|
private let appGroup = "group.\(BitchatApp.bundleID)"
|
||||||
|
|
||||||
|
private func isSandboxed() -> Bool {
|
||||||
|
#if os(macOS)
|
||||||
|
// More robust sandbox detection using multiple methods
|
||||||
|
|
||||||
|
// Method 1: Check environment variable (can be spoofed)
|
||||||
|
let environment = ProcessInfo.processInfo.environment
|
||||||
|
let hasEnvVar = environment["APP_SANDBOX_CONTAINER_ID"] != nil
|
||||||
|
|
||||||
|
// Method 2: Check if we can access a path outside sandbox
|
||||||
|
let homeDir = FileManager.default.homeDirectoryForCurrentUser
|
||||||
|
let testPath = homeDir.appendingPathComponent("../../../tmp/bitchat_sandbox_test_\(UUID().uuidString)")
|
||||||
|
let canWriteOutsideSandbox = FileManager.default.createFile(atPath: testPath.path, contents: nil, attributes: nil)
|
||||||
|
if canWriteOutsideSandbox {
|
||||||
|
try? FileManager.default.removeItem(at: testPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method 3: Check container path
|
||||||
|
let containerPath = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first?.path ?? ""
|
||||||
|
let hasContainerPath = containerPath.contains("/Containers/")
|
||||||
|
|
||||||
|
// If any method indicates sandbox, we consider it sandboxed
|
||||||
|
return hasEnvVar || !canWriteOutsideSandbox || hasContainerPath
|
||||||
|
#else
|
||||||
|
// iOS is always sandboxed
|
||||||
|
return true
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Identity Keys
|
// MARK: - Identity Keys
|
||||||
|
|
||||||
func saveIdentityKey(_ keyData: Data, forKey key: String) -> Bool {
|
func saveIdentityKey(_ keyData: Data, forKey key: String) -> Bool {
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
import BitLogger
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct LocationNotesCounterDependencies {
|
||||||
|
typealias RelayLookup = @MainActor (_ geohash: String, _ count: Int) -> [String]
|
||||||
|
typealias Subscribe = @MainActor (_ filter: NostrFilter, _ id: String, _ relays: [String], _ handler: @escaping (NostrEvent) -> Void, _ onEOSE: (() -> Void)?) -> Void
|
||||||
|
typealias Unsubscribe = @MainActor (_ id: String) -> Void
|
||||||
|
|
||||||
|
var relayLookup: RelayLookup
|
||||||
|
var subscribe: Subscribe
|
||||||
|
var unsubscribe: Unsubscribe
|
||||||
|
|
||||||
|
static let live = LocationNotesCounterDependencies(
|
||||||
|
relayLookup: { geohash, count in
|
||||||
|
GeoRelayDirectory.shared.closestRelays(toGeohash: geohash, count: count)
|
||||||
|
},
|
||||||
|
subscribe: { filter, id, relays, handler, onEOSE in
|
||||||
|
NostrRelayManager.shared.subscribe(
|
||||||
|
filter: filter,
|
||||||
|
id: id,
|
||||||
|
relayUrls: relays,
|
||||||
|
handler: handler,
|
||||||
|
onEOSE: onEOSE
|
||||||
|
)
|
||||||
|
},
|
||||||
|
unsubscribe: { id in
|
||||||
|
NostrRelayManager.shared.unsubscribe(id: id)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Lightweight background counter for location notes (kind 1) at building-level geohash (8 chars).
|
||||||
|
@MainActor
|
||||||
|
final class LocationNotesCounter: ObservableObject {
|
||||||
|
static let shared = LocationNotesCounter()
|
||||||
|
|
||||||
|
@Published private(set) var geohash: String? = nil
|
||||||
|
@Published private(set) var count: Int? = 0
|
||||||
|
@Published private(set) var initialLoadComplete: Bool = false
|
||||||
|
@Published private(set) var relayAvailable: Bool = true
|
||||||
|
|
||||||
|
private var subscriptionID: String? = nil
|
||||||
|
private var noteIDs = Set<String>()
|
||||||
|
private let dependencies: LocationNotesCounterDependencies
|
||||||
|
|
||||||
|
private init(dependencies: LocationNotesCounterDependencies = .live) {
|
||||||
|
self.dependencies = dependencies
|
||||||
|
}
|
||||||
|
|
||||||
|
init(testDependencies: LocationNotesCounterDependencies) {
|
||||||
|
self.dependencies = testDependencies
|
||||||
|
}
|
||||||
|
|
||||||
|
func subscribe(geohash gh: String) {
|
||||||
|
let norm = gh.lowercased()
|
||||||
|
if geohash == norm, subscriptionID != nil { return }
|
||||||
|
// Validate geohash (building-level precision: 8 chars)
|
||||||
|
guard Geohash.isValidBuildingGeohash(norm) else {
|
||||||
|
SecureLogger.warning("LocationNotesCounter: rejecting invalid geohash '\(norm)' (expected 8 valid base32 chars)", category: .session)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Unsubscribe previous without clearing count to avoid flicker
|
||||||
|
if let sub = subscriptionID { dependencies.unsubscribe(sub) }
|
||||||
|
subscriptionID = nil
|
||||||
|
geohash = norm
|
||||||
|
noteIDs.removeAll()
|
||||||
|
initialLoadComplete = false
|
||||||
|
relayAvailable = true
|
||||||
|
|
||||||
|
// Subscribe only to the building geohash (precision 8)
|
||||||
|
let subID = "locnotes-count-\(norm)-\(UUID().uuidString.prefix(6))"
|
||||||
|
let relays = dependencies.relayLookup(norm, TransportConfig.nostrGeoRelayCount)
|
||||||
|
guard !relays.isEmpty else {
|
||||||
|
relayAvailable = false
|
||||||
|
initialLoadComplete = true
|
||||||
|
count = 0
|
||||||
|
SecureLogger.warning("LocationNotesCounter: no geo relays for geohash=\(norm)", category: .session)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
subscriptionID = subID
|
||||||
|
let filter = NostrFilter.geohashNotes(norm, since: nil, limit: 200)
|
||||||
|
dependencies.subscribe(filter, subID, relays, { [weak self] event in
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard event.kind == NostrProtocol.EventKind.textNote.rawValue else { return }
|
||||||
|
guard event.tags.contains(where: { $0.count >= 2 && $0[0].lowercased() == "g" && $0[1].lowercased() == norm }) else { return }
|
||||||
|
if !self.noteIDs.contains(event.id) {
|
||||||
|
self.noteIDs.insert(event.id)
|
||||||
|
self.count = self.noteIDs.count
|
||||||
|
}
|
||||||
|
}, { [weak self] in
|
||||||
|
self?.initialLoadComplete = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func cancel() {
|
||||||
|
if let sub = subscriptionID { dependencies.unsubscribe(sub) }
|
||||||
|
subscriptionID = nil
|
||||||
|
geohash = nil
|
||||||
|
count = 0
|
||||||
|
noteIDs.removeAll()
|
||||||
|
relayAvailable = true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -163,22 +163,14 @@ final class LocationNotesManager: ObservableObject {
|
|||||||
|
|
||||||
subscriptionID = subID
|
subscriptionID = subID
|
||||||
initialLoadComplete = false
|
initialLoadComplete = false
|
||||||
|
// For persistent notes, allow relays to return recent history without an aggressive time cutoff
|
||||||
// Subscribe to center + 8 neighbors (± 1 grid)
|
let filter = NostrFilter.geohashNotes(geohash, since: nil, limit: 200)
|
||||||
let neighbors = Geohash.neighbors(of: geohash)
|
|
||||||
let allGeohashes = [geohash] + neighbors
|
|
||||||
let filter = NostrFilter.geohashNotes(allGeohashes, since: nil, limit: 200)
|
|
||||||
|
|
||||||
// Build a set of valid geohashes for tag matching (includes all 9 cells)
|
|
||||||
let validGeohashes = Set(allGeohashes.map { $0.lowercased() })
|
|
||||||
|
|
||||||
dependencies.subscribe(filter, subID, relays, { [weak self] event in
|
dependencies.subscribe(filter, subID, relays, { [weak self] event in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
guard event.kind == NostrProtocol.EventKind.textNote.rawValue else { return }
|
guard event.kind == NostrProtocol.EventKind.textNote.rawValue else { return }
|
||||||
// Ensure matching tag - accept any of our 9 geohashes
|
// Ensure matching tag
|
||||||
guard event.tags.contains(where: { tag in
|
guard event.tags.contains(where: { $0.count >= 2 && $0[0].lowercased() == "g" && $0[1].lowercased() == self.geohash }) else { return }
|
||||||
tag.count >= 2 && tag[0].lowercased() == "g" && validGeohashes.contains(tag[1].lowercased())
|
|
||||||
}) else { return }
|
|
||||||
guard !self.noteIDs.contains(event.id) else { return }
|
guard !self.noteIDs.contains(event.id) else { return }
|
||||||
self.noteIDs.insert(event.id)
|
self.noteIDs.insert(event.id)
|
||||||
let nick = event.tags.first(where: { $0.first?.lowercased() == "n" && $0.count >= 2 })?.dropFirst().first
|
let nick = event.tags.first(where: { $0.first?.lowercased() == "n" && $0.count >= 2 })?.dropFirst().first
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
/// Tracks observed mesh topology and computes hop-by-hop routes.
|
|
||||||
final class MeshTopologyTracker {
|
|
||||||
private typealias RoutingID = Data
|
|
||||||
|
|
||||||
private let queue = DispatchQueue(label: "mesh.topology", attributes: .concurrent)
|
|
||||||
private let hopSize = 8
|
|
||||||
private var adjacency: [RoutingID: Set<RoutingID>] = [:]
|
|
||||||
|
|
||||||
func reset() {
|
|
||||||
queue.sync(flags: .barrier) {
|
|
||||||
self.adjacency.removeAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func recordDirectLink(between a: Data?, and b: Data?) {
|
|
||||||
guard let left = sanitize(a), let right = sanitize(b), left != right else { return }
|
|
||||||
queue.sync(flags: .barrier) {
|
|
||||||
var setA = self.adjacency[left] ?? []
|
|
||||||
setA.insert(right)
|
|
||||||
self.adjacency[left] = setA
|
|
||||||
|
|
||||||
var setB = self.adjacency[right] ?? []
|
|
||||||
setB.insert(left)
|
|
||||||
self.adjacency[right] = setB
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeDirectLink(between a: Data?, and b: Data?) {
|
|
||||||
guard let left = sanitize(a), let right = sanitize(b), left != right else { return }
|
|
||||||
queue.sync(flags: .barrier) {
|
|
||||||
if var setA = self.adjacency[left] {
|
|
||||||
setA.remove(right)
|
|
||||||
self.adjacency[left] = setA.isEmpty ? nil : setA
|
|
||||||
}
|
|
||||||
if var setB = self.adjacency[right] {
|
|
||||||
setB.remove(left)
|
|
||||||
self.adjacency[right] = setB.isEmpty ? nil : setB
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func removePeer(_ data: Data?) {
|
|
||||||
guard let peer = sanitize(data) else { return }
|
|
||||||
queue.sync(flags: .barrier) {
|
|
||||||
guard let neighbors = self.adjacency.removeValue(forKey: peer) else { return }
|
|
||||||
for neighbor in neighbors {
|
|
||||||
if var set = self.adjacency[neighbor] {
|
|
||||||
set.remove(peer)
|
|
||||||
self.adjacency[neighbor] = set.isEmpty ? nil : set
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func recordRoute(_ hops: [Data]) {
|
|
||||||
let sanitized = hops.compactMap { sanitize($0) }
|
|
||||||
guard sanitized.count >= 2 else { return }
|
|
||||||
queue.sync(flags: .barrier) {
|
|
||||||
for idx in 0..<(sanitized.count - 1) {
|
|
||||||
let left = sanitized[idx]
|
|
||||||
let right = sanitized[idx + 1]
|
|
||||||
guard left != right else { continue }
|
|
||||||
|
|
||||||
var setA = self.adjacency[left] ?? []
|
|
||||||
setA.insert(right)
|
|
||||||
self.adjacency[left] = setA
|
|
||||||
|
|
||||||
var setB = self.adjacency[right] ?? []
|
|
||||||
setB.insert(left)
|
|
||||||
self.adjacency[right] = setB
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func computeRoute(from start: Data?, to goal: Data?, maxHops: Int = 255) -> [Data]? {
|
|
||||||
guard let source = sanitize(start), let target = sanitize(goal) else { return nil }
|
|
||||||
if source == target { return [source] }
|
|
||||||
|
|
||||||
let graph = queue.sync { adjacency }
|
|
||||||
guard graph[source] != nil, graph[target] != nil else { return nil }
|
|
||||||
|
|
||||||
var visited: Set<RoutingID> = [source]
|
|
||||||
var queuePaths: [[RoutingID]] = [[source]]
|
|
||||||
var index = 0
|
|
||||||
|
|
||||||
while index < queuePaths.count {
|
|
||||||
let path = queuePaths[index]
|
|
||||||
index += 1
|
|
||||||
guard path.count <= maxHops else { continue }
|
|
||||||
guard let last = path.last, let neighbors = graph[last] else { continue }
|
|
||||||
|
|
||||||
for neighbor in neighbors {
|
|
||||||
if visited.contains(neighbor) { continue }
|
|
||||||
var nextPath = path
|
|
||||||
nextPath.append(neighbor)
|
|
||||||
if neighbor == target { return nextPath }
|
|
||||||
if nextPath.count <= maxHops {
|
|
||||||
queuePaths.append(nextPath)
|
|
||||||
}
|
|
||||||
visited.insert(neighbor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Helpers
|
|
||||||
|
|
||||||
private func sanitize(_ data: Data?) -> Data? {
|
|
||||||
guard var value = data, !value.isEmpty else { return nil }
|
|
||||||
if value.count > hopSize {
|
|
||||||
value = Data(value.prefix(hopSize))
|
|
||||||
} else if value.count < hopSize {
|
|
||||||
value.append(Data(repeating: 0, count: hopSize - value.count))
|
|
||||||
}
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -177,18 +177,18 @@ final class NoiseEncryptionService {
|
|||||||
private let rekeyCheckInterval: TimeInterval = 60.0 // Check every minute
|
private let rekeyCheckInterval: TimeInterval = 60.0 // Check every minute
|
||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
private var onPeerAuthenticatedHandlers: [((PeerID, String) -> Void)] = [] // Array of handlers for peer authentication
|
private var onPeerAuthenticatedHandlers: [((String, String) -> Void)] = [] // Array of handlers for peer authentication
|
||||||
var onHandshakeRequired: ((PeerID) -> Void)? // peerID needs handshake
|
var onHandshakeRequired: ((PeerID) -> Void)? // peerID needs handshake
|
||||||
|
|
||||||
// Add a handler for peer authentication
|
// Add a handler for peer authentication
|
||||||
func addOnPeerAuthenticatedHandler(_ handler: @escaping (PeerID, String) -> Void) {
|
func addOnPeerAuthenticatedHandler(_ handler: @escaping (String, String) -> Void) {
|
||||||
serviceQueue.async(flags: .barrier) { [weak self] in
|
serviceQueue.async(flags: .barrier) { [weak self] in
|
||||||
self?.onPeerAuthenticatedHandlers.append(handler)
|
self?.onPeerAuthenticatedHandlers.append(handler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Legacy support - setting this will add to the handlers array
|
// Legacy support - setting this will add to the handlers array
|
||||||
var onPeerAuthenticated: ((PeerID, String) -> Void)? {
|
var onPeerAuthenticated: ((String, String) -> Void)? {
|
||||||
get { nil } // Always return nil for backward compatibility
|
get { nil } // Always return nil for backward compatibility
|
||||||
set {
|
set {
|
||||||
if let handler = newValue {
|
if let handler = newValue {
|
||||||
@@ -546,7 +546,7 @@ final class NoiseEncryptionService {
|
|||||||
// Notify all handlers about authentication
|
// Notify all handlers about authentication
|
||||||
serviceQueue.async { [weak self] in
|
serviceQueue.async { [weak self] in
|
||||||
self?.onPeerAuthenticatedHandlers.forEach { handler in
|
self?.onPeerAuthenticatedHandlers.forEach { handler in
|
||||||
handler(peerID, fingerprint)
|
handler(peerID.id, fingerprint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ final class NostrTransport: Transport {
|
|||||||
SecureLogger.error("NostrTransport: failed to decode npub -> hex: \(error)", category: .session)
|
SecureLogger.error("NostrTransport: failed to decode npub -> hex: \(error)", category: .session)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let embedded = NostrEmbeddedBitChat.encodePMForNostr(content: content, messageID: messageID, recipientPeerID: peerID, senderPeerID: senderPeerID) else {
|
guard let embedded = NostrEmbeddedBitChat.encodePMForNostr(content: content, messageID: messageID, recipientPeerID: peerID.id, senderPeerID: senderPeerID.id) else {
|
||||||
SecureLogger.error("NostrTransport: failed to embed PM packet", category: .session)
|
SecureLogger.error("NostrTransport: failed to embed PM packet", category: .session)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -114,7 +114,7 @@ final class NostrTransport: Transport {
|
|||||||
guard hrp == "npub" else { return }
|
guard hrp == "npub" else { return }
|
||||||
recipientHex = data.hexEncodedString()
|
recipientHex = data.hexEncodedString()
|
||||||
} catch { return }
|
} catch { return }
|
||||||
guard let embedded = NostrEmbeddedBitChat.encodePMForNostr(content: content, messageID: UUID().uuidString, recipientPeerID: peerID, senderPeerID: senderPeerID) else {
|
guard let embedded = NostrEmbeddedBitChat.encodePMForNostr(content: content, messageID: UUID().uuidString, recipientPeerID: peerID.id, senderPeerID: senderPeerID.id) else {
|
||||||
SecureLogger.error("NostrTransport: failed to embed favorite notification", category: .session)
|
SecureLogger.error("NostrTransport: failed to embed favorite notification", category: .session)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ final class NostrTransport: Transport {
|
|||||||
guard hrp == "npub" else { return }
|
guard hrp == "npub" else { return }
|
||||||
recipientHex = data.hexEncodedString()
|
recipientHex = data.hexEncodedString()
|
||||||
} catch { return }
|
} catch { return }
|
||||||
guard let ack = NostrEmbeddedBitChat.encodeAckForNostr(type: .delivered, messageID: messageID, recipientPeerID: peerID, senderPeerID: senderPeerID) else {
|
guard let ack = NostrEmbeddedBitChat.encodeAckForNostr(type: .delivered, messageID: messageID, recipientPeerID: peerID.id, senderPeerID: senderPeerID.id) else {
|
||||||
SecureLogger.error("NostrTransport: failed to embed DELIVERED ack", category: .session)
|
SecureLogger.error("NostrTransport: failed to embed DELIVERED ack", category: .session)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ extension NostrTransport {
|
|||||||
func sendDeliveryAckGeohash(for messageID: String, toRecipientHex recipientHex: String, from identity: NostrIdentity) {
|
func sendDeliveryAckGeohash(for messageID: String, toRecipientHex recipientHex: String, from identity: NostrIdentity) {
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
SecureLogger.debug("GeoDM: send DELIVERED -> recip=\(recipientHex.prefix(8))… mid=\(messageID.prefix(8))… from=\(identity.publicKeyHex.prefix(8))…", category: .session)
|
SecureLogger.debug("GeoDM: send DELIVERED -> recip=\(recipientHex.prefix(8))… mid=\(messageID.prefix(8))… from=\(identity.publicKeyHex.prefix(8))…", category: .session)
|
||||||
guard let embedded = NostrEmbeddedBitChat.encodeAckForNostrNoRecipient(type: .delivered, messageID: messageID, senderPeerID: senderPeerID) else { return }
|
guard let embedded = NostrEmbeddedBitChat.encodeAckForNostrNoRecipient(type: .delivered, messageID: messageID, senderPeerID: senderPeerID.id) else { return }
|
||||||
guard let event = try? NostrProtocol.createPrivateMessage(content: embedded, recipientPubkey: recipientHex, senderIdentity: identity) else { return }
|
guard let event = try? NostrProtocol.createPrivateMessage(content: embedded, recipientPubkey: recipientHex, senderIdentity: identity) else { return }
|
||||||
NostrRelayManager.registerPendingGiftWrap(id: event.id)
|
NostrRelayManager.registerPendingGiftWrap(id: event.id)
|
||||||
NostrRelayManager.shared.sendEvent(event)
|
NostrRelayManager.shared.sendEvent(event)
|
||||||
@@ -171,7 +171,7 @@ extension NostrTransport {
|
|||||||
func sendReadReceiptGeohash(_ messageID: String, toRecipientHex recipientHex: String, from identity: NostrIdentity) {
|
func sendReadReceiptGeohash(_ messageID: String, toRecipientHex recipientHex: String, from identity: NostrIdentity) {
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
SecureLogger.debug("GeoDM: send READ -> recip=\(recipientHex.prefix(8))… mid=\(messageID.prefix(8))… from=\(identity.publicKeyHex.prefix(8))…", category: .session)
|
SecureLogger.debug("GeoDM: send READ -> recip=\(recipientHex.prefix(8))… mid=\(messageID.prefix(8))… from=\(identity.publicKeyHex.prefix(8))…", category: .session)
|
||||||
guard let embedded = NostrEmbeddedBitChat.encodeAckForNostrNoRecipient(type: .readReceipt, messageID: messageID, senderPeerID: senderPeerID) else { return }
|
guard let embedded = NostrEmbeddedBitChat.encodeAckForNostrNoRecipient(type: .readReceipt, messageID: messageID, senderPeerID: senderPeerID.id) else { return }
|
||||||
guard let event = try? NostrProtocol.createPrivateMessage(content: embedded, recipientPubkey: recipientHex, senderIdentity: identity) else { return }
|
guard let event = try? NostrProtocol.createPrivateMessage(content: embedded, recipientPubkey: recipientHex, senderIdentity: identity) else { return }
|
||||||
NostrRelayManager.registerPendingGiftWrap(id: event.id)
|
NostrRelayManager.registerPendingGiftWrap(id: event.id)
|
||||||
NostrRelayManager.shared.sendEvent(event)
|
NostrRelayManager.shared.sendEvent(event)
|
||||||
@@ -184,7 +184,7 @@ extension NostrTransport {
|
|||||||
guard !recipientHex.isEmpty else { return }
|
guard !recipientHex.isEmpty else { return }
|
||||||
SecureLogger.debug("GeoDM: send PM -> recip=\(recipientHex.prefix(8))… mid=\(messageID.prefix(8))… from=\(identity.publicKeyHex.prefix(8))…", category: .session)
|
SecureLogger.debug("GeoDM: send PM -> recip=\(recipientHex.prefix(8))… mid=\(messageID.prefix(8))… from=\(identity.publicKeyHex.prefix(8))…", category: .session)
|
||||||
// Build embedded BitChat packet without recipient peer ID
|
// Build embedded BitChat packet without recipient peer ID
|
||||||
guard let embedded = NostrEmbeddedBitChat.encodePMForNostrNoRecipient(content: content, messageID: messageID, senderPeerID: senderPeerID) else {
|
guard let embedded = NostrEmbeddedBitChat.encodePMForNostrNoRecipient(content: content, messageID: messageID, senderPeerID: senderPeerID.id) else {
|
||||||
SecureLogger.error("NostrTransport: failed to embed geohash PM packet", category: .session)
|
SecureLogger.error("NostrTransport: failed to embed geohash PM packet", category: .session)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -223,7 +223,7 @@ extension NostrTransport {
|
|||||||
guard hrp == "npub" else { scheduleNextReadAck(); return }
|
guard hrp == "npub" else { scheduleNextReadAck(); return }
|
||||||
recipientHex = data.hexEncodedString()
|
recipientHex = data.hexEncodedString()
|
||||||
} catch { scheduleNextReadAck(); return }
|
} catch { scheduleNextReadAck(); return }
|
||||||
guard let ack = NostrEmbeddedBitChat.encodeAckForNostr(type: .readReceipt, messageID: item.receipt.originalMessageID, recipientPeerID: item.peerID, senderPeerID: senderPeerID) else {
|
guard let ack = NostrEmbeddedBitChat.encodeAckForNostr(type: .readReceipt, messageID: item.receipt.originalMessageID, recipientPeerID: item.peerID.id, senderPeerID: senderPeerID.id) else {
|
||||||
SecureLogger.error("NostrTransport: failed to embed READ ack", category: .session)
|
SecureLogger.error("NostrTransport: failed to embed READ ack", category: .session)
|
||||||
scheduleNextReadAck(); return
|
scheduleNextReadAck(); return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,19 +29,14 @@ final class NotificationService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendLocalNotification(
|
func sendLocalNotification(title: String, body: String, identifier: String, userInfo: [String: Any]? = nil) {
|
||||||
title: String,
|
// For now, skip app state check entirely to avoid thread issues
|
||||||
body: String,
|
// The NotificationDelegate will handle foreground presentation
|
||||||
identifier: String,
|
DispatchQueue.main.async {
|
||||||
userInfo: [String: Any]? = nil,
|
|
||||||
interruptionLevel: UNNotificationInterruptionLevel = .active
|
|
||||||
) {
|
|
||||||
let content = UNMutableNotificationContent()
|
let content = UNMutableNotificationContent()
|
||||||
content.title = title
|
content.title = title
|
||||||
content.body = body
|
content.body = body
|
||||||
content.sound = .default
|
content.sound = .default
|
||||||
content.interruptionLevel = interruptionLevel
|
|
||||||
|
|
||||||
if let userInfo = userInfo {
|
if let userInfo = userInfo {
|
||||||
content.userInfo = userInfo
|
content.userInfo = userInfo
|
||||||
}
|
}
|
||||||
@@ -52,7 +47,10 @@ final class NotificationService {
|
|||||||
trigger: nil // Deliver immediately
|
trigger: nil // Deliver immediately
|
||||||
)
|
)
|
||||||
|
|
||||||
UNUserNotificationCenter.current().add(request)
|
UNUserNotificationCenter.current().add(request) { _ in
|
||||||
|
// Notification added
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendMentionNotification(from sender: String, message: String) {
|
func sendMentionNotification(from sender: String, message: String) {
|
||||||
@@ -63,11 +61,11 @@ final class NotificationService {
|
|||||||
sendLocalNotification(title: title, body: body, identifier: identifier)
|
sendLocalNotification(title: title, body: body, identifier: identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendPrivateMessageNotification(from sender: String, message: String, peerID: PeerID) {
|
func sendPrivateMessageNotification(from sender: String, message: String, peerID: String) {
|
||||||
let title = "🔒 DM from \(sender)"
|
let title = "🔒 DM from \(sender)"
|
||||||
let body = message
|
let body = message
|
||||||
let identifier = "private-\(UUID().uuidString)"
|
let identifier = "private-\(UUID().uuidString)"
|
||||||
let userInfo = ["peerID": peerID.id, "senderName": sender]
|
let userInfo = ["peerID": peerID, "senderName": sender]
|
||||||
|
|
||||||
sendLocalNotification(title: title, body: body, identifier: identifier, userInfo: userInfo)
|
sendLocalNotification(title: title, body: body, identifier: identifier, userInfo: userInfo)
|
||||||
}
|
}
|
||||||
@@ -86,11 +84,24 @@ final class NotificationService {
|
|||||||
let body = peerCount == 1 ? "1 person around" : "\(peerCount) people around"
|
let body = peerCount == 1 ? "1 person around" : "\(peerCount) people around"
|
||||||
let identifier = "network-available-\(Date().timeIntervalSince1970)"
|
let identifier = "network-available-\(Date().timeIntervalSince1970)"
|
||||||
|
|
||||||
sendLocalNotification(
|
// For network notifications, we want to show them even in foreground
|
||||||
title: title,
|
// No app state check - let the notification delegate handle presentation
|
||||||
body: body,
|
DispatchQueue.main.async {
|
||||||
|
let content = UNMutableNotificationContent()
|
||||||
|
content.title = title
|
||||||
|
content.body = body
|
||||||
|
content.sound = .default
|
||||||
|
content.interruptionLevel = .timeSensitive // Make it more prominent
|
||||||
|
|
||||||
|
let request = UNNotificationRequest(
|
||||||
identifier: identifier,
|
identifier: identifier,
|
||||||
interruptionLevel: .timeSensitive
|
content: content,
|
||||||
|
trigger: nil // Deliver immediately
|
||||||
)
|
)
|
||||||
|
|
||||||
|
UNUserNotificationCenter.current().add(request) { _ in
|
||||||
|
// Notification added
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ final class PrivateChatManager: ObservableObject {
|
|||||||
// Create read receipt using the simplified method
|
// Create read receipt using the simplified method
|
||||||
let receipt = ReadReceipt(
|
let receipt = ReadReceipt(
|
||||||
originalMessageID: message.id,
|
originalMessageID: message.id,
|
||||||
readerID: meshService?.myPeerID ?? PeerID(str: ""),
|
readerID: meshService?.myPeerID.id ?? "",
|
||||||
readerNickname: meshService?.myNickname ?? ""
|
readerNickname: meshService?.myNickname ?? ""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ struct RelayController {
|
|||||||
senderIsSelf: Bool,
|
senderIsSelf: Bool,
|
||||||
isEncrypted: Bool,
|
isEncrypted: Bool,
|
||||||
isDirectedEncrypted: Bool,
|
isDirectedEncrypted: Bool,
|
||||||
isFragment: Bool,
|
|
||||||
isDirectedFragment: Bool,
|
isDirectedFragment: Bool,
|
||||||
isHandshake: Bool,
|
isHandshake: Bool,
|
||||||
isAnnounce: Bool,
|
isAnnounce: Bool,
|
||||||
@@ -37,16 +36,6 @@ struct RelayController {
|
|||||||
return RelayDecision(shouldRelay: true, newTTL: newTTL, delayMs: delayMs)
|
return RelayDecision(shouldRelay: true, newTTL: newTTL, delayMs: delayMs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if isFragment {
|
|
||||||
let ttlLimit = min(ttlCap, TransportConfig.bleFragmentRelayTtlCap)
|
|
||||||
guard ttlLimit > 1 else {
|
|
||||||
return RelayDecision(shouldRelay: false, newTTL: ttlLimit, delayMs: 0)
|
|
||||||
}
|
|
||||||
let newTTL = ttlLimit &- 1
|
|
||||||
let delayMs = Int.random(in: TransportConfig.bleFragmentRelayMinDelayMs...TransportConfig.bleFragmentRelayMaxDelayMs)
|
|
||||||
return RelayDecision(shouldRelay: true, newTTL: newTTL, delayMs: delayMs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TTL clamping for broadcast
|
// TTL clamping for broadcast
|
||||||
// - Dense graphs: keep lower but still allow multi-hop bridging
|
// - Dense graphs: keep lower but still allow multi-hop bridging
|
||||||
// - Announces get a bit more headroom
|
// - Announces get a bit more headroom
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ protocol Transport: AnyObject {
|
|||||||
|
|
||||||
// Messaging
|
// Messaging
|
||||||
func sendMessage(_ content: String, mentions: [String])
|
func sendMessage(_ content: String, mentions: [String])
|
||||||
func sendMessage(_ content: String, mentions: [String], messageID: String, timestamp: Date)
|
|
||||||
func sendPrivateMessage(_ content: String, to peerID: PeerID, recipientNickname: String, messageID: String)
|
func sendPrivateMessage(_ content: String, to peerID: PeerID, recipientNickname: String, messageID: String)
|
||||||
func sendReadReceipt(_ receipt: ReadReceipt, to peerID: PeerID)
|
func sendReadReceipt(_ receipt: ReadReceipt, to peerID: PeerID)
|
||||||
func sendFavoriteNotification(to peerID: PeerID, isFavorite: Bool)
|
func sendFavoriteNotification(to peerID: PeerID, isFavorite: Bool)
|
||||||
@@ -66,10 +65,6 @@ extension Transport {
|
|||||||
func sendFileBroadcast(_ packet: BitchatFilePacket, transferId: String) {}
|
func sendFileBroadcast(_ packet: BitchatFilePacket, transferId: String) {}
|
||||||
func sendFilePrivate(_ packet: BitchatFilePacket, to peerID: PeerID, transferId: String) {}
|
func sendFilePrivate(_ packet: BitchatFilePacket, to peerID: PeerID, transferId: String) {}
|
||||||
func cancelTransfer(_ transferId: String) {}
|
func cancelTransfer(_ transferId: String) {}
|
||||||
|
|
||||||
func sendMessage(_ content: String, mentions: [String], messageID: String, timestamp: Date) {
|
|
||||||
sendMessage(content, mentions: mentions)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol TransportPeerEventsDelegate: AnyObject {
|
protocol TransportPeerEventsDelegate: AnyObject {
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ enum TransportConfig {
|
|||||||
static let messageTTLDefault: UInt8 = 7 // Default TTL for mesh flooding
|
static let messageTTLDefault: UInt8 = 7 // Default TTL for mesh flooding
|
||||||
static let bleMaxInFlightAssemblies: Int = 128 // Cap concurrent fragment assemblies
|
static let bleMaxInFlightAssemblies: Int = 128 // Cap concurrent fragment assemblies
|
||||||
static let bleHighDegreeThreshold: Int = 6 // For adaptive TTL/probabilistic relays
|
static let bleHighDegreeThreshold: Int = 6 // For adaptive TTL/probabilistic relays
|
||||||
static let bleMaxConcurrentTransfers: Int = 2 // Limit simultaneous large media sends
|
|
||||||
static let bleFragmentRelayMinDelayMs: Int = 8 // Faster forwarding for media fragments
|
|
||||||
static let bleFragmentRelayMaxDelayMs: Int = 25 // Upper jitter bound for fragment relays
|
|
||||||
static let bleFragmentRelayTtlCap: UInt8 = 5 // Clamp fragment TTL to contain floods
|
|
||||||
|
|
||||||
// UI / Storage Caps
|
// UI / Storage Caps
|
||||||
static let privateChatCap: Int = 1337
|
static let privateChatCap: Int = 1337
|
||||||
@@ -70,7 +66,6 @@ enum TransportConfig {
|
|||||||
static let uiAnimationMediumSeconds: TimeInterval = 0.2
|
static let uiAnimationMediumSeconds: TimeInterval = 0.2
|
||||||
static let uiAnimationSidebarSeconds: TimeInterval = 0.25
|
static let uiAnimationSidebarSeconds: TimeInterval = 0.25
|
||||||
static let uiRecentCutoffFiveMinutesSeconds: TimeInterval = 5 * 60
|
static let uiRecentCutoffFiveMinutesSeconds: TimeInterval = 5 * 60
|
||||||
static let uiMeshEmptyConfirmationSeconds: TimeInterval = 30.0
|
|
||||||
|
|
||||||
// BLE maintenance & thresholds
|
// BLE maintenance & thresholds
|
||||||
static let bleMaintenanceInterval: TimeInterval = 5.0
|
static let bleMaintenanceInterval: TimeInterval = 5.0
|
||||||
@@ -150,9 +145,6 @@ enum TransportConfig {
|
|||||||
|
|
||||||
// Geo relay directory
|
// Geo relay directory
|
||||||
static let geoRelayFetchIntervalSeconds: TimeInterval = 60 * 60 * 24
|
static let geoRelayFetchIntervalSeconds: TimeInterval = 60 * 60 * 24
|
||||||
static let geoRelayRefreshCheckIntervalSeconds: TimeInterval = 60 * 60
|
|
||||||
static let geoRelayRetryInitialSeconds: TimeInterval = 60
|
|
||||||
static let geoRelayRetryMaxSeconds: TimeInterval = 60 * 60
|
|
||||||
|
|
||||||
// BLE operational delays
|
// BLE operational delays
|
||||||
static let bleInitialAnnounceDelaySeconds: TimeInterval = 0.6
|
static let bleInitialAnnounceDelaySeconds: TimeInterval = 0.6
|
||||||
|
|||||||
@@ -8,55 +8,6 @@ final class GossipSyncManager {
|
|||||||
func signPacketForBroadcast(_ packet: BitchatPacket) -> BitchatPacket
|
func signPacketForBroadcast(_ packet: BitchatPacket) -> BitchatPacket
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct PacketStore {
|
|
||||||
private(set) var packets: [String: BitchatPacket] = [:]
|
|
||||||
private(set) var order: [String] = []
|
|
||||||
|
|
||||||
mutating func insert(idHex: String, packet: BitchatPacket, capacity: Int) {
|
|
||||||
guard capacity > 0 else { return }
|
|
||||||
if packets[idHex] != nil {
|
|
||||||
packets[idHex] = packet
|
|
||||||
return
|
|
||||||
}
|
|
||||||
packets[idHex] = packet
|
|
||||||
order.append(idHex)
|
|
||||||
while order.count > capacity {
|
|
||||||
let victim = order.removeFirst()
|
|
||||||
packets.removeValue(forKey: victim)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func allPackets(isFresh: (BitchatPacket) -> Bool) -> [BitchatPacket] {
|
|
||||||
order.compactMap { key in
|
|
||||||
guard let packet = packets[key], isFresh(packet) else { return nil }
|
|
||||||
return packet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func remove(where shouldRemove: (BitchatPacket) -> Bool) {
|
|
||||||
var nextOrder: [String] = []
|
|
||||||
for key in order {
|
|
||||||
guard let packet = packets[key] else { continue }
|
|
||||||
if shouldRemove(packet) {
|
|
||||||
packets.removeValue(forKey: key)
|
|
||||||
} else {
|
|
||||||
nextOrder.append(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
order = nextOrder
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func removeExpired(isFresh: (BitchatPacket) -> Bool) {
|
|
||||||
remove { !isFresh($0) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct SyncSchedule {
|
|
||||||
let types: SyncTypeFlags
|
|
||||||
let interval: TimeInterval
|
|
||||||
var lastSent: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
var seenCapacity: Int = 1000 // max packets per sync (cap across types)
|
var seenCapacity: Int = 1000 // max packets per sync (cap across types)
|
||||||
var gcsMaxBytes: Int = 400 // filter size budget (128..1024)
|
var gcsMaxBytes: Int = 400 // filter size budget (128..1024)
|
||||||
@@ -65,43 +16,25 @@ final class GossipSyncManager {
|
|||||||
var maintenanceIntervalSeconds: TimeInterval = 30.0
|
var maintenanceIntervalSeconds: TimeInterval = 30.0
|
||||||
var stalePeerCleanupIntervalSeconds: TimeInterval = 60.0
|
var stalePeerCleanupIntervalSeconds: TimeInterval = 60.0
|
||||||
var stalePeerTimeoutSeconds: TimeInterval = 60.0
|
var stalePeerTimeoutSeconds: TimeInterval = 60.0
|
||||||
var fragmentCapacity: Int = 600
|
|
||||||
var fileTransferCapacity: Int = 200
|
|
||||||
var fragmentSyncIntervalSeconds: TimeInterval = 30.0
|
|
||||||
var fileTransferSyncIntervalSeconds: TimeInterval = 60.0
|
|
||||||
var messageSyncIntervalSeconds: TimeInterval = 15.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private let myPeerID: PeerID
|
private let myPeerID: PeerID
|
||||||
private let config: Config
|
private let config: Config
|
||||||
weak var delegate: Delegate?
|
weak var delegate: Delegate?
|
||||||
|
|
||||||
// Storage: broadcast packets by type, and latest announce per sender
|
// Storage: broadcast messages (ordered by insert), and latest announce per sender
|
||||||
private var messages = PacketStore()
|
private var messages: [String: BitchatPacket] = [:] // idHex -> packet
|
||||||
private var fragments = PacketStore()
|
private var messageOrder: [String] = []
|
||||||
private var fileTransfers = PacketStore()
|
private var latestAnnouncementByPeer: [String: (id: String, packet: BitchatPacket)] = [:]
|
||||||
private var latestAnnouncementByPeer: [PeerID: (id: String, packet: BitchatPacket)] = [:]
|
|
||||||
|
|
||||||
// Timer
|
// Timer
|
||||||
private var periodicTimer: DispatchSourceTimer?
|
private var periodicTimer: DispatchSourceTimer?
|
||||||
private let queue = DispatchQueue(label: "mesh.sync", qos: .utility)
|
private let queue = DispatchQueue(label: "mesh.sync", qos: .utility)
|
||||||
private var lastStalePeerCleanup: Date = .distantPast
|
private var lastStalePeerCleanup: Date = .distantPast
|
||||||
private var syncSchedules: [SyncSchedule] = []
|
|
||||||
|
|
||||||
init(myPeerID: PeerID, config: Config = Config()) {
|
init(myPeerID: PeerID, config: Config = Config()) {
|
||||||
self.myPeerID = myPeerID
|
self.myPeerID = myPeerID
|
||||||
self.config = config
|
self.config = config
|
||||||
var schedules: [SyncSchedule] = []
|
|
||||||
if config.seenCapacity > 0 && config.messageSyncIntervalSeconds > 0 {
|
|
||||||
schedules.append(SyncSchedule(types: .publicMessages, interval: config.messageSyncIntervalSeconds, lastSent: .distantPast))
|
|
||||||
}
|
|
||||||
if config.fragmentCapacity > 0 && config.fragmentSyncIntervalSeconds > 0 {
|
|
||||||
schedules.append(SyncSchedule(types: .fragment, interval: config.fragmentSyncIntervalSeconds, lastSent: .distantPast))
|
|
||||||
}
|
|
||||||
if config.fileTransferCapacity > 0 && config.fileTransferSyncIntervalSeconds > 0 {
|
|
||||||
schedules.append(SyncSchedule(types: .fileTransfer, interval: config.fileTransferSyncIntervalSeconds, lastSent: .distantPast))
|
|
||||||
}
|
|
||||||
syncSchedules = schedules
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func start() {
|
func start() {
|
||||||
@@ -122,18 +55,7 @@ final class GossipSyncManager {
|
|||||||
|
|
||||||
func scheduleInitialSyncToPeer(_ peerID: PeerID, delaySeconds: TimeInterval = 5.0) {
|
func scheduleInitialSyncToPeer(_ peerID: PeerID, delaySeconds: TimeInterval = 5.0) {
|
||||||
queue.asyncAfter(deadline: .now() + delaySeconds) { [weak self] in
|
queue.asyncAfter(deadline: .now() + delaySeconds) { [weak self] in
|
||||||
guard let self = self else { return }
|
self?.sendRequestSync(to: peerID)
|
||||||
self.sendRequestSync(to: peerID, types: .publicMessages)
|
|
||||||
if self.config.fragmentCapacity > 0 && self.config.fragmentSyncIntervalSeconds > 0 {
|
|
||||||
self.queue.asyncAfter(deadline: .now() + 0.5) { [weak self] in
|
|
||||||
self?.sendRequestSync(to: peerID, types: .fragment)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if self.config.fileTransferCapacity > 0 && self.config.fileTransferSyncIntervalSeconds > 0 {
|
|
||||||
self.queue.asyncAfter(deadline: .now() + 1.0) { [weak self] in
|
|
||||||
self?.sendRequestSync(to: peerID, types: .fileTransfer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,45 +87,47 @@ final class GossipSyncManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func _onPublicPacketSeen(_ packet: BitchatPacket) {
|
private func _onPublicPacketSeen(_ packet: BitchatPacket) {
|
||||||
guard let messageType = MessageType(rawValue: packet.type) else { return }
|
let mt = MessageType(rawValue: packet.type)
|
||||||
let isBroadcastRecipient: Bool = {
|
let isBroadcastRecipient: Bool = {
|
||||||
guard let r = packet.recipientID else { return true }
|
guard let r = packet.recipientID else { return true }
|
||||||
return r.count == 8 && r.allSatisfy { $0 == 0xFF }
|
return r.count == 8 && r.allSatisfy { $0 == 0xFF }
|
||||||
}()
|
}()
|
||||||
|
let isBroadcastMessage = (mt == .message && isBroadcastRecipient)
|
||||||
|
let isAnnounce = (mt == .announce)
|
||||||
|
guard isBroadcastMessage || isAnnounce else { return }
|
||||||
|
|
||||||
switch messageType {
|
// Reject expired packets to prevent ghost peers and old messages
|
||||||
case .announce:
|
|
||||||
guard isPacketFresh(packet) else { return }
|
guard isPacketFresh(packet) else { return }
|
||||||
|
|
||||||
|
if isAnnounce {
|
||||||
guard isAnnouncementFresh(packet) else {
|
guard isAnnouncementFresh(packet) else {
|
||||||
let sender = PeerID(hexData: packet.senderID)
|
let sender = packet.senderID.hexEncodedString().lowercased()
|
||||||
removeState(for: sender)
|
removeState(forNormalizedPeerID: sender)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let idHex = PacketIdUtil.computeId(packet).hexEncodedString()
|
let idHex = PacketIdUtil.computeId(packet).hexEncodedString()
|
||||||
let sender = PeerID(hexData: packet.senderID)
|
|
||||||
|
if isBroadcastMessage {
|
||||||
|
if messages[idHex] == nil {
|
||||||
|
messages[idHex] = packet
|
||||||
|
messageOrder.append(idHex)
|
||||||
|
// Enforce capacity
|
||||||
|
let cap = max(1, config.seenCapacity)
|
||||||
|
while messageOrder.count > cap {
|
||||||
|
let victim = messageOrder.removeFirst()
|
||||||
|
messages.removeValue(forKey: victim)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if isAnnounce {
|
||||||
|
let sender = packet.senderID.hexEncodedString().lowercased()
|
||||||
latestAnnouncementByPeer[sender] = (id: idHex, packet: packet)
|
latestAnnouncementByPeer[sender] = (id: idHex, packet: packet)
|
||||||
case .message:
|
|
||||||
guard isBroadcastRecipient else { return }
|
|
||||||
guard isPacketFresh(packet) else { return }
|
|
||||||
let idHex = PacketIdUtil.computeId(packet).hexEncodedString()
|
|
||||||
messages.insert(idHex: idHex, packet: packet, capacity: max(1, config.seenCapacity))
|
|
||||||
case .fragment:
|
|
||||||
guard isBroadcastRecipient else { return }
|
|
||||||
guard isPacketFresh(packet) else { return }
|
|
||||||
let idHex = PacketIdUtil.computeId(packet).hexEncodedString()
|
|
||||||
fragments.insert(idHex: idHex, packet: packet, capacity: max(1, config.fragmentCapacity))
|
|
||||||
case .fileTransfer:
|
|
||||||
guard isBroadcastRecipient else { return }
|
|
||||||
guard isPacketFresh(packet) else { return }
|
|
||||||
let idHex = PacketIdUtil.computeId(packet).hexEncodedString()
|
|
||||||
fileTransfers.insert(idHex: idHex, packet: packet, capacity: max(1, config.fileTransferCapacity))
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func sendRequestSync(for types: SyncTypeFlags) {
|
private func sendRequestSync() {
|
||||||
let payload = buildGcsPayload(for: types)
|
let payload = buildGcsPayload()
|
||||||
let pkt = BitchatPacket(
|
let pkt = BitchatPacket(
|
||||||
type: MessageType.requestSync.rawValue,
|
type: MessageType.requestSync.rawValue,
|
||||||
senderID: Data(hexString: myPeerID.id) ?? Data(),
|
senderID: Data(hexString: myPeerID.id) ?? Data(),
|
||||||
@@ -217,8 +141,8 @@ final class GossipSyncManager {
|
|||||||
delegate?.sendPacket(signed)
|
delegate?.sendPacket(signed)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func sendRequestSync(to peerID: PeerID, types: SyncTypeFlags) {
|
private func sendRequestSync(to peerID: PeerID) {
|
||||||
let payload = buildGcsPayload(for: types)
|
let payload = buildGcsPayload()
|
||||||
var recipient = Data()
|
var recipient = Data()
|
||||||
var temp = peerID.id
|
var temp = peerID.id
|
||||||
while temp.count >= 2 && recipient.count < 8 {
|
while temp.count >= 2 && recipient.count < 8 {
|
||||||
@@ -246,7 +170,6 @@ final class GossipSyncManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func _handleRequestSync(from peerID: PeerID, request: RequestSyncPacket) {
|
private func _handleRequestSync(from peerID: PeerID, request: RequestSyncPacket) {
|
||||||
let requestedTypes = (request.types ?? .publicMessages)
|
|
||||||
// Decode GCS into sorted set and prepare membership checker
|
// Decode GCS into sorted set and prepare membership checker
|
||||||
let sorted = GCSFilter.decodeToSortedSet(p: request.p, m: request.m, data: request.data)
|
let sorted = GCSFilter.decodeToSortedSet(p: request.p, m: request.m, data: request.data)
|
||||||
func mightContain(_ id: Data) -> Bool {
|
func mightContain(_ id: Data) -> Bool {
|
||||||
@@ -254,7 +177,7 @@ final class GossipSyncManager {
|
|||||||
return GCSFilter.contains(sortedValues: sorted, candidate: bucket)
|
return GCSFilter.contains(sortedValues: sorted, candidate: bucket)
|
||||||
}
|
}
|
||||||
|
|
||||||
if requestedTypes.contains(.announce) {
|
// 1) Announcements: send latest per peer if requester lacks them (and not expired)
|
||||||
for (_, pair) in latestAnnouncementByPeer {
|
for (_, pair) in latestAnnouncementByPeer {
|
||||||
let (idHex, pkt) = pair
|
let (idHex, pkt) = pair
|
||||||
guard isPacketFresh(pkt) else { continue }
|
guard isPacketFresh(pkt) else { continue }
|
||||||
@@ -265,11 +188,11 @@ final class GossipSyncManager {
|
|||||||
delegate?.sendPacket(to: peerID, packet: toSend)
|
delegate?.sendPacket(to: peerID, packet: toSend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if requestedTypes.contains(.message) {
|
// 2) Broadcast messages: send all missing (and not expired)
|
||||||
let toSendMsgs = messages.allPackets(isFresh: isPacketFresh)
|
let toSendMsgs = messageOrder.compactMap { messages[$0] }
|
||||||
for pkt in toSendMsgs {
|
for pkt in toSendMsgs {
|
||||||
|
guard isPacketFresh(pkt) else { continue }
|
||||||
let idBytes = PacketIdUtil.computeId(pkt)
|
let idBytes = PacketIdUtil.computeId(pkt)
|
||||||
if !mightContain(idBytes) {
|
if !mightContain(idBytes) {
|
||||||
var toSend = pkt
|
var toSend = pkt
|
||||||
@@ -279,75 +202,35 @@ final class GossipSyncManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if requestedTypes.contains(.fragment) {
|
|
||||||
let frags = fragments.allPackets(isFresh: isPacketFresh)
|
|
||||||
for pkt in frags {
|
|
||||||
let idBytes = PacketIdUtil.computeId(pkt)
|
|
||||||
if !mightContain(idBytes) {
|
|
||||||
var toSend = pkt
|
|
||||||
toSend.ttl = 0
|
|
||||||
delegate?.sendPacket(to: peerID, packet: toSend)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if requestedTypes.contains(.fileTransfer) {
|
|
||||||
let files = fileTransfers.allPackets(isFresh: isPacketFresh)
|
|
||||||
for pkt in files {
|
|
||||||
let idBytes = PacketIdUtil.computeId(pkt)
|
|
||||||
if !mightContain(idBytes) {
|
|
||||||
var toSend = pkt
|
|
||||||
toSend.ttl = 0
|
|
||||||
delegate?.sendPacket(to: peerID, packet: toSend)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build REQUEST_SYNC payload using current candidates and GCS params
|
// Build REQUEST_SYNC payload using current candidates and GCS params
|
||||||
private func buildGcsPayload(for types: SyncTypeFlags) -> Data {
|
private func buildGcsPayload() -> Data {
|
||||||
|
// Collect candidates: latest announce per peer + broadcast messages (only fresh)
|
||||||
var candidates: [BitchatPacket] = []
|
var candidates: [BitchatPacket] = []
|
||||||
if types.contains(.announce) {
|
candidates.reserveCapacity(latestAnnouncementByPeer.count + messageOrder.count)
|
||||||
for (_, pair) in latestAnnouncementByPeer where isPacketFresh(pair.packet) {
|
for (_, pair) in latestAnnouncementByPeer {
|
||||||
|
if isPacketFresh(pair.packet) {
|
||||||
candidates.append(pair.packet)
|
candidates.append(pair.packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if types.contains(.message) {
|
for id in messageOrder {
|
||||||
candidates.append(contentsOf: messages.allPackets(isFresh: isPacketFresh))
|
if let p = messages[id], isPacketFresh(p) {
|
||||||
|
candidates.append(p)
|
||||||
}
|
}
|
||||||
if types.contains(.fragment) {
|
|
||||||
candidates.append(contentsOf: fragments.allPackets(isFresh: isPacketFresh))
|
|
||||||
}
|
}
|
||||||
if types.contains(.fileTransfer) {
|
|
||||||
candidates.append(contentsOf: fileTransfers.allPackets(isFresh: isPacketFresh))
|
|
||||||
}
|
|
||||||
if candidates.isEmpty {
|
|
||||||
let p = GCSFilter.deriveP(targetFpr: config.gcsTargetFpr)
|
|
||||||
let req = RequestSyncPacket(p: p, m: 1, data: Data(), types: types)
|
|
||||||
return req.encode()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort by timestamp desc
|
// Sort by timestamp desc
|
||||||
candidates.sort { $0.timestamp > $1.timestamp }
|
candidates.sort { $0.timestamp > $1.timestamp }
|
||||||
|
|
||||||
let p = GCSFilter.deriveP(targetFpr: config.gcsTargetFpr)
|
let p = GCSFilter.deriveP(targetFpr: config.gcsTargetFpr)
|
||||||
let nMax = GCSFilter.estimateMaxElements(sizeBytes: config.gcsMaxBytes, p: p)
|
let nMax = GCSFilter.estimateMaxElements(sizeBytes: config.gcsMaxBytes, p: p)
|
||||||
let cap: Int
|
let cap = max(1, config.seenCapacity)
|
||||||
if types == .fragment {
|
|
||||||
cap = max(1, config.fragmentCapacity)
|
|
||||||
} else if types == .fileTransfer {
|
|
||||||
cap = max(1, config.fileTransferCapacity)
|
|
||||||
} else {
|
|
||||||
cap = max(1, config.seenCapacity)
|
|
||||||
}
|
|
||||||
let takeN = min(candidates.count, min(nMax, cap))
|
let takeN = min(candidates.count, min(nMax, cap))
|
||||||
if takeN <= 0 {
|
if takeN <= 0 {
|
||||||
let req = RequestSyncPacket(p: p, m: 1, data: Data(), types: types)
|
let req = RequestSyncPacket(p: p, m: 1, data: Data())
|
||||||
return req.encode()
|
return req.encode()
|
||||||
}
|
}
|
||||||
let ids: [Data] = candidates.prefix(takeN).map { PacketIdUtil.computeId($0) }
|
let ids: [Data] = candidates.prefix(takeN).map { PacketIdUtil.computeId($0) }
|
||||||
let params = GCSFilter.buildFilter(ids: ids, maxBytes: config.gcsMaxBytes, targetFpr: config.gcsTargetFpr)
|
let params = GCSFilter.buildFilter(ids: ids, maxBytes: config.gcsMaxBytes, targetFpr: config.gcsTargetFpr)
|
||||||
let req = RequestSyncPacket(p: params.p, m: params.m, data: params.data, types: types)
|
let req = RequestSyncPacket(p: params.p, m: params.m, data: params.data)
|
||||||
return req.encode()
|
return req.encode()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,21 +241,20 @@ final class GossipSyncManager {
|
|||||||
isPacketFresh(pair.packet)
|
isPacketFresh(pair.packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
messages.removeExpired(isFresh: isPacketFresh)
|
// Remove expired messages
|
||||||
fragments.removeExpired(isFresh: isPacketFresh)
|
let expiredMessageIds = messages.compactMap { id, pkt in
|
||||||
fileTransfers.removeExpired(isFresh: isPacketFresh)
|
isPacketFresh(pkt) ? nil : id
|
||||||
|
}
|
||||||
|
for id in expiredMessageIds {
|
||||||
|
messages.removeValue(forKey: id)
|
||||||
|
messageOrder.removeAll { $0 == id }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func performPeriodicMaintenance(now: Date = Date()) {
|
private func performPeriodicMaintenance(now: Date = Date()) {
|
||||||
cleanupExpiredMessages()
|
cleanupExpiredMessages()
|
||||||
cleanupStaleAnnouncementsIfNeeded(now: now)
|
cleanupStaleAnnouncementsIfNeeded(now: now)
|
||||||
for index in syncSchedules.indices {
|
sendRequestSync()
|
||||||
guard syncSchedules[index].interval > 0 else { continue }
|
|
||||||
if syncSchedules[index].lastSent == .distantPast || now.timeIntervalSince(syncSchedules[index].lastSent) >= syncSchedules[index].interval {
|
|
||||||
syncSchedules[index].lastSent = now
|
|
||||||
sendRequestSync(for: syncSchedules[index].types)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func cleanupStaleAnnouncementsIfNeeded(now: Date) {
|
private func cleanupStaleAnnouncementsIfNeeded(now: Date) {
|
||||||
@@ -388,27 +270,40 @@ final class GossipSyncManager {
|
|||||||
let nowMs = UInt64(now.timeIntervalSince1970 * 1000)
|
let nowMs = UInt64(now.timeIntervalSince1970 * 1000)
|
||||||
guard nowMs >= timeoutMs else { return }
|
guard nowMs >= timeoutMs else { return }
|
||||||
let cutoff = nowMs - timeoutMs
|
let cutoff = nowMs - timeoutMs
|
||||||
let stalePeerIDs = latestAnnouncementByPeer.compactMap { peerID, pair in
|
let stalePeerIDs = latestAnnouncementByPeer.compactMap { (peerHex, pair) -> String? in
|
||||||
pair.packet.timestamp < cutoff ? peerID : nil
|
pair.packet.timestamp < cutoff ? peerHex.lowercased() : nil
|
||||||
}
|
}
|
||||||
guard !stalePeerIDs.isEmpty else { return }
|
guard !stalePeerIDs.isEmpty else { return }
|
||||||
for peerKey in stalePeerIDs {
|
for peerKey in stalePeerIDs {
|
||||||
removeState(for: peerKey)
|
removeState(forNormalizedPeerID: peerKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicit removal hook for LEAVE/stale peer
|
// Explicit removal hook for LEAVE/stale peer
|
||||||
func removeAnnouncementForPeer(_ peerID: PeerID) {
|
func removeAnnouncementForPeer(_ peerID: PeerID) {
|
||||||
queue.async { [weak self] in
|
queue.async { [weak self] in
|
||||||
self?.removeState(for: peerID)
|
self?._removeAnnouncementForPeer(peerID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func removeState(for peerID: PeerID) {
|
private func _removeAnnouncementForPeer(_ peerID: PeerID) {
|
||||||
_ = latestAnnouncementByPeer.removeValue(forKey: peerID)
|
let normalizedPeerID = peerID.id.lowercased()
|
||||||
messages.remove { PeerID(hexData: $0.senderID) == peerID }
|
removeState(forNormalizedPeerID: normalizedPeerID)
|
||||||
fragments.remove { PeerID(hexData: $0.senderID) == peerID }
|
}
|
||||||
fileTransfers.remove { PeerID(hexData: $0.senderID) == peerID }
|
|
||||||
|
private func removeState(forNormalizedPeerID normalizedPeerID: String) {
|
||||||
|
_ = latestAnnouncementByPeer.removeValue(forKey: normalizedPeerID)
|
||||||
|
// Remove messages from this peer
|
||||||
|
// Collect IDs to remove first to avoid concurrent modification
|
||||||
|
let messageIdsToRemove = messages.compactMap { (id, message) -> String? in
|
||||||
|
message.senderID.hexEncodedString().lowercased() == normalizedPeerID ? id : nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove messages and update messageOrder
|
||||||
|
for id in messageIdsToRemove {
|
||||||
|
messages.removeValue(forKey: id)
|
||||||
|
messageOrder.removeAll { $0 == id }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,13 +317,13 @@ extension GossipSyncManager {
|
|||||||
|
|
||||||
func _hasAnnouncement(for peerID: PeerID) -> Bool {
|
func _hasAnnouncement(for peerID: PeerID) -> Bool {
|
||||||
queue.sync {
|
queue.sync {
|
||||||
latestAnnouncementByPeer[peerID] != nil
|
latestAnnouncementByPeer[peerID.id.lowercased()] != nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func _messageCount(for peerID: PeerID) -> Int {
|
func _messageCount(for peerID: PeerID) -> Int {
|
||||||
queue.sync {
|
queue.sync {
|
||||||
messages.allPackets { _ in true }.filter { PeerID(hexData: $0.senderID) == peerID }.count
|
messages.values.filter { $0.senderID.hexEncodedString().lowercased() == peerID.id.lowercased() }.count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
/// Bitfield describing which message types are covered by a REQUEST_SYNC round.
|
|
||||||
/// Matches the Android mapping (bit index -> message type).
|
|
||||||
struct SyncTypeFlags: OptionSet {
|
|
||||||
let rawValue: UInt64
|
|
||||||
|
|
||||||
init(rawValue: UInt64) {
|
|
||||||
self.rawValue = rawValue & 0x00FF_FFFF_FFFF_FFFF // Trim to max 8 bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func bitIndex(for type: MessageType) -> Int? {
|
|
||||||
switch type {
|
|
||||||
case .announce: return 0
|
|
||||||
case .message: return 1
|
|
||||||
case .leave: return 2
|
|
||||||
case .noiseHandshake: return 3
|
|
||||||
case .noiseEncrypted: return 4
|
|
||||||
case .fragment: return 5
|
|
||||||
case .requestSync: return 6
|
|
||||||
case .fileTransfer: return 7
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func type(forBit index: Int) -> MessageType? {
|
|
||||||
switch index {
|
|
||||||
case 0: return .announce
|
|
||||||
case 1: return .message
|
|
||||||
case 2: return .leave
|
|
||||||
case 3: return .noiseHandshake
|
|
||||||
case 4: return .noiseEncrypted
|
|
||||||
case 5: return .fragment
|
|
||||||
case 6: return .requestSync
|
|
||||||
case 7: return .fileTransfer
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static let announce = SyncTypeFlags(messageTypes: [.announce])
|
|
||||||
static let message = SyncTypeFlags(messageTypes: [.message])
|
|
||||||
static let fragment = SyncTypeFlags(messageTypes: [.fragment])
|
|
||||||
static let fileTransfer = SyncTypeFlags(messageTypes: [.fileTransfer])
|
|
||||||
|
|
||||||
static let publicMessages = SyncTypeFlags(messageTypes: [.announce, .message])
|
|
||||||
|
|
||||||
init(messageTypes: [MessageType]) {
|
|
||||||
var raw: UInt64 = 0
|
|
||||||
for type in messageTypes {
|
|
||||||
guard let bit = SyncTypeFlags.bitIndex(for: type) else { continue }
|
|
||||||
raw |= (1 << UInt64(bit))
|
|
||||||
}
|
|
||||||
self.init(rawValue: raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
func contains(_ type: MessageType) -> Bool {
|
|
||||||
guard let bit = SyncTypeFlags.bitIndex(for: type) else { return false }
|
|
||||||
return contains(SyncTypeFlags(rawValue: 1 << UInt64(bit)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func union(_ other: SyncTypeFlags) -> SyncTypeFlags {
|
|
||||||
SyncTypeFlags(rawValue: rawValue | other.rawValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
func intersection(_ other: SyncTypeFlags) -> SyncTypeFlags {
|
|
||||||
SyncTypeFlags(rawValue: rawValue & other.rawValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
func toMessageTypes() -> [MessageType] {
|
|
||||||
guard rawValue != 0 else { return [] }
|
|
||||||
var types: [MessageType] = []
|
|
||||||
for bit in 0..<64 {
|
|
||||||
guard (rawValue & (1 << UInt64(bit))) != 0 else { continue }
|
|
||||||
if let type = SyncTypeFlags.type(forBit: bit) {
|
|
||||||
types.append(type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return types
|
|
||||||
}
|
|
||||||
|
|
||||||
func toData() -> Data? {
|
|
||||||
guard rawValue != 0 else { return nil }
|
|
||||||
var value = rawValue
|
|
||||||
var bytes: [UInt8] = []
|
|
||||||
while value > 0 && bytes.count < 8 {
|
|
||||||
bytes.append(UInt8(value & 0xFF))
|
|
||||||
value >>= 8
|
|
||||||
}
|
|
||||||
while let last = bytes.last, last == 0 {
|
|
||||||
bytes.removeLast()
|
|
||||||
}
|
|
||||||
guard !bytes.isEmpty, bytes.count <= 8 else { return nil }
|
|
||||||
return Data(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func decode(_ data: Data) -> SyncTypeFlags? {
|
|
||||||
guard (1...8).contains(data.count) else { return nil }
|
|
||||||
var raw: UInt64 = 0
|
|
||||||
for (index, byte) in data.enumerated() {
|
|
||||||
raw |= UInt64(byte) << UInt64(index * 8)
|
|
||||||
}
|
|
||||||
return SyncTypeFlags(rawValue: raw)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -62,12 +62,14 @@ struct CompressionUtil {
|
|||||||
// 2. Data appears to be already compressed (high entropy)
|
// 2. Data appears to be already compressed (high entropy)
|
||||||
guard data.count >= compressionThreshold else { return false }
|
guard data.count >= compressionThreshold else { return false }
|
||||||
|
|
||||||
// Quick uniqueness check — a high diversity of bytes usually means the
|
// Simple entropy check - count unique bytes
|
||||||
// payload is already compressed. We only need to know how many unique
|
var byteFrequency = [UInt8: Int]()
|
||||||
// values exist rather than keeping full frequency counts.
|
for byte in data {
|
||||||
let uniqueByteCount = Set(data).count
|
byteFrequency[byte, default: 0] += 1
|
||||||
let sampleSize = min(data.count, 256)
|
}
|
||||||
let uniqueByteRatio = Double(uniqueByteCount) / Double(sampleSize)
|
|
||||||
|
// If we have very high byte diversity, data is likely already compressed
|
||||||
|
let uniqueByteRatio = Double(byteFrequency.count) / Double(min(data.count, 256))
|
||||||
return uniqueByteRatio < 0.9 // Compress if less than 90% unique bytes
|
return uniqueByteRatio < 0.9 // Compress if less than 90% unique bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,19 +5,9 @@ enum FileTransferLimits {
|
|||||||
/// Absolute ceiling enforced for any file payload (voice, image, other).
|
/// Absolute ceiling enforced for any file payload (voice, image, other).
|
||||||
static let maxPayloadBytes: Int = 1 * 1024 * 1024 // 1 MiB
|
static let maxPayloadBytes: Int = 1 * 1024 * 1024 // 1 MiB
|
||||||
/// Voice notes stay small for low-latency relays.
|
/// Voice notes stay small for low-latency relays.
|
||||||
static let maxVoiceNoteBytes: Int = 512 * 1024 // 512 KiB
|
static let maxVoiceNoteBytes: Int = 1 * 1024 * 1024 // 1 MiB
|
||||||
/// Compressed images after downscaling should comfortably fit under this budget.
|
/// Compressed images after downscaling should comfortably fit under this budget.
|
||||||
static let maxImageBytes: Int = 512 * 1024 // 512 KiB
|
static let maxImageBytes: Int = 1 * 1024 * 1024 // 1 MiB
|
||||||
/// Worst-case size once TLV metadata and binary packet framing are included for the largest payloads.
|
|
||||||
static let maxFramedFileBytes: Int = {
|
|
||||||
let maxMetadataBytes = Int(UInt16.max) * 2 // fileName + mimeType TLVs
|
|
||||||
let tlvEnvelopeOverhead = 18 + maxMetadataBytes // TLV tags + lengths + metadata bytes
|
|
||||||
let binaryEnvelopeOverhead = BinaryProtocol.v2HeaderSize
|
|
||||||
+ BinaryProtocol.senderIDSize
|
|
||||||
+ BinaryProtocol.recipientIDSize
|
|
||||||
+ BinaryProtocol.signatureSize
|
|
||||||
return maxPayloadBytes + tlvEnvelopeOverhead + binaryEnvelopeOverhead
|
|
||||||
}()
|
|
||||||
|
|
||||||
static func isValidPayload(_ size: Int) -> Bool {
|
static func isValidPayload(_ size: Int) -> Bool {
|
||||||
size <= maxPayloadBytes
|
size <= maxPayloadBytes
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import BitLogger
|
|
||||||
|
|
||||||
/// Comprehensive input validation for BitChat protocol
|
/// Comprehensive input validation for BitChat protocol
|
||||||
/// Prevents injection attacks, buffer overflows, and malformed data
|
/// Prevents injection attacks, buffer overflows, and malformed data
|
||||||
@@ -17,28 +16,29 @@ struct InputValidator {
|
|||||||
// MARK: - String Content Validation
|
// MARK: - String Content Validation
|
||||||
|
|
||||||
/// Validates and sanitizes user-provided strings used in UI
|
/// Validates and sanitizes user-provided strings used in UI
|
||||||
///
|
|
||||||
/// Rejects strings containing control characters to prevent potential security issues
|
|
||||||
/// and UI rendering problems. This strict approach ensures data integrity at input time.
|
|
||||||
static func validateUserString(_ string: String, maxLength: Int) -> String? {
|
static func validateUserString(_ string: String, maxLength: Int) -> String? {
|
||||||
|
// Check empty
|
||||||
|
guard !string.isEmpty else { return nil }
|
||||||
|
|
||||||
|
// Trim whitespace
|
||||||
let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines)
|
let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
guard !trimmed.isEmpty else { return nil }
|
guard !trimmed.isEmpty else { return nil }
|
||||||
|
|
||||||
|
// Check length
|
||||||
guard trimmed.count <= maxLength else { return nil }
|
guard trimmed.count <= maxLength else { return nil }
|
||||||
|
|
||||||
// Reject control characters outright instead of rewriting the string.
|
// Remove control characters
|
||||||
// This prevents injection attacks and ensures consistent UI rendering.
|
|
||||||
let controlChars = CharacterSet.controlCharacters
|
let controlChars = CharacterSet.controlCharacters
|
||||||
if !trimmed.unicodeScalars.allSatisfy({ !controlChars.contains($0) }) {
|
let cleaned = trimmed.components(separatedBy: controlChars).joined()
|
||||||
// Log rejection for monitoring, without exposing actual content for privacy
|
|
||||||
let controlCharCount = trimmed.unicodeScalars.filter { controlChars.contains($0) }.count
|
|
||||||
SecureLogger.debug(
|
|
||||||
"Input validation rejected string (length: \(trimmed.count), control chars: \(controlCharCount))",
|
|
||||||
category: .security
|
|
||||||
)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return trimmed
|
// Ensure valid UTF-8 (should already be, but double-check)
|
||||||
|
guard cleaned.data(using: .utf8) != nil else { return nil }
|
||||||
|
|
||||||
|
// Prevent zero-width characters and other invisible unicode
|
||||||
|
let invisibleChars = CharacterSet(charactersIn: "\u{200B}\u{200C}\u{200D}\u{FEFF}")
|
||||||
|
let visible = cleaned.components(separatedBy: invisibleChars).joined()
|
||||||
|
|
||||||
|
return visible.isEmpty ? nil : visible
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates nickname
|
/// Validates nickname
|
||||||
|
|||||||
+1033
-435
File diff suppressed because it is too large
Load Diff
@@ -1,118 +0,0 @@
|
|||||||
//
|
|
||||||
// GeoChannelCoordinator.swift
|
|
||||||
// bitchat
|
|
||||||
//
|
|
||||||
// Centralizes Combine wiring for location channel selection and sampling.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Combine
|
|
||||||
import Foundation
|
|
||||||
import Tor
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
final class GeoChannelCoordinator {
|
|
||||||
private let locationManager: LocationChannelManager
|
|
||||||
private let bookmarksStore: GeohashBookmarksStore
|
|
||||||
private let torManager: TorManager
|
|
||||||
|
|
||||||
private let onChannelSwitch: (ChannelID) -> Void
|
|
||||||
private let beginSampling: ([String]) -> Void
|
|
||||||
private let endSampling: () -> Void
|
|
||||||
|
|
||||||
private var cancellables = Set<AnyCancellable>()
|
|
||||||
private var regionalGeohashes: [String] = []
|
|
||||||
private var bookmarkedGeohashes: [String] = []
|
|
||||||
|
|
||||||
init(
|
|
||||||
locationManager: LocationChannelManager? = nil,
|
|
||||||
bookmarksStore: GeohashBookmarksStore? = nil,
|
|
||||||
torManager: TorManager? = nil,
|
|
||||||
onChannelSwitch: @escaping (ChannelID) -> Void,
|
|
||||||
beginSampling: @escaping ([String]) -> Void,
|
|
||||||
endSampling: @escaping () -> Void
|
|
||||||
) {
|
|
||||||
self.locationManager = locationManager ?? Self.defaultLocationManager()
|
|
||||||
self.bookmarksStore = bookmarksStore ?? GeohashBookmarksStore.shared
|
|
||||||
self.torManager = torManager ?? Self.defaultTorManager()
|
|
||||||
self.onChannelSwitch = onChannelSwitch
|
|
||||||
self.beginSampling = beginSampling
|
|
||||||
self.endSampling = endSampling
|
|
||||||
|
|
||||||
start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func start() {
|
|
||||||
regionalGeohashes = locationManager.availableChannels.map { $0.geohash }
|
|
||||||
bookmarkedGeohashes = bookmarksStore.bookmarks
|
|
||||||
|
|
||||||
locationManager.$selectedChannel
|
|
||||||
.receive(on: DispatchQueue.main)
|
|
||||||
.sink { [weak self] channel in
|
|
||||||
guard let self else { return }
|
|
||||||
Task { @MainActor in
|
|
||||||
self.onChannelSwitch(channel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.store(in: &cancellables)
|
|
||||||
|
|
||||||
locationManager.$availableChannels
|
|
||||||
.receive(on: DispatchQueue.main)
|
|
||||||
.sink { [weak self] channels in
|
|
||||||
guard let self else { return }
|
|
||||||
self.regionalGeohashes = channels.map { $0.geohash }
|
|
||||||
self.updateSampling()
|
|
||||||
}
|
|
||||||
.store(in: &cancellables)
|
|
||||||
|
|
||||||
bookmarksStore.$bookmarks
|
|
||||||
.receive(on: DispatchQueue.main)
|
|
||||||
.sink { [weak self] bookmarks in
|
|
||||||
guard let self else { return }
|
|
||||||
self.bookmarkedGeohashes = bookmarks
|
|
||||||
self.updateSampling()
|
|
||||||
}
|
|
||||||
.store(in: &cancellables)
|
|
||||||
|
|
||||||
locationManager.$permissionState
|
|
||||||
.receive(on: DispatchQueue.main)
|
|
||||||
.sink { [weak self] state in
|
|
||||||
guard let self, state == .authorized else { return }
|
|
||||||
Task { @MainActor [weak self] in
|
|
||||||
self?.locationManager.refreshChannels()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.store(in: &cancellables)
|
|
||||||
|
|
||||||
Task { @MainActor in
|
|
||||||
self.onChannelSwitch(self.locationManager.selectedChannel)
|
|
||||||
}
|
|
||||||
updateSampling()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func updateSampling() {
|
|
||||||
let union = Array(Set(regionalGeohashes).union(bookmarkedGeohashes))
|
|
||||||
Task { @MainActor in
|
|
||||||
guard !union.isEmpty else {
|
|
||||||
endSampling()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if torManager.isForeground() {
|
|
||||||
beginSampling(union)
|
|
||||||
} else {
|
|
||||||
endSampling()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func refreshSampling() {
|
|
||||||
updateSampling()
|
|
||||||
}
|
|
||||||
private static func defaultLocationManager() -> LocationChannelManager {
|
|
||||||
LocationChannelManager.shared
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
private static func defaultTorManager() -> TorManager {
|
|
||||||
TorManager.shared
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
//
|
|
||||||
// MessageRateLimiter.swift
|
|
||||||
// bitchat
|
|
||||||
//
|
|
||||||
// Handles per-sender and per-content token buckets for public message intake.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct MessageRateLimiter {
|
|
||||||
private struct TokenBucket {
|
|
||||||
var capacity: Double
|
|
||||||
var tokens: Double
|
|
||||||
var refillPerSec: Double
|
|
||||||
var lastRefill: Date
|
|
||||||
|
|
||||||
mutating func allow(cost: Double = 1.0, now: Date = Date()) -> Bool {
|
|
||||||
let dt = now.timeIntervalSince(lastRefill)
|
|
||||||
if dt > 0 {
|
|
||||||
tokens = min(capacity, tokens + dt * refillPerSec)
|
|
||||||
lastRefill = now
|
|
||||||
}
|
|
||||||
if tokens >= cost {
|
|
||||||
tokens -= cost
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var senderBuckets: [String: TokenBucket] = [:]
|
|
||||||
private var contentBuckets: [String: TokenBucket] = [:]
|
|
||||||
|
|
||||||
private let senderCapacity: Double
|
|
||||||
private let senderRefill: Double
|
|
||||||
private let contentCapacity: Double
|
|
||||||
private let contentRefill: Double
|
|
||||||
|
|
||||||
init(
|
|
||||||
senderCapacity: Double,
|
|
||||||
senderRefillPerSec: Double,
|
|
||||||
contentCapacity: Double,
|
|
||||||
contentRefillPerSec: Double
|
|
||||||
) {
|
|
||||||
self.senderCapacity = senderCapacity
|
|
||||||
self.senderRefill = senderRefillPerSec
|
|
||||||
self.contentCapacity = contentCapacity
|
|
||||||
self.contentRefill = contentRefillPerSec
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func allow(senderKey: String, contentKey: String, now: Date = Date()) -> Bool {
|
|
||||||
var senderBucket = senderBuckets[senderKey] ?? TokenBucket(
|
|
||||||
capacity: senderCapacity,
|
|
||||||
tokens: senderCapacity,
|
|
||||||
refillPerSec: senderRefill,
|
|
||||||
lastRefill: now
|
|
||||||
)
|
|
||||||
let senderAllowed = senderBucket.allow(now: now)
|
|
||||||
senderBuckets[senderKey] = senderBucket
|
|
||||||
|
|
||||||
var contentBucket = contentBuckets[contentKey] ?? TokenBucket(
|
|
||||||
capacity: contentCapacity,
|
|
||||||
tokens: contentCapacity,
|
|
||||||
refillPerSec: contentRefill,
|
|
||||||
lastRefill: now
|
|
||||||
)
|
|
||||||
let contentAllowed = contentBucket.allow(now: now)
|
|
||||||
contentBuckets[contentKey] = contentBucket
|
|
||||||
|
|
||||||
return senderAllowed && contentAllowed
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func reset() {
|
|
||||||
senderBuckets.removeAll()
|
|
||||||
contentBuckets.removeAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
//
|
|
||||||
// MinimalDistancePalette.swift
|
|
||||||
// bitchat
|
|
||||||
//
|
|
||||||
// Lightweight palette generator that keeps peer colors evenly spaced.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
final class MinimalDistancePalette {
|
|
||||||
struct Config {
|
|
||||||
let slotCount: Int
|
|
||||||
let avoidCenterHue: Double
|
|
||||||
let avoidHueDelta: Double
|
|
||||||
let saturationLight: Double
|
|
||||||
let saturationDark: Double
|
|
||||||
let baseBrightnessLight: Double
|
|
||||||
let baseBrightnessDark: Double
|
|
||||||
let ringBrightnessDeltaLight: Double
|
|
||||||
let ringBrightnessDeltaDark: Double
|
|
||||||
let preferredBiasWeight: Double
|
|
||||||
let goldenStep: Int
|
|
||||||
|
|
||||||
init(
|
|
||||||
slotCount: Int,
|
|
||||||
avoidCenterHue: Double,
|
|
||||||
avoidHueDelta: Double,
|
|
||||||
saturationLight: Double,
|
|
||||||
saturationDark: Double,
|
|
||||||
baseBrightnessLight: Double,
|
|
||||||
baseBrightnessDark: Double,
|
|
||||||
ringBrightnessDeltaLight: Double,
|
|
||||||
ringBrightnessDeltaDark: Double,
|
|
||||||
preferredBiasWeight: Double = 0.05,
|
|
||||||
goldenStep: Int = 7
|
|
||||||
) {
|
|
||||||
self.slotCount = slotCount
|
|
||||||
self.avoidCenterHue = avoidCenterHue
|
|
||||||
self.avoidHueDelta = avoidHueDelta
|
|
||||||
self.saturationLight = saturationLight
|
|
||||||
self.saturationDark = saturationDark
|
|
||||||
self.baseBrightnessLight = baseBrightnessLight
|
|
||||||
self.baseBrightnessDark = baseBrightnessDark
|
|
||||||
self.ringBrightnessDeltaLight = ringBrightnessDeltaLight
|
|
||||||
self.ringBrightnessDeltaDark = ringBrightnessDeltaDark
|
|
||||||
self.preferredBiasWeight = preferredBiasWeight
|
|
||||||
self.goldenStep = goldenStep
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct Entry {
|
|
||||||
let slot: Int
|
|
||||||
let ring: Int
|
|
||||||
let hue: Double
|
|
||||||
}
|
|
||||||
|
|
||||||
private let config: Config
|
|
||||||
private var currentSeeds: [String: String] = [:]
|
|
||||||
private var entries: [String: Entry] = [:]
|
|
||||||
private var previousEntries: [String: Entry] = [:]
|
|
||||||
|
|
||||||
init(config: Config) {
|
|
||||||
self.config = config
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
func ensurePalette(for seeds: [String: String]) {
|
|
||||||
guard seeds != currentSeeds || entries.count != seeds.count else { return }
|
|
||||||
previousEntries = entries
|
|
||||||
currentSeeds = seeds
|
|
||||||
rebuildEntries()
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
func color(for identifier: String, isDark: Bool) -> Color? {
|
|
||||||
guard let entry = entries[identifier] else { return nil }
|
|
||||||
let saturation = isDark ? config.saturationDark : config.saturationLight
|
|
||||||
let baseBrightness = isDark ? config.baseBrightnessDark : config.baseBrightnessLight
|
|
||||||
let ringDelta = isDark ? config.ringBrightnessDeltaDark : config.ringBrightnessDeltaLight
|
|
||||||
let brightness = min(1.0, max(0.0, baseBrightness + ringDelta * Double(entry.ring)))
|
|
||||||
return Color(hue: entry.hue, saturation: saturation, brightness: brightness)
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
func reset() {
|
|
||||||
currentSeeds.removeAll()
|
|
||||||
entries.removeAll()
|
|
||||||
previousEntries.removeAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
private func rebuildEntries() {
|
|
||||||
guard !currentSeeds.isEmpty else {
|
|
||||||
entries.removeAll()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let slotCount = max(8, config.slotCount)
|
|
||||||
var slots: [Double] = []
|
|
||||||
for idx in 0..<slotCount {
|
|
||||||
let hue = Double(idx) / Double(slotCount)
|
|
||||||
if abs(hue - config.avoidCenterHue) < config.avoidHueDelta {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
slots.append(hue)
|
|
||||||
}
|
|
||||||
if slots.isEmpty {
|
|
||||||
for idx in 0..<slotCount {
|
|
||||||
slots.append(Double(idx) / Double(slotCount))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func circularDistance(_ a: Double, _ b: Double) -> Double {
|
|
||||||
let diff = abs(a - b)
|
|
||||||
return diff > 0.5 ? 1.0 - diff : diff
|
|
||||||
}
|
|
||||||
|
|
||||||
let peerIDs = currentSeeds.keys.sorted()
|
|
||||||
let preferredIndex: [String: Int] = Dictionary(uniqueKeysWithValues: peerIDs.map { id in
|
|
||||||
let seed = currentSeeds[id] ?? id
|
|
||||||
let hash = seed.djb2()
|
|
||||||
let index = Int(hash % UInt64(slots.count))
|
|
||||||
return (id, index)
|
|
||||||
})
|
|
||||||
|
|
||||||
var mapping: [String: Entry] = [:]
|
|
||||||
var usedSlots = Set<Int>()
|
|
||||||
var usedHues: [Double] = []
|
|
||||||
|
|
||||||
let prior = entries.isEmpty ? previousEntries : entries
|
|
||||||
for (id, entry) in prior {
|
|
||||||
guard currentSeeds.keys.contains(id), entry.slot < slots.count else { continue }
|
|
||||||
let hue = slots[entry.slot]
|
|
||||||
mapping[id] = Entry(slot: entry.slot, ring: entry.ring, hue: hue)
|
|
||||||
usedSlots.insert(entry.slot)
|
|
||||||
usedHues.append(hue)
|
|
||||||
}
|
|
||||||
|
|
||||||
let unassigned = peerIDs.filter { mapping[$0] == nil }
|
|
||||||
for id in unassigned {
|
|
||||||
let preferred = preferredIndex[id] ?? 0
|
|
||||||
if !usedSlots.contains(preferred), preferred < slots.count {
|
|
||||||
let hue = slots[preferred]
|
|
||||||
mapping[id] = Entry(slot: preferred, ring: 0, hue: hue)
|
|
||||||
usedSlots.insert(preferred)
|
|
||||||
usedHues.append(hue)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var bestSlot: Int?
|
|
||||||
var bestScore = -Double.infinity
|
|
||||||
for slot in 0..<slots.count where !usedSlots.contains(slot) {
|
|
||||||
let hue = slots[slot]
|
|
||||||
let minDistance = usedHues.isEmpty ? 1.0 : usedHues.map { circularDistance(hue, $0) }.min() ?? 1.0
|
|
||||||
let bias = 1.0 - (Double((abs(slot - (preferredIndex[id] ?? 0)) % slots.count)) / Double(slots.count))
|
|
||||||
let score = minDistance + config.preferredBiasWeight * bias
|
|
||||||
if score > bestScore {
|
|
||||||
bestScore = score
|
|
||||||
bestSlot = slot
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let slot = bestSlot {
|
|
||||||
let hue = slots[slot]
|
|
||||||
mapping[id] = Entry(slot: slot, ring: 0, hue: hue)
|
|
||||||
usedSlots.insert(slot)
|
|
||||||
usedHues.append(hue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let remaining = peerIDs.filter { mapping[$0] == nil }
|
|
||||||
if !remaining.isEmpty {
|
|
||||||
for (index, id) in remaining.enumerated() {
|
|
||||||
let preferred = preferredIndex[id] ?? 0
|
|
||||||
let slot = (preferred + index * config.goldenStep) % slots.count
|
|
||||||
let hue = slots[slot]
|
|
||||||
mapping[id] = Entry(slot: slot, ring: 1, hue: hue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
entries = mapping
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension MinimalDistancePalette.Config {
|
|
||||||
static let mesh = MinimalDistancePalette.Config(
|
|
||||||
slotCount: TransportConfig.uiPeerPaletteSlots,
|
|
||||||
avoidCenterHue: 30.0 / 360.0,
|
|
||||||
avoidHueDelta: TransportConfig.uiColorHueAvoidanceDelta,
|
|
||||||
saturationLight: 0.70,
|
|
||||||
saturationDark: 0.80,
|
|
||||||
baseBrightnessLight: 0.45,
|
|
||||||
baseBrightnessDark: 0.75,
|
|
||||||
ringBrightnessDeltaLight: TransportConfig.uiPeerPaletteRingBrightnessDeltaLight,
|
|
||||||
ringBrightnessDeltaDark: TransportConfig.uiPeerPaletteRingBrightnessDeltaDark
|
|
||||||
)
|
|
||||||
|
|
||||||
static let nostr = MinimalDistancePalette.Config(
|
|
||||||
slotCount: TransportConfig.uiPeerPaletteSlots,
|
|
||||||
avoidCenterHue: 30.0 / 360.0,
|
|
||||||
avoidHueDelta: TransportConfig.uiColorHueAvoidanceDelta,
|
|
||||||
saturationLight: 0.70,
|
|
||||||
saturationDark: 0.80,
|
|
||||||
baseBrightnessLight: 0.45,
|
|
||||||
baseBrightnessDark: 0.75,
|
|
||||||
ringBrightnessDeltaLight: TransportConfig.uiPeerPaletteRingBrightnessDeltaLight,
|
|
||||||
ringBrightnessDeltaDark: TransportConfig.uiPeerPaletteRingBrightnessDeltaDark
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
//
|
|
||||||
// PublicMessagePipeline.swift
|
|
||||||
// bitchat
|
|
||||||
//
|
|
||||||
// Handles batching and deduplication of public chat messages before surfacing them to the UI.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
protocol PublicMessagePipelineDelegate: AnyObject {
|
|
||||||
func pipelineCurrentMessages(_ pipeline: PublicMessagePipeline) -> [BitchatMessage]
|
|
||||||
func pipeline(_ pipeline: PublicMessagePipeline, setMessages messages: [BitchatMessage])
|
|
||||||
func pipeline(_ pipeline: PublicMessagePipeline, normalizeContent content: String) -> String
|
|
||||||
func pipeline(_ pipeline: PublicMessagePipeline, contentTimestampForKey key: String) -> Date?
|
|
||||||
func pipeline(_ pipeline: PublicMessagePipeline, recordContentKey key: String, timestamp: Date)
|
|
||||||
func pipelineTrimMessages(_ pipeline: PublicMessagePipeline)
|
|
||||||
func pipelinePrewarmMessage(_ pipeline: PublicMessagePipeline, message: BitchatMessage)
|
|
||||||
func pipelineSetBatchingState(_ pipeline: PublicMessagePipeline, isBatching: Bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
final class PublicMessagePipeline {
|
|
||||||
weak var delegate: PublicMessagePipelineDelegate?
|
|
||||||
|
|
||||||
private var buffer: [BitchatMessage] = []
|
|
||||||
private var timer: Timer?
|
|
||||||
private let baseFlushInterval: TimeInterval
|
|
||||||
private var dynamicFlushInterval: TimeInterval
|
|
||||||
private var recentBatchSizes: [Int] = []
|
|
||||||
private let maxRecentBatchSamples: Int
|
|
||||||
private let dedupWindow: TimeInterval
|
|
||||||
private var activeChannel: ChannelID = .mesh
|
|
||||||
|
|
||||||
init(
|
|
||||||
baseFlushInterval: TimeInterval = TransportConfig.basePublicFlushInterval,
|
|
||||||
maxRecentBatchSamples: Int = 10,
|
|
||||||
dedupWindow: TimeInterval = 1.0
|
|
||||||
) {
|
|
||||||
self.baseFlushInterval = baseFlushInterval
|
|
||||||
self.dynamicFlushInterval = baseFlushInterval
|
|
||||||
self.maxRecentBatchSamples = maxRecentBatchSamples
|
|
||||||
self.dedupWindow = dedupWindow
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
|
||||||
timer?.invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateActiveChannel(_ channel: ChannelID) {
|
|
||||||
activeChannel = channel
|
|
||||||
}
|
|
||||||
|
|
||||||
func enqueue(_ message: BitchatMessage) {
|
|
||||||
buffer.append(message)
|
|
||||||
scheduleFlush()
|
|
||||||
}
|
|
||||||
|
|
||||||
func flushIfNeeded() {
|
|
||||||
flushBuffer()
|
|
||||||
}
|
|
||||||
|
|
||||||
func reset() {
|
|
||||||
timer?.invalidate()
|
|
||||||
timer = nil
|
|
||||||
buffer.removeAll(keepingCapacity: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private extension PublicMessagePipeline {
|
|
||||||
func scheduleFlush() {
|
|
||||||
guard timer == nil else { return }
|
|
||||||
timer = Timer.scheduledTimer(withTimeInterval: dynamicFlushInterval, repeats: false) { [weak self] _ in
|
|
||||||
guard let self else { return }
|
|
||||||
Task { @MainActor in
|
|
||||||
self.flushBuffer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func flushBuffer() {
|
|
||||||
timer?.invalidate()
|
|
||||||
timer = nil
|
|
||||||
guard !buffer.isEmpty else { return }
|
|
||||||
guard let delegate = delegate else {
|
|
||||||
buffer.removeAll(keepingCapacity: false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate.pipelineSetBatchingState(self, isBatching: true)
|
|
||||||
|
|
||||||
var existingIDs = Set(delegate.pipelineCurrentMessages(self).map { $0.id })
|
|
||||||
var pending: [(message: BitchatMessage, contentKey: String)] = []
|
|
||||||
var batchContentLatest: [String: Date] = [:]
|
|
||||||
|
|
||||||
for message in buffer {
|
|
||||||
if existingIDs.contains(message.id) { continue }
|
|
||||||
let contentKey = delegate.pipeline(self, normalizeContent: message.content)
|
|
||||||
if let ts = delegate.pipeline(self, contentTimestampForKey: contentKey),
|
|
||||||
abs(ts.timeIntervalSince(message.timestamp)) < dedupWindow {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if let ts = batchContentLatest[contentKey],
|
|
||||||
abs(ts.timeIntervalSince(message.timestamp)) < dedupWindow {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
existingIDs.insert(message.id)
|
|
||||||
pending.append((message, contentKey))
|
|
||||||
batchContentLatest[contentKey] = message.timestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.removeAll(keepingCapacity: true)
|
|
||||||
guard !pending.isEmpty else {
|
|
||||||
delegate.pipelineSetBatchingState(self, isBatching: false)
|
|
||||||
if !buffer.isEmpty { scheduleFlush() }
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pending.sort { $0.message.timestamp < $1.message.timestamp }
|
|
||||||
|
|
||||||
var messages = delegate.pipelineCurrentMessages(self)
|
|
||||||
let threshold = lateInsertThreshold(for: activeChannel)
|
|
||||||
let lastTimestamp = messages.last?.timestamp ?? .distantPast
|
|
||||||
|
|
||||||
for item in pending {
|
|
||||||
let message = item.message
|
|
||||||
if threshold == 0 || message.timestamp < lastTimestamp.addingTimeInterval(-threshold) {
|
|
||||||
let index = insertionIndex(for: message.timestamp, in: messages)
|
|
||||||
if index >= messages.count {
|
|
||||||
messages.append(message)
|
|
||||||
} else {
|
|
||||||
messages.insert(message, at: index)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
messages.append(message)
|
|
||||||
}
|
|
||||||
delegate.pipeline(self, recordContentKey: item.contentKey, timestamp: message.timestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate.pipeline(self, setMessages: messages)
|
|
||||||
delegate.pipelineTrimMessages(self)
|
|
||||||
|
|
||||||
updateFlushInterval(withBatchSize: pending.count)
|
|
||||||
|
|
||||||
for item in pending {
|
|
||||||
delegate.pipelinePrewarmMessage(self, message: item.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate.pipelineSetBatchingState(self, isBatching: false)
|
|
||||||
|
|
||||||
if !buffer.isEmpty {
|
|
||||||
scheduleFlush()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateFlushInterval(withBatchSize size: Int) {
|
|
||||||
recentBatchSizes.append(size)
|
|
||||||
if recentBatchSizes.count > maxRecentBatchSamples {
|
|
||||||
recentBatchSizes.removeFirst(recentBatchSizes.count - maxRecentBatchSamples)
|
|
||||||
}
|
|
||||||
let avg = recentBatchSizes.isEmpty
|
|
||||||
? 0.0
|
|
||||||
: Double(recentBatchSizes.reduce(0, +)) / Double(recentBatchSizes.count)
|
|
||||||
dynamicFlushInterval = avg > 100.0 ? 0.12 : baseFlushInterval
|
|
||||||
}
|
|
||||||
|
|
||||||
func lateInsertThreshold(for channel: ChannelID) -> TimeInterval {
|
|
||||||
switch channel {
|
|
||||||
case .mesh:
|
|
||||||
return TransportConfig.uiLateInsertThreshold
|
|
||||||
case .location:
|
|
||||||
return TransportConfig.uiLateInsertThresholdGeo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func insertionIndex(for timestamp: Date, in messages: [BitchatMessage]) -> Int {
|
|
||||||
var low = 0
|
|
||||||
var high = messages.count
|
|
||||||
while low < high {
|
|
||||||
let mid = (low + high) / 2
|
|
||||||
if messages[mid].timestamp < timestamp {
|
|
||||||
low = mid + 1
|
|
||||||
} else {
|
|
||||||
high = mid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return low
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
//
|
|
||||||
// PublicTimelineStore.swift
|
|
||||||
// bitchat
|
|
||||||
//
|
|
||||||
// Maintains mesh and geohash public timelines with simple caps and helpers.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct PublicTimelineStore {
|
|
||||||
private var meshTimeline: [BitchatMessage] = []
|
|
||||||
private var geohashTimelines: [String: [BitchatMessage]] = [:]
|
|
||||||
private var pendingGeohashSystemMessages: [String] = []
|
|
||||||
|
|
||||||
private let meshCap: Int
|
|
||||||
private let geohashCap: Int
|
|
||||||
|
|
||||||
init(meshCap: Int, geohashCap: Int) {
|
|
||||||
self.meshCap = meshCap
|
|
||||||
self.geohashCap = geohashCap
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func append(_ message: BitchatMessage, to channel: ChannelID) {
|
|
||||||
switch channel {
|
|
||||||
case .mesh:
|
|
||||||
guard !meshTimeline.contains(where: { $0.id == message.id }) else { return }
|
|
||||||
meshTimeline.append(message)
|
|
||||||
trimMeshTimelineIfNeeded()
|
|
||||||
case .location(let channel):
|
|
||||||
append(message, toGeohash: channel.geohash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func append(_ message: BitchatMessage, toGeohash geohash: String) {
|
|
||||||
var timeline = geohashTimelines[geohash] ?? []
|
|
||||||
guard !timeline.contains(where: { $0.id == message.id }) else { return }
|
|
||||||
timeline.append(message)
|
|
||||||
trimGeohashTimelineIfNeeded(&timeline)
|
|
||||||
geohashTimelines[geohash] = timeline
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Append message if absent, returning true when stored.
|
|
||||||
mutating func appendIfAbsent(_ message: BitchatMessage, toGeohash geohash: String) -> Bool {
|
|
||||||
var timeline = geohashTimelines[geohash] ?? []
|
|
||||||
guard !timeline.contains(where: { $0.id == message.id }) else { return false }
|
|
||||||
timeline.append(message)
|
|
||||||
trimGeohashTimelineIfNeeded(&timeline)
|
|
||||||
geohashTimelines[geohash] = timeline
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func messages(for channel: ChannelID) -> [BitchatMessage] {
|
|
||||||
switch channel {
|
|
||||||
case .mesh:
|
|
||||||
return meshTimeline
|
|
||||||
case .location(let channel):
|
|
||||||
let cleaned = geohashTimelines[channel.geohash]?.cleanedAndDeduped() ?? []
|
|
||||||
geohashTimelines[channel.geohash] = cleaned
|
|
||||||
return cleaned
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func clear(channel: ChannelID) {
|
|
||||||
switch channel {
|
|
||||||
case .mesh:
|
|
||||||
meshTimeline.removeAll()
|
|
||||||
case .location(let channel):
|
|
||||||
geohashTimelines[channel.geohash] = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
mutating func removeMessage(withID id: String) -> BitchatMessage? {
|
|
||||||
if let index = meshTimeline.firstIndex(where: { $0.id == id }) {
|
|
||||||
return meshTimeline.remove(at: index)
|
|
||||||
}
|
|
||||||
|
|
||||||
for key in Array(geohashTimelines.keys) {
|
|
||||||
var timeline = geohashTimelines[key] ?? []
|
|
||||||
if let index = timeline.firstIndex(where: { $0.id == id }) {
|
|
||||||
let removed = timeline.remove(at: index)
|
|
||||||
geohashTimelines[key] = timeline.isEmpty ? nil : timeline
|
|
||||||
return removed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func removeMessages(in geohash: String, where predicate: (BitchatMessage) -> Bool) {
|
|
||||||
var timeline = geohashTimelines[geohash] ?? []
|
|
||||||
timeline.removeAll(where: predicate)
|
|
||||||
geohashTimelines[geohash] = timeline.isEmpty ? nil : timeline
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func mutateGeohash(_ geohash: String, _ transform: (inout [BitchatMessage]) -> Void) {
|
|
||||||
var timeline = geohashTimelines[geohash] ?? []
|
|
||||||
transform(&timeline)
|
|
||||||
geohashTimelines[geohash] = timeline.isEmpty ? nil : timeline
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func queueGeohashSystemMessage(_ content: String) {
|
|
||||||
pendingGeohashSystemMessages.append(content)
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func drainPendingGeohashSystemMessages() -> [String] {
|
|
||||||
defer { pendingGeohashSystemMessages.removeAll(keepingCapacity: false) }
|
|
||||||
return pendingGeohashSystemMessages
|
|
||||||
}
|
|
||||||
|
|
||||||
func geohashKeys() -> [String] {
|
|
||||||
Array(geohashTimelines.keys)
|
|
||||||
}
|
|
||||||
|
|
||||||
private mutating func trimMeshTimelineIfNeeded() {
|
|
||||||
guard meshTimeline.count > meshCap else { return }
|
|
||||||
meshTimeline = Array(meshTimeline.suffix(meshCap))
|
|
||||||
}
|
|
||||||
|
|
||||||
private func trimGeohashTimelineIfNeeded(_ timeline: inout [BitchatMessage]) {
|
|
||||||
guard timeline.count > geohashCap else { return }
|
|
||||||
timeline = Array(timeline.suffix(geohashCap))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
//
|
|
||||||
// CommandSuggestionsView.swift
|
|
||||||
// bitchat
|
|
||||||
//
|
|
||||||
// Created by Islam on 29/10/2025.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct CommandSuggestionsView: View {
|
|
||||||
@EnvironmentObject private var viewModel: ChatViewModel
|
|
||||||
@ObservedObject private var locationManager = LocationChannelManager.shared
|
|
||||||
|
|
||||||
@Binding var messageText: String
|
|
||||||
|
|
||||||
let textColor: Color
|
|
||||||
let backgroundColor: Color
|
|
||||||
let secondaryTextColor: Color
|
|
||||||
|
|
||||||
private var filteredCommands: [CommandInfo] {
|
|
||||||
guard messageText.hasPrefix("/") && !messageText.contains(" ") else { return [] }
|
|
||||||
let isGeoPublic = locationManager.selectedChannel.isLocation
|
|
||||||
let isGeoDM = viewModel.selectedPrivateChatPeer?.isGeoDM == true
|
|
||||||
return CommandInfo.all(isGeoPublic: isGeoPublic, isGeoDM: isGeoDM).filter { command in
|
|
||||||
command.alias.starts(with: messageText.lowercased())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
|
||||||
ForEach(filteredCommands) { command in
|
|
||||||
Button {
|
|
||||||
messageText = command.alias + " "
|
|
||||||
} label: {
|
|
||||||
buttonRow(for: command)
|
|
||||||
}
|
|
||||||
.buttonStyle(.plain)
|
|
||||||
.background(Color.gray.opacity(0.1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.background(backgroundColor)
|
|
||||||
.overlay(
|
|
||||||
RoundedRectangle(cornerRadius: 4)
|
|
||||||
.stroke(secondaryTextColor.opacity(0.3), lineWidth: 1)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func buttonRow(for command: CommandInfo) -> some View {
|
|
||||||
HStack {
|
|
||||||
Text(command.alias)
|
|
||||||
.font(.bitchatSystem(size: 11, design: .monospaced))
|
|
||||||
.foregroundColor(textColor)
|
|
||||||
.fontWeight(.medium)
|
|
||||||
|
|
||||||
if let placeholder = command.placeholder {
|
|
||||||
Text(placeholder)
|
|
||||||
.font(.bitchatSystem(size: 10, design: .monospaced))
|
|
||||||
.foregroundColor(secondaryTextColor.opacity(0.8))
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Text(command.description)
|
|
||||||
.font(.bitchatSystem(size: 10, design: .monospaced))
|
|
||||||
.foregroundColor(secondaryTextColor)
|
|
||||||
}
|
|
||||||
.padding(.horizontal, 12)
|
|
||||||
.padding(.vertical, 3)
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@available(iOS 17, macOS 14, *)
|
|
||||||
#Preview {
|
|
||||||
@Previewable @State var messageText: String = "/"
|
|
||||||
let keychain = KeychainManager()
|
|
||||||
let viewModel = ChatViewModel(
|
|
||||||
keychain: keychain,
|
|
||||||
idBridge: NostrIdentityBridge(),
|
|
||||||
identityManager: SecureIdentityStateManager(keychain)
|
|
||||||
)
|
|
||||||
|
|
||||||
CommandSuggestionsView(
|
|
||||||
messageText: $messageText,
|
|
||||||
textColor: .green,
|
|
||||||
backgroundColor: .primary,
|
|
||||||
secondaryTextColor: .secondary
|
|
||||||
)
|
|
||||||
.environmentObject(viewModel)
|
|
||||||
}
|
|
||||||
+319
-344
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ import SwiftUI
|
|||||||
|
|
||||||
struct FingerprintView: View {
|
struct FingerprintView: View {
|
||||||
@ObservedObject var viewModel: ChatViewModel
|
@ObservedObject var viewModel: ChatViewModel
|
||||||
let peerID: PeerID
|
let peerID: String
|
||||||
@Environment(\.dismiss) var dismiss
|
@Environment(\.dismiss) var dismiss
|
||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.colorScheme) var colorScheme
|
||||||
|
|
||||||
@@ -65,12 +65,15 @@ struct FingerprintView: View {
|
|||||||
|
|
||||||
VStack(alignment: .leading, spacing: 16) {
|
VStack(alignment: .leading, spacing: 16) {
|
||||||
// Prefer short mesh ID for session/encryption status
|
// Prefer short mesh ID for session/encryption status
|
||||||
let statusPeerID = viewModel.getShortIDForNoiseKey(peerID)
|
let statusPeerID: String = {
|
||||||
|
if peerID.count == 64, let short = viewModel.getShortIDForNoiseKey(peerID) { return short.id }
|
||||||
|
return peerID
|
||||||
|
}()
|
||||||
// Resolve a friendly name
|
// Resolve a friendly name
|
||||||
let peerNickname: String = {
|
let peerNickname: String = {
|
||||||
if let p = viewModel.getPeer(byID: statusPeerID) { return p.displayName }
|
if let p = viewModel.getPeer(byID: PeerID(str: statusPeerID)) { return p.displayName }
|
||||||
if let name = viewModel.meshService.peerNickname(peerID: statusPeerID) { return name }
|
if let name = viewModel.meshService.peerNickname(peerID: PeerID(str: statusPeerID)) { return name }
|
||||||
if let data = peerID.noiseKey {
|
if peerID.count == 64, let data = Data(hexString: peerID) {
|
||||||
if let fav = FavoritesPersistenceService.shared.getFavoriteStatus(for: data), !fav.peerNickname.isEmpty { return fav.peerNickname }
|
if let fav = FavoritesPersistenceService.shared.getFavoriteStatus(for: data), !fav.peerNickname.isEmpty { return fav.peerNickname }
|
||||||
let fp = data.sha256Fingerprint()
|
let fp = data.sha256Fingerprint()
|
||||||
if let social = viewModel.identityManager.getSocialIdentity(for: fp) {
|
if let social = viewModel.identityManager.getSocialIdentity(for: fp) {
|
||||||
@@ -81,7 +84,7 @@ struct FingerprintView: View {
|
|||||||
return Strings.unknownPeer()
|
return Strings.unknownPeer()
|
||||||
}()
|
}()
|
||||||
// Accurate encryption state based on short ID session
|
// Accurate encryption state based on short ID session
|
||||||
let encryptionStatus = viewModel.getEncryptionStatus(for: statusPeerID)
|
let encryptionStatus = viewModel.getEncryptionStatus(for: PeerID(str: statusPeerID))
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
if let icon = encryptionStatus.icon {
|
if let icon = encryptionStatus.icon {
|
||||||
@@ -112,7 +115,7 @@ struct FingerprintView: View {
|
|||||||
.font(.bitchatSystem(size: 12, weight: .bold, design: .monospaced))
|
.font(.bitchatSystem(size: 12, weight: .bold, design: .monospaced))
|
||||||
.foregroundColor(textColor.opacity(0.7))
|
.foregroundColor(textColor.opacity(0.7))
|
||||||
|
|
||||||
if let fingerprint = viewModel.getFingerprint(for: statusPeerID) {
|
if let fingerprint = viewModel.getFingerprint(for: PeerID(str: statusPeerID)) {
|
||||||
Text(formatFingerprint(fingerprint))
|
Text(formatFingerprint(fingerprint))
|
||||||
.font(.bitchatSystem(size: 14, design: .monospaced))
|
.font(.bitchatSystem(size: 14, design: .monospaced))
|
||||||
.foregroundColor(textColor)
|
.foregroundColor(textColor)
|
||||||
@@ -173,6 +176,7 @@ struct FingerprintView: View {
|
|||||||
// Verification status
|
// Verification status
|
||||||
if encryptionStatus == .noiseSecured || encryptionStatus == .noiseVerified {
|
if encryptionStatus == .noiseSecured || encryptionStatus == .noiseVerified {
|
||||||
let isVerified = encryptionStatus == .noiseVerified
|
let isVerified = encryptionStatus == .noiseVerified
|
||||||
|
let peerID = PeerID(str: peerID)
|
||||||
|
|
||||||
VStack(spacing: 12) {
|
VStack(spacing: 12) {
|
||||||
Text(isVerified ? Strings.verifiedBadge : Strings.notVerifiedBadge)
|
Text(isVerified ? Strings.verifiedBadge : Strings.notVerifiedBadge)
|
||||||
@@ -236,6 +240,8 @@ struct FingerprintView: View {
|
|||||||
.padding()
|
.padding()
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
|
.presentationDetents([.large])
|
||||||
|
.presentationDragIndicator(.visible)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func formatFingerprint(_ fingerprint: String) -> String {
|
private func formatFingerprint(_ fingerprint: String) -> String {
|
||||||
|
|||||||
@@ -125,6 +125,9 @@ struct LocationChannelsSheet: View {
|
|||||||
.navigationTitle("")
|
.navigationTitle("")
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#if os(iOS)
|
||||||
|
.presentationDetents([.large])
|
||||||
|
#endif
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
.frame(minWidth: 420, minHeight: 520)
|
.frame(minWidth: 420, minHeight: 520)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -78,6 +78,9 @@ struct LocationNotesView: View {
|
|||||||
.navigationTitle("")
|
.navigationTitle("")
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#if os(iOS)
|
||||||
|
.presentationDetents([.large])
|
||||||
|
#endif
|
||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
.onDisappear { manager.cancel() }
|
.onDisappear { manager.cancel() }
|
||||||
.onChange(of: geohash) { newValue in
|
.onChange(of: geohash) { newValue in
|
||||||
@@ -138,7 +141,7 @@ struct LocationNotesView: View {
|
|||||||
String(
|
String(
|
||||||
format: String(localized: "location_notes.header", comment: "Header displaying the geohash and localized note count"),
|
format: String(localized: "location_notes.header", comment: "Header displaying the geohash and localized note count"),
|
||||||
locale: .current,
|
locale: .current,
|
||||||
"\(geohash) ± 1", count
|
geohash, count
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct FileAttachmentView: View {
|
||||||
|
private let url: URL
|
||||||
|
private let isSending: Bool
|
||||||
|
private let progress: Double?
|
||||||
|
private let onCancel: (() -> Void)?
|
||||||
|
|
||||||
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
|
#if os(iOS)
|
||||||
|
@State private var showExporter = false
|
||||||
|
#endif
|
||||||
|
|
||||||
|
init(url: URL, isSending: Bool, progress: Double?, onCancel: (() -> Void)?) {
|
||||||
|
self.url = url
|
||||||
|
self.isSending = isSending
|
||||||
|
self.progress = progress
|
||||||
|
self.onCancel = onCancel
|
||||||
|
}
|
||||||
|
|
||||||
|
private var fileName: String {
|
||||||
|
url.lastPathComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
private var normalizedProgress: Double? {
|
||||||
|
guard let progress = progress else { return nil }
|
||||||
|
return max(0, min(1, progress))
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack(alignment: .center, spacing: 12) {
|
||||||
|
Image(systemName: "doc.fill")
|
||||||
|
.foregroundColor(Color.blue)
|
||||||
|
.font(.bitchatSystem(size: 24))
|
||||||
|
|
||||||
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
|
Text(fileName)
|
||||||
|
.font(.bitchatSystem(size: 14, weight: .medium))
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
.lineLimit(2)
|
||||||
|
Text(url.lastPathComponent)
|
||||||
|
.font(.bitchatSystem(size: 11, design: .monospaced))
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
.lineLimit(1)
|
||||||
|
if let progress = normalizedProgress {
|
||||||
|
ProgressView(value: progress)
|
||||||
|
.progressViewStyle(.linear)
|
||||||
|
.tint(Color.blue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Button(action: openFile) {
|
||||||
|
Text("open", comment: "Button to open attached file")
|
||||||
|
.font(.bitchatSystem(size: 13, weight: .semibold))
|
||||||
|
.padding(.horizontal, 12)
|
||||||
|
.padding(.vertical, 6)
|
||||||
|
.background(
|
||||||
|
Capsule().fill(Color.blue.opacity(0.15))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
|
||||||
|
if let onCancel = onCancel, isSending {
|
||||||
|
Button(action: onCancel) {
|
||||||
|
Image(systemName: "xmark")
|
||||||
|
.font(.bitchatSystem(size: 11, weight: .bold))
|
||||||
|
.frame(width: 26, height: 26)
|
||||||
|
.background(Circle().fill(Color.red.opacity(0.9)))
|
||||||
|
.foregroundColor(.white)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(12)
|
||||||
|
.background(
|
||||||
|
RoundedRectangle(cornerRadius: 14)
|
||||||
|
.fill(colorScheme == .dark ? Color.black.opacity(0.6) : Color.white)
|
||||||
|
)
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: 14)
|
||||||
|
.stroke(Color.gray.opacity(0.2), lineWidth: 1)
|
||||||
|
)
|
||||||
|
#if os(iOS)
|
||||||
|
.sheet(isPresented: $showExporter) {
|
||||||
|
FileExportController(url: url)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private func openFile() {
|
||||||
|
#if os(iOS)
|
||||||
|
showExporter = true
|
||||||
|
#else
|
||||||
|
NSWorkspace.shared.open(url)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if os(iOS)
|
||||||
|
import UniformTypeIdentifiers
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
private struct FileExportController: UIViewControllerRepresentable {
|
||||||
|
let url: URL
|
||||||
|
|
||||||
|
func makeUIViewController(context: Context) -> UIDocumentPickerViewController {
|
||||||
|
let controller = UIDocumentPickerViewController(forExporting: [url])
|
||||||
|
controller.shouldShowFileExtensions = true
|
||||||
|
return controller
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
import AppKit
|
||||||
|
#endif
|
||||||
@@ -4,9 +4,9 @@ struct MeshPeerList: View {
|
|||||||
@ObservedObject var viewModel: ChatViewModel
|
@ObservedObject var viewModel: ChatViewModel
|
||||||
let textColor: Color
|
let textColor: Color
|
||||||
let secondaryTextColor: Color
|
let secondaryTextColor: Color
|
||||||
let onTapPeer: (PeerID) -> Void
|
let onTapPeer: (String) -> Void
|
||||||
let onToggleFavorite: (PeerID) -> Void
|
let onToggleFavorite: (String) -> Void
|
||||||
let onShowFingerprint: (PeerID) -> Void
|
let onShowFingerprint: (String) -> Void
|
||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.colorScheme) var colorScheme
|
||||||
|
|
||||||
@State private var orderedIDs: [String] = []
|
@State private var orderedIDs: [String] = []
|
||||||
@@ -130,7 +130,7 @@ struct MeshPeerList: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !isMe {
|
if !isMe {
|
||||||
Button(action: { onToggleFavorite(peer.peerID) }) {
|
Button(action: { onToggleFavorite(peer.peerID.id) }) {
|
||||||
Image(systemName: (peer.favoriteStatus?.isFavorite ?? false) ? "star.fill" : "star")
|
Image(systemName: (peer.favoriteStatus?.isFavorite ?? false) ? "star.fill" : "star")
|
||||||
.font(.bitchatSystem(size: 12))
|
.font(.bitchatSystem(size: 12))
|
||||||
.foregroundColor((peer.favoriteStatus?.isFavorite ?? false) ? .yellow : secondaryTextColor)
|
.foregroundColor((peer.favoriteStatus?.isFavorite ?? false) ? .yellow : secondaryTextColor)
|
||||||
@@ -142,8 +142,8 @@ struct MeshPeerList: View {
|
|||||||
.padding(.vertical, 4)
|
.padding(.vertical, 4)
|
||||||
.padding(.top, idx == 0 ? 10 : 0)
|
.padding(.top, idx == 0 ? 10 : 0)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.onTapGesture { if !isMe { onTapPeer(peer.peerID) } }
|
.onTapGesture { if !isMe { onTapPeer(peer.peerID.id) } }
|
||||||
.onTapGesture(count: 2) { if !isMe { onShowFingerprint(peer.peerID) } }
|
.onTapGesture(count: 2) { if !isMe { onShowFingerprint(peer.peerID.id) } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Seed and update order outside result builder
|
// Seed and update order outside result builder
|
||||||
|
|||||||
@@ -388,6 +388,10 @@ struct VerificationSheetView: View {
|
|||||||
.padding(.vertical, 14)
|
.padding(.vertical, 14)
|
||||||
}
|
}
|
||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
|
#if os(iOS)
|
||||||
|
.presentationDetents([.large])
|
||||||
|
.presentationDragIndicator(.visible)
|
||||||
|
#endif
|
||||||
.onDisappear { showingScanner = false }
|
.onDisappear { showingScanner = false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -298,5 +298,5 @@ private final class MockBitchatDelegate: BitchatDelegate {
|
|||||||
func didUpdateMessageDeliveryStatus(_ messageID: String, status: DeliveryStatus) {}
|
func didUpdateMessageDeliveryStatus(_ messageID: String, status: DeliveryStatus) {}
|
||||||
func didReceiveNoisePayload(from peerID: PeerID, type: NoisePayloadType, payload: Data, timestamp: Date) {}
|
func didReceiveNoisePayload(from peerID: PeerID, type: NoisePayloadType, payload: Data, timestamp: Date) {}
|
||||||
func didUpdateBluetoothState(_ state: CBManagerState) {}
|
func didUpdateBluetoothState(_ state: CBManagerState) {}
|
||||||
func didReceivePublicMessage(from peerID: PeerID, nickname: String, content: String, timestamp: Date, messageID: String?) {}
|
func didReceivePublicMessage(from peerID: String, nickname: String, content: String, timestamp: Date) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,11 +186,11 @@ struct PrivateChatE2ETests {
|
|||||||
// Bob relays private messages for Charlie
|
// Bob relays private messages for Charlie
|
||||||
bob.packetDeliveryHandler = { packet in
|
bob.packetDeliveryHandler = { packet in
|
||||||
if let recipientID = packet.recipientID,
|
if let recipientID = packet.recipientID,
|
||||||
PeerID(data: recipientID) == charlie.peerID {
|
String(data: recipientID, encoding: .utf8) == charlie.peerID {
|
||||||
// Relay to Charlie
|
// Relay to Charlie
|
||||||
var relayPacket = packet
|
var relayPacket = packet
|
||||||
relayPacket.ttl = packet.ttl - 1
|
relayPacket.ttl = packet.ttl - 1
|
||||||
charlie.simulateIncomingPacket(relayPacket)
|
self.charlie.simulateIncomingPacket(relayPacket)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -388,7 +388,7 @@ struct PublicChatE2ETests {
|
|||||||
|
|
||||||
if let message = BitchatMessage(packet.payload) {
|
if let message = BitchatMessage(packet.payload) {
|
||||||
// Don't relay own messages
|
// Don't relay own messages
|
||||||
guard message.senderPeerID != node.peerID else { return }
|
guard message.senderPeerID?.id != node.peerID else { return }
|
||||||
|
|
||||||
// Create relay message
|
// Create relay message
|
||||||
let relayMessage = BitchatMessage(
|
let relayMessage = BitchatMessage(
|
||||||
|
|||||||
@@ -93,62 +93,6 @@ struct FragmentationTests {
|
|||||||
#expect(capture.publicMessages.first?.content.count == 2048)
|
#expect(capture.publicMessages.first?.content.count == 2048)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test("Max-sized file transfer survives reassembly")
|
|
||||||
func maxSizedFileTransferSurvivesReassembly() async throws {
|
|
||||||
let ble = BLEService(
|
|
||||||
keychain: mockKeychain,
|
|
||||||
idBridge: idBridge,
|
|
||||||
identityManager: mockIdentityManager
|
|
||||||
)
|
|
||||||
let capture = CaptureDelegate()
|
|
||||||
ble.delegate = capture
|
|
||||||
|
|
||||||
let remoteID = PeerID(str: "CAFEBABECAFEBABE")
|
|
||||||
let fileContent = Data(repeating: 0x42, count: FileTransferLimits.maxPayloadBytes)
|
|
||||||
let filePacket = BitchatFilePacket(
|
|
||||||
fileName: "limit.bin",
|
|
||||||
fileSize: UInt64(fileContent.count),
|
|
||||||
mimeType: "application/octet-stream",
|
|
||||||
content: fileContent
|
|
||||||
)
|
|
||||||
let encoded = try #require(filePacket.encode(), "File packet encoding failed")
|
|
||||||
|
|
||||||
let packet = BitchatPacket(
|
|
||||||
type: MessageType.fileTransfer.rawValue,
|
|
||||||
senderID: Data(hexString: remoteID.id) ?? Data(),
|
|
||||||
recipientID: nil,
|
|
||||||
timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
|
|
||||||
payload: encoded,
|
|
||||||
signature: nil,
|
|
||||||
ttl: 7,
|
|
||||||
version: 2
|
|
||||||
)
|
|
||||||
|
|
||||||
let fragments = fragmentPacket(packet, fragmentSize: 4096, pad: false)
|
|
||||||
#expect(!fragments.isEmpty)
|
|
||||||
|
|
||||||
for (i, fragment) in fragments.enumerated() {
|
|
||||||
let delay = 5 * Double(i) * 0.001
|
|
||||||
Task {
|
|
||||||
try await sleep(delay)
|
|
||||||
ble._test_handlePacket(fragment, fromPeerID: remoteID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try await sleep(1.0)
|
|
||||||
|
|
||||||
let message = try #require(capture.receivedMessages.first, "Expected file transfer message")
|
|
||||||
#expect(message.content.hasPrefix("[file]"))
|
|
||||||
|
|
||||||
if let fileName = message.content.split(separator: " ").last {
|
|
||||||
let base = try FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
|
|
||||||
let filesRoot = base.appendingPathComponent("files", isDirectory: true)
|
|
||||||
let incoming = filesRoot.appendingPathComponent("files/incoming", isDirectory: true)
|
|
||||||
let url = incoming.appendingPathComponent(String(fileName))
|
|
||||||
try? FileManager.default.removeItem(at: url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("Invalid fragment header is ignored")
|
@Test("Invalid fragment header is ignored")
|
||||||
func invalidFragmentHeaderIsIgnored() async throws {
|
func invalidFragmentHeaderIsIgnored() async throws {
|
||||||
let ble = BLEService(
|
let ble = BLEService(
|
||||||
@@ -198,10 +142,7 @@ struct FragmentationTests {
|
|||||||
extension FragmentationTests {
|
extension FragmentationTests {
|
||||||
private final class CaptureDelegate: BitchatDelegate {
|
private final class CaptureDelegate: BitchatDelegate {
|
||||||
var publicMessages: [(peerID: PeerID, nickname: String, content: String)] = []
|
var publicMessages: [(peerID: PeerID, nickname: String, content: String)] = []
|
||||||
var receivedMessages: [BitchatMessage] = []
|
func didReceiveMessage(_ message: BitchatMessage) {}
|
||||||
func didReceiveMessage(_ message: BitchatMessage) {
|
|
||||||
receivedMessages.append(message)
|
|
||||||
}
|
|
||||||
func didConnectToPeer(_ peerID: PeerID) {}
|
func didConnectToPeer(_ peerID: PeerID) {}
|
||||||
func didDisconnectFromPeer(_ peerID: PeerID) {}
|
func didDisconnectFromPeer(_ peerID: PeerID) {}
|
||||||
func didUpdatePeerList(_ peers: [PeerID]) {}
|
func didUpdatePeerList(_ peers: [PeerID]) {}
|
||||||
@@ -209,7 +150,7 @@ extension FragmentationTests {
|
|||||||
func didUpdateMessageDeliveryStatus(_ messageID: String, status: DeliveryStatus) {}
|
func didUpdateMessageDeliveryStatus(_ messageID: String, status: DeliveryStatus) {}
|
||||||
func didReceiveNoisePayload(from peerID: PeerID, type: NoisePayloadType, payload: Data, timestamp: Date) {}
|
func didReceiveNoisePayload(from peerID: PeerID, type: NoisePayloadType, payload: Data, timestamp: Date) {}
|
||||||
func didUpdateBluetoothState(_ state: CBManagerState) {}
|
func didUpdateBluetoothState(_ state: CBManagerState) {}
|
||||||
func didReceivePublicMessage(from peerID: PeerID, nickname: String, content: String, timestamp: Date, messageID: String?) {
|
func didReceivePublicMessage(from peerID: PeerID, nickname: String, content: String, timestamp: Date) {
|
||||||
publicMessages.append((peerID, nickname, content))
|
publicMessages.append((peerID, nickname, content))
|
||||||
}
|
}
|
||||||
func didReceiveRegionalPublicMessage(from peerID: PeerID, nickname: String, content: String, timestamp: Date) {}
|
func didReceiveRegionalPublicMessage(from peerID: PeerID, nickname: String, content: String, timestamp: Date) {}
|
||||||
@@ -232,8 +173,8 @@ extension FragmentationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper: fragment a packet using the same header format BLEService expects
|
// Helper: fragment a packet using the same header format BLEService expects
|
||||||
private func fragmentPacket(_ packet: BitchatPacket, fragmentSize: Int, fragmentID: Data? = nil, pad: Bool = true) -> [BitchatPacket] {
|
private func fragmentPacket(_ packet: BitchatPacket, fragmentSize: Int, fragmentID: Data? = nil) -> [BitchatPacket] {
|
||||||
guard let fullData = packet.toBinaryData(padding: pad) else { return [] }
|
let fullData = packet.toBinaryData() ?? Data()
|
||||||
let fid = fragmentID ?? Data((0..<8).map { _ in UInt8.random(in: 0...255) })
|
let fid = fragmentID ?? Data((0..<8).map { _ in UInt8.random(in: 0...255) })
|
||||||
let chunks: [Data] = stride(from: 0, to: fullData.count, by: fragmentSize).map { off in
|
let chunks: [Data] = stride(from: 0, to: fullData.count, by: fragmentSize).map { off in
|
||||||
Data(fullData[off..<min(off + fragmentSize, fullData.count)])
|
Data(fullData[off..<min(off + fragmentSize, fullData.count)])
|
||||||
|
|||||||
@@ -125,138 +125,16 @@ struct GossipSyncManagerTests {
|
|||||||
#expect(manager._hasAnnouncement(for: PeerID(str: peerHex)) == false)
|
#expect(manager._hasAnnouncement(for: PeerID(str: peerHex)) == false)
|
||||||
#expect(manager._messageCount(for: PeerID(str: peerHex)) == 0)
|
#expect(manager._messageCount(for: PeerID(str: peerHex)) == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test func maintenanceEmitsTypedSyncRequests() throws {
|
|
||||||
var config = GossipSyncManager.Config()
|
|
||||||
config.seenCapacity = 10
|
|
||||||
config.fragmentCapacity = 5
|
|
||||||
config.fileTransferCapacity = 4
|
|
||||||
config.messageSyncIntervalSeconds = 1
|
|
||||||
config.fragmentSyncIntervalSeconds = 1
|
|
||||||
config.fileTransferSyncIntervalSeconds = 1
|
|
||||||
config.maintenanceIntervalSeconds = 0
|
|
||||||
|
|
||||||
let manager = GossipSyncManager(myPeerID: myPeerID, config: config)
|
|
||||||
let delegate = RecordingDelegate()
|
|
||||||
manager.delegate = delegate
|
|
||||||
|
|
||||||
let sender = try #require(Data(hexString: "1122334455667788"))
|
|
||||||
let now = UInt64(Date().timeIntervalSince1970 * 1000)
|
|
||||||
|
|
||||||
let announcePacket = BitchatPacket(
|
|
||||||
type: MessageType.announce.rawValue,
|
|
||||||
senderID: sender,
|
|
||||||
recipientID: nil,
|
|
||||||
timestamp: now,
|
|
||||||
payload: Data(),
|
|
||||||
signature: nil,
|
|
||||||
ttl: 1
|
|
||||||
)
|
|
||||||
let messagePacket = BitchatPacket(
|
|
||||||
type: MessageType.message.rawValue,
|
|
||||||
senderID: sender,
|
|
||||||
recipientID: nil,
|
|
||||||
timestamp: now,
|
|
||||||
payload: Data([0x01]),
|
|
||||||
signature: nil,
|
|
||||||
ttl: 1
|
|
||||||
)
|
|
||||||
let fragmentPacket = BitchatPacket(
|
|
||||||
type: MessageType.fragment.rawValue,
|
|
||||||
senderID: sender,
|
|
||||||
recipientID: nil,
|
|
||||||
timestamp: now,
|
|
||||||
payload: Data([0xAA]),
|
|
||||||
signature: nil,
|
|
||||||
ttl: 1
|
|
||||||
)
|
|
||||||
let filePacket = BitchatPacket(
|
|
||||||
type: MessageType.fileTransfer.rawValue,
|
|
||||||
senderID: sender,
|
|
||||||
recipientID: nil,
|
|
||||||
timestamp: now,
|
|
||||||
payload: Data([0xBB]),
|
|
||||||
signature: nil,
|
|
||||||
ttl: 1,
|
|
||||||
version: 2
|
|
||||||
)
|
|
||||||
|
|
||||||
manager.onPublicPacketSeen(announcePacket)
|
|
||||||
manager.onPublicPacketSeen(messagePacket)
|
|
||||||
manager.onPublicPacketSeen(fragmentPacket)
|
|
||||||
manager.onPublicPacketSeen(filePacket)
|
|
||||||
|
|
||||||
manager._performMaintenanceSynchronously(now: Date())
|
|
||||||
|
|
||||||
let sentPackets = delegate.packets
|
|
||||||
#expect(sentPackets.count == 3)
|
|
||||||
let decoded = sentPackets.compactMap { RequestSyncPacket.decode(from: $0.payload) }
|
|
||||||
#expect(decoded.count == 3)
|
|
||||||
#expect(decoded[0].types == .publicMessages)
|
|
||||||
#expect(decoded[1].types == .fragment)
|
|
||||||
#expect(decoded[2].types == .fileTransfer)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func handleRequestSyncHonorsTypeFilter() async throws {
|
|
||||||
var config = GossipSyncManager.Config()
|
|
||||||
config.seenCapacity = 5
|
|
||||||
config.fragmentCapacity = 5
|
|
||||||
config.fileTransferCapacity = 0
|
|
||||||
config.messageSyncIntervalSeconds = 0
|
|
||||||
config.fragmentSyncIntervalSeconds = 0
|
|
||||||
config.fileTransferSyncIntervalSeconds = 0
|
|
||||||
|
|
||||||
let manager = GossipSyncManager(myPeerID: myPeerID, config: config)
|
|
||||||
let delegate = RecordingDelegate()
|
|
||||||
manager.delegate = delegate
|
|
||||||
|
|
||||||
let sender = try #require(Data(hexString: "aabbccddeeff0011"))
|
|
||||||
let now = UInt64(Date().timeIntervalSince1970 * 1000)
|
|
||||||
|
|
||||||
let messagePacket = BitchatPacket(
|
|
||||||
type: MessageType.message.rawValue,
|
|
||||||
senderID: sender,
|
|
||||||
recipientID: nil,
|
|
||||||
timestamp: now,
|
|
||||||
payload: Data([0x10]),
|
|
||||||
signature: nil,
|
|
||||||
ttl: 1
|
|
||||||
)
|
|
||||||
|
|
||||||
let fragmentPacket = BitchatPacket(
|
|
||||||
type: MessageType.fragment.rawValue,
|
|
||||||
senderID: sender,
|
|
||||||
recipientID: nil,
|
|
||||||
timestamp: now,
|
|
||||||
payload: Data([0x20]),
|
|
||||||
signature: nil,
|
|
||||||
ttl: 1
|
|
||||||
)
|
|
||||||
|
|
||||||
manager.onPublicPacketSeen(messagePacket)
|
|
||||||
manager.onPublicPacketSeen(fragmentPacket)
|
|
||||||
|
|
||||||
let peer = PeerID(str: "FFFFFFFFFFFFFFFF")
|
|
||||||
let request = RequestSyncPacket(p: 4, m: 1, data: Data(), types: .fragment)
|
|
||||||
manager.handleRequestSync(from: peer, request: request)
|
|
||||||
|
|
||||||
try await sleep(0.01)
|
|
||||||
let sentPackets = delegate.packets
|
|
||||||
#expect(sentPackets.count == 1)
|
|
||||||
#expect(sentPackets[0].type == MessageType.fragment.rawValue)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class RecordingDelegate: GossipSyncManager.Delegate {
|
private final class RecordingDelegate: GossipSyncManager.Delegate {
|
||||||
var onSend: (() -> Void)?
|
var onSend: (() -> Void)?
|
||||||
private(set) var lastPacket: BitchatPacket?
|
private(set) var lastPacket: BitchatPacket?
|
||||||
private(set) var packets: [BitchatPacket] = []
|
|
||||||
private let lock = NSLock()
|
private let lock = NSLock()
|
||||||
|
|
||||||
func sendPacket(_ packet: BitchatPacket) {
|
func sendPacket(_ packet: BitchatPacket) {
|
||||||
lock.lock()
|
lock.lock()
|
||||||
lastPacket = packet
|
lastPacket = packet
|
||||||
packets.append(packet)
|
|
||||||
lock.unlock()
|
lock.unlock()
|
||||||
onSend?()
|
onSend?()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,192 +0,0 @@
|
|||||||
//
|
|
||||||
// InputValidatorTests.swift
|
|
||||||
// bitchatTests
|
|
||||||
//
|
|
||||||
// This is free and unencumbered software released into the public domain.
|
|
||||||
// For more information, see <https://unlicense.org>
|
|
||||||
//
|
|
||||||
|
|
||||||
import Testing
|
|
||||||
import Foundation
|
|
||||||
@testable import bitchat
|
|
||||||
|
|
||||||
struct InputValidatorTests {
|
|
||||||
|
|
||||||
// MARK: - Basic Validation Tests
|
|
||||||
|
|
||||||
@Test func validStringPassesValidation() throws {
|
|
||||||
let result = InputValidator.validateUserString("Hello World", maxLength: 100)
|
|
||||||
#expect(result == "Hello World")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func emptyStringReturnsNil() throws {
|
|
||||||
let result = InputValidator.validateUserString("", maxLength: 100)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func whitespaceOnlyStringReturnsNil() throws {
|
|
||||||
let result = InputValidator.validateUserString(" \n\t ", maxLength: 100)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func stringExceedingMaxLengthReturnsNil() throws {
|
|
||||||
let longString = String(repeating: "a", count: 101)
|
|
||||||
let result = InputValidator.validateUserString(longString, maxLength: 100)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func stringAtMaxLengthIsAccepted() throws {
|
|
||||||
let exactString = String(repeating: "a", count: 100)
|
|
||||||
let result = InputValidator.validateUserString(exactString, maxLength: 100)
|
|
||||||
#expect(result == exactString)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func whitespaceIsTrimmed() throws {
|
|
||||||
let result = InputValidator.validateUserString(" Hello ", maxLength: 100)
|
|
||||||
#expect(result == "Hello")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Control Character Tests
|
|
||||||
|
|
||||||
@Test func nullCharacterIsRejected() throws {
|
|
||||||
let stringWithNull = "Hello\u{0000}World"
|
|
||||||
let result = InputValidator.validateUserString(stringWithNull, maxLength: 100)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func bellCharacterIsRejected() throws {
|
|
||||||
let stringWithBell = "Hello\u{0007}World"
|
|
||||||
let result = InputValidator.validateUserString(stringWithBell, maxLength: 100)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func backspaceCharacterIsRejected() throws {
|
|
||||||
let stringWithBackspace = "Hello\u{0008}World"
|
|
||||||
let result = InputValidator.validateUserString(stringWithBackspace, maxLength: 100)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func escapeCharacterIsRejected() throws {
|
|
||||||
let stringWithEscape = "Hello\u{001B}World"
|
|
||||||
let result = InputValidator.validateUserString(stringWithEscape, maxLength: 100)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func deleteCharacterIsRejected() throws {
|
|
||||||
let stringWithDelete = "Hello\u{007F}World"
|
|
||||||
let result = InputValidator.validateUserString(stringWithDelete, maxLength: 100)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func multipleControlCharactersAreRejected() throws {
|
|
||||||
let stringWithMultiple = "Hello\u{0000}\u{0007}\u{001B}World"
|
|
||||||
let result = InputValidator.validateUserString(stringWithMultiple, maxLength: 100)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Unicode and Special Character Tests
|
|
||||||
|
|
||||||
@Test func emojiIsAccepted() throws {
|
|
||||||
let result = InputValidator.validateUserString("Hello 👋 World", maxLength: 100)
|
|
||||||
#expect(result == "Hello 👋 World")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func unicodeCharactersAreAccepted() throws {
|
|
||||||
let result = InputValidator.validateUserString("Hello 世界 مرحبا", maxLength: 100)
|
|
||||||
#expect(result == "Hello 世界 مرحبا")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func specialCharactersAreAccepted() throws {
|
|
||||||
let result = InputValidator.validateUserString("Hello!@#$%^&*()_+-=[]{}|;':\",./<>?", maxLength: 100)
|
|
||||||
#expect(result == "Hello!@#$%^&*()_+-=[]{}|;':\",./<>?")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Nickname Validation Tests
|
|
||||||
|
|
||||||
@Test func validNicknameIsAccepted() throws {
|
|
||||||
let result = InputValidator.validateNickname("Alice")
|
|
||||||
#expect(result == "Alice")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func nicknameWithEmojiIsAccepted() throws {
|
|
||||||
let result = InputValidator.validateNickname("Alice 🚀")
|
|
||||||
#expect(result == "Alice 🚀")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func nicknameTooLongIsRejected() throws {
|
|
||||||
let longNickname = String(repeating: "a", count: 51)
|
|
||||||
let result = InputValidator.validateNickname(longNickname)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func nicknameAtMaxLengthIsAccepted() throws {
|
|
||||||
let exactNickname = String(repeating: "a", count: 50)
|
|
||||||
let result = InputValidator.validateNickname(exactNickname)
|
|
||||||
#expect(result == exactNickname)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func nicknameWithControlCharacterIsRejected() throws {
|
|
||||||
let result = InputValidator.validateNickname("Alice\u{0000}")
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Timestamp Validation Tests
|
|
||||||
|
|
||||||
@Test func currentTimestampIsValid() throws {
|
|
||||||
let now = Date()
|
|
||||||
let result = InputValidator.validateTimestamp(now)
|
|
||||||
#expect(result == true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func timestampWithinOneHourIsValid() throws {
|
|
||||||
let thirtyMinutesAgo = Date().addingTimeInterval(-30 * 60)
|
|
||||||
let result = InputValidator.validateTimestamp(thirtyMinutesAgo)
|
|
||||||
#expect(result == true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func timestampTwoHoursAgoIsInvalid() throws {
|
|
||||||
let twoHoursAgo = Date().addingTimeInterval(-2 * 3600)
|
|
||||||
let result = InputValidator.validateTimestamp(twoHoursAgo)
|
|
||||||
#expect(result == false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func timestampTwoHoursInFutureIsInvalid() throws {
|
|
||||||
let twoHoursFromNow = Date().addingTimeInterval(2 * 3600)
|
|
||||||
let result = InputValidator.validateTimestamp(twoHoursFromNow)
|
|
||||||
#expect(result == false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func timestampAtOneHourBoundaryIsValid() throws {
|
|
||||||
// Just slightly within the one-hour window
|
|
||||||
let almostOneHourAgo = Date().addingTimeInterval(-3599)
|
|
||||||
let result = InputValidator.validateTimestamp(almostOneHourAgo)
|
|
||||||
#expect(result == true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Edge Cases
|
|
||||||
|
|
||||||
@Test func singleCharacterStringIsAccepted() throws {
|
|
||||||
let result = InputValidator.validateUserString("a", maxLength: 100)
|
|
||||||
#expect(result == "a")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func stringWithOnlyNewlinesIsRejected() throws {
|
|
||||||
let result = InputValidator.validateUserString("\n\n\n", maxLength: 100)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func stringWithMixedWhitespaceIsTrimmed() throws {
|
|
||||||
let result = InputValidator.validateUserString(" \t\nHello\n\t ", maxLength: 100)
|
|
||||||
#expect(result == "Hello")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func stringWithLeadingControlCharacterIsRejected() throws {
|
|
||||||
let result = InputValidator.validateUserString("\u{0000}Hello", maxLength: 100)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func stringWithTrailingControlCharacterIsRejected() throws {
|
|
||||||
let result = InputValidator.validateUserString("Hello\u{0000}", maxLength: 100)
|
|
||||||
#expect(result == nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -91,3 +91,61 @@ struct LocationNotesManagerTests {
|
|||||||
case shouldNotDerive
|
case shouldNotDerive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
struct LocationNotesCounterTests {
|
||||||
|
@Test func subscribeWithoutRelaysMarksUnavailable() {
|
||||||
|
var subscribeCalled = false
|
||||||
|
let deps = LocationNotesCounterDependencies(
|
||||||
|
relayLookup: { _, _ in [] },
|
||||||
|
subscribe: { _, _, _, _, _ in subscribeCalled = true },
|
||||||
|
unsubscribe: { _ in }
|
||||||
|
)
|
||||||
|
|
||||||
|
let counter = LocationNotesCounter(testDependencies: deps)
|
||||||
|
counter.subscribe(geohash: "u4pruydq")
|
||||||
|
|
||||||
|
#expect(!subscribeCalled)
|
||||||
|
#expect(!counter.relayAvailable)
|
||||||
|
#expect(counter.initialLoadComplete)
|
||||||
|
#expect(counter.count == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test func subscribeCountsUniqueNotes() {
|
||||||
|
var storedHandler: ((NostrEvent) -> Void)?
|
||||||
|
var storedEOSE: (() -> Void)?
|
||||||
|
let deps = LocationNotesCounterDependencies(
|
||||||
|
relayLookup: { _, _ in ["wss://relay.geo"] },
|
||||||
|
subscribe: { filter, id, relays, handler, eose in
|
||||||
|
#expect(relays == ["wss://relay.geo"])
|
||||||
|
#expect(filter.kinds == [1])
|
||||||
|
#expect(!id.isEmpty)
|
||||||
|
storedHandler = handler
|
||||||
|
storedEOSE = eose
|
||||||
|
},
|
||||||
|
unsubscribe: { _ in }
|
||||||
|
)
|
||||||
|
|
||||||
|
let counter = LocationNotesCounter(testDependencies: deps)
|
||||||
|
counter.subscribe(geohash: "u4pruydq")
|
||||||
|
|
||||||
|
var first = NostrEvent(
|
||||||
|
pubkey: "pub",
|
||||||
|
createdAt: Date(),
|
||||||
|
kind: .textNote,
|
||||||
|
tags: [["g", "u4pruydq"]],
|
||||||
|
content: "a"
|
||||||
|
)
|
||||||
|
first.id = "eventA"
|
||||||
|
storedHandler?(first)
|
||||||
|
|
||||||
|
let duplicate = first
|
||||||
|
storedHandler?(duplicate)
|
||||||
|
|
||||||
|
storedEOSE?()
|
||||||
|
|
||||||
|
#expect(counter.relayAvailable)
|
||||||
|
#expect(counter.count == 1)
|
||||||
|
#expect(counter.initialLoadComplete)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
//
|
|
||||||
// MimeTypeTests.swift
|
|
||||||
// bitchatTests
|
|
||||||
//
|
|
||||||
// This is free and unencumbered software released into the public domain.
|
|
||||||
// For more information, see <https://unlicense.org>
|
|
||||||
//
|
|
||||||
|
|
||||||
import Testing
|
|
||||||
import Foundation
|
|
||||||
@testable import bitchat
|
|
||||||
|
|
||||||
// MARK: - MimeType Mapping and Signature Tests
|
|
||||||
|
|
||||||
struct MimeTypeTests {
|
|
||||||
|
|
||||||
// MARK: MIME → Enum Parsing + Default Extension
|
|
||||||
@Test(arguments: [
|
|
||||||
("image/jpeg", MimeType.jpeg, "jpg"),
|
|
||||||
("image/jpg", MimeType.jpeg, "jpg"),
|
|
||||||
("image/png", MimeType.png, "png"),
|
|
||||||
("image/gif", MimeType.gif, "gif"),
|
|
||||||
("image/webp", MimeType.webp, "webp"),
|
|
||||||
("audio/mp4", MimeType.mp4Audio, "m4a"),
|
|
||||||
("audio/m4a", MimeType.m4a, "m4a"),
|
|
||||||
("audio/aac", MimeType.aac, "m4a"),
|
|
||||||
("audio/mpeg", MimeType.mpeg, "mp3"),
|
|
||||||
("audio/mp3", MimeType.mp3, "mp3"),
|
|
||||||
("audio/wav", MimeType.wav, "wav"),
|
|
||||||
("audio/x-wav", MimeType.xWav, "wav"),
|
|
||||||
("audio/ogg", MimeType.ogg, "ogg"),
|
|
||||||
("application/pdf", MimeType.pdf, "pdf"),
|
|
||||||
("application/octet-stream", MimeType.octetStream, "bin")
|
|
||||||
])
|
|
||||||
func mimeTypeParsingAndExtensions(
|
|
||||||
mimeString: String,
|
|
||||||
expectedType: MimeType,
|
|
||||||
expectedExt: String
|
|
||||||
) throws {
|
|
||||||
guard let mime = MimeType(mimeString) else {
|
|
||||||
Issue.record("Failed to parse \(mimeString)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
#expect(mime == expectedType, "Expected \(expectedType) for \(mimeString)")
|
|
||||||
#expect(mime.mimeString == expectedType.mimeString)
|
|
||||||
#expect(mime.defaultExtension == expectedExt)
|
|
||||||
#expect(mime.isAllowed)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - File Signature Validation
|
|
||||||
@Test(arguments: [
|
|
||||||
// === Image types ===
|
|
||||||
(MimeType.jpeg, [0xFF, 0xD8, 0xFF]),
|
|
||||||
(MimeType.png, [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]),
|
|
||||||
(MimeType.gif, [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]), // "GIF89a"
|
|
||||||
(MimeType.webp, [0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x57, 0x45, 0x42, 0x50]), // "RIFF....WEBP"
|
|
||||||
|
|
||||||
// === Audio types ===
|
|
||||||
(MimeType.mp3, [0x49, 0x44, 0x33]), // "ID3"
|
|
||||||
(MimeType.wav, [0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x57, 0x41, 0x56, 0x45]), // "RIFF....WAVE"
|
|
||||||
(MimeType.ogg, [0x4F, 0x67, 0x67, 0x53]), // "OggS"
|
|
||||||
|
|
||||||
// === Application types ===
|
|
||||||
(MimeType.pdf, [0x25, 0x50, 0x44, 0x46]) // "%PDF"
|
|
||||||
])
|
|
||||||
func validSignatures(mime: MimeType, bytes: [UInt8]) throws {
|
|
||||||
let data = Data(bytes)
|
|
||||||
#expect(mime.matches(data: data),
|
|
||||||
"Expected \(mime.mimeString) to match its signature")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Negative Tests
|
|
||||||
@Test func invalidDataDoesNotMatch() throws {
|
|
||||||
let badData = Data(repeating: 0x00, count: 16)
|
|
||||||
for mime in MimeType.allCases where mime != .octetStream {
|
|
||||||
#expect(!mime.matches(data: badData),
|
|
||||||
"Unexpectedly matched \(mime.mimeString) with zeroed data")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Octet-stream (generic binary)
|
|
||||||
@Test func octetStreamAlwaysMatches() throws {
|
|
||||||
let randomData = Data([0x00, 0x11, 0x22, 0x33])
|
|
||||||
#expect(MimeType.octetStream.matches(data: randomData),
|
|
||||||
"application/octet-stream should always be considered valid")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -203,7 +203,10 @@ final class MockBLEService: NSObject {
|
|||||||
let target = bus.service(for: recipientPeerID) {
|
let target = bus.service(for: recipientPeerID) {
|
||||||
target.simulateIncomingPacket(packet)
|
target.simulateIncomingPacket(packet)
|
||||||
} else {
|
} else {
|
||||||
// Not directly connected: deliver to neighbors for relay
|
// Not directly connected: deliver to neighbors for relay; also deliver directly if target is known
|
||||||
|
if let target = bus.service(for: recipientPeerID) {
|
||||||
|
target.simulateIncomingPacket(packet)
|
||||||
|
}
|
||||||
for neighbor in neighbors() where neighbor.peerID != recipientPeerID {
|
for neighbor in neighbors() where neighbor.peerID != recipientPeerID {
|
||||||
neighbor.simulateIncomingPacket(packet)
|
neighbor.simulateIncomingPacket(packet)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ struct NostrProtocolTests {
|
|||||||
|
|
||||||
// Build a DELIVERED ack embedded payload (geohash-style, no recipient peer ID)
|
// Build a DELIVERED ack embedded payload (geohash-style, no recipient peer ID)
|
||||||
let messageID = "TEST-MSG-DELIVERED-1"
|
let messageID = "TEST-MSG-DELIVERED-1"
|
||||||
let senderPeerID = PeerID(str: "0123456789abcdef") // 8-byte hex peer ID
|
let senderPeerID = "0123456789abcdef" // 8-byte hex peer ID
|
||||||
|
|
||||||
let embedded = try #require(
|
let embedded = try #require(
|
||||||
NostrEmbeddedBitChat.encodeAckForNostrNoRecipient(type: .delivered, messageID: messageID, senderPeerID: senderPeerID),
|
NostrEmbeddedBitChat.encodeAckForNostrNoRecipient(type: .delivered, messageID: messageID, senderPeerID: senderPeerID),
|
||||||
@@ -176,7 +176,7 @@ struct NostrProtocolTests {
|
|||||||
let recipient = try NostrIdentity.generate()
|
let recipient = try NostrIdentity.generate()
|
||||||
|
|
||||||
let messageID = "TEST-MSG-READ-1"
|
let messageID = "TEST-MSG-READ-1"
|
||||||
let senderPeerID = PeerID(str: "fedcba9876543210") // 8-byte hex peer ID
|
let senderPeerID = "fedcba9876543210" // 8-byte hex peer ID
|
||||||
let embedded = try #require(
|
let embedded = try #require(
|
||||||
NostrEmbeddedBitChat.encodeAckForNostrNoRecipient(type: .readReceipt, messageID: messageID, senderPeerID: senderPeerID),
|
NostrEmbeddedBitChat.encodeAckForNostrNoRecipient(type: .readReceipt, messageID: messageID, senderPeerID: senderPeerID),
|
||||||
"Failed to embed read ack"
|
"Failed to embed read ack"
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ struct NotificationStreamAssemblerTests {
|
|||||||
#expect(decoded.timestamp == packet.timestamp)
|
#expect(decoded.timestamp == packet.timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAssemblesCompressedLargeFrame() throws {
|
@Test func assemblesCompressedLargeFrame() throws {
|
||||||
var assembler = NotificationStreamAssembler()
|
var assembler = NotificationStreamAssembler()
|
||||||
|
|
||||||
// Keep the fixture below FileTransferLimits.maxPayloadBytes so encoding succeeds while still exercising compression.
|
// Keep the fixture below FileTransferLimits.maxPayloadBytes so encoding succeeds while still exercising compression.
|
||||||
@@ -108,7 +108,6 @@ struct NotificationStreamAssemblerTests {
|
|||||||
content: largeContent
|
content: largeContent
|
||||||
)
|
)
|
||||||
let tlvPayload = try #require(filePacket.encode(), "Failed to encode file packet")
|
let tlvPayload = try #require(filePacket.encode(), "Failed to encode file packet")
|
||||||
|
|
||||||
let senderID = Data(repeating: 0xAA, count: BinaryProtocol.senderIDSize)
|
let senderID = Data(repeating: 0xAA, count: BinaryProtocol.senderIDSize)
|
||||||
let packet = BitchatPacket(
|
let packet = BitchatPacket(
|
||||||
type: MessageType.fileTransfer.rawValue,
|
type: MessageType.fileTransfer.rawValue,
|
||||||
@@ -125,7 +124,7 @@ struct NotificationStreamAssemblerTests {
|
|||||||
|
|
||||||
#expect(BinaryProtocol.Offsets.flags < frame.count)
|
#expect(BinaryProtocol.Offsets.flags < frame.count)
|
||||||
let flags = frame[frame.startIndex + BinaryProtocol.Offsets.flags]
|
let flags = frame[frame.startIndex + BinaryProtocol.Offsets.flags]
|
||||||
#expect((flags & BinaryProtocol.Flags.isCompressed) != 0, "Frame should be compressed for large payloads")
|
#expect(flags & BinaryProtocol.Flags.isCompressed != 0, "Frame should be compressed for large payloads")
|
||||||
|
|
||||||
let splitIndex = min(4096, frame.count / 2)
|
let splitIndex = min(4096, frame.count / 2)
|
||||||
var result = assembler.append(frame.prefix(splitIndex))
|
var result = assembler.append(frame.prefix(splitIndex))
|
||||||
@@ -134,7 +133,7 @@ struct NotificationStreamAssemblerTests {
|
|||||||
result = assembler.append(frame.suffix(from: splitIndex))
|
result = assembler.append(frame.suffix(from: splitIndex))
|
||||||
#expect(result.frames.count == 1)
|
#expect(result.frames.count == 1)
|
||||||
#expect(result.droppedPrefixes.isEmpty)
|
#expect(result.droppedPrefixes.isEmpty)
|
||||||
#expect(result.reset == false)
|
#expect(!result.reset)
|
||||||
|
|
||||||
let assembled = try #require(result.frames.first, "Missing assembled frame")
|
let assembled = try #require(result.frames.first, "Missing assembled frame")
|
||||||
#expect(assembled.count == frame.count)
|
#expect(assembled.count == frame.count)
|
||||||
|
|||||||
@@ -55,86 +55,6 @@ struct BinaryProtocolTests {
|
|||||||
#expect(decodedPacket.signature == TestConstants.testSignature)
|
#expect(decodedPacket.signature == TestConstants.testSignature)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test func packetWithRouteRoundTrip() throws {
|
|
||||||
let route: [Data] = [
|
|
||||||
try #require(Data(hexString: "0102030405060708")),
|
|
||||||
try #require(Data(hexString: "1112131415161718")),
|
|
||||||
try #require(Data(hexString: "2122232425262728"))
|
|
||||||
]
|
|
||||||
|
|
||||||
var packet = BitchatPacket(
|
|
||||||
type: 0x01,
|
|
||||||
senderID: route[0],
|
|
||||||
recipientID: route.last,
|
|
||||||
timestamp: 1_720_000_000_000,
|
|
||||||
payload: Data("route-test".utf8),
|
|
||||||
signature: nil,
|
|
||||||
ttl: 6
|
|
||||||
)
|
|
||||||
packet.route = route
|
|
||||||
|
|
||||||
let encoded = try #require(BinaryProtocol.encode(packet), "Failed to encode packet with route")
|
|
||||||
let flagsByte = encoded[BinaryProtocol.Offsets.flags]
|
|
||||||
#expect((flagsByte & BinaryProtocol.Flags.hasRoute) != 0)
|
|
||||||
|
|
||||||
let decoded = try #require(BinaryProtocol.decode(encoded), "Failed to decode packet with route")
|
|
||||||
let decodedRoute = try #require(decoded.route)
|
|
||||||
#expect(decodedRoute.count == route.count)
|
|
||||||
for (expected, actual) in zip(route, decodedRoute) {
|
|
||||||
#expect(actual == expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func packetWithRoutePadsShortHop() throws {
|
|
||||||
let sender = try #require(Data(hexString: "0011223344556677"))
|
|
||||||
let destination = try #require(Data(hexString: "8899aabbccddeeff"))
|
|
||||||
let shortHop = Data([0xAA, 0xBB, 0xCC])
|
|
||||||
|
|
||||||
var packet = BitchatPacket(
|
|
||||||
type: 0x02,
|
|
||||||
senderID: sender,
|
|
||||||
recipientID: destination,
|
|
||||||
timestamp: 1_730_000_000_000,
|
|
||||||
payload: Data("pad-test".utf8),
|
|
||||||
signature: nil,
|
|
||||||
ttl: 5
|
|
||||||
)
|
|
||||||
packet.route = [shortHop, destination]
|
|
||||||
|
|
||||||
let encoded = try #require(BinaryProtocol.encode(packet), "Failed to encode packet with short hop route")
|
|
||||||
let decoded = try #require(BinaryProtocol.decode(encoded), "Failed to decode packet with short hop route")
|
|
||||||
let decodedRoute = try #require(decoded.route)
|
|
||||||
let firstHop = try #require(decodedRoute.first)
|
|
||||||
#expect(firstHop.count == BinaryProtocol.senderIDSize)
|
|
||||||
#expect(firstHop.prefix(shortHop.count) == shortHop)
|
|
||||||
let paddingBytes = firstHop.suffix(firstHop.count - shortHop.count)
|
|
||||||
#expect(paddingBytes.allSatisfy { $0 == 0 })
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func packetWithRouteAndCompressedPayload() throws {
|
|
||||||
let route: [Data] = [
|
|
||||||
try #require(Data(hexString: "0101010101010101")),
|
|
||||||
try #require(Data(hexString: "0202020202020202"))
|
|
||||||
]
|
|
||||||
let repeatedString = String(repeating: "compress-me", count: 150)
|
|
||||||
var packet = BitchatPacket(
|
|
||||||
type: 0x03,
|
|
||||||
senderID: route[0],
|
|
||||||
recipientID: route.last,
|
|
||||||
timestamp: 1_740_000_000_000,
|
|
||||||
payload: Data(repeatedString.utf8),
|
|
||||||
signature: nil,
|
|
||||||
ttl: 7
|
|
||||||
)
|
|
||||||
packet.route = route
|
|
||||||
|
|
||||||
let encoded = try #require(BinaryProtocol.encode(packet), "Failed to encode packet with route and compression")
|
|
||||||
let decoded = try #require(BinaryProtocol.decode(encoded), "Failed to decode packet with route and compression")
|
|
||||||
#expect(decoded.payload == Data(repeatedString.utf8))
|
|
||||||
let decodedRoute = try #require(decoded.route)
|
|
||||||
#expect(decodedRoute == route)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Compression Tests
|
// MARK: - Compression Tests
|
||||||
|
|
||||||
@Test("Create a large, compressible payload above current threshold (2048B)")
|
@Test("Create a large, compressible payload above current threshold (2048B)")
|
||||||
@@ -148,9 +68,10 @@ struct BinaryProtocolTests {
|
|||||||
let encodedData = try #require(BinaryProtocol.encode(packet), "Failed to encode packet with large payload")
|
let encodedData = try #require(BinaryProtocol.encode(packet), "Failed to encode packet with large payload")
|
||||||
|
|
||||||
// The encoded size should be smaller than uncompressed due to compression
|
// The encoded size should be smaller than uncompressed due to compression
|
||||||
let headerSize = try #require(BinaryProtocol.headerSize(for: packet.version), "Invalid packet version")
|
let headerSize = try #require(BinaryProtocol.headerSize(for: packet.version), "Invalid version")
|
||||||
|
|
||||||
let uncompressedSize = headerSize + BinaryProtocol.senderIDSize + largePayload.count
|
let uncompressedSize = headerSize + BinaryProtocol.senderIDSize + largePayload.count
|
||||||
#expect(encodedData.count < uncompressedSize, "Compressed packet should be smaller than uncompressed form")
|
#expect(encodedData.count < uncompressedSize)
|
||||||
|
|
||||||
// Decode and verify
|
// Decode and verify
|
||||||
let decodedPacket = try #require(BinaryProtocol.decode(encodedData), "Failed to decode compressed packet")
|
let decodedPacket = try #require(BinaryProtocol.decode(encodedData), "Failed to decode compressed packet")
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
//
|
|
||||||
// MeshTopologyTrackerTests.swift
|
|
||||||
// bitchatTests
|
|
||||||
//
|
|
||||||
// This is free and unencumbered software released into the public domain.
|
|
||||||
// For more information, see <https://unlicense.org>
|
|
||||||
//
|
|
||||||
|
|
||||||
import Testing
|
|
||||||
import Foundation
|
|
||||||
@testable import bitchat
|
|
||||||
|
|
||||||
struct MeshTopologyTrackerTests {
|
|
||||||
private func hex(_ value: String) throws -> Data {
|
|
||||||
try #require(Data(hexString: value))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func directLinkProducesRoute() throws {
|
|
||||||
let tracker = MeshTopologyTracker()
|
|
||||||
let a = try hex("0102030405060708")
|
|
||||||
let b = try hex("1112131415161718")
|
|
||||||
|
|
||||||
tracker.recordDirectLink(between: a, and: b)
|
|
||||||
let route = try #require(tracker.computeRoute(from: a, to: b))
|
|
||||||
#expect(route == [a, b])
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func multiHopRouteComputation() throws {
|
|
||||||
let tracker = MeshTopologyTracker()
|
|
||||||
let a = try hex("0001020304050607")
|
|
||||||
let b = try hex("1011121314151617")
|
|
||||||
let c = try hex("2021222324252627")
|
|
||||||
let d = try hex("3031323334353637")
|
|
||||||
|
|
||||||
tracker.recordDirectLink(between: a, and: b)
|
|
||||||
tracker.recordDirectLink(between: b, and: c)
|
|
||||||
tracker.recordDirectLink(between: c, and: d)
|
|
||||||
|
|
||||||
let route = try #require(tracker.computeRoute(from: a, to: d))
|
|
||||||
#expect(route == [a, b, c, d])
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func recordRouteAddsEdges() throws {
|
|
||||||
let tracker = MeshTopologyTracker()
|
|
||||||
var a = Data([0xAA, 0xBB, 0xCC])
|
|
||||||
let b = try hex("4445464748494A4B")
|
|
||||||
let c = try hex("5455565758595A5B")
|
|
||||||
|
|
||||||
tracker.recordRoute([a, b, c])
|
|
||||||
|
|
||||||
a.append(Data(repeating: 0, count: BinaryProtocol.senderIDSize - a.count))
|
|
||||||
let route = try #require(tracker.computeRoute(from: a, to: c))
|
|
||||||
#expect(route.first == a)
|
|
||||||
#expect(route.last == c)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func removingDirectLinkBreaksRoute() throws {
|
|
||||||
let tracker = MeshTopologyTracker()
|
|
||||||
let a = try hex("0101010101010101")
|
|
||||||
let b = try hex("0202020202020202")
|
|
||||||
let c = try hex("0303030303030303")
|
|
||||||
|
|
||||||
tracker.recordDirectLink(between: a, and: b)
|
|
||||||
tracker.recordDirectLink(between: b, and: c)
|
|
||||||
let initialRoute = try #require(tracker.computeRoute(from: a, to: c))
|
|
||||||
#expect(initialRoute == [a, b, c])
|
|
||||||
|
|
||||||
tracker.removeDirectLink(between: b, and: c)
|
|
||||||
#expect(tracker.computeRoute(from: a, to: c) == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func removingPeerClearsEdges() throws {
|
|
||||||
let tracker = MeshTopologyTracker()
|
|
||||||
let a = try hex("0F0E0D0C0B0A0908")
|
|
||||||
let b = try hex("0A0B0C0D0E0F0001")
|
|
||||||
let c = try hex("0011223344556677")
|
|
||||||
|
|
||||||
tracker.recordRoute([a, b, c])
|
|
||||||
let initialRoute = try #require(tracker.computeRoute(from: a, to: c))
|
|
||||||
#expect(initialRoute == [a, b, c])
|
|
||||||
|
|
||||||
tracker.removePeer(b)
|
|
||||||
#expect(tracker.computeRoute(from: a, to: c) == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -218,26 +218,6 @@ struct PeerIDTests {
|
|||||||
#expect(short == peerID)
|
#expect(short == peerID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test func routingData_fromShortID() throws {
|
|
||||||
let peerID = PeerID(str: hex16)
|
|
||||||
let routing = try #require(peerID.routingData)
|
|
||||||
#expect(routing.count == 8)
|
|
||||||
#expect(routing == Data(hexString: hex16))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func routingData_fromNoiseKey() throws {
|
|
||||||
let peerID = PeerID(str: hex64)
|
|
||||||
let routing = try #require(peerID.routingData)
|
|
||||||
let expectedShort = peerID.toShort()
|
|
||||||
#expect(routing == Data(hexString: expectedShort.id))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func routingPeerRoundTrip() throws {
|
|
||||||
let raw = try #require(Data(hexString: hex16))
|
|
||||||
let peerID = try #require(PeerID(routingData: raw))
|
|
||||||
#expect(peerID.routingData == raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Codable
|
// MARK: - Codable
|
||||||
|
|
||||||
@Test func codable_emptyPrefix() throws {
|
@Test func codable_emptyPrefix() throws {
|
||||||
@@ -293,7 +273,7 @@ struct PeerIDTests {
|
|||||||
@Test func comparable_sorting_and_equality() {
|
@Test func comparable_sorting_and_equality() {
|
||||||
let p1 = PeerID(str: "aaa")
|
let p1 = PeerID(str: "aaa")
|
||||||
let p2 = PeerID(str: "bbb")
|
let p2 = PeerID(str: "bbb")
|
||||||
let p3 = PeerID(str: "BBB")
|
let p3 = PeerID(str: "bbb")
|
||||||
|
|
||||||
#expect(p1 < p2)
|
#expect(p1 < p2)
|
||||||
#expect(p2 >= p1)
|
#expect(p2 >= p1)
|
||||||
@@ -304,18 +284,44 @@ struct PeerIDTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test func equality() {
|
@Test func equality() {
|
||||||
let peerID = PeerID(str: "aaa")
|
let string = "aaa"
|
||||||
|
let peerID = PeerID(str: string)
|
||||||
|
let badString = "bbb"
|
||||||
|
|
||||||
|
// PeerID == String
|
||||||
|
#expect(peerID == string)
|
||||||
|
#expect(peerID == Optional(string))
|
||||||
|
#expect(Optional(peerID) == string)
|
||||||
|
#expect(Optional(peerID) == Optional(string))
|
||||||
|
|
||||||
|
// PeerID != String
|
||||||
|
#expect(peerID != badString)
|
||||||
|
#expect(peerID != Optional(badString))
|
||||||
|
#expect(Optional(peerID) != badString)
|
||||||
|
#expect(Optional(peerID) != Optional(badString))
|
||||||
|
|
||||||
|
// String == PeerID
|
||||||
|
#expect(string == peerID)
|
||||||
|
#expect(Optional(string) == peerID)
|
||||||
|
#expect(string == Optional(peerID))
|
||||||
|
#expect(Optional(string) == Optional(peerID))
|
||||||
|
|
||||||
|
// String != PeerID
|
||||||
|
#expect(badString != peerID)
|
||||||
|
#expect(Optional(badString) != peerID)
|
||||||
|
#expect(badString != Optional(peerID))
|
||||||
|
#expect(Optional(badString) != Optional(peerID))
|
||||||
|
|
||||||
// Regular PeerID <> PeerID
|
// Regular PeerID <> PeerID
|
||||||
#expect(peerID == PeerID(str: "AAA"))
|
#expect(peerID == PeerID(str: "aaa"))
|
||||||
#expect(peerID == Optional(PeerID(str: "AAA")))
|
#expect(peerID == Optional(PeerID(str: "aaa")))
|
||||||
#expect(PeerID(str: "AAA") == peerID)
|
#expect(PeerID(str: "aaa") == peerID)
|
||||||
#expect(Optional(PeerID(str: "AAA")) == Optional(peerID))
|
#expect(Optional(PeerID(str: "aaa")) == Optional(peerID))
|
||||||
|
|
||||||
#expect(peerID != PeerID(str: "BBB"))
|
#expect(peerID != PeerID(str: "bbb"))
|
||||||
#expect(peerID != Optional(PeerID(str: "BBB")))
|
#expect(peerID != Optional(PeerID(str: "bbb")))
|
||||||
#expect(PeerID(str: "BBB") != peerID)
|
#expect(PeerID(str: "bbb") != peerID)
|
||||||
#expect(Optional(PeerID(str: "BBB")) != Optional(peerID))
|
#expect(Optional(PeerID(str: "bbb")) != Optional(peerID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Computed properties
|
// MARK: - Computed properties
|
||||||
|
|||||||
@@ -18,10 +18,6 @@ let package = Package(
|
|||||||
.target(
|
.target(
|
||||||
name: "BitLogger",
|
name: "BitLogger",
|
||||||
path: "Sources"
|
path: "Sources"
|
||||||
),
|
|
||||||
.testTarget(
|
|
||||||
name: "BitLoggerTests",
|
|
||||||
dependencies: ["BitLogger"]
|
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,9 +6,7 @@
|
|||||||
// For more information, see <https://unlicense.org>
|
// For more information, see <https://unlicense.org>
|
||||||
//
|
//
|
||||||
|
|
||||||
#if canImport(os.log)
|
|
||||||
import os.log
|
import os.log
|
||||||
#endif
|
|
||||||
|
|
||||||
public extension OSLog {
|
public extension OSLog {
|
||||||
private static let subsystem = "chat.bitchat"
|
private static let subsystem = "chat.bitchat"
|
||||||
|
|||||||
@@ -7,53 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
#if canImport(os.log)
|
|
||||||
import os.log
|
import os.log
|
||||||
#else
|
|
||||||
public struct OSLog {
|
|
||||||
public let subsystem: String
|
|
||||||
public let category: String
|
|
||||||
|
|
||||||
public init(subsystem: String, category: String) {
|
|
||||||
self.subsystem = subsystem
|
|
||||||
self.category = category
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct OSLogType: CustomStringConvertible {
|
|
||||||
private let label: String
|
|
||||||
|
|
||||||
private init(_ label: String) {
|
|
||||||
self.label = label
|
|
||||||
}
|
|
||||||
|
|
||||||
public var description: String { label }
|
|
||||||
|
|
||||||
public static let debug = OSLogType("debug")
|
|
||||||
public static let info = OSLogType("info")
|
|
||||||
public static let `default` = OSLogType("default")
|
|
||||||
public static let error = OSLogType("error")
|
|
||||||
public static let fault = OSLogType("fault")
|
|
||||||
}
|
|
||||||
|
|
||||||
@usableFromInline
|
|
||||||
let secureLoggerFallbackFormatter: ISO8601DateFormatter = {
|
|
||||||
let formatter = ISO8601DateFormatter()
|
|
||||||
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
|
|
||||||
return formatter
|
|
||||||
}()
|
|
||||||
|
|
||||||
@usableFromInline
|
|
||||||
func os_log(_ message: StaticString, log: OSLog, type: OSLogType, _ args: CVarArg...) {
|
|
||||||
let rawFormat = String(describing: message)
|
|
||||||
let format = rawFormat
|
|
||||||
.replacingOccurrences(of: "%{public}@", with: "%@")
|
|
||||||
.replacingOccurrences(of: "%{private}@", with: "%@")
|
|
||||||
let formatted = String(format: format, arguments: args)
|
|
||||||
let timestamp = secureLoggerFallbackFormatter.string(from: Date())
|
|
||||||
print("[\(timestamp)] [\(log.subsystem)::\(log.category)] [\(type.description)] \(formatted)")
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Centralized security-aware logging framework
|
/// Centralized security-aware logging framework
|
||||||
/// Provides safe logging that filters sensitive data and security events
|
/// Provides safe logging that filters sensitive data and security events
|
||||||
@@ -68,6 +22,22 @@ public final class SecureLogger {
|
|||||||
return formatter
|
return formatter
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// MARK: - Cached Regex Patterns
|
||||||
|
|
||||||
|
private static let fingerprintPattern = #/[a-fA-F0-9]{64}/#
|
||||||
|
private static let base64Pattern = #/[A-Za-z0-9+/]{40,}={0,2}/#
|
||||||
|
private static let passwordPattern = #/password["\s:=]+["']?[^"'\s]+["']?/#
|
||||||
|
private static let peerIDPattern = #/peerID: ([a-zA-Z0-9]{8})[a-zA-Z0-9]+/#
|
||||||
|
|
||||||
|
// MARK: - Sanitization Cache
|
||||||
|
|
||||||
|
private static let sanitizationCache: NSCache<NSString, NSString> = {
|
||||||
|
let cache = NSCache<NSString, NSString>()
|
||||||
|
cache.countLimit = 100 // Keep last 100 sanitized strings
|
||||||
|
return cache
|
||||||
|
}()
|
||||||
|
private static let cacheQueue = DispatchQueue(label: "chat.bitchat.securelogger.cache", attributes: .concurrent)
|
||||||
|
|
||||||
// MARK: - Log Levels
|
// MARK: - Log Levels
|
||||||
|
|
||||||
enum LogLevel {
|
enum LogLevel {
|
||||||
@@ -145,8 +115,8 @@ public extension SecureLogger {
|
|||||||
static func error(_ error: Error, context: @autoclosure () -> String, category: OSLog = .noise,
|
static func error(_ error: Error, context: @autoclosure () -> String, category: OSLog = .noise,
|
||||||
file: String = #file, line: Int = #line, function: String = #function) {
|
file: String = #file, line: Int = #line, function: String = #function) {
|
||||||
let location = formatLocation(file: file, line: line, function: function)
|
let location = formatLocation(file: file, line: line, function: function)
|
||||||
let sanitized = context().sanitized()
|
let sanitized = sanitize(context())
|
||||||
let errorDesc = error.localizedDescription.sanitized()
|
let errorDesc = sanitize(error.localizedDescription)
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
os_log("%{public}@ Error in %{public}@: %{public}@", log: category, type: .error, location, sanitized, errorDesc)
|
os_log("%{public}@ Error in %{public}@: %{public}@", log: category, type: .error, location, sanitized, errorDesc)
|
||||||
@@ -170,15 +140,15 @@ public extension SecureLogger {
|
|||||||
var message: String {
|
var message: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .handshakeStarted(let peerID):
|
case .handshakeStarted(let peerID):
|
||||||
return "Handshake started with peer: \(peerID.sanitized())"
|
return "Handshake started with peer: \(sanitize(peerID))"
|
||||||
case .handshakeCompleted(let peerID):
|
case .handshakeCompleted(let peerID):
|
||||||
return "Handshake completed with peer: \(peerID.sanitized())"
|
return "Handshake completed with peer: \(sanitize(peerID))"
|
||||||
case .handshakeFailed(let peerID, let error):
|
case .handshakeFailed(let peerID, let error):
|
||||||
return "Handshake failed with peer: \(peerID.sanitized()), error: \(error)"
|
return "Handshake failed with peer: \(sanitize(peerID)), error: \(error)"
|
||||||
case .sessionExpired(let peerID):
|
case .sessionExpired(let peerID):
|
||||||
return "Session expired for peer: \(peerID.sanitized())"
|
return "Session expired for peer: \(sanitize(peerID))"
|
||||||
case .authenticationFailed(let peerID):
|
case .authenticationFailed(let peerID):
|
||||||
return "Authentication failed for peer: \(peerID.sanitized())"
|
return "Authentication failed for peer: \(sanitize(peerID))"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,7 +203,7 @@ private extension SecureLogger {
|
|||||||
file: String, line: Int, function: String) {
|
file: String, line: Int, function: String) {
|
||||||
guard shouldLog(level) else { return }
|
guard shouldLog(level) else { return }
|
||||||
let location = formatLocation(file: file, line: line, function: function)
|
let location = formatLocation(file: file, line: line, function: function)
|
||||||
let sanitized = "\(location) \(message())".sanitized()
|
let sanitized = sanitize("\(location) \(message())")
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
os_log("%{public}@", log: category, type: level.osLogType, sanitized)
|
os_log("%{public}@", log: category, type: level.osLogType, sanitized)
|
||||||
@@ -266,6 +236,58 @@ private extension SecureLogger {
|
|||||||
let timestamp = timestampFormatter.string(from: Date())
|
let timestamp = timestampFormatter.string(from: Date())
|
||||||
return "[\(timestamp)] [\(fileName):\(line) \(function)]"
|
return "[\(timestamp)] [\(fileName):\(line) \(function)]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sanitize strings to remove potentially sensitive data
|
||||||
|
static func sanitize(_ input: String) -> String {
|
||||||
|
let key = input as NSString
|
||||||
|
|
||||||
|
// Check cache first
|
||||||
|
var cachedValue: String?
|
||||||
|
cacheQueue.sync {
|
||||||
|
cachedValue = sanitizationCache.object(forKey: key) as String?
|
||||||
|
}
|
||||||
|
|
||||||
|
if let cached = cachedValue {
|
||||||
|
return cached
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform sanitization
|
||||||
|
var sanitized = input
|
||||||
|
|
||||||
|
// Remove full fingerprints (keep first 8 chars for debugging)
|
||||||
|
sanitized = sanitized.replacing(fingerprintPattern) { match in
|
||||||
|
let fingerprint = String(match.output)
|
||||||
|
return String(fingerprint.prefix(8)) + "..."
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove base64 encoded data that might be keys
|
||||||
|
sanitized = sanitized.replacing(base64Pattern) { _ in
|
||||||
|
"<base64-data>"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove potential passwords (assuming they're in quotes or after "password:")
|
||||||
|
sanitized = sanitized.replacing(passwordPattern) { _ in
|
||||||
|
"password: <redacted>"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truncate peer IDs to first 8 characters
|
||||||
|
sanitized = sanitized.replacing(peerIDPattern) { match in
|
||||||
|
"peerID: \(match.1)..."
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the result
|
||||||
|
cacheQueue.sync {
|
||||||
|
sanitizationCache.setObject(sanitized as NSString, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sanitized
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sanitize individual values
|
||||||
|
static func sanitize<T>(_ value: T) -> String {
|
||||||
|
let stringValue = String(describing: value)
|
||||||
|
return sanitize(stringValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Migration Helper
|
// MARK: - Migration Helper
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
//
|
|
||||||
// String+Sanitization.swift
|
|
||||||
// BitLogger
|
|
||||||
//
|
|
||||||
// This is free and unencumbered software released into the public domain.
|
|
||||||
// For more information, see <https://unlicense.org>
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
extension String {
|
|
||||||
/// Sanitize strings to remove potentially sensitive data
|
|
||||||
func sanitized() -> String {
|
|
||||||
let key = self as NSString
|
|
||||||
|
|
||||||
// Check cache first
|
|
||||||
if let cached = Self.queue.sync(execute: { Self.cache.object(forKey: key) }) {
|
|
||||||
return cached as String
|
|
||||||
}
|
|
||||||
|
|
||||||
var sanitized = self
|
|
||||||
|
|
||||||
// Remove full fingerprints (keep first 8 chars for debugging)
|
|
||||||
let fingerprintPattern = #/[a-fA-F0-9]{64}/#
|
|
||||||
sanitized = sanitized.replacing(fingerprintPattern) { match in
|
|
||||||
let fingerprint = String(match.output)
|
|
||||||
return String(fingerprint.prefix(8)) + "..."
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove base64 encoded data that might be keys
|
|
||||||
let base64Pattern = #/[A-Za-z0-9+/]{40,}={0,2}/#
|
|
||||||
sanitized = sanitized.replacing(base64Pattern) { _ in
|
|
||||||
"<base64-data>"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove potential passwords (assuming they're in quotes or after "password:")
|
|
||||||
let passwordPattern = #/password["\s:=]+["']?[^"'\s]+["']?/#
|
|
||||||
sanitized = sanitized.replacing(passwordPattern) { _ in
|
|
||||||
"password: <redacted>"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Truncate peer IDs to first 8 characters
|
|
||||||
let peerIDPattern = #/peerID: ([a-zA-Z0-9]{8})[a-zA-Z0-9]+/#
|
|
||||||
sanitized = sanitized.replacing(peerIDPattern) { match in
|
|
||||||
"peerID: \(match.1)..."
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache the result
|
|
||||||
Self.queue.sync {
|
|
||||||
Self.cache.setObject(sanitized as NSString, forKey: key)
|
|
||||||
}
|
|
||||||
|
|
||||||
return sanitized
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Cache Helpers
|
|
||||||
|
|
||||||
private extension String {
|
|
||||||
static let queue = DispatchQueue(label: "chat.bitchat.securelogger.cache", attributes: .concurrent)
|
|
||||||
|
|
||||||
static let cache: NSCache<NSString, NSString> = {
|
|
||||||
let cache = NSCache<NSString, NSString>()
|
|
||||||
cache.countLimit = 100 // Keep last 100 sanitized strings
|
|
||||||
return cache
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
//
|
|
||||||
// StringSanitizationTests.swift
|
|
||||||
// BitLogger
|
|
||||||
//
|
|
||||||
// Created by Islam on 19/10/2025.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Testing
|
|
||||||
@testable import BitLogger
|
|
||||||
|
|
||||||
struct StringSanitizationTests {
|
|
||||||
|
|
||||||
@Test("64-hex fingerprint is truncated to first 8 chars followed by ellipsis")
|
|
||||||
func fingerprintTruncation() async throws {
|
|
||||||
let fingerprint = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
|
||||||
#expect(fingerprint.count == 64)
|
|
||||||
|
|
||||||
let input = "fingerprint=\(fingerprint)"
|
|
||||||
let output = input.sanitized()
|
|
||||||
|
|
||||||
#expect(output.contains("fingerprint=01234567..."))
|
|
||||||
// Ensure no full fingerprint remains
|
|
||||||
#expect(output.contains(fingerprint) == false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("Multiple fingerprints in a string are all truncated")
|
|
||||||
func multipleFingerprintTruncation() async throws {
|
|
||||||
let fp1 = String(repeating: "a", count: 64)
|
|
||||||
let fp2 = String(repeating: "b", count: 64)
|
|
||||||
let input = "fp1=\(fp1) fp2=\(fp2)"
|
|
||||||
let output = input.sanitized()
|
|
||||||
#expect(output.contains("fp1=aaaaaaaa..."))
|
|
||||||
#expect(output.contains("fp2=bbbbbbbb..."))
|
|
||||||
#expect(output.contains(fp1) == false)
|
|
||||||
#expect(output.contains(fp2) == false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("Base64-like long data is replaced with <base64-data>")
|
|
||||||
func base64Replacement() async throws {
|
|
||||||
// 44+ chars of base64 characters
|
|
||||||
let base64ish = "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo5ODc2NTQzMjE="
|
|
||||||
let input = "payload=\(base64ish)"
|
|
||||||
let output = input.sanitized()
|
|
||||||
#expect(output == "payload=<base64-data>")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("Base64-like without padding is replaced with <base64-data>")
|
|
||||||
func base64NoPaddingReplacement() async throws {
|
|
||||||
let base64ish = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
|
||||||
#expect(base64ish.count >= 40)
|
|
||||||
let input = "b64:\(base64ish)"
|
|
||||||
let output = input.sanitized()
|
|
||||||
#expect(output == "b64:<base64-data>")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("Short base64-like strings (below threshold) are not replaced")
|
|
||||||
func shortBase64NotReplaced() async throws {
|
|
||||||
let short = "QUJDREVGR0hJSktMTU5P" // < 40 chars
|
|
||||||
let input = "payload=\(short)"
|
|
||||||
let output = input.sanitized()
|
|
||||||
#expect(output == input)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("Password redaction for key:value formats", arguments: [
|
|
||||||
"password: secret123",
|
|
||||||
"password=secret123",
|
|
||||||
"password = secret123",
|
|
||||||
"password: 'secret123'",
|
|
||||||
"password:\"secret123\"",
|
|
||||||
"password='secret123'"
|
|
||||||
])
|
|
||||||
func passwordRedactionKeyValue(password: String) async throws {
|
|
||||||
#expect(password.sanitized() == "password: <redacted>")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("Password redaction inside wider messages")
|
|
||||||
func passwordRedactionInContext() async throws {
|
|
||||||
let input = "user=john password: 'p@ssW0rd' attempt=1"
|
|
||||||
let output = input.sanitized()
|
|
||||||
#expect(output == "user=john password: <redacted> attempt=1")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("PeerID is truncated to first 8 chars followed by ellipsis")
|
|
||||||
func peerIDTruncation() async throws {
|
|
||||||
let peer = "ABCDEF12GHIJKL34"
|
|
||||||
let input = "peerID: \(peer)"
|
|
||||||
let output = input.sanitized()
|
|
||||||
#expect(output == "peerID: ABCDEF12...")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("PeerID not truncated when exactly 8 chars")
|
|
||||||
func peerIDExactlyEightNotTruncated() async throws {
|
|
||||||
let peer = "ABCDEF12"
|
|
||||||
let input = "peerID: \(peer)"
|
|
||||||
let output = input.sanitized()
|
|
||||||
// Pattern only matches when there are more than 8 trailing chars, so unchanged
|
|
||||||
#expect(output == input)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("Non-matching content remains unchanged")
|
|
||||||
func nonMatchingUnchanged() async throws {
|
|
||||||
let input = "Hello world 123 - nothing sensitive here."
|
|
||||||
let output = input.sanitized()
|
|
||||||
#expect(output == input)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("Idempotency: sanitizing twice yields same result")
|
|
||||||
func idempotentSanitization() async throws {
|
|
||||||
let input = """
|
|
||||||
fingerprint=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
|
|
||||||
password: "superSecret" \
|
|
||||||
peerID: ZYXWVUT987654321 \
|
|
||||||
payload=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
|
|
||||||
"""
|
|
||||||
let once = input.sanitized()
|
|
||||||
let twice = once.sanitized()
|
|
||||||
#expect(once == twice)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("Mixed content: all rules apply in a single string")
|
|
||||||
func mixedContent() async throws {
|
|
||||||
let fingerprint = "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210"
|
|
||||||
let base64ish = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
|
||||||
let peer = "PEERID01EXTRA"
|
|
||||||
let input = "fp=\(fingerprint) password='x' peerID: \(peer) data=\(base64ish)"
|
|
||||||
let output = input.sanitized()
|
|
||||||
#expect(output.contains("fp=fedcba98..."))
|
|
||||||
#expect(output.contains("password: <redacted>"))
|
|
||||||
#expect(output.contains("peerID: PEERID01..."))
|
|
||||||
#expect(output.contains("data=<base64-data>"))
|
|
||||||
#expect(output.contains(fingerprint) == false)
|
|
||||||
#expect(output.contains(base64ish) == false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test("Cache returns consistent result for repeated inputs")
|
|
||||||
func cacheHitConsistency() async throws {
|
|
||||||
let input = "password: hunter2"
|
|
||||||
let first = input.sanitized()
|
|
||||||
let second = input.sanitized()
|
|
||||||
#expect(first == "password: <redacted>")
|
|
||||||
#expect(first == second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
<key>BinaryPath</key>
|
<key>BinaryPath</key>
|
||||||
<string>tor-nolzma.framework/tor-nolzma</string>
|
<string>tor-nolzma.framework/tor-nolzma</string>
|
||||||
<key>LibraryIdentifier</key>
|
<key>LibraryIdentifier</key>
|
||||||
<string>ios-arm64</string>
|
<string>macos-arm64</string>
|
||||||
<key>LibraryPath</key>
|
<key>LibraryPath</key>
|
||||||
<string>tor-nolzma.framework</string>
|
<string>tor-nolzma.framework</string>
|
||||||
<key>SupportedArchitectures</key>
|
<key>SupportedArchitectures</key>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<string>arm64</string>
|
<string>arm64</string>
|
||||||
</array>
|
</array>
|
||||||
<key>SupportedPlatform</key>
|
<key>SupportedPlatform</key>
|
||||||
<string>ios</string>
|
<string>macos</string>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>BinaryPath</key>
|
<key>BinaryPath</key>
|
||||||
@@ -36,9 +36,9 @@
|
|||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>BinaryPath</key>
|
<key>BinaryPath</key>
|
||||||
<string>tor-nolzma.framework/Versions/A/tor-nolzma</string>
|
<string>tor-nolzma.framework/tor-nolzma</string>
|
||||||
<key>LibraryIdentifier</key>
|
<key>LibraryIdentifier</key>
|
||||||
<string>macos-arm64</string>
|
<string>ios-arm64</string>
|
||||||
<key>LibraryPath</key>
|
<key>LibraryPath</key>
|
||||||
<string>tor-nolzma.framework</string>
|
<string>tor-nolzma.framework</string>
|
||||||
<key>SupportedArchitectures</key>
|
<key>SupportedArchitectures</key>
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
<string>arm64</string>
|
<string>arm64</string>
|
||||||
</array>
|
</array>
|
||||||
<key>SupportedPlatform</key>
|
<key>SupportedPlatform</key>
|
||||||
<string>macos</string>
|
<string>ios</string>
|
||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
|
|||||||
-4
@@ -203,10 +203,6 @@ struct or_options_t {
|
|||||||
/** Above this value, consider ourselves low on RAM. */
|
/** Above this value, consider ourselves low on RAM. */
|
||||||
uint64_t MaxMemInQueues_low_threshold;
|
uint64_t MaxMemInQueues_low_threshold;
|
||||||
|
|
||||||
uint64_t MaxHSDirCacheBytes;/**< If we have more memory than this allocated
|
|
||||||
* for the hidden service directory cache,
|
|
||||||
* run the HS cache OOM handler */
|
|
||||||
|
|
||||||
/** @name port booleans
|
/** @name port booleans
|
||||||
*
|
*
|
||||||
* Derived booleans: For server ports and ControlPort, true iff there is a
|
* Derived booleans: For server ports and ControlPort, true iff there is a
|
||||||
|
|||||||
+1
-3
@@ -1,7 +1,7 @@
|
|||||||
/* Copyright (c) 2001 Matej Pfajfar.
|
/* Copyright (c) 2001 Matej Pfajfar.
|
||||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||||
* Copyright (c) 2007-2025, The Tor Project, Inc. */
|
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||||
/* See LICENSE for licensing information */
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,6 +39,4 @@ int channelpadding_get_circuits_available_timeout(void);
|
|||||||
unsigned int channelpadding_get_channel_idle_timeout(const channel_t *, int);
|
unsigned int channelpadding_get_channel_idle_timeout(const channel_t *, int);
|
||||||
void channelpadding_new_consensus_params(const networkstatus_t *ns);
|
void channelpadding_new_consensus_params(const networkstatus_t *ns);
|
||||||
|
|
||||||
void channelpadding_log_heartbeat(void);
|
|
||||||
|
|
||||||
#endif /* !defined(TOR_CHANNELPADDING_H) */
|
#endif /* !defined(TOR_CHANNELPADDING_H) */
|
||||||
|
|||||||
-12
@@ -88,18 +88,6 @@ struct edge_connection_t {
|
|||||||
* for this edge, used to compute advisory rates */
|
* for this edge, used to compute advisory rates */
|
||||||
uint64_t drain_start_usec;
|
uint64_t drain_start_usec;
|
||||||
|
|
||||||
/**
|
|
||||||
* Monotime timestamp of when we started the XOFF grace period for this edge.
|
|
||||||
*
|
|
||||||
* See the comments on `XOFF_GRACE_PERIOD_USEC` for an explanation on how
|
|
||||||
* this is used.
|
|
||||||
*
|
|
||||||
* A value of 0 is considered "unset". This isn't great, but we set this
|
|
||||||
* field as the output from `monotime_absolute_usec()` which should only ever
|
|
||||||
* be 0 within the first 1 microsecond of initializing the monotonic timer
|
|
||||||
* subsystem. */
|
|
||||||
uint64_t xoff_grace_period_start_usec;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of bytes written since we either emptied our buffers,
|
* Number of bytes written since we either emptied our buffers,
|
||||||
* or sent an advisory drate rate. Can wrap, buf if so,
|
* or sent an advisory drate rate. Can wrap, buf if so,
|
||||||
|
|||||||
-1
@@ -122,7 +122,6 @@ void hs_cache_client_intro_state_purge(void);
|
|||||||
|
|
||||||
bool hs_cache_client_new_auth_parse(const ed25519_public_key_t *service_pk);
|
bool hs_cache_client_new_auth_parse(const ed25519_public_key_t *service_pk);
|
||||||
|
|
||||||
uint64_t hs_cache_get_max_bytes(void);
|
|
||||||
size_t hs_cache_get_total_allocation(void);
|
size_t hs_cache_get_total_allocation(void);
|
||||||
void hs_cache_decrement_allocation(size_t n);
|
void hs_cache_decrement_allocation(size_t n);
|
||||||
void hs_cache_increment_allocation(size_t n);
|
void hs_cache_increment_allocation(size_t n);
|
||||||
|
|||||||
+9
-9
@@ -7,12 +7,12 @@
|
|||||||
/* All assert failures are fatal */
|
/* All assert failures are fatal */
|
||||||
/* #undef ALL_BUGS_ARE_FATAL */
|
/* #undef ALL_BUGS_ARE_FATAL */
|
||||||
|
|
||||||
/* # for 0.4.8.19 Approximate date when this software was released. (Updated
|
/* # for 0.4.8.17 Approximate date when this software was released. (Updated
|
||||||
when the version changes.) */
|
when the version changes.) */
|
||||||
#define APPROX_RELEASE_DATE "2025-10-06"
|
#define APPROX_RELEASE_DATE "2025-06-30"
|
||||||
|
|
||||||
/* tor's build directory */
|
/* tor's build directory */
|
||||||
#define BUILDDIR "/Users/jack/vibe/Tor.framework/build/tor"
|
#define BUILDDIR "/Users/jack/vibe/Tor.framework-408.17.4/build/tor"
|
||||||
|
|
||||||
/* Compiler name */
|
/* Compiler name */
|
||||||
#define COMPILER /**/
|
#define COMPILER /**/
|
||||||
@@ -24,10 +24,10 @@
|
|||||||
#define COMPILER_VERSION "17.0.0"
|
#define COMPILER_VERSION "17.0.0"
|
||||||
|
|
||||||
/* tor's configuration directory */
|
/* tor's configuration directory */
|
||||||
#define CONFDIR "/Users/jack/vibe/Tor.framework/build/iphonesimulator/libtor-nolzma-arm64/etc/tor"
|
#define CONFDIR "/Users/jack/vibe/Tor.framework-408.17.4/build/iphonesimulator/libtor-nolzma-arm64/etc/tor"
|
||||||
|
|
||||||
/* Flags passed to configure */
|
/* Flags passed to configure */
|
||||||
#define CONFIG_FLAGS "--enable-silent-rules --enable-pic --disable-module-relay --disable-module-dirauth --disable-tool-name-check --disable-unittests --enable-static-openssl --enable-static-libevent --disable-asciidoc --disable-system-torrc --disable-linker-hardening --disable-dependency-tracking --disable-manpage --disable-html-manual --disable-gcc-warnings-advisory --enable-lzma=no --disable-zstd --with-libevent-dir=/Users/jack/vibe/Tor.framework/build/iphonesimulator/libevent-arm64 --with-openssl-dir=/Users/jack/vibe/Tor.framework/build/iphonesimulator/libssl-arm64 --prefix=/Users/jack/vibe/Tor.framework/build/iphonesimulator/libtor-nolzma-arm64 CC=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.0.sdk -Os -ffunction-sections -fdata-sections CPP=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -E -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.0.sdk CPPFLAGS=-Isrc/core -I/Users/jack/vibe/Tor.framework/build/iphonesimulator/libssl-arm64/include -I/Users/jack/vibe/Tor.framework/build/iphonesimulator/libevent-arm64/include -miphonesimulator-version-min=12.0 -Os -ffunction-sections -fdata-sections LDFLAGS=-lz cross_compiling=yes ac_cv_func__NSGetEnviron=no ac_cv_func_clock_gettime=no ac_cv_func_getentropy=no"
|
#define CONFIG_FLAGS "--enable-silent-rules --enable-pic --disable-module-relay --disable-module-dirauth --disable-tool-name-check --disable-unittests --enable-static-openssl --enable-static-libevent --disable-asciidoc --disable-system-torrc --disable-linker-hardening --disable-dependency-tracking --disable-manpage --disable-html-manual --disable-gcc-warnings-advisory --enable-lzma=no --disable-zstd --with-libevent-dir=/Users/jack/vibe/Tor.framework-408.17.4/build/iphonesimulator/libevent-arm64 --with-openssl-dir=/Users/jack/vibe/Tor.framework-408.17.4/build/iphonesimulator/libssl-arm64 --prefix=/Users/jack/vibe/Tor.framework-408.17.4/build/iphonesimulator/libtor-nolzma-arm64 CC=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator18.5.sdk CPP=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -E -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator18.5.sdk CFLAGS=-Os -ffunction-sections -fdata-sections -miphonesimulator-version-min=12.0 CPPFLAGS= -Isrc/core -I/Users/jack/vibe/Tor.framework-408.17.4/build/iphonesimulator/libssl-arm64/include -I/Users/jack/vibe/Tor.framework-408.17.4/build/iphonesimulator/libevent-arm64/include -miphonesimulator-version-min=12.0 LDFLAGS=-lz LZMA_CFLAGS=-I/Users/jack/vibe/Tor.framework-408.17.4/build/iphonesimulator/liblzma-arm64/include LZMA_LIBS=/Users/jack/vibe/Tor.framework-408.17.4/build/iphonesimulator/liblzma-arm64/lib/liblzma.a cross_compiling=yes ac_cv_func__NSGetEnviron=no ac_cv_func_clock_gettime=no ac_cv_func_getentropy=no"
|
||||||
|
|
||||||
/* Enable smartlist debugging */
|
/* Enable smartlist debugging */
|
||||||
/* #undef DEBUG_SMARTLIST */
|
/* #undef DEBUG_SMARTLIST */
|
||||||
@@ -720,7 +720,7 @@
|
|||||||
#define PACKAGE_NAME "tor"
|
#define PACKAGE_NAME "tor"
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
/* Define to the full name and version of this package. */
|
||||||
#define PACKAGE_STRING "tor 0.4.8.19"
|
#define PACKAGE_STRING "tor 0.4.8.17"
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
/* Define to the one symbol short name of this package. */
|
||||||
#define PACKAGE_TARNAME "tor"
|
#define PACKAGE_TARNAME "tor"
|
||||||
@@ -729,7 +729,7 @@
|
|||||||
#define PACKAGE_URL ""
|
#define PACKAGE_URL ""
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
/* Define to the version of this package. */
|
||||||
#define PACKAGE_VERSION "0.4.8.19"
|
#define PACKAGE_VERSION "0.4.8.17"
|
||||||
|
|
||||||
/* How to access the PC from a struct ucontext */
|
/* How to access the PC from a struct ucontext */
|
||||||
/* #undef PC_FROM_UCONTEXT */
|
/* #undef PC_FROM_UCONTEXT */
|
||||||
@@ -780,7 +780,7 @@
|
|||||||
#define SIZEOF___INT64 0
|
#define SIZEOF___INT64 0
|
||||||
|
|
||||||
/* tor's sourcedir directory */
|
/* tor's sourcedir directory */
|
||||||
#define SRCDIR "/Users/jack/vibe/Tor.framework/build/tor"
|
#define SRCDIR "/Users/jack/vibe/Tor.framework-408.17.4/build/tor"
|
||||||
|
|
||||||
/* Set to 1 if we can compile a simple stdatomic example. */
|
/* Set to 1 if we can compile a simple stdatomic example. */
|
||||||
#define STDATOMIC_WORKS 1
|
#define STDATOMIC_WORKS 1
|
||||||
@@ -908,7 +908,7 @@
|
|||||||
#define USING_TWOS_COMPLEMENT 1
|
#define USING_TWOS_COMPLEMENT 1
|
||||||
|
|
||||||
/* Version number of package */
|
/* Version number of package */
|
||||||
#define VERSION "0.4.8.19"
|
#define VERSION "0.4.8.17"
|
||||||
|
|
||||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
/* Copyright (c) 2003-2004, Roger Dingledine
|
/* Copyright (c) 2003-2004, Roger Dingledine
|
||||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||||
* Copyright (c) 2007-2025, The Tor Project, Inc. */
|
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||||
/* See LICENSE for licensing information */
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -361,9 +361,9 @@ monotime_coarse_diff_msec32(const monotime_coarse_t *start,
|
|||||||
#endif /* SIZEOF_VOID_P == 8 */
|
#endif /* SIZEOF_VOID_P == 8 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TOR_UNIT_TESTS
|
||||||
void tor_sleep_msec(int msec);
|
void tor_sleep_msec(int msec);
|
||||||
|
|
||||||
#ifdef TOR_UNIT_TESTS
|
|
||||||
void monotime_enable_test_mocking(void);
|
void monotime_enable_test_mocking(void);
|
||||||
void monotime_disable_test_mocking(void);
|
void monotime_disable_test_mocking(void);
|
||||||
void monotime_set_mock_time_nsec(int64_t);
|
void monotime_set_mock_time_nsec(int64_t);
|
||||||
|
|||||||
+8
-8
@@ -144,7 +144,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(X509_ALGOR, X509_ALGOR, X509_ALGOR)
|
|||||||
#define sk_X509_ALGOR_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr))
|
#define sk_X509_ALGOR_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr))
|
||||||
#define sk_X509_ALGOR_pop(sk) ((X509_ALGOR *)OPENSSL_sk_pop(ossl_check_X509_ALGOR_sk_type(sk)))
|
#define sk_X509_ALGOR_pop(sk) ((X509_ALGOR *)OPENSSL_sk_pop(ossl_check_X509_ALGOR_sk_type(sk)))
|
||||||
#define sk_X509_ALGOR_shift(sk) ((X509_ALGOR *)OPENSSL_sk_shift(ossl_check_X509_ALGOR_sk_type(sk)))
|
#define sk_X509_ALGOR_shift(sk) ((X509_ALGOR *)OPENSSL_sk_shift(ossl_check_X509_ALGOR_sk_type(sk)))
|
||||||
#define sk_X509_ALGOR_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_freefunc_type(freefunc))
|
#define sk_X509_ALGOR_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_X509_ALGOR_sk_type(sk),ossl_check_X509_ALGOR_freefunc_type(freefunc))
|
||||||
#define sk_X509_ALGOR_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr), (idx))
|
#define sk_X509_ALGOR_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr), (idx))
|
||||||
#define sk_X509_ALGOR_set(sk, idx, ptr) ((X509_ALGOR *)OPENSSL_sk_set(ossl_check_X509_ALGOR_sk_type(sk), (idx), ossl_check_X509_ALGOR_type(ptr)))
|
#define sk_X509_ALGOR_set(sk, idx, ptr) ((X509_ALGOR *)OPENSSL_sk_set(ossl_check_X509_ALGOR_sk_type(sk), (idx), ossl_check_X509_ALGOR_type(ptr)))
|
||||||
#define sk_X509_ALGOR_find(sk, ptr) OPENSSL_sk_find(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr))
|
#define sk_X509_ALGOR_find(sk, ptr) OPENSSL_sk_find(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr))
|
||||||
@@ -246,7 +246,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(ASN1_STRING_TABLE, ASN1_STRING_TABLE, ASN1_STRING_T
|
|||||||
#define sk_ASN1_STRING_TABLE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr))
|
#define sk_ASN1_STRING_TABLE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr))
|
||||||
#define sk_ASN1_STRING_TABLE_pop(sk) ((ASN1_STRING_TABLE *)OPENSSL_sk_pop(ossl_check_ASN1_STRING_TABLE_sk_type(sk)))
|
#define sk_ASN1_STRING_TABLE_pop(sk) ((ASN1_STRING_TABLE *)OPENSSL_sk_pop(ossl_check_ASN1_STRING_TABLE_sk_type(sk)))
|
||||||
#define sk_ASN1_STRING_TABLE_shift(sk) ((ASN1_STRING_TABLE *)OPENSSL_sk_shift(ossl_check_ASN1_STRING_TABLE_sk_type(sk)))
|
#define sk_ASN1_STRING_TABLE_shift(sk) ((ASN1_STRING_TABLE *)OPENSSL_sk_shift(ossl_check_ASN1_STRING_TABLE_sk_type(sk)))
|
||||||
#define sk_ASN1_STRING_TABLE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_freefunc_type(freefunc))
|
#define sk_ASN1_STRING_TABLE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_STRING_TABLE_sk_type(sk),ossl_check_ASN1_STRING_TABLE_freefunc_type(freefunc))
|
||||||
#define sk_ASN1_STRING_TABLE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr), (idx))
|
#define sk_ASN1_STRING_TABLE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr), (idx))
|
||||||
#define sk_ASN1_STRING_TABLE_set(sk, idx, ptr) ((ASN1_STRING_TABLE *)OPENSSL_sk_set(ossl_check_ASN1_STRING_TABLE_sk_type(sk), (idx), ossl_check_ASN1_STRING_TABLE_type(ptr)))
|
#define sk_ASN1_STRING_TABLE_set(sk, idx, ptr) ((ASN1_STRING_TABLE *)OPENSSL_sk_set(ossl_check_ASN1_STRING_TABLE_sk_type(sk), (idx), ossl_check_ASN1_STRING_TABLE_type(ptr)))
|
||||||
#define sk_ASN1_STRING_TABLE_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr))
|
#define sk_ASN1_STRING_TABLE_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr))
|
||||||
@@ -259,7 +259,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(ASN1_STRING_TABLE, ASN1_STRING_TABLE, ASN1_STRING_T
|
|||||||
#define sk_ASN1_STRING_TABLE_set_cmp_func(sk, cmp) ((sk_ASN1_STRING_TABLE_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_compfunc_type(cmp)))
|
#define sk_ASN1_STRING_TABLE_set_cmp_func(sk, cmp) ((sk_ASN1_STRING_TABLE_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_compfunc_type(cmp)))
|
||||||
|
|
||||||
|
|
||||||
/* size limits: this stuff is taken straight from RFC 5280 */
|
/* size limits: this stuff is taken straight from RFC2459 */
|
||||||
|
|
||||||
# define ub_name 32768
|
# define ub_name 32768
|
||||||
# define ub_common_name 64
|
# define ub_common_name 64
|
||||||
@@ -567,7 +567,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(ASN1_TYPE, ASN1_TYPE, ASN1_TYPE)
|
|||||||
#define sk_ASN1_TYPE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr))
|
#define sk_ASN1_TYPE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr))
|
||||||
#define sk_ASN1_TYPE_pop(sk) ((ASN1_TYPE *)OPENSSL_sk_pop(ossl_check_ASN1_TYPE_sk_type(sk)))
|
#define sk_ASN1_TYPE_pop(sk) ((ASN1_TYPE *)OPENSSL_sk_pop(ossl_check_ASN1_TYPE_sk_type(sk)))
|
||||||
#define sk_ASN1_TYPE_shift(sk) ((ASN1_TYPE *)OPENSSL_sk_shift(ossl_check_ASN1_TYPE_sk_type(sk)))
|
#define sk_ASN1_TYPE_shift(sk) ((ASN1_TYPE *)OPENSSL_sk_shift(ossl_check_ASN1_TYPE_sk_type(sk)))
|
||||||
#define sk_ASN1_TYPE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_freefunc_type(freefunc))
|
#define sk_ASN1_TYPE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_TYPE_sk_type(sk),ossl_check_ASN1_TYPE_freefunc_type(freefunc))
|
||||||
#define sk_ASN1_TYPE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr), (idx))
|
#define sk_ASN1_TYPE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr), (idx))
|
||||||
#define sk_ASN1_TYPE_set(sk, idx, ptr) ((ASN1_TYPE *)OPENSSL_sk_set(ossl_check_ASN1_TYPE_sk_type(sk), (idx), ossl_check_ASN1_TYPE_type(ptr)))
|
#define sk_ASN1_TYPE_set(sk, idx, ptr) ((ASN1_TYPE *)OPENSSL_sk_set(ossl_check_ASN1_TYPE_sk_type(sk), (idx), ossl_check_ASN1_TYPE_type(ptr)))
|
||||||
#define sk_ASN1_TYPE_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr))
|
#define sk_ASN1_TYPE_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr))
|
||||||
@@ -647,7 +647,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(ASN1_OBJECT, ASN1_OBJECT, ASN1_OBJECT)
|
|||||||
#define sk_ASN1_OBJECT_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr))
|
#define sk_ASN1_OBJECT_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr))
|
||||||
#define sk_ASN1_OBJECT_pop(sk) ((ASN1_OBJECT *)OPENSSL_sk_pop(ossl_check_ASN1_OBJECT_sk_type(sk)))
|
#define sk_ASN1_OBJECT_pop(sk) ((ASN1_OBJECT *)OPENSSL_sk_pop(ossl_check_ASN1_OBJECT_sk_type(sk)))
|
||||||
#define sk_ASN1_OBJECT_shift(sk) ((ASN1_OBJECT *)OPENSSL_sk_shift(ossl_check_ASN1_OBJECT_sk_type(sk)))
|
#define sk_ASN1_OBJECT_shift(sk) ((ASN1_OBJECT *)OPENSSL_sk_shift(ossl_check_ASN1_OBJECT_sk_type(sk)))
|
||||||
#define sk_ASN1_OBJECT_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_freefunc_type(freefunc))
|
#define sk_ASN1_OBJECT_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_OBJECT_sk_type(sk),ossl_check_ASN1_OBJECT_freefunc_type(freefunc))
|
||||||
#define sk_ASN1_OBJECT_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr), (idx))
|
#define sk_ASN1_OBJECT_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr), (idx))
|
||||||
#define sk_ASN1_OBJECT_set(sk, idx, ptr) ((ASN1_OBJECT *)OPENSSL_sk_set(ossl_check_ASN1_OBJECT_sk_type(sk), (idx), ossl_check_ASN1_OBJECT_type(ptr)))
|
#define sk_ASN1_OBJECT_set(sk, idx, ptr) ((ASN1_OBJECT *)OPENSSL_sk_set(ossl_check_ASN1_OBJECT_sk_type(sk), (idx), ossl_check_ASN1_OBJECT_type(ptr)))
|
||||||
#define sk_ASN1_OBJECT_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr))
|
#define sk_ASN1_OBJECT_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr))
|
||||||
@@ -713,7 +713,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(ASN1_INTEGER, ASN1_INTEGER, ASN1_INTEGER)
|
|||||||
#define sk_ASN1_INTEGER_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr))
|
#define sk_ASN1_INTEGER_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr))
|
||||||
#define sk_ASN1_INTEGER_pop(sk) ((ASN1_INTEGER *)OPENSSL_sk_pop(ossl_check_ASN1_INTEGER_sk_type(sk)))
|
#define sk_ASN1_INTEGER_pop(sk) ((ASN1_INTEGER *)OPENSSL_sk_pop(ossl_check_ASN1_INTEGER_sk_type(sk)))
|
||||||
#define sk_ASN1_INTEGER_shift(sk) ((ASN1_INTEGER *)OPENSSL_sk_shift(ossl_check_ASN1_INTEGER_sk_type(sk)))
|
#define sk_ASN1_INTEGER_shift(sk) ((ASN1_INTEGER *)OPENSSL_sk_shift(ossl_check_ASN1_INTEGER_sk_type(sk)))
|
||||||
#define sk_ASN1_INTEGER_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_freefunc_type(freefunc))
|
#define sk_ASN1_INTEGER_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_INTEGER_sk_type(sk),ossl_check_ASN1_INTEGER_freefunc_type(freefunc))
|
||||||
#define sk_ASN1_INTEGER_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr), (idx))
|
#define sk_ASN1_INTEGER_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr), (idx))
|
||||||
#define sk_ASN1_INTEGER_set(sk, idx, ptr) ((ASN1_INTEGER *)OPENSSL_sk_set(ossl_check_ASN1_INTEGER_sk_type(sk), (idx), ossl_check_ASN1_INTEGER_type(ptr)))
|
#define sk_ASN1_INTEGER_set(sk, idx, ptr) ((ASN1_INTEGER *)OPENSSL_sk_set(ossl_check_ASN1_INTEGER_sk_type(sk), (idx), ossl_check_ASN1_INTEGER_type(ptr)))
|
||||||
#define sk_ASN1_INTEGER_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr))
|
#define sk_ASN1_INTEGER_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr))
|
||||||
@@ -775,7 +775,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(ASN1_UTF8STRING, ASN1_UTF8STRING, ASN1_UTF8STRING)
|
|||||||
#define sk_ASN1_UTF8STRING_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr))
|
#define sk_ASN1_UTF8STRING_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr))
|
||||||
#define sk_ASN1_UTF8STRING_pop(sk) ((ASN1_UTF8STRING *)OPENSSL_sk_pop(ossl_check_ASN1_UTF8STRING_sk_type(sk)))
|
#define sk_ASN1_UTF8STRING_pop(sk) ((ASN1_UTF8STRING *)OPENSSL_sk_pop(ossl_check_ASN1_UTF8STRING_sk_type(sk)))
|
||||||
#define sk_ASN1_UTF8STRING_shift(sk) ((ASN1_UTF8STRING *)OPENSSL_sk_shift(ossl_check_ASN1_UTF8STRING_sk_type(sk)))
|
#define sk_ASN1_UTF8STRING_shift(sk) ((ASN1_UTF8STRING *)OPENSSL_sk_shift(ossl_check_ASN1_UTF8STRING_sk_type(sk)))
|
||||||
#define sk_ASN1_UTF8STRING_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_freefunc_type(freefunc))
|
#define sk_ASN1_UTF8STRING_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_UTF8STRING_sk_type(sk),ossl_check_ASN1_UTF8STRING_freefunc_type(freefunc))
|
||||||
#define sk_ASN1_UTF8STRING_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr), (idx))
|
#define sk_ASN1_UTF8STRING_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr), (idx))
|
||||||
#define sk_ASN1_UTF8STRING_set(sk, idx, ptr) ((ASN1_UTF8STRING *)OPENSSL_sk_set(ossl_check_ASN1_UTF8STRING_sk_type(sk), (idx), ossl_check_ASN1_UTF8STRING_type(ptr)))
|
#define sk_ASN1_UTF8STRING_set(sk, idx, ptr) ((ASN1_UTF8STRING *)OPENSSL_sk_set(ossl_check_ASN1_UTF8STRING_sk_type(sk), (idx), ossl_check_ASN1_UTF8STRING_type(ptr)))
|
||||||
#define sk_ASN1_UTF8STRING_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr))
|
#define sk_ASN1_UTF8STRING_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr))
|
||||||
@@ -812,7 +812,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(ASN1_GENERALSTRING, ASN1_GENERALSTRING, ASN1_GENERA
|
|||||||
#define sk_ASN1_GENERALSTRING_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr))
|
#define sk_ASN1_GENERALSTRING_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr))
|
||||||
#define sk_ASN1_GENERALSTRING_pop(sk) ((ASN1_GENERALSTRING *)OPENSSL_sk_pop(ossl_check_ASN1_GENERALSTRING_sk_type(sk)))
|
#define sk_ASN1_GENERALSTRING_pop(sk) ((ASN1_GENERALSTRING *)OPENSSL_sk_pop(ossl_check_ASN1_GENERALSTRING_sk_type(sk)))
|
||||||
#define sk_ASN1_GENERALSTRING_shift(sk) ((ASN1_GENERALSTRING *)OPENSSL_sk_shift(ossl_check_ASN1_GENERALSTRING_sk_type(sk)))
|
#define sk_ASN1_GENERALSTRING_shift(sk) ((ASN1_GENERALSTRING *)OPENSSL_sk_shift(ossl_check_ASN1_GENERALSTRING_sk_type(sk)))
|
||||||
#define sk_ASN1_GENERALSTRING_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_freefunc_type(freefunc))
|
#define sk_ASN1_GENERALSTRING_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_GENERALSTRING_sk_type(sk),ossl_check_ASN1_GENERALSTRING_freefunc_type(freefunc))
|
||||||
#define sk_ASN1_GENERALSTRING_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr), (idx))
|
#define sk_ASN1_GENERALSTRING_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr), (idx))
|
||||||
#define sk_ASN1_GENERALSTRING_set(sk, idx, ptr) ((ASN1_GENERALSTRING *)OPENSSL_sk_set(ossl_check_ASN1_GENERALSTRING_sk_type(sk), (idx), ossl_check_ASN1_GENERALSTRING_type(ptr)))
|
#define sk_ASN1_GENERALSTRING_set(sk, idx, ptr) ((ASN1_GENERALSTRING *)OPENSSL_sk_set(ossl_check_ASN1_GENERALSTRING_sk_type(sk), (idx), ossl_check_ASN1_GENERALSTRING_type(ptr)))
|
||||||
#define sk_ASN1_GENERALSTRING_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr))
|
#define sk_ASN1_GENERALSTRING_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr))
|
||||||
|
|||||||
+1
-1
@@ -909,7 +909,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(ASN1_VALUE, ASN1_VALUE, ASN1_VALUE)
|
|||||||
#define sk_ASN1_VALUE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr))
|
#define sk_ASN1_VALUE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr))
|
||||||
#define sk_ASN1_VALUE_pop(sk) ((ASN1_VALUE *)OPENSSL_sk_pop(ossl_check_ASN1_VALUE_sk_type(sk)))
|
#define sk_ASN1_VALUE_pop(sk) ((ASN1_VALUE *)OPENSSL_sk_pop(ossl_check_ASN1_VALUE_sk_type(sk)))
|
||||||
#define sk_ASN1_VALUE_shift(sk) ((ASN1_VALUE *)OPENSSL_sk_shift(ossl_check_ASN1_VALUE_sk_type(sk)))
|
#define sk_ASN1_VALUE_shift(sk) ((ASN1_VALUE *)OPENSSL_sk_shift(ossl_check_ASN1_VALUE_sk_type(sk)))
|
||||||
#define sk_ASN1_VALUE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_freefunc_type(freefunc))
|
#define sk_ASN1_VALUE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_VALUE_sk_type(sk),ossl_check_ASN1_VALUE_freefunc_type(freefunc))
|
||||||
#define sk_ASN1_VALUE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr), (idx))
|
#define sk_ASN1_VALUE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr), (idx))
|
||||||
#define sk_ASN1_VALUE_set(sk, idx, ptr) ((ASN1_VALUE *)OPENSSL_sk_set(ossl_check_ASN1_VALUE_sk_type(sk), (idx), ossl_check_ASN1_VALUE_type(ptr)))
|
#define sk_ASN1_VALUE_set(sk, idx, ptr) ((ASN1_VALUE *)OPENSSL_sk_set(ossl_check_ASN1_VALUE_sk_type(sk), (idx), ossl_check_ASN1_VALUE_type(ptr)))
|
||||||
#define sk_ASN1_VALUE_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr))
|
#define sk_ASN1_VALUE_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr))
|
||||||
|
|||||||
+1
-1
@@ -348,7 +348,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(BIO, BIO, BIO)
|
|||||||
#define sk_BIO_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr))
|
#define sk_BIO_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr))
|
||||||
#define sk_BIO_pop(sk) ((BIO *)OPENSSL_sk_pop(ossl_check_BIO_sk_type(sk)))
|
#define sk_BIO_pop(sk) ((BIO *)OPENSSL_sk_pop(ossl_check_BIO_sk_type(sk)))
|
||||||
#define sk_BIO_shift(sk) ((BIO *)OPENSSL_sk_shift(ossl_check_BIO_sk_type(sk)))
|
#define sk_BIO_shift(sk) ((BIO *)OPENSSL_sk_shift(ossl_check_BIO_sk_type(sk)))
|
||||||
#define sk_BIO_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_BIO_sk_type(sk), ossl_check_BIO_freefunc_type(freefunc))
|
#define sk_BIO_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_BIO_sk_type(sk),ossl_check_BIO_freefunc_type(freefunc))
|
||||||
#define sk_BIO_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr), (idx))
|
#define sk_BIO_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr), (idx))
|
||||||
#define sk_BIO_set(sk, idx, ptr) ((BIO *)OPENSSL_sk_set(ossl_check_BIO_sk_type(sk), (idx), ossl_check_BIO_type(ptr)))
|
#define sk_BIO_set(sk, idx, ptr) ((BIO *)OPENSSL_sk_set(ossl_check_BIO_sk_type(sk), (idx), ossl_check_BIO_type(ptr)))
|
||||||
#define sk_BIO_find(sk, ptr) OPENSSL_sk_find(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr))
|
#define sk_BIO_find(sk, ptr) OPENSSL_sk_find(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr))
|
||||||
|
|||||||
+6
-6
@@ -234,7 +234,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CMP_CERTSTATUS, OSSL_CMP_CERTSTATUS, OSSL_CMP_
|
|||||||
#define sk_OSSL_CMP_CERTSTATUS_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr))
|
#define sk_OSSL_CMP_CERTSTATUS_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr))
|
||||||
#define sk_OSSL_CMP_CERTSTATUS_pop(sk) ((OSSL_CMP_CERTSTATUS *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk)))
|
#define sk_OSSL_CMP_CERTSTATUS_pop(sk) ((OSSL_CMP_CERTSTATUS *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk)))
|
||||||
#define sk_OSSL_CMP_CERTSTATUS_shift(sk) ((OSSL_CMP_CERTSTATUS *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk)))
|
#define sk_OSSL_CMP_CERTSTATUS_shift(sk) ((OSSL_CMP_CERTSTATUS *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk)))
|
||||||
#define sk_OSSL_CMP_CERTSTATUS_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_freefunc_type(freefunc))
|
#define sk_OSSL_CMP_CERTSTATUS_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk),ossl_check_OSSL_CMP_CERTSTATUS_freefunc_type(freefunc))
|
||||||
#define sk_OSSL_CMP_CERTSTATUS_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr), (idx))
|
#define sk_OSSL_CMP_CERTSTATUS_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr), (idx))
|
||||||
#define sk_OSSL_CMP_CERTSTATUS_set(sk, idx, ptr) ((OSSL_CMP_CERTSTATUS *)OPENSSL_sk_set(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), (idx), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr)))
|
#define sk_OSSL_CMP_CERTSTATUS_set(sk, idx, ptr) ((OSSL_CMP_CERTSTATUS *)OPENSSL_sk_set(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), (idx), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr)))
|
||||||
#define sk_OSSL_CMP_CERTSTATUS_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr))
|
#define sk_OSSL_CMP_CERTSTATUS_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_CERTSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CERTSTATUS_type(ptr))
|
||||||
@@ -263,7 +263,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CMP_ITAV, OSSL_CMP_ITAV, OSSL_CMP_ITAV)
|
|||||||
#define sk_OSSL_CMP_ITAV_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr))
|
#define sk_OSSL_CMP_ITAV_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr))
|
||||||
#define sk_OSSL_CMP_ITAV_pop(sk) ((OSSL_CMP_ITAV *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_ITAV_sk_type(sk)))
|
#define sk_OSSL_CMP_ITAV_pop(sk) ((OSSL_CMP_ITAV *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_ITAV_sk_type(sk)))
|
||||||
#define sk_OSSL_CMP_ITAV_shift(sk) ((OSSL_CMP_ITAV *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_ITAV_sk_type(sk)))
|
#define sk_OSSL_CMP_ITAV_shift(sk) ((OSSL_CMP_ITAV *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_ITAV_sk_type(sk)))
|
||||||
#define sk_OSSL_CMP_ITAV_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_freefunc_type(freefunc))
|
#define sk_OSSL_CMP_ITAV_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_ITAV_sk_type(sk),ossl_check_OSSL_CMP_ITAV_freefunc_type(freefunc))
|
||||||
#define sk_OSSL_CMP_ITAV_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr), (idx))
|
#define sk_OSSL_CMP_ITAV_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr), (idx))
|
||||||
#define sk_OSSL_CMP_ITAV_set(sk, idx, ptr) ((OSSL_CMP_ITAV *)OPENSSL_sk_set(ossl_check_OSSL_CMP_ITAV_sk_type(sk), (idx), ossl_check_OSSL_CMP_ITAV_type(ptr)))
|
#define sk_OSSL_CMP_ITAV_set(sk, idx, ptr) ((OSSL_CMP_ITAV *)OPENSSL_sk_set(ossl_check_OSSL_CMP_ITAV_sk_type(sk), (idx), ossl_check_OSSL_CMP_ITAV_type(ptr)))
|
||||||
#define sk_OSSL_CMP_ITAV_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr))
|
#define sk_OSSL_CMP_ITAV_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_ITAV_sk_type(sk), ossl_check_OSSL_CMP_ITAV_type(ptr))
|
||||||
@@ -292,7 +292,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CMP_CRLSTATUS, OSSL_CMP_CRLSTATUS, OSSL_CMP_CR
|
|||||||
#define sk_OSSL_CMP_CRLSTATUS_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CRLSTATUS_type(ptr))
|
#define sk_OSSL_CMP_CRLSTATUS_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CRLSTATUS_type(ptr))
|
||||||
#define sk_OSSL_CMP_CRLSTATUS_pop(sk) ((OSSL_CMP_CRLSTATUS *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk)))
|
#define sk_OSSL_CMP_CRLSTATUS_pop(sk) ((OSSL_CMP_CRLSTATUS *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk)))
|
||||||
#define sk_OSSL_CMP_CRLSTATUS_shift(sk) ((OSSL_CMP_CRLSTATUS *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk)))
|
#define sk_OSSL_CMP_CRLSTATUS_shift(sk) ((OSSL_CMP_CRLSTATUS *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk)))
|
||||||
#define sk_OSSL_CMP_CRLSTATUS_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CRLSTATUS_freefunc_type(freefunc))
|
#define sk_OSSL_CMP_CRLSTATUS_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk),ossl_check_OSSL_CMP_CRLSTATUS_freefunc_type(freefunc))
|
||||||
#define sk_OSSL_CMP_CRLSTATUS_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CRLSTATUS_type(ptr), (idx))
|
#define sk_OSSL_CMP_CRLSTATUS_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CRLSTATUS_type(ptr), (idx))
|
||||||
#define sk_OSSL_CMP_CRLSTATUS_set(sk, idx, ptr) ((OSSL_CMP_CRLSTATUS *)OPENSSL_sk_set(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk), (idx), ossl_check_OSSL_CMP_CRLSTATUS_type(ptr)))
|
#define sk_OSSL_CMP_CRLSTATUS_set(sk, idx, ptr) ((OSSL_CMP_CRLSTATUS *)OPENSSL_sk_set(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk), (idx), ossl_check_OSSL_CMP_CRLSTATUS_type(ptr)))
|
||||||
#define sk_OSSL_CMP_CRLSTATUS_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CRLSTATUS_type(ptr))
|
#define sk_OSSL_CMP_CRLSTATUS_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_CRLSTATUS_sk_type(sk), ossl_check_OSSL_CMP_CRLSTATUS_type(ptr))
|
||||||
@@ -334,7 +334,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CMP_PKISI, OSSL_CMP_PKISI, OSSL_CMP_PKISI)
|
|||||||
#define sk_OSSL_CMP_PKISI_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr))
|
#define sk_OSSL_CMP_PKISI_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr))
|
||||||
#define sk_OSSL_CMP_PKISI_pop(sk) ((OSSL_CMP_PKISI *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_PKISI_sk_type(sk)))
|
#define sk_OSSL_CMP_PKISI_pop(sk) ((OSSL_CMP_PKISI *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_PKISI_sk_type(sk)))
|
||||||
#define sk_OSSL_CMP_PKISI_shift(sk) ((OSSL_CMP_PKISI *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_PKISI_sk_type(sk)))
|
#define sk_OSSL_CMP_PKISI_shift(sk) ((OSSL_CMP_PKISI *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_PKISI_sk_type(sk)))
|
||||||
#define sk_OSSL_CMP_PKISI_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_freefunc_type(freefunc))
|
#define sk_OSSL_CMP_PKISI_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_PKISI_sk_type(sk),ossl_check_OSSL_CMP_PKISI_freefunc_type(freefunc))
|
||||||
#define sk_OSSL_CMP_PKISI_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr), (idx))
|
#define sk_OSSL_CMP_PKISI_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr), (idx))
|
||||||
#define sk_OSSL_CMP_PKISI_set(sk, idx, ptr) ((OSSL_CMP_PKISI *)OPENSSL_sk_set(ossl_check_OSSL_CMP_PKISI_sk_type(sk), (idx), ossl_check_OSSL_CMP_PKISI_type(ptr)))
|
#define sk_OSSL_CMP_PKISI_set(sk, idx, ptr) ((OSSL_CMP_PKISI *)OPENSSL_sk_set(ossl_check_OSSL_CMP_PKISI_sk_type(sk), (idx), ossl_check_OSSL_CMP_PKISI_type(ptr)))
|
||||||
#define sk_OSSL_CMP_PKISI_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr))
|
#define sk_OSSL_CMP_PKISI_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_PKISI_sk_type(sk), ossl_check_OSSL_CMP_PKISI_type(ptr))
|
||||||
@@ -362,7 +362,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CMP_CERTREPMESSAGE, OSSL_CMP_CERTREPMESSAGE, O
|
|||||||
#define sk_OSSL_CMP_CERTREPMESSAGE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr))
|
#define sk_OSSL_CMP_CERTREPMESSAGE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr))
|
||||||
#define sk_OSSL_CMP_CERTREPMESSAGE_pop(sk) ((OSSL_CMP_CERTREPMESSAGE *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk)))
|
#define sk_OSSL_CMP_CERTREPMESSAGE_pop(sk) ((OSSL_CMP_CERTREPMESSAGE *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk)))
|
||||||
#define sk_OSSL_CMP_CERTREPMESSAGE_shift(sk) ((OSSL_CMP_CERTREPMESSAGE *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk)))
|
#define sk_OSSL_CMP_CERTREPMESSAGE_shift(sk) ((OSSL_CMP_CERTREPMESSAGE *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk)))
|
||||||
#define sk_OSSL_CMP_CERTREPMESSAGE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_freefunc_type(freefunc))
|
#define sk_OSSL_CMP_CERTREPMESSAGE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk),ossl_check_OSSL_CMP_CERTREPMESSAGE_freefunc_type(freefunc))
|
||||||
#define sk_OSSL_CMP_CERTREPMESSAGE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr), (idx))
|
#define sk_OSSL_CMP_CERTREPMESSAGE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr), (idx))
|
||||||
#define sk_OSSL_CMP_CERTREPMESSAGE_set(sk, idx, ptr) ((OSSL_CMP_CERTREPMESSAGE *)OPENSSL_sk_set(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), (idx), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr)))
|
#define sk_OSSL_CMP_CERTREPMESSAGE_set(sk, idx, ptr) ((OSSL_CMP_CERTREPMESSAGE *)OPENSSL_sk_set(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), (idx), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr)))
|
||||||
#define sk_OSSL_CMP_CERTREPMESSAGE_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr))
|
#define sk_OSSL_CMP_CERTREPMESSAGE_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_CERTREPMESSAGE_sk_type(sk), ossl_check_OSSL_CMP_CERTREPMESSAGE_type(ptr))
|
||||||
@@ -392,7 +392,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CMP_CERTRESPONSE, OSSL_CMP_CERTRESPONSE, OSSL_
|
|||||||
#define sk_OSSL_CMP_CERTRESPONSE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr))
|
#define sk_OSSL_CMP_CERTRESPONSE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr))
|
||||||
#define sk_OSSL_CMP_CERTRESPONSE_pop(sk) ((OSSL_CMP_CERTRESPONSE *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk)))
|
#define sk_OSSL_CMP_CERTRESPONSE_pop(sk) ((OSSL_CMP_CERTRESPONSE *)OPENSSL_sk_pop(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk)))
|
||||||
#define sk_OSSL_CMP_CERTRESPONSE_shift(sk) ((OSSL_CMP_CERTRESPONSE *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk)))
|
#define sk_OSSL_CMP_CERTRESPONSE_shift(sk) ((OSSL_CMP_CERTRESPONSE *)OPENSSL_sk_shift(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk)))
|
||||||
#define sk_OSSL_CMP_CERTRESPONSE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_freefunc_type(freefunc))
|
#define sk_OSSL_CMP_CERTRESPONSE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk),ossl_check_OSSL_CMP_CERTRESPONSE_freefunc_type(freefunc))
|
||||||
#define sk_OSSL_CMP_CERTRESPONSE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr), (idx))
|
#define sk_OSSL_CMP_CERTRESPONSE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr), (idx))
|
||||||
#define sk_OSSL_CMP_CERTRESPONSE_set(sk, idx, ptr) ((OSSL_CMP_CERTRESPONSE *)OPENSSL_sk_set(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), (idx), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr)))
|
#define sk_OSSL_CMP_CERTRESPONSE_set(sk, idx, ptr) ((OSSL_CMP_CERTRESPONSE *)OPENSSL_sk_set(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), (idx), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr)))
|
||||||
#define sk_OSSL_CMP_CERTRESPONSE_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr))
|
#define sk_OSSL_CMP_CERTRESPONSE_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CMP_CERTRESPONSE_sk_type(sk), ossl_check_OSSL_CMP_CERTRESPONSE_type(ptr))
|
||||||
|
|||||||
+4
-13
@@ -58,7 +58,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(CMS_SignerInfo, CMS_SignerInfo, CMS_SignerInfo)
|
|||||||
#define sk_CMS_SignerInfo_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_CMS_SignerInfo_sk_type(sk), ossl_check_CMS_SignerInfo_type(ptr))
|
#define sk_CMS_SignerInfo_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_CMS_SignerInfo_sk_type(sk), ossl_check_CMS_SignerInfo_type(ptr))
|
||||||
#define sk_CMS_SignerInfo_pop(sk) ((CMS_SignerInfo *)OPENSSL_sk_pop(ossl_check_CMS_SignerInfo_sk_type(sk)))
|
#define sk_CMS_SignerInfo_pop(sk) ((CMS_SignerInfo *)OPENSSL_sk_pop(ossl_check_CMS_SignerInfo_sk_type(sk)))
|
||||||
#define sk_CMS_SignerInfo_shift(sk) ((CMS_SignerInfo *)OPENSSL_sk_shift(ossl_check_CMS_SignerInfo_sk_type(sk)))
|
#define sk_CMS_SignerInfo_shift(sk) ((CMS_SignerInfo *)OPENSSL_sk_shift(ossl_check_CMS_SignerInfo_sk_type(sk)))
|
||||||
#define sk_CMS_SignerInfo_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_CMS_SignerInfo_sk_type(sk), ossl_check_CMS_SignerInfo_freefunc_type(freefunc))
|
#define sk_CMS_SignerInfo_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_CMS_SignerInfo_sk_type(sk),ossl_check_CMS_SignerInfo_freefunc_type(freefunc))
|
||||||
#define sk_CMS_SignerInfo_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_CMS_SignerInfo_sk_type(sk), ossl_check_CMS_SignerInfo_type(ptr), (idx))
|
#define sk_CMS_SignerInfo_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_CMS_SignerInfo_sk_type(sk), ossl_check_CMS_SignerInfo_type(ptr), (idx))
|
||||||
#define sk_CMS_SignerInfo_set(sk, idx, ptr) ((CMS_SignerInfo *)OPENSSL_sk_set(ossl_check_CMS_SignerInfo_sk_type(sk), (idx), ossl_check_CMS_SignerInfo_type(ptr)))
|
#define sk_CMS_SignerInfo_set(sk, idx, ptr) ((CMS_SignerInfo *)OPENSSL_sk_set(ossl_check_CMS_SignerInfo_sk_type(sk), (idx), ossl_check_CMS_SignerInfo_type(ptr)))
|
||||||
#define sk_CMS_SignerInfo_find(sk, ptr) OPENSSL_sk_find(ossl_check_CMS_SignerInfo_sk_type(sk), ossl_check_CMS_SignerInfo_type(ptr))
|
#define sk_CMS_SignerInfo_find(sk, ptr) OPENSSL_sk_find(ossl_check_CMS_SignerInfo_sk_type(sk), ossl_check_CMS_SignerInfo_type(ptr))
|
||||||
@@ -84,7 +84,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(CMS_RecipientEncryptedKey, CMS_RecipientEncryptedKe
|
|||||||
#define sk_CMS_RecipientEncryptedKey_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk), ossl_check_CMS_RecipientEncryptedKey_type(ptr))
|
#define sk_CMS_RecipientEncryptedKey_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk), ossl_check_CMS_RecipientEncryptedKey_type(ptr))
|
||||||
#define sk_CMS_RecipientEncryptedKey_pop(sk) ((CMS_RecipientEncryptedKey *)OPENSSL_sk_pop(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk)))
|
#define sk_CMS_RecipientEncryptedKey_pop(sk) ((CMS_RecipientEncryptedKey *)OPENSSL_sk_pop(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk)))
|
||||||
#define sk_CMS_RecipientEncryptedKey_shift(sk) ((CMS_RecipientEncryptedKey *)OPENSSL_sk_shift(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk)))
|
#define sk_CMS_RecipientEncryptedKey_shift(sk) ((CMS_RecipientEncryptedKey *)OPENSSL_sk_shift(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk)))
|
||||||
#define sk_CMS_RecipientEncryptedKey_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk), ossl_check_CMS_RecipientEncryptedKey_freefunc_type(freefunc))
|
#define sk_CMS_RecipientEncryptedKey_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk),ossl_check_CMS_RecipientEncryptedKey_freefunc_type(freefunc))
|
||||||
#define sk_CMS_RecipientEncryptedKey_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk), ossl_check_CMS_RecipientEncryptedKey_type(ptr), (idx))
|
#define sk_CMS_RecipientEncryptedKey_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk), ossl_check_CMS_RecipientEncryptedKey_type(ptr), (idx))
|
||||||
#define sk_CMS_RecipientEncryptedKey_set(sk, idx, ptr) ((CMS_RecipientEncryptedKey *)OPENSSL_sk_set(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk), (idx), ossl_check_CMS_RecipientEncryptedKey_type(ptr)))
|
#define sk_CMS_RecipientEncryptedKey_set(sk, idx, ptr) ((CMS_RecipientEncryptedKey *)OPENSSL_sk_set(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk), (idx), ossl_check_CMS_RecipientEncryptedKey_type(ptr)))
|
||||||
#define sk_CMS_RecipientEncryptedKey_find(sk, ptr) OPENSSL_sk_find(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk), ossl_check_CMS_RecipientEncryptedKey_type(ptr))
|
#define sk_CMS_RecipientEncryptedKey_find(sk, ptr) OPENSSL_sk_find(ossl_check_CMS_RecipientEncryptedKey_sk_type(sk), ossl_check_CMS_RecipientEncryptedKey_type(ptr))
|
||||||
@@ -110,7 +110,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(CMS_RecipientInfo, CMS_RecipientInfo, CMS_Recipient
|
|||||||
#define sk_CMS_RecipientInfo_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_CMS_RecipientInfo_sk_type(sk), ossl_check_CMS_RecipientInfo_type(ptr))
|
#define sk_CMS_RecipientInfo_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_CMS_RecipientInfo_sk_type(sk), ossl_check_CMS_RecipientInfo_type(ptr))
|
||||||
#define sk_CMS_RecipientInfo_pop(sk) ((CMS_RecipientInfo *)OPENSSL_sk_pop(ossl_check_CMS_RecipientInfo_sk_type(sk)))
|
#define sk_CMS_RecipientInfo_pop(sk) ((CMS_RecipientInfo *)OPENSSL_sk_pop(ossl_check_CMS_RecipientInfo_sk_type(sk)))
|
||||||
#define sk_CMS_RecipientInfo_shift(sk) ((CMS_RecipientInfo *)OPENSSL_sk_shift(ossl_check_CMS_RecipientInfo_sk_type(sk)))
|
#define sk_CMS_RecipientInfo_shift(sk) ((CMS_RecipientInfo *)OPENSSL_sk_shift(ossl_check_CMS_RecipientInfo_sk_type(sk)))
|
||||||
#define sk_CMS_RecipientInfo_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_CMS_RecipientInfo_sk_type(sk), ossl_check_CMS_RecipientInfo_freefunc_type(freefunc))
|
#define sk_CMS_RecipientInfo_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_CMS_RecipientInfo_sk_type(sk),ossl_check_CMS_RecipientInfo_freefunc_type(freefunc))
|
||||||
#define sk_CMS_RecipientInfo_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_CMS_RecipientInfo_sk_type(sk), ossl_check_CMS_RecipientInfo_type(ptr), (idx))
|
#define sk_CMS_RecipientInfo_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_CMS_RecipientInfo_sk_type(sk), ossl_check_CMS_RecipientInfo_type(ptr), (idx))
|
||||||
#define sk_CMS_RecipientInfo_set(sk, idx, ptr) ((CMS_RecipientInfo *)OPENSSL_sk_set(ossl_check_CMS_RecipientInfo_sk_type(sk), (idx), ossl_check_CMS_RecipientInfo_type(ptr)))
|
#define sk_CMS_RecipientInfo_set(sk, idx, ptr) ((CMS_RecipientInfo *)OPENSSL_sk_set(ossl_check_CMS_RecipientInfo_sk_type(sk), (idx), ossl_check_CMS_RecipientInfo_type(ptr)))
|
||||||
#define sk_CMS_RecipientInfo_find(sk, ptr) OPENSSL_sk_find(ossl_check_CMS_RecipientInfo_sk_type(sk), ossl_check_CMS_RecipientInfo_type(ptr))
|
#define sk_CMS_RecipientInfo_find(sk, ptr) OPENSSL_sk_find(ossl_check_CMS_RecipientInfo_sk_type(sk), ossl_check_CMS_RecipientInfo_type(ptr))
|
||||||
@@ -136,7 +136,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(CMS_RevocationInfoChoice, CMS_RevocationInfoChoice,
|
|||||||
#define sk_CMS_RevocationInfoChoice_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_CMS_RevocationInfoChoice_sk_type(sk), ossl_check_CMS_RevocationInfoChoice_type(ptr))
|
#define sk_CMS_RevocationInfoChoice_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_CMS_RevocationInfoChoice_sk_type(sk), ossl_check_CMS_RevocationInfoChoice_type(ptr))
|
||||||
#define sk_CMS_RevocationInfoChoice_pop(sk) ((CMS_RevocationInfoChoice *)OPENSSL_sk_pop(ossl_check_CMS_RevocationInfoChoice_sk_type(sk)))
|
#define sk_CMS_RevocationInfoChoice_pop(sk) ((CMS_RevocationInfoChoice *)OPENSSL_sk_pop(ossl_check_CMS_RevocationInfoChoice_sk_type(sk)))
|
||||||
#define sk_CMS_RevocationInfoChoice_shift(sk) ((CMS_RevocationInfoChoice *)OPENSSL_sk_shift(ossl_check_CMS_RevocationInfoChoice_sk_type(sk)))
|
#define sk_CMS_RevocationInfoChoice_shift(sk) ((CMS_RevocationInfoChoice *)OPENSSL_sk_shift(ossl_check_CMS_RevocationInfoChoice_sk_type(sk)))
|
||||||
#define sk_CMS_RevocationInfoChoice_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_CMS_RevocationInfoChoice_sk_type(sk), ossl_check_CMS_RevocationInfoChoice_freefunc_type(freefunc))
|
#define sk_CMS_RevocationInfoChoice_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_CMS_RevocationInfoChoice_sk_type(sk),ossl_check_CMS_RevocationInfoChoice_freefunc_type(freefunc))
|
||||||
#define sk_CMS_RevocationInfoChoice_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_CMS_RevocationInfoChoice_sk_type(sk), ossl_check_CMS_RevocationInfoChoice_type(ptr), (idx))
|
#define sk_CMS_RevocationInfoChoice_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_CMS_RevocationInfoChoice_sk_type(sk), ossl_check_CMS_RevocationInfoChoice_type(ptr), (idx))
|
||||||
#define sk_CMS_RevocationInfoChoice_set(sk, idx, ptr) ((CMS_RevocationInfoChoice *)OPENSSL_sk_set(ossl_check_CMS_RevocationInfoChoice_sk_type(sk), (idx), ossl_check_CMS_RevocationInfoChoice_type(ptr)))
|
#define sk_CMS_RevocationInfoChoice_set(sk, idx, ptr) ((CMS_RevocationInfoChoice *)OPENSSL_sk_set(ossl_check_CMS_RevocationInfoChoice_sk_type(sk), (idx), ossl_check_CMS_RevocationInfoChoice_type(ptr)))
|
||||||
#define sk_CMS_RevocationInfoChoice_find(sk, ptr) OPENSSL_sk_find(ossl_check_CMS_RevocationInfoChoice_sk_type(sk), ossl_check_CMS_RevocationInfoChoice_type(ptr))
|
#define sk_CMS_RevocationInfoChoice_find(sk, ptr) OPENSSL_sk_find(ossl_check_CMS_RevocationInfoChoice_sk_type(sk), ossl_check_CMS_RevocationInfoChoice_type(ptr))
|
||||||
@@ -168,7 +168,6 @@ CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
|
|||||||
# define CMS_RECIPINFO_KEK 2
|
# define CMS_RECIPINFO_KEK 2
|
||||||
# define CMS_RECIPINFO_PASS 3
|
# define CMS_RECIPINFO_PASS 3
|
||||||
# define CMS_RECIPINFO_OTHER 4
|
# define CMS_RECIPINFO_OTHER 4
|
||||||
# define CMS_RECIPINFO_KEM 5
|
|
||||||
|
|
||||||
/* S/MIME related flags */
|
/* S/MIME related flags */
|
||||||
|
|
||||||
@@ -500,14 +499,6 @@ int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
|
|||||||
int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
|
int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
|
||||||
ASN1_OCTET_STRING *ukm, int keylen);
|
ASN1_OCTET_STRING *ukm, int keylen);
|
||||||
|
|
||||||
int CMS_RecipientInfo_kemri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
|
|
||||||
int CMS_RecipientInfo_kemri_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk);
|
|
||||||
EVP_CIPHER_CTX *CMS_RecipientInfo_kemri_get0_ctx(CMS_RecipientInfo *ri);
|
|
||||||
X509_ALGOR *CMS_RecipientInfo_kemri_get0_kdf_alg(CMS_RecipientInfo *ri);
|
|
||||||
int CMS_RecipientInfo_kemri_set_ukm(CMS_RecipientInfo *ri,
|
|
||||||
const unsigned char *ukm,
|
|
||||||
int ukmLength);
|
|
||||||
|
|
||||||
/* Backward compatibility for spelling errors. */
|
/* Backward compatibility for spelling errors. */
|
||||||
# define CMS_R_UNKNOWN_DIGEST_ALGORITM CMS_R_UNKNOWN_DIGEST_ALGORITHM
|
# define CMS_R_UNKNOWN_DIGEST_ALGORITM CMS_R_UNKNOWN_DIGEST_ALGORITHM
|
||||||
# define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE \
|
# define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE \
|
||||||
|
|||||||
-3
@@ -67,7 +67,6 @@
|
|||||||
# define CMS_R_NOT_A_SIGNED_RECEIPT 165
|
# define CMS_R_NOT_A_SIGNED_RECEIPT 165
|
||||||
# define CMS_R_NOT_ENCRYPTED_DATA 122
|
# define CMS_R_NOT_ENCRYPTED_DATA 122
|
||||||
# define CMS_R_NOT_KEK 123
|
# define CMS_R_NOT_KEK 123
|
||||||
# define CMS_R_NOT_KEM 197
|
|
||||||
# define CMS_R_NOT_KEY_AGREEMENT 181
|
# define CMS_R_NOT_KEY_AGREEMENT 181
|
||||||
# define CMS_R_NOT_KEY_TRANSPORT 124
|
# define CMS_R_NOT_KEY_TRANSPORT 124
|
||||||
# define CMS_R_NOT_PWRI 177
|
# define CMS_R_NOT_PWRI 177
|
||||||
@@ -107,12 +106,10 @@
|
|||||||
# define CMS_R_UNKNOWN_CIPHER 148
|
# define CMS_R_UNKNOWN_CIPHER 148
|
||||||
# define CMS_R_UNKNOWN_DIGEST_ALGORITHM 149
|
# define CMS_R_UNKNOWN_DIGEST_ALGORITHM 149
|
||||||
# define CMS_R_UNKNOWN_ID 150
|
# define CMS_R_UNKNOWN_ID 150
|
||||||
# define CMS_R_UNKNOWN_KDF_ALGORITHM 198
|
|
||||||
# define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 151
|
# define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 151
|
||||||
# define CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM 194
|
# define CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM 194
|
||||||
# define CMS_R_UNSUPPORTED_CONTENT_TYPE 152
|
# define CMS_R_UNSUPPORTED_CONTENT_TYPE 152
|
||||||
# define CMS_R_UNSUPPORTED_ENCRYPTION_TYPE 192
|
# define CMS_R_UNSUPPORTED_ENCRYPTION_TYPE 192
|
||||||
# define CMS_R_UNSUPPORTED_KDF_ALGORITHM 199
|
|
||||||
# define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153
|
# define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153
|
||||||
# define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM 179
|
# define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM 179
|
||||||
# define CMS_R_UNSUPPORTED_LABEL_SOURCE 193
|
# define CMS_R_UNSUPPORTED_LABEL_SOURCE 193
|
||||||
|
|||||||
+1
-1
@@ -78,7 +78,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(SSL_COMP, SSL_COMP, SSL_COMP)
|
|||||||
#define sk_SSL_COMP_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
|
#define sk_SSL_COMP_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
|
||||||
#define sk_SSL_COMP_pop(sk) ((SSL_COMP *)OPENSSL_sk_pop(ossl_check_SSL_COMP_sk_type(sk)))
|
#define sk_SSL_COMP_pop(sk) ((SSL_COMP *)OPENSSL_sk_pop(ossl_check_SSL_COMP_sk_type(sk)))
|
||||||
#define sk_SSL_COMP_shift(sk) ((SSL_COMP *)OPENSSL_sk_shift(ossl_check_SSL_COMP_sk_type(sk)))
|
#define sk_SSL_COMP_shift(sk) ((SSL_COMP *)OPENSSL_sk_shift(ossl_check_SSL_COMP_sk_type(sk)))
|
||||||
#define sk_SSL_COMP_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_freefunc_type(freefunc))
|
#define sk_SSL_COMP_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SSL_COMP_sk_type(sk),ossl_check_SSL_COMP_freefunc_type(freefunc))
|
||||||
#define sk_SSL_COMP_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr), (idx))
|
#define sk_SSL_COMP_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr), (idx))
|
||||||
#define sk_SSL_COMP_set(sk, idx, ptr) ((SSL_COMP *)OPENSSL_sk_set(ossl_check_SSL_COMP_sk_type(sk), (idx), ossl_check_SSL_COMP_type(ptr)))
|
#define sk_SSL_COMP_set(sk, idx, ptr) ((SSL_COMP *)OPENSSL_sk_set(ossl_check_SSL_COMP_sk_type(sk), (idx), ossl_check_SSL_COMP_type(ptr)))
|
||||||
#define sk_SSL_COMP_find(sk, ptr) OPENSSL_sk_find(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
|
#define sk_SSL_COMP_find(sk, ptr) OPENSSL_sk_find(ossl_check_SSL_COMP_sk_type(sk), ossl_check_SSL_COMP_type(ptr))
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(CONF_VALUE, CONF_VALUE, CONF_VALUE)
|
|||||||
#define sk_CONF_VALUE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_CONF_VALUE_sk_type(sk), ossl_check_CONF_VALUE_type(ptr))
|
#define sk_CONF_VALUE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_CONF_VALUE_sk_type(sk), ossl_check_CONF_VALUE_type(ptr))
|
||||||
#define sk_CONF_VALUE_pop(sk) ((CONF_VALUE *)OPENSSL_sk_pop(ossl_check_CONF_VALUE_sk_type(sk)))
|
#define sk_CONF_VALUE_pop(sk) ((CONF_VALUE *)OPENSSL_sk_pop(ossl_check_CONF_VALUE_sk_type(sk)))
|
||||||
#define sk_CONF_VALUE_shift(sk) ((CONF_VALUE *)OPENSSL_sk_shift(ossl_check_CONF_VALUE_sk_type(sk)))
|
#define sk_CONF_VALUE_shift(sk) ((CONF_VALUE *)OPENSSL_sk_shift(ossl_check_CONF_VALUE_sk_type(sk)))
|
||||||
#define sk_CONF_VALUE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_CONF_VALUE_sk_type(sk), ossl_check_CONF_VALUE_freefunc_type(freefunc))
|
#define sk_CONF_VALUE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_CONF_VALUE_sk_type(sk),ossl_check_CONF_VALUE_freefunc_type(freefunc))
|
||||||
#define sk_CONF_VALUE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_CONF_VALUE_sk_type(sk), ossl_check_CONF_VALUE_type(ptr), (idx))
|
#define sk_CONF_VALUE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_CONF_VALUE_sk_type(sk), ossl_check_CONF_VALUE_type(ptr), (idx))
|
||||||
#define sk_CONF_VALUE_set(sk, idx, ptr) ((CONF_VALUE *)OPENSSL_sk_set(ossl_check_CONF_VALUE_sk_type(sk), (idx), ossl_check_CONF_VALUE_type(ptr)))
|
#define sk_CONF_VALUE_set(sk, idx, ptr) ((CONF_VALUE *)OPENSSL_sk_set(ossl_check_CONF_VALUE_sk_type(sk), (idx), ossl_check_CONF_VALUE_type(ptr)))
|
||||||
#define sk_CONF_VALUE_find(sk, ptr) OPENSSL_sk_find(ossl_check_CONF_VALUE_sk_type(sk), ossl_check_CONF_VALUE_type(ptr))
|
#define sk_CONF_VALUE_find(sk, ptr) OPENSSL_sk_find(ossl_check_CONF_VALUE_sk_type(sk), ossl_check_CONF_VALUE_type(ptr))
|
||||||
|
|||||||
+1
-7
@@ -30,7 +30,7 @@ extern "C" {
|
|||||||
# ifndef OPENSSL_SYS_iOS
|
# ifndef OPENSSL_SYS_iOS
|
||||||
# define OPENSSL_SYS_iOS 1
|
# define OPENSSL_SYS_iOS 1
|
||||||
# endif
|
# endif
|
||||||
# define OPENSSL_CONFIGURED_API 30600
|
# define OPENSSL_CONFIGURED_API 30500
|
||||||
# ifndef OPENSSL_RAND_SEED_OS
|
# ifndef OPENSSL_RAND_SEED_OS
|
||||||
# define OPENSSL_RAND_SEED_OS
|
# define OPENSSL_RAND_SEED_OS
|
||||||
# endif
|
# endif
|
||||||
@@ -43,9 +43,6 @@ extern "C" {
|
|||||||
# ifndef OPENSSL_NO_AFALGENG
|
# ifndef OPENSSL_NO_AFALGENG
|
||||||
# define OPENSSL_NO_AFALGENG
|
# define OPENSSL_NO_AFALGENG
|
||||||
# endif
|
# endif
|
||||||
# ifndef OPENSSL_NO_ALLOCFAIL_TESTS
|
|
||||||
# define OPENSSL_NO_ALLOCFAIL_TESTS
|
|
||||||
# endif
|
|
||||||
# ifndef OPENSSL_NO_ASAN
|
# ifndef OPENSSL_NO_ASAN
|
||||||
# define OPENSSL_NO_ASAN
|
# define OPENSSL_NO_ASAN
|
||||||
# endif
|
# endif
|
||||||
@@ -124,9 +121,6 @@ extern "C" {
|
|||||||
# ifndef OPENSSL_NO_KTLS
|
# ifndef OPENSSL_NO_KTLS
|
||||||
# define OPENSSL_NO_KTLS
|
# define OPENSSL_NO_KTLS
|
||||||
# endif
|
# endif
|
||||||
# ifndef OPENSSL_NO_LMS
|
|
||||||
# define OPENSSL_NO_LMS
|
|
||||||
# endif
|
|
||||||
# ifndef OPENSSL_NO_LOADERENG
|
# ifndef OPENSSL_NO_LOADERENG
|
||||||
# define OPENSSL_NO_LOADERENG
|
# define OPENSSL_NO_LOADERENG
|
||||||
# endif
|
# endif
|
||||||
|
|||||||
+46
-61
@@ -253,10 +253,6 @@ OSSL_CORE_MAKE_FUNC(int, provider_up_ref,
|
|||||||
OSSL_CORE_MAKE_FUNC(int, provider_free,
|
OSSL_CORE_MAKE_FUNC(int, provider_free,
|
||||||
(const OSSL_CORE_HANDLE *prov, int deactivate))
|
(const OSSL_CORE_HANDLE *prov, int deactivate))
|
||||||
|
|
||||||
/* Additional error functions provided by the core */
|
|
||||||
# define OSSL_FUNC_CORE_COUNT_TO_MARK 120
|
|
||||||
OSSL_CORE_MAKE_FUNC(int, core_count_to_mark, (const OSSL_CORE_HANDLE *prov))
|
|
||||||
|
|
||||||
/* Functions provided by the provider to the Core, reserved numbers 1024-1535 */
|
/* Functions provided by the provider to the Core, reserved numbers 1024-1535 */
|
||||||
# define OSSL_FUNC_PROVIDER_TEARDOWN 1024
|
# define OSSL_FUNC_PROVIDER_TEARDOWN 1024
|
||||||
OSSL_CORE_MAKE_FUNC(void, provider_teardown, (void *provctx))
|
OSSL_CORE_MAKE_FUNC(void, provider_teardown, (void *provctx))
|
||||||
@@ -503,52 +499,6 @@ OSSL_CORE_MAKE_FUNC(int, mac_set_ctx_params,
|
|||||||
(void *mctx, const OSSL_PARAM params[]))
|
(void *mctx, const OSSL_PARAM params[]))
|
||||||
OSSL_CORE_MAKE_FUNC(int, mac_init_skey, (void *mctx, void *key, const OSSL_PARAM params[]))
|
OSSL_CORE_MAKE_FUNC(int, mac_init_skey, (void *mctx, void *key, const OSSL_PARAM params[]))
|
||||||
|
|
||||||
/*-
|
|
||||||
* Symmetric key management
|
|
||||||
*
|
|
||||||
* The Key Management takes care of provider side of symmetric key objects, and
|
|
||||||
* includes essentially everything that manipulates the keys themselves and
|
|
||||||
* their parameters.
|
|
||||||
*
|
|
||||||
* The key objects are commonly referred to as |keydata|, and it MUST be able
|
|
||||||
* to contain parameters if the key has any, and the secret key.
|
|
||||||
*
|
|
||||||
* Key objects are created with OSSL_FUNC_skeymgmt_import() (there is no
|
|
||||||
* dedicated memory allocation function), exported with
|
|
||||||
* OSSL_FUNC_skeymgmt_export() and destroyed with OSSL_FUNC_keymgmt_free().
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Key data subset selection - individual bits */
|
|
||||||
# define OSSL_SKEYMGMT_SELECT_PARAMETERS 0x01
|
|
||||||
# define OSSL_SKEYMGMT_SELECT_SECRET_KEY 0x02
|
|
||||||
|
|
||||||
/* Key data subset selection - combinations */
|
|
||||||
# define OSSL_SKEYMGMT_SELECT_ALL \
|
|
||||||
(OSSL_SKEYMGMT_SELECT_PARAMETERS | OSSL_SKEYMGMT_SELECT_SECRET_KEY)
|
|
||||||
|
|
||||||
# define OSSL_FUNC_SKEYMGMT_FREE 1
|
|
||||||
# define OSSL_FUNC_SKEYMGMT_IMPORT 2
|
|
||||||
# define OSSL_FUNC_SKEYMGMT_EXPORT 3
|
|
||||||
# define OSSL_FUNC_SKEYMGMT_GENERATE 4
|
|
||||||
# define OSSL_FUNC_SKEYMGMT_GET_KEY_ID 5
|
|
||||||
# define OSSL_FUNC_SKEYMGMT_IMP_SETTABLE_PARAMS 6
|
|
||||||
# define OSSL_FUNC_SKEYMGMT_GEN_SETTABLE_PARAMS 7
|
|
||||||
|
|
||||||
OSSL_CORE_MAKE_FUNC(void, skeymgmt_free, (void *keydata))
|
|
||||||
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *,
|
|
||||||
skeymgmt_imp_settable_params, (void *provctx))
|
|
||||||
OSSL_CORE_MAKE_FUNC(void *, skeymgmt_import, (void *provctx, int selection,
|
|
||||||
const OSSL_PARAM params[]))
|
|
||||||
OSSL_CORE_MAKE_FUNC(int, skeymgmt_export,
|
|
||||||
(void *keydata, int selection,
|
|
||||||
OSSL_CALLBACK *param_cb, void *cbarg))
|
|
||||||
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *,
|
|
||||||
skeymgmt_gen_settable_params, (void *provctx))
|
|
||||||
OSSL_CORE_MAKE_FUNC(void *, skeymgmt_generate, (void *provctx,
|
|
||||||
const OSSL_PARAM params[]))
|
|
||||||
OSSL_CORE_MAKE_FUNC(const char *, skeymgmt_get_key_id, (void *keydata))
|
|
||||||
|
|
||||||
/* KDFs and PRFs */
|
/* KDFs and PRFs */
|
||||||
|
|
||||||
# define OSSL_FUNC_KDF_NEWCTX 1
|
# define OSSL_FUNC_KDF_NEWCTX 1
|
||||||
@@ -562,8 +512,6 @@ OSSL_CORE_MAKE_FUNC(const char *, skeymgmt_get_key_id, (void *keydata))
|
|||||||
# define OSSL_FUNC_KDF_GET_PARAMS 9
|
# define OSSL_FUNC_KDF_GET_PARAMS 9
|
||||||
# define OSSL_FUNC_KDF_GET_CTX_PARAMS 10
|
# define OSSL_FUNC_KDF_GET_CTX_PARAMS 10
|
||||||
# define OSSL_FUNC_KDF_SET_CTX_PARAMS 11
|
# define OSSL_FUNC_KDF_SET_CTX_PARAMS 11
|
||||||
# define OSSL_FUNC_KDF_SET_SKEY 12
|
|
||||||
# define OSSL_FUNC_KDF_DERIVE_SKEY 13
|
|
||||||
|
|
||||||
OSSL_CORE_MAKE_FUNC(void *, kdf_newctx, (void *provctx))
|
OSSL_CORE_MAKE_FUNC(void *, kdf_newctx, (void *provctx))
|
||||||
OSSL_CORE_MAKE_FUNC(void *, kdf_dupctx, (void *src))
|
OSSL_CORE_MAKE_FUNC(void *, kdf_dupctx, (void *src))
|
||||||
@@ -581,11 +529,6 @@ OSSL_CORE_MAKE_FUNC(int, kdf_get_ctx_params,
|
|||||||
(void *kctx, OSSL_PARAM params[]))
|
(void *kctx, OSSL_PARAM params[]))
|
||||||
OSSL_CORE_MAKE_FUNC(int, kdf_set_ctx_params,
|
OSSL_CORE_MAKE_FUNC(int, kdf_set_ctx_params,
|
||||||
(void *kctx, const OSSL_PARAM params[]))
|
(void *kctx, const OSSL_PARAM params[]))
|
||||||
OSSL_CORE_MAKE_FUNC(int, kdf_set_skey,
|
|
||||||
(void *kctx, void *skeydata, const char *paramname))
|
|
||||||
OSSL_CORE_MAKE_FUNC(void *, kdf_derive_skey, (void *ctx, const char *key_type, void *provctx,
|
|
||||||
OSSL_FUNC_skeymgmt_import_fn *import,
|
|
||||||
size_t keylen, const OSSL_PARAM params[]))
|
|
||||||
|
|
||||||
/* RAND */
|
/* RAND */
|
||||||
|
|
||||||
@@ -826,7 +769,6 @@ OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keymgmt_export_types_ex,
|
|||||||
# define OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS 8
|
# define OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS 8
|
||||||
# define OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS 9
|
# define OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS 9
|
||||||
# define OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS 10
|
# define OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS 10
|
||||||
# define OSSL_FUNC_KEYEXCH_DERIVE_SKEY 11
|
|
||||||
|
|
||||||
OSSL_CORE_MAKE_FUNC(void *, keyexch_newctx, (void *provctx))
|
OSSL_CORE_MAKE_FUNC(void *, keyexch_newctx, (void *provctx))
|
||||||
OSSL_CORE_MAKE_FUNC(int, keyexch_init, (void *ctx, void *provkey,
|
OSSL_CORE_MAKE_FUNC(int, keyexch_init, (void *ctx, void *provkey,
|
||||||
@@ -844,9 +786,6 @@ OSSL_CORE_MAKE_FUNC(int, keyexch_get_ctx_params, (void *ctx,
|
|||||||
OSSL_PARAM params[]))
|
OSSL_PARAM params[]))
|
||||||
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keyexch_gettable_ctx_params,
|
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, keyexch_gettable_ctx_params,
|
||||||
(void *ctx, void *provctx))
|
(void *ctx, void *provctx))
|
||||||
OSSL_CORE_MAKE_FUNC(void *, keyexch_derive_skey, (void *ctx, const char *key_type, void *provctx,
|
|
||||||
OSSL_FUNC_skeymgmt_import_fn *import,
|
|
||||||
size_t keylen, const OSSL_PARAM params[]))
|
|
||||||
|
|
||||||
/* Signature */
|
/* Signature */
|
||||||
|
|
||||||
@@ -960,6 +899,52 @@ OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, signature_settable_ctx_md_params,
|
|||||||
(void *ctx))
|
(void *ctx))
|
||||||
OSSL_CORE_MAKE_FUNC(const char **, signature_query_key_types, (void))
|
OSSL_CORE_MAKE_FUNC(const char **, signature_query_key_types, (void))
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Symmetric key management
|
||||||
|
*
|
||||||
|
* The Key Management takes care of provider side of symmetric key objects, and
|
||||||
|
* includes essentially everything that manipulates the keys themselves and
|
||||||
|
* their parameters.
|
||||||
|
*
|
||||||
|
* The key objects are commonly referred to as |keydata|, and it MUST be able
|
||||||
|
* to contain parameters if the key has any, and the secret key.
|
||||||
|
*
|
||||||
|
* Key objects are created with OSSL_FUNC_skeymgmt_import() (there is no
|
||||||
|
* dedicated memory allocation function), exported with
|
||||||
|
* OSSL_FUNC_skeymgmt_export() and destroyed with OSSL_FUNC_keymgmt_free().
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Key data subset selection - individual bits */
|
||||||
|
# define OSSL_SKEYMGMT_SELECT_PARAMETERS 0x01
|
||||||
|
# define OSSL_SKEYMGMT_SELECT_SECRET_KEY 0x02
|
||||||
|
|
||||||
|
/* Key data subset selection - combinations */
|
||||||
|
# define OSSL_SKEYMGMT_SELECT_ALL \
|
||||||
|
(OSSL_SKEYMGMT_SELECT_PARAMETERS | OSSL_SKEYMGMT_SELECT_SECRET_KEY)
|
||||||
|
|
||||||
|
# define OSSL_FUNC_SKEYMGMT_FREE 1
|
||||||
|
# define OSSL_FUNC_SKEYMGMT_IMPORT 2
|
||||||
|
# define OSSL_FUNC_SKEYMGMT_EXPORT 3
|
||||||
|
# define OSSL_FUNC_SKEYMGMT_GENERATE 4
|
||||||
|
# define OSSL_FUNC_SKEYMGMT_GET_KEY_ID 5
|
||||||
|
# define OSSL_FUNC_SKEYMGMT_IMP_SETTABLE_PARAMS 6
|
||||||
|
# define OSSL_FUNC_SKEYMGMT_GEN_SETTABLE_PARAMS 7
|
||||||
|
|
||||||
|
OSSL_CORE_MAKE_FUNC(void, skeymgmt_free, (void *keydata))
|
||||||
|
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *,
|
||||||
|
skeymgmt_imp_settable_params, (void *provctx))
|
||||||
|
OSSL_CORE_MAKE_FUNC(void *, skeymgmt_import, (void *provctx, int selection,
|
||||||
|
const OSSL_PARAM params[]))
|
||||||
|
OSSL_CORE_MAKE_FUNC(int, skeymgmt_export,
|
||||||
|
(void *keydata, int selection,
|
||||||
|
OSSL_CALLBACK *param_cb, void *cbarg))
|
||||||
|
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *,
|
||||||
|
skeymgmt_gen_settable_params, (void *provctx))
|
||||||
|
OSSL_CORE_MAKE_FUNC(void *, skeymgmt_generate, (void *provctx,
|
||||||
|
const OSSL_PARAM params[]))
|
||||||
|
OSSL_CORE_MAKE_FUNC(const char *, skeymgmt_get_key_id, (void *keydata))
|
||||||
|
|
||||||
/* Asymmetric Ciphers */
|
/* Asymmetric Ciphers */
|
||||||
|
|
||||||
# define OSSL_FUNC_ASYM_CIPHER_NEWCTX 1
|
# define OSSL_FUNC_ASYM_CIPHER_NEWCTX 1
|
||||||
|
|||||||
-9
@@ -65,9 +65,6 @@ extern "C" {
|
|||||||
|
|
||||||
/* Known KDF names */
|
/* Known KDF names */
|
||||||
# define OSSL_KDF_NAME_HKDF "HKDF"
|
# define OSSL_KDF_NAME_HKDF "HKDF"
|
||||||
# define OSSL_KDF_NAME_HKDF_SHA256 "HKDF-SHA256"
|
|
||||||
# define OSSL_KDF_NAME_HKDF_SHA384 "HKDF-SHA384"
|
|
||||||
# define OSSL_KDF_NAME_HKDF_SHA512 "HKDF-SHA512"
|
|
||||||
# define OSSL_KDF_NAME_TLS1_3_KDF "TLS13-KDF"
|
# define OSSL_KDF_NAME_TLS1_3_KDF "TLS13-KDF"
|
||||||
# define OSSL_KDF_NAME_PBKDF1 "PBKDF1"
|
# define OSSL_KDF_NAME_PBKDF1 "PBKDF1"
|
||||||
# define OSSL_KDF_NAME_PBKDF2 "PBKDF2"
|
# define OSSL_KDF_NAME_PBKDF2 "PBKDF2"
|
||||||
@@ -127,7 +124,6 @@ extern "C" {
|
|||||||
# define OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR "fips-indicator"
|
# define OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR "fips-indicator"
|
||||||
# define OSSL_ALG_PARAM_MAC "mac"
|
# define OSSL_ALG_PARAM_MAC "mac"
|
||||||
# define OSSL_ALG_PARAM_PROPERTIES "properties"
|
# define OSSL_ALG_PARAM_PROPERTIES "properties"
|
||||||
# define OSSL_ALG_PARAM_SECURITY_CATEGORY "security-category"
|
|
||||||
# define OSSL_ASYM_CIPHER_PARAM_DIGEST OSSL_PKEY_PARAM_DIGEST
|
# define OSSL_ASYM_CIPHER_PARAM_DIGEST OSSL_PKEY_PARAM_DIGEST
|
||||||
# define OSSL_ASYM_CIPHER_PARAM_ENGINE OSSL_PKEY_PARAM_ENGINE
|
# define OSSL_ASYM_CIPHER_PARAM_ENGINE OSSL_PKEY_PARAM_ENGINE
|
||||||
# define OSSL_ASYM_CIPHER_PARAM_FIPS_APPROVED_INDICATOR OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR
|
# define OSSL_ASYM_CIPHER_PARAM_FIPS_APPROVED_INDICATOR OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR
|
||||||
@@ -168,7 +164,6 @@ extern "C" {
|
|||||||
# define OSSL_CAPABILITY_TLS_SIGALG_SECURITY_BITS "tls-sigalg-sec-bits"
|
# define OSSL_CAPABILITY_TLS_SIGALG_SECURITY_BITS "tls-sigalg-sec-bits"
|
||||||
# define OSSL_CAPABILITY_TLS_SIGALG_SIG_NAME "tls-sigalg-sig-name"
|
# define OSSL_CAPABILITY_TLS_SIGALG_SIG_NAME "tls-sigalg-sig-name"
|
||||||
# define OSSL_CAPABILITY_TLS_SIGALG_SIG_OID "tls-sigalg-sig-oid"
|
# define OSSL_CAPABILITY_TLS_SIGALG_SIG_OID "tls-sigalg-sig-oid"
|
||||||
# define OSSL_CIPHER_HMAC_PARAM_MAC OSSL_CIPHER_PARAM_AEAD_TAG
|
|
||||||
# define OSSL_CIPHER_PARAM_AEAD "aead"
|
# define OSSL_CIPHER_PARAM_AEAD "aead"
|
||||||
# define OSSL_CIPHER_PARAM_AEAD_IVLEN OSSL_CIPHER_PARAM_IVLEN
|
# define OSSL_CIPHER_PARAM_AEAD_IVLEN OSSL_CIPHER_PARAM_IVLEN
|
||||||
# define OSSL_CIPHER_PARAM_AEAD_IV_GENERATED "iv-generated"
|
# define OSSL_CIPHER_PARAM_AEAD_IV_GENERATED "iv-generated"
|
||||||
@@ -188,7 +183,6 @@ extern "C" {
|
|||||||
# define OSSL_CIPHER_PARAM_CTS_MODE "cts_mode"
|
# define OSSL_CIPHER_PARAM_CTS_MODE "cts_mode"
|
||||||
# define OSSL_CIPHER_PARAM_CUSTOM_IV "custom-iv"
|
# define OSSL_CIPHER_PARAM_CUSTOM_IV "custom-iv"
|
||||||
# define OSSL_CIPHER_PARAM_DECRYPT_ONLY "decrypt-only"
|
# define OSSL_CIPHER_PARAM_DECRYPT_ONLY "decrypt-only"
|
||||||
# define OSSL_CIPHER_PARAM_ENCRYPT_THEN_MAC "encrypt-then-mac"
|
|
||||||
# define OSSL_CIPHER_PARAM_FIPS_APPROVED_INDICATOR OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR
|
# define OSSL_CIPHER_PARAM_FIPS_APPROVED_INDICATOR OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR
|
||||||
# define OSSL_CIPHER_PARAM_FIPS_ENCRYPT_CHECK "encrypt-check"
|
# define OSSL_CIPHER_PARAM_FIPS_ENCRYPT_CHECK "encrypt-check"
|
||||||
# define OSSL_CIPHER_PARAM_HAS_RAND_KEY "has-randkey"
|
# define OSSL_CIPHER_PARAM_HAS_RAND_KEY "has-randkey"
|
||||||
@@ -362,8 +356,6 @@ extern "C" {
|
|||||||
# define OSSL_PKEY_PARAM_ALGORITHM_ID_PARAMS OSSL_ALG_PARAM_ALGORITHM_ID_PARAMS
|
# define OSSL_PKEY_PARAM_ALGORITHM_ID_PARAMS OSSL_ALG_PARAM_ALGORITHM_ID_PARAMS
|
||||||
# define OSSL_PKEY_PARAM_BITS "bits"
|
# define OSSL_PKEY_PARAM_BITS "bits"
|
||||||
# define OSSL_PKEY_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER
|
# define OSSL_PKEY_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER
|
||||||
# define OSSL_PKEY_PARAM_CMS_KEMRI_KDF_ALGORITHM "kemri-kdf-alg"
|
|
||||||
# define OSSL_PKEY_PARAM_CMS_RI_TYPE "ri-type"
|
|
||||||
# define OSSL_PKEY_PARAM_DEFAULT_DIGEST "default-digest"
|
# define OSSL_PKEY_PARAM_DEFAULT_DIGEST "default-digest"
|
||||||
# define OSSL_PKEY_PARAM_DHKEM_IKM "dhkem-ikm"
|
# define OSSL_PKEY_PARAM_DHKEM_IKM "dhkem-ikm"
|
||||||
# define OSSL_PKEY_PARAM_DH_GENERATOR "safeprime-generator"
|
# define OSSL_PKEY_PARAM_DH_GENERATOR "safeprime-generator"
|
||||||
@@ -490,7 +482,6 @@ extern "C" {
|
|||||||
# define OSSL_PKEY_PARAM_RSA_TEST_XQ1 "xq1"
|
# define OSSL_PKEY_PARAM_RSA_TEST_XQ1 "xq1"
|
||||||
# define OSSL_PKEY_PARAM_RSA_TEST_XQ2 "xq2"
|
# define OSSL_PKEY_PARAM_RSA_TEST_XQ2 "xq2"
|
||||||
# define OSSL_PKEY_PARAM_SECURITY_BITS "security-bits"
|
# define OSSL_PKEY_PARAM_SECURITY_BITS "security-bits"
|
||||||
# define OSSL_PKEY_PARAM_SECURITY_CATEGORY OSSL_ALG_PARAM_SECURITY_CATEGORY
|
|
||||||
# define OSSL_PKEY_PARAM_SLH_DSA_SEED "seed"
|
# define OSSL_PKEY_PARAM_SLH_DSA_SEED "seed"
|
||||||
# define OSSL_PKEY_PARAM_USE_COFACTOR_ECDH OSSL_PKEY_PARAM_USE_COFACTOR_FLAG
|
# define OSSL_PKEY_PARAM_USE_COFACTOR_ECDH OSSL_PKEY_PARAM_USE_COFACTOR_FLAG
|
||||||
# define OSSL_PKEY_PARAM_USE_COFACTOR_FLAG "use-cofactor-flag"
|
# define OSSL_PKEY_PARAM_USE_COFACTOR_FLAG "use-cofactor-flag"
|
||||||
|
|||||||
+3
-3
@@ -68,7 +68,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CRMF_MSG, OSSL_CRMF_MSG, OSSL_CRMF_MSG)
|
|||||||
#define sk_OSSL_CRMF_MSG_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr))
|
#define sk_OSSL_CRMF_MSG_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr))
|
||||||
#define sk_OSSL_CRMF_MSG_pop(sk) ((OSSL_CRMF_MSG *)OPENSSL_sk_pop(ossl_check_OSSL_CRMF_MSG_sk_type(sk)))
|
#define sk_OSSL_CRMF_MSG_pop(sk) ((OSSL_CRMF_MSG *)OPENSSL_sk_pop(ossl_check_OSSL_CRMF_MSG_sk_type(sk)))
|
||||||
#define sk_OSSL_CRMF_MSG_shift(sk) ((OSSL_CRMF_MSG *)OPENSSL_sk_shift(ossl_check_OSSL_CRMF_MSG_sk_type(sk)))
|
#define sk_OSSL_CRMF_MSG_shift(sk) ((OSSL_CRMF_MSG *)OPENSSL_sk_shift(ossl_check_OSSL_CRMF_MSG_sk_type(sk)))
|
||||||
#define sk_OSSL_CRMF_MSG_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_freefunc_type(freefunc))
|
#define sk_OSSL_CRMF_MSG_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CRMF_MSG_sk_type(sk),ossl_check_OSSL_CRMF_MSG_freefunc_type(freefunc))
|
||||||
#define sk_OSSL_CRMF_MSG_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr), (idx))
|
#define sk_OSSL_CRMF_MSG_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr), (idx))
|
||||||
#define sk_OSSL_CRMF_MSG_set(sk, idx, ptr) ((OSSL_CRMF_MSG *)OPENSSL_sk_set(ossl_check_OSSL_CRMF_MSG_sk_type(sk), (idx), ossl_check_OSSL_CRMF_MSG_type(ptr)))
|
#define sk_OSSL_CRMF_MSG_set(sk, idx, ptr) ((OSSL_CRMF_MSG *)OPENSSL_sk_set(ossl_check_OSSL_CRMF_MSG_sk_type(sk), (idx), ossl_check_OSSL_CRMF_MSG_type(ptr)))
|
||||||
#define sk_OSSL_CRMF_MSG_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr))
|
#define sk_OSSL_CRMF_MSG_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CRMF_MSG_sk_type(sk), ossl_check_OSSL_CRMF_MSG_type(ptr))
|
||||||
@@ -98,7 +98,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, OSSL_CRMF_ATTRIBUT
|
|||||||
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk), ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_type(ptr))
|
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk), ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_type(ptr))
|
||||||
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_pop(sk) ((OSSL_CRMF_ATTRIBUTETYPEANDVALUE *)OPENSSL_sk_pop(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk)))
|
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_pop(sk) ((OSSL_CRMF_ATTRIBUTETYPEANDVALUE *)OPENSSL_sk_pop(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk)))
|
||||||
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_shift(sk) ((OSSL_CRMF_ATTRIBUTETYPEANDVALUE *)OPENSSL_sk_shift(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk)))
|
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_shift(sk) ((OSSL_CRMF_ATTRIBUTETYPEANDVALUE *)OPENSSL_sk_shift(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk)))
|
||||||
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk), ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_freefunc_type(freefunc))
|
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk),ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_freefunc_type(freefunc))
|
||||||
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk), ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_type(ptr), (idx))
|
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk), ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_type(ptr), (idx))
|
||||||
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_set(sk, idx, ptr) ((OSSL_CRMF_ATTRIBUTETYPEANDVALUE *)OPENSSL_sk_set(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk), (idx), ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_type(ptr)))
|
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_set(sk, idx, ptr) ((OSSL_CRMF_ATTRIBUTETYPEANDVALUE *)OPENSSL_sk_set(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk), (idx), ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_type(ptr)))
|
||||||
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk), ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_type(ptr))
|
#define sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_sk_type(sk), ossl_check_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_type(ptr))
|
||||||
@@ -133,7 +133,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OSSL_CRMF_CERTID, OSSL_CRMF_CERTID, OSSL_CRMF_CERTI
|
|||||||
#define sk_OSSL_CRMF_CERTID_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr))
|
#define sk_OSSL_CRMF_CERTID_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr))
|
||||||
#define sk_OSSL_CRMF_CERTID_pop(sk) ((OSSL_CRMF_CERTID *)OPENSSL_sk_pop(ossl_check_OSSL_CRMF_CERTID_sk_type(sk)))
|
#define sk_OSSL_CRMF_CERTID_pop(sk) ((OSSL_CRMF_CERTID *)OPENSSL_sk_pop(ossl_check_OSSL_CRMF_CERTID_sk_type(sk)))
|
||||||
#define sk_OSSL_CRMF_CERTID_shift(sk) ((OSSL_CRMF_CERTID *)OPENSSL_sk_shift(ossl_check_OSSL_CRMF_CERTID_sk_type(sk)))
|
#define sk_OSSL_CRMF_CERTID_shift(sk) ((OSSL_CRMF_CERTID *)OPENSSL_sk_shift(ossl_check_OSSL_CRMF_CERTID_sk_type(sk)))
|
||||||
#define sk_OSSL_CRMF_CERTID_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_freefunc_type(freefunc))
|
#define sk_OSSL_CRMF_CERTID_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OSSL_CRMF_CERTID_sk_type(sk),ossl_check_OSSL_CRMF_CERTID_freefunc_type(freefunc))
|
||||||
#define sk_OSSL_CRMF_CERTID_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr), (idx))
|
#define sk_OSSL_CRMF_CERTID_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr), (idx))
|
||||||
#define sk_OSSL_CRMF_CERTID_set(sk, idx, ptr) ((OSSL_CRMF_CERTID *)OPENSSL_sk_set(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), (idx), ossl_check_OSSL_CRMF_CERTID_type(ptr)))
|
#define sk_OSSL_CRMF_CERTID_set(sk, idx, ptr) ((OSSL_CRMF_CERTID *)OPENSSL_sk_set(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), (idx), ossl_check_OSSL_CRMF_CERTID_type(ptr)))
|
||||||
#define sk_OSSL_CRMF_CERTID_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr))
|
#define sk_OSSL_CRMF_CERTID_find(sk, ptr) OPENSSL_sk_find(ossl_check_OSSL_CRMF_CERTID_sk_type(sk), ossl_check_OSSL_CRMF_CERTID_type(ptr))
|
||||||
|
|||||||
+5
-36
@@ -2,7 +2,7 @@
|
|||||||
* WARNING: do not edit!
|
* WARNING: do not edit!
|
||||||
* Generated by Makefile from include/openssl/crypto.h.in
|
* Generated by Makefile from include/openssl/crypto.h.in
|
||||||
*
|
*
|
||||||
* Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
@@ -102,25 +102,13 @@ int CRYPTO_atomic_store(uint64_t *dst, uint64_t val, CRYPTO_RWLOCK *lock);
|
|||||||
CRYPTO_malloc(num, OPENSSL_FILE, OPENSSL_LINE)
|
CRYPTO_malloc(num, OPENSSL_FILE, OPENSSL_LINE)
|
||||||
# define OPENSSL_zalloc(num) \
|
# define OPENSSL_zalloc(num) \
|
||||||
CRYPTO_zalloc(num, OPENSSL_FILE, OPENSSL_LINE)
|
CRYPTO_zalloc(num, OPENSSL_FILE, OPENSSL_LINE)
|
||||||
# define OPENSSL_malloc_array(num, size) \
|
|
||||||
CRYPTO_malloc_array(num, size, OPENSSL_FILE, OPENSSL_LINE)
|
|
||||||
# define OPENSSL_calloc(num, size) \
|
|
||||||
CRYPTO_calloc(num, size, OPENSSL_FILE, OPENSSL_LINE)
|
|
||||||
# define OPENSSL_aligned_alloc(num, alignment, freeptr) \
|
# define OPENSSL_aligned_alloc(num, alignment, freeptr) \
|
||||||
CRYPTO_aligned_alloc(num, alignment, freeptr, \
|
CRYPTO_aligned_alloc(num, alignment, freeptr, \
|
||||||
OPENSSL_FILE, OPENSSL_LINE)
|
OPENSSL_FILE, OPENSSL_LINE)
|
||||||
# define OPENSSL_aligned_alloc_array(num, size, alignment, freeptr) \
|
|
||||||
CRYPTO_aligned_alloc_array(num, size, alignment, freeptr, \
|
|
||||||
OPENSSL_FILE, OPENSSL_LINE)
|
|
||||||
# define OPENSSL_realloc(addr, num) \
|
# define OPENSSL_realloc(addr, num) \
|
||||||
CRYPTO_realloc(addr, num, OPENSSL_FILE, OPENSSL_LINE)
|
CRYPTO_realloc(addr, num, OPENSSL_FILE, OPENSSL_LINE)
|
||||||
# define OPENSSL_clear_realloc(addr, old_num, num) \
|
# define OPENSSL_clear_realloc(addr, old_num, num) \
|
||||||
CRYPTO_clear_realloc(addr, old_num, num, OPENSSL_FILE, OPENSSL_LINE)
|
CRYPTO_clear_realloc(addr, old_num, num, OPENSSL_FILE, OPENSSL_LINE)
|
||||||
# define OPENSSL_realloc_array(addr, num, size) \
|
|
||||||
CRYPTO_realloc_array(addr, num, size, OPENSSL_FILE, OPENSSL_LINE)
|
|
||||||
# define OPENSSL_clear_realloc_array(addr, old_num, num, size) \
|
|
||||||
CRYPTO_clear_realloc_array(addr, old_num, num, size, \
|
|
||||||
OPENSSL_FILE, OPENSSL_LINE)
|
|
||||||
# define OPENSSL_clear_free(addr, num) \
|
# define OPENSSL_clear_free(addr, num) \
|
||||||
CRYPTO_clear_free(addr, num, OPENSSL_FILE, OPENSSL_LINE)
|
CRYPTO_clear_free(addr, num, OPENSSL_FILE, OPENSSL_LINE)
|
||||||
# define OPENSSL_free(addr) \
|
# define OPENSSL_free(addr) \
|
||||||
@@ -135,10 +123,6 @@ int CRYPTO_atomic_store(uint64_t *dst, uint64_t val, CRYPTO_RWLOCK *lock);
|
|||||||
CRYPTO_secure_malloc(num, OPENSSL_FILE, OPENSSL_LINE)
|
CRYPTO_secure_malloc(num, OPENSSL_FILE, OPENSSL_LINE)
|
||||||
# define OPENSSL_secure_zalloc(num) \
|
# define OPENSSL_secure_zalloc(num) \
|
||||||
CRYPTO_secure_zalloc(num, OPENSSL_FILE, OPENSSL_LINE)
|
CRYPTO_secure_zalloc(num, OPENSSL_FILE, OPENSSL_LINE)
|
||||||
# define OPENSSL_secure_malloc_array(num, size) \
|
|
||||||
CRYPTO_secure_malloc_array(num, size, OPENSSL_FILE, OPENSSL_LINE)
|
|
||||||
# define OPENSSL_secure_calloc(num, size) \
|
|
||||||
CRYPTO_secure_calloc(num, size, OPENSSL_FILE, OPENSSL_LINE)
|
|
||||||
# define OPENSSL_secure_free(addr) \
|
# define OPENSSL_secure_free(addr) \
|
||||||
CRYPTO_secure_free(addr, OPENSSL_FILE, OPENSSL_LINE)
|
CRYPTO_secure_free(addr, OPENSSL_FILE, OPENSSL_LINE)
|
||||||
# define OPENSSL_secure_clear_free(addr, num) \
|
# define OPENSSL_secure_clear_free(addr, num) \
|
||||||
@@ -225,7 +209,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(void, void, void)
|
|||||||
#define sk_void_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_void_sk_type(sk), ossl_check_void_type(ptr))
|
#define sk_void_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_void_sk_type(sk), ossl_check_void_type(ptr))
|
||||||
#define sk_void_pop(sk) ((void *)OPENSSL_sk_pop(ossl_check_void_sk_type(sk)))
|
#define sk_void_pop(sk) ((void *)OPENSSL_sk_pop(ossl_check_void_sk_type(sk)))
|
||||||
#define sk_void_shift(sk) ((void *)OPENSSL_sk_shift(ossl_check_void_sk_type(sk)))
|
#define sk_void_shift(sk) ((void *)OPENSSL_sk_shift(ossl_check_void_sk_type(sk)))
|
||||||
#define sk_void_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_void_sk_type(sk), ossl_check_void_freefunc_type(freefunc))
|
#define sk_void_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_void_sk_type(sk),ossl_check_void_freefunc_type(freefunc))
|
||||||
#define sk_void_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_void_sk_type(sk), ossl_check_void_type(ptr), (idx))
|
#define sk_void_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_void_sk_type(sk), ossl_check_void_type(ptr), (idx))
|
||||||
#define sk_void_set(sk, idx, ptr) ((void *)OPENSSL_sk_set(ossl_check_void_sk_type(sk), (idx), ossl_check_void_type(ptr)))
|
#define sk_void_set(sk, idx, ptr) ((void *)OPENSSL_sk_set(ossl_check_void_sk_type(sk), (idx), ossl_check_void_type(ptr)))
|
||||||
#define sk_void_find(sk, ptr) OPENSSL_sk_find(ossl_check_void_sk_type(sk), ossl_check_void_type(ptr))
|
#define sk_void_find(sk, ptr) OPENSSL_sk_find(ossl_check_void_sk_type(sk), ossl_check_void_type(ptr))
|
||||||
@@ -371,37 +355,22 @@ void CRYPTO_get_mem_functions(CRYPTO_malloc_fn *malloc_fn,
|
|||||||
|
|
||||||
OSSL_CRYPTO_ALLOC void *CRYPTO_malloc(size_t num, const char *file, int line);
|
OSSL_CRYPTO_ALLOC void *CRYPTO_malloc(size_t num, const char *file, int line);
|
||||||
OSSL_CRYPTO_ALLOC void *CRYPTO_zalloc(size_t num, const char *file, int line);
|
OSSL_CRYPTO_ALLOC void *CRYPTO_zalloc(size_t num, const char *file, int line);
|
||||||
OSSL_CRYPTO_ALLOC void *CRYPTO_malloc_array(size_t num, size_t size,
|
|
||||||
const char *file, int line);
|
|
||||||
OSSL_CRYPTO_ALLOC void *CRYPTO_calloc(size_t num, size_t size,
|
|
||||||
const char *file, int line);
|
|
||||||
OSSL_CRYPTO_ALLOC void *CRYPTO_aligned_alloc(size_t num, size_t align,
|
OSSL_CRYPTO_ALLOC void *CRYPTO_aligned_alloc(size_t num, size_t align,
|
||||||
void **freeptr, const char *file,
|
void **freeptr, const char *file,
|
||||||
int line);
|
int line);
|
||||||
OSSL_CRYPTO_ALLOC void *CRYPTO_aligned_alloc_array(size_t num, size_t size,
|
OSSL_CRYPTO_ALLOC void *CRYPTO_memdup(const void *str, size_t siz, const char *file, int line);
|
||||||
size_t align, void **freeptr,
|
OSSL_CRYPTO_ALLOC char *CRYPTO_strdup(const char *str, const char *file, int line);
|
||||||
const char *file, int line);
|
OSSL_CRYPTO_ALLOC char *CRYPTO_strndup(const char *str, size_t s, const char *file, int line);
|
||||||
void *CRYPTO_memdup(const void *str, size_t siz, const char *file, int line);
|
|
||||||
char *CRYPTO_strdup(const char *str, const char *file, int line);
|
|
||||||
char *CRYPTO_strndup(const char *str, size_t s, const char *file, int line);
|
|
||||||
void CRYPTO_free(void *ptr, const char *file, int line);
|
void CRYPTO_free(void *ptr, const char *file, int line);
|
||||||
void CRYPTO_clear_free(void *ptr, size_t num, const char *file, int line);
|
void CRYPTO_clear_free(void *ptr, size_t num, const char *file, int line);
|
||||||
void *CRYPTO_realloc(void *addr, size_t num, const char *file, int line);
|
void *CRYPTO_realloc(void *addr, size_t num, const char *file, int line);
|
||||||
void *CRYPTO_clear_realloc(void *addr, size_t old_num, size_t num,
|
void *CRYPTO_clear_realloc(void *addr, size_t old_num, size_t num,
|
||||||
const char *file, int line);
|
const char *file, int line);
|
||||||
void *CRYPTO_realloc_array(void *addr, size_t num, size_t size,
|
|
||||||
const char *file, int line);
|
|
||||||
void *CRYPTO_clear_realloc_array(void *addr, size_t old_num, size_t num,
|
|
||||||
size_t size, const char *file, int line);
|
|
||||||
|
|
||||||
int CRYPTO_secure_malloc_init(size_t sz, size_t minsize);
|
int CRYPTO_secure_malloc_init(size_t sz, size_t minsize);
|
||||||
int CRYPTO_secure_malloc_done(void);
|
int CRYPTO_secure_malloc_done(void);
|
||||||
OSSL_CRYPTO_ALLOC void *CRYPTO_secure_malloc(size_t num, const char *file, int line);
|
OSSL_CRYPTO_ALLOC void *CRYPTO_secure_malloc(size_t num, const char *file, int line);
|
||||||
OSSL_CRYPTO_ALLOC void *CRYPTO_secure_zalloc(size_t num, const char *file, int line);
|
OSSL_CRYPTO_ALLOC void *CRYPTO_secure_zalloc(size_t num, const char *file, int line);
|
||||||
OSSL_CRYPTO_ALLOC void *CRYPTO_secure_malloc_array(size_t num, size_t size,
|
|
||||||
const char *file, int line);
|
|
||||||
OSSL_CRYPTO_ALLOC void *CRYPTO_secure_calloc(size_t num, size_t size,
|
|
||||||
const char *file, int line);
|
|
||||||
void CRYPTO_secure_free(void *ptr, const char *file, int line);
|
void CRYPTO_secure_free(void *ptr, const char *file, int line);
|
||||||
void CRYPTO_secure_clear_free(void *ptr, size_t num,
|
void CRYPTO_secure_clear_free(void *ptr, size_t num,
|
||||||
const char *file, int line);
|
const char *file, int line);
|
||||||
|
|||||||
+2
-2
@@ -54,7 +54,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(SCT, SCT, SCT)
|
|||||||
#define sk_SCT_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SCT_sk_type(sk), ossl_check_SCT_type(ptr))
|
#define sk_SCT_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_SCT_sk_type(sk), ossl_check_SCT_type(ptr))
|
||||||
#define sk_SCT_pop(sk) ((SCT *)OPENSSL_sk_pop(ossl_check_SCT_sk_type(sk)))
|
#define sk_SCT_pop(sk) ((SCT *)OPENSSL_sk_pop(ossl_check_SCT_sk_type(sk)))
|
||||||
#define sk_SCT_shift(sk) ((SCT *)OPENSSL_sk_shift(ossl_check_SCT_sk_type(sk)))
|
#define sk_SCT_shift(sk) ((SCT *)OPENSSL_sk_shift(ossl_check_SCT_sk_type(sk)))
|
||||||
#define sk_SCT_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SCT_sk_type(sk), ossl_check_SCT_freefunc_type(freefunc))
|
#define sk_SCT_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_SCT_sk_type(sk),ossl_check_SCT_freefunc_type(freefunc))
|
||||||
#define sk_SCT_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SCT_sk_type(sk), ossl_check_SCT_type(ptr), (idx))
|
#define sk_SCT_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_SCT_sk_type(sk), ossl_check_SCT_type(ptr), (idx))
|
||||||
#define sk_SCT_set(sk, idx, ptr) ((SCT *)OPENSSL_sk_set(ossl_check_SCT_sk_type(sk), (idx), ossl_check_SCT_type(ptr)))
|
#define sk_SCT_set(sk, idx, ptr) ((SCT *)OPENSSL_sk_set(ossl_check_SCT_sk_type(sk), (idx), ossl_check_SCT_type(ptr)))
|
||||||
#define sk_SCT_find(sk, ptr) OPENSSL_sk_find(ossl_check_SCT_sk_type(sk), ossl_check_SCT_type(ptr))
|
#define sk_SCT_find(sk, ptr) OPENSSL_sk_find(ossl_check_SCT_sk_type(sk), ossl_check_SCT_type(ptr))
|
||||||
@@ -80,7 +80,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(CTLOG, CTLOG, CTLOG)
|
|||||||
#define sk_CTLOG_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_CTLOG_sk_type(sk), ossl_check_CTLOG_type(ptr))
|
#define sk_CTLOG_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_CTLOG_sk_type(sk), ossl_check_CTLOG_type(ptr))
|
||||||
#define sk_CTLOG_pop(sk) ((CTLOG *)OPENSSL_sk_pop(ossl_check_CTLOG_sk_type(sk)))
|
#define sk_CTLOG_pop(sk) ((CTLOG *)OPENSSL_sk_pop(ossl_check_CTLOG_sk_type(sk)))
|
||||||
#define sk_CTLOG_shift(sk) ((CTLOG *)OPENSSL_sk_shift(ossl_check_CTLOG_sk_type(sk)))
|
#define sk_CTLOG_shift(sk) ((CTLOG *)OPENSSL_sk_shift(ossl_check_CTLOG_sk_type(sk)))
|
||||||
#define sk_CTLOG_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_CTLOG_sk_type(sk), ossl_check_CTLOG_freefunc_type(freefunc))
|
#define sk_CTLOG_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_CTLOG_sk_type(sk),ossl_check_CTLOG_freefunc_type(freefunc))
|
||||||
#define sk_CTLOG_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_CTLOG_sk_type(sk), ossl_check_CTLOG_type(ptr), (idx))
|
#define sk_CTLOG_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_CTLOG_sk_type(sk), ossl_check_CTLOG_type(ptr), (idx))
|
||||||
#define sk_CTLOG_set(sk, idx, ptr) ((CTLOG *)OPENSSL_sk_set(ossl_check_CTLOG_sk_type(sk), (idx), ossl_check_CTLOG_type(ptr)))
|
#define sk_CTLOG_set(sk, idx, ptr) ((CTLOG *)OPENSSL_sk_set(ossl_check_CTLOG_sk_type(sk), (idx), ossl_check_CTLOG_type(ptr)))
|
||||||
#define sk_CTLOG_find(sk, ptr) OPENSSL_sk_find(ossl_check_CTLOG_sk_type(sk), ossl_check_CTLOG_type(ptr))
|
#define sk_CTLOG_find(sk, ptr) OPENSSL_sk_find(ossl_check_CTLOG_sk_type(sk), ossl_check_CTLOG_type(ptr))
|
||||||
|
|||||||
+2
-2
@@ -46,7 +46,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(ESS_CERT_ID, ESS_CERT_ID, ESS_CERT_ID)
|
|||||||
#define sk_ESS_CERT_ID_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr))
|
#define sk_ESS_CERT_ID_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr))
|
||||||
#define sk_ESS_CERT_ID_pop(sk) ((ESS_CERT_ID *)OPENSSL_sk_pop(ossl_check_ESS_CERT_ID_sk_type(sk)))
|
#define sk_ESS_CERT_ID_pop(sk) ((ESS_CERT_ID *)OPENSSL_sk_pop(ossl_check_ESS_CERT_ID_sk_type(sk)))
|
||||||
#define sk_ESS_CERT_ID_shift(sk) ((ESS_CERT_ID *)OPENSSL_sk_shift(ossl_check_ESS_CERT_ID_sk_type(sk)))
|
#define sk_ESS_CERT_ID_shift(sk) ((ESS_CERT_ID *)OPENSSL_sk_shift(ossl_check_ESS_CERT_ID_sk_type(sk)))
|
||||||
#define sk_ESS_CERT_ID_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_freefunc_type(freefunc))
|
#define sk_ESS_CERT_ID_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ESS_CERT_ID_sk_type(sk),ossl_check_ESS_CERT_ID_freefunc_type(freefunc))
|
||||||
#define sk_ESS_CERT_ID_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr), (idx))
|
#define sk_ESS_CERT_ID_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr), (idx))
|
||||||
#define sk_ESS_CERT_ID_set(sk, idx, ptr) ((ESS_CERT_ID *)OPENSSL_sk_set(ossl_check_ESS_CERT_ID_sk_type(sk), (idx), ossl_check_ESS_CERT_ID_type(ptr)))
|
#define sk_ESS_CERT_ID_set(sk, idx, ptr) ((ESS_CERT_ID *)OPENSSL_sk_set(ossl_check_ESS_CERT_ID_sk_type(sk), (idx), ossl_check_ESS_CERT_ID_type(ptr)))
|
||||||
#define sk_ESS_CERT_ID_find(sk, ptr) OPENSSL_sk_find(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr))
|
#define sk_ESS_CERT_ID_find(sk, ptr) OPENSSL_sk_find(ossl_check_ESS_CERT_ID_sk_type(sk), ossl_check_ESS_CERT_ID_type(ptr))
|
||||||
@@ -78,7 +78,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(ESS_CERT_ID_V2, ESS_CERT_ID_V2, ESS_CERT_ID_V2)
|
|||||||
#define sk_ESS_CERT_ID_V2_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr))
|
#define sk_ESS_CERT_ID_V2_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr))
|
||||||
#define sk_ESS_CERT_ID_V2_pop(sk) ((ESS_CERT_ID_V2 *)OPENSSL_sk_pop(ossl_check_ESS_CERT_ID_V2_sk_type(sk)))
|
#define sk_ESS_CERT_ID_V2_pop(sk) ((ESS_CERT_ID_V2 *)OPENSSL_sk_pop(ossl_check_ESS_CERT_ID_V2_sk_type(sk)))
|
||||||
#define sk_ESS_CERT_ID_V2_shift(sk) ((ESS_CERT_ID_V2 *)OPENSSL_sk_shift(ossl_check_ESS_CERT_ID_V2_sk_type(sk)))
|
#define sk_ESS_CERT_ID_V2_shift(sk) ((ESS_CERT_ID_V2 *)OPENSSL_sk_shift(ossl_check_ESS_CERT_ID_V2_sk_type(sk)))
|
||||||
#define sk_ESS_CERT_ID_V2_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_freefunc_type(freefunc))
|
#define sk_ESS_CERT_ID_V2_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ESS_CERT_ID_V2_sk_type(sk),ossl_check_ESS_CERT_ID_V2_freefunc_type(freefunc))
|
||||||
#define sk_ESS_CERT_ID_V2_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr), (idx))
|
#define sk_ESS_CERT_ID_V2_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr), (idx))
|
||||||
#define sk_ESS_CERT_ID_V2_set(sk, idx, ptr) ((ESS_CERT_ID_V2 *)OPENSSL_sk_set(ossl_check_ESS_CERT_ID_V2_sk_type(sk), (idx), ossl_check_ESS_CERT_ID_V2_type(ptr)))
|
#define sk_ESS_CERT_ID_V2_set(sk, idx, ptr) ((ESS_CERT_ID_V2 *)OPENSSL_sk_set(ossl_check_ESS_CERT_ID_V2_sk_type(sk), (idx), ossl_check_ESS_CERT_ID_V2_type(ptr)))
|
||||||
#define sk_ESS_CERT_ID_V2_find(sk, ptr) OPENSSL_sk_find(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr))
|
#define sk_ESS_CERT_ID_V2_find(sk, ptr) OPENSSL_sk_find(ossl_check_ESS_CERT_ID_V2_sk_type(sk), ossl_check_ESS_CERT_ID_V2_type(ptr))
|
||||||
|
|||||||
+17
-52
@@ -376,7 +376,6 @@ OSSL_DEPRECATEDIN_3_0 int
|
|||||||
/* For supplementary wrap cipher support */
|
/* For supplementary wrap cipher support */
|
||||||
# define EVP_CIPH_FLAG_GET_WRAP_CIPHER 0x4000000
|
# define EVP_CIPH_FLAG_GET_WRAP_CIPHER 0x4000000
|
||||||
# define EVP_CIPH_FLAG_INVERSE_CIPHER 0x8000000
|
# define EVP_CIPH_FLAG_INVERSE_CIPHER 0x8000000
|
||||||
# define EVP_CIPH_FLAG_ENC_THEN_MAC 0x10000000
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cipher context flag to indicate we can handle wrap mode: if allowed in
|
* Cipher context flag to indicate we can handle wrap mode: if allowed in
|
||||||
@@ -519,40 +518,33 @@ typedef int (EVP_PBE_KEYGEN_EX) (EVP_CIPHER_CTX *ctx, const char *pass,
|
|||||||
int en_de, OSSL_LIB_CTX *libctx, const char *propq);
|
int en_de, OSSL_LIB_CTX *libctx, const char *propq);
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_DEPRECATED_3_0
|
# ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||||
# define EVP_PKEY_assign_RSA(pkey, rsa) EVP_PKEY_assign((pkey), EVP_PKEY_RSA, \
|
# define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
|
||||||
(rsa))
|
(rsa))
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_DEPRECATED_3_6
|
|
||||||
# ifndef OPENSSL_NO_DSA
|
# ifndef OPENSSL_NO_DSA
|
||||||
# define EVP_PKEY_assign_DSA(pkey, dsa) EVP_PKEY_assign((pkey), EVP_PKEY_DSA, \
|
# define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\
|
||||||
(dsa))
|
(dsa))
|
||||||
# endif
|
# endif
|
||||||
# endif
|
|
||||||
|
|
||||||
# if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0)
|
# if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0)
|
||||||
# define EVP_PKEY_assign_DH(pkey, dh) EVP_PKEY_assign((pkey), EVP_PKEY_DH, (dh))
|
# define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,(dh))
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_DEPRECATED_3_0
|
# ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||||
# ifndef OPENSSL_NO_EC
|
# ifndef OPENSSL_NO_EC
|
||||||
# define EVP_PKEY_assign_EC_KEY(pkey, eckey) EVP_PKEY_assign((pkey), \
|
# define EVP_PKEY_assign_EC_KEY(pkey,eckey) \
|
||||||
EVP_PKEY_EC, \
|
EVP_PKEY_assign((pkey), EVP_PKEY_EC, (eckey))
|
||||||
(eckey))
|
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# ifndef OPENSSL_NO_DEPRECATED_3_6
|
|
||||||
# ifndef OPENSSL_NO_SIPHASH
|
# ifndef OPENSSL_NO_SIPHASH
|
||||||
# define EVP_PKEY_assign_SIPHASH(pkey, shkey) EVP_PKEY_assign((pkey), \
|
# define EVP_PKEY_assign_SIPHASH(pkey,shkey) EVP_PKEY_assign((pkey),\
|
||||||
EVP_PKEY_SIPHASH, \
|
EVP_PKEY_SIPHASH,(shkey))
|
||||||
(shkey))
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_POLY1305
|
# ifndef OPENSSL_NO_POLY1305
|
||||||
# define EVP_PKEY_assign_POLY1305(pkey, polykey) EVP_PKEY_assign((pkey), \
|
# define EVP_PKEY_assign_POLY1305(pkey,polykey) EVP_PKEY_assign((pkey),\
|
||||||
EVP_PKEY_POLY1305, \
|
EVP_PKEY_POLY1305,(polykey))
|
||||||
(polykey))
|
|
||||||
# endif
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
/* Add some extra combinations */
|
/* Add some extra combinations */
|
||||||
@@ -1378,7 +1370,6 @@ int EVP_PKEY_get_bits(const EVP_PKEY *pkey);
|
|||||||
# define EVP_PKEY_bits EVP_PKEY_get_bits
|
# define EVP_PKEY_bits EVP_PKEY_get_bits
|
||||||
int EVP_PKEY_get_security_bits(const EVP_PKEY *pkey);
|
int EVP_PKEY_get_security_bits(const EVP_PKEY *pkey);
|
||||||
# define EVP_PKEY_security_bits EVP_PKEY_get_security_bits
|
# define EVP_PKEY_security_bits EVP_PKEY_get_security_bits
|
||||||
int EVP_PKEY_get_security_category(const EVP_PKEY *pkey);
|
|
||||||
int EVP_PKEY_get_size(const EVP_PKEY *pkey);
|
int EVP_PKEY_get_size(const EVP_PKEY *pkey);
|
||||||
# define EVP_PKEY_size EVP_PKEY_get_size
|
# define EVP_PKEY_size EVP_PKEY_get_size
|
||||||
int EVP_PKEY_can_sign(const EVP_PKEY *pkey);
|
int EVP_PKEY_can_sign(const EVP_PKEY *pkey);
|
||||||
@@ -1466,7 +1457,6 @@ EVP_PKEY *d2i_AutoPrivateKey_ex(EVP_PKEY **a, const unsigned char **pp,
|
|||||||
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
|
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
|
||||||
long length);
|
long length);
|
||||||
int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp);
|
int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp);
|
||||||
int i2d_PKCS8PrivateKey(const EVP_PKEY *a, unsigned char **pp);
|
|
||||||
|
|
||||||
int i2d_KeyParams(const EVP_PKEY *a, unsigned char **pp);
|
int i2d_KeyParams(const EVP_PKEY *a, unsigned char **pp);
|
||||||
EVP_PKEY *d2i_KeyParams(int type, EVP_PKEY **a, const unsigned char **pp,
|
EVP_PKEY *d2i_KeyParams(int type, EVP_PKEY **a, const unsigned char **pp,
|
||||||
@@ -1625,30 +1615,25 @@ int EVP_PBE_get(int *ptype, int *ppbe_nid, size_t num);
|
|||||||
# define ASN1_PKEY_CTRL_GET1_TLS_ENCPT 0xa
|
# define ASN1_PKEY_CTRL_GET1_TLS_ENCPT 0xa
|
||||||
# define ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED 0xb
|
# define ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED 0xb
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_DEPRECATED_3_6
|
int EVP_PKEY_asn1_get_count(void);
|
||||||
OSSL_DEPRECATEDIN_3_6 int EVP_PKEY_asn1_get_count(void);
|
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);
|
||||||
OSSL_DEPRECATEDIN_3_6 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);
|
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type);
|
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type);
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
|
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
|
||||||
const char *str, int len);
|
const char *str, int len);
|
||||||
OSSL_DEPRECATEDIN_3_6 int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth);
|
int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth);
|
||||||
OSSL_DEPRECATEDIN_3_6 int EVP_PKEY_asn1_add_alias(int to, int from);
|
int EVP_PKEY_asn1_add_alias(int to, int from);
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *pkey_base_id,
|
int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *pkey_base_id,
|
||||||
int *ppkey_flags, const char **pinfo,
|
int *ppkey_flags, const char **pinfo,
|
||||||
const char **ppem_str,
|
const char **ppem_str,
|
||||||
const EVP_PKEY_ASN1_METHOD *ameth);
|
const EVP_PKEY_ASN1_METHOD *ameth);
|
||||||
|
|
||||||
OSSL_DEPRECATEDIN_3_6 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey);
|
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey);
|
||||||
OSSL_DEPRECATEDIN_3_6 EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
|
EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
|
||||||
const char *pem_str,
|
const char *pem_str,
|
||||||
const char *info);
|
const char *info);
|
||||||
OSSL_DEPRECATEDIN_3_6 void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
|
void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
|
||||||
const EVP_PKEY_ASN1_METHOD *src);
|
const EVP_PKEY_ASN1_METHOD *src);
|
||||||
OSSL_DEPRECATEDIN_3_6 void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth);
|
void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth);
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*pub_decode) (EVP_PKEY *pk,
|
int (*pub_decode) (EVP_PKEY *pk,
|
||||||
const X509_PUBKEY *pub),
|
const X509_PUBKEY *pub),
|
||||||
@@ -1661,7 +1646,6 @@ void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
|
|||||||
int indent, ASN1_PCTX *pctx),
|
int indent, ASN1_PCTX *pctx),
|
||||||
int (*pkey_size) (const EVP_PKEY *pk),
|
int (*pkey_size) (const EVP_PKEY *pk),
|
||||||
int (*pkey_bits) (const EVP_PKEY *pk));
|
int (*pkey_bits) (const EVP_PKEY *pk));
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*priv_decode) (EVP_PKEY *pk,
|
int (*priv_decode) (EVP_PKEY *pk,
|
||||||
const PKCS8_PRIV_KEY_INFO
|
const PKCS8_PRIV_KEY_INFO
|
||||||
@@ -1672,7 +1656,6 @@ void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
|
|||||||
const EVP_PKEY *pkey,
|
const EVP_PKEY *pkey,
|
||||||
int indent,
|
int indent,
|
||||||
ASN1_PCTX *pctx));
|
ASN1_PCTX *pctx));
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*param_decode) (EVP_PKEY *pkey,
|
int (*param_decode) (EVP_PKEY *pkey,
|
||||||
const unsigned char **pder,
|
const unsigned char **pder,
|
||||||
@@ -1689,14 +1672,11 @@ void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
|
|||||||
int indent,
|
int indent,
|
||||||
ASN1_PCTX *pctx));
|
ASN1_PCTX *pctx));
|
||||||
|
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
void (*pkey_free) (EVP_PKEY *pkey));
|
void (*pkey_free) (EVP_PKEY *pkey));
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*pkey_ctrl) (EVP_PKEY *pkey, int op,
|
int (*pkey_ctrl) (EVP_PKEY *pkey, int op,
|
||||||
long arg1, void *arg2));
|
long arg1, void *arg2));
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*item_verify) (EVP_MD_CTX *ctx,
|
int (*item_verify) (EVP_MD_CTX *ctx,
|
||||||
const ASN1_ITEM *it,
|
const ASN1_ITEM *it,
|
||||||
@@ -1711,51 +1691,41 @@ void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
|
|||||||
X509_ALGOR *alg2,
|
X509_ALGOR *alg2,
|
||||||
ASN1_BIT_STRING *sig));
|
ASN1_BIT_STRING *sig));
|
||||||
|
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_siginf(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_siginf(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*siginf_set) (X509_SIG_INFO *siginf,
|
int (*siginf_set) (X509_SIG_INFO *siginf,
|
||||||
const X509_ALGOR *alg,
|
const X509_ALGOR *alg,
|
||||||
const ASN1_STRING *sig));
|
const ASN1_STRING *sig));
|
||||||
|
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*pkey_check) (const EVP_PKEY *pk));
|
int (*pkey_check) (const EVP_PKEY *pk));
|
||||||
|
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*pkey_pub_check) (const EVP_PKEY *pk));
|
int (*pkey_pub_check) (const EVP_PKEY *pk));
|
||||||
|
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*pkey_param_check) (const EVP_PKEY *pk));
|
int (*pkey_param_check) (const EVP_PKEY *pk));
|
||||||
|
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_set_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_set_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*set_priv_key) (EVP_PKEY *pk,
|
int (*set_priv_key) (EVP_PKEY *pk,
|
||||||
const unsigned char
|
const unsigned char
|
||||||
*priv,
|
*priv,
|
||||||
size_t len));
|
size_t len));
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_set_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_set_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*set_pub_key) (EVP_PKEY *pk,
|
int (*set_pub_key) (EVP_PKEY *pk,
|
||||||
const unsigned char *pub,
|
const unsigned char *pub,
|
||||||
size_t len));
|
size_t len));
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*get_priv_key) (const EVP_PKEY *pk,
|
int (*get_priv_key) (const EVP_PKEY *pk,
|
||||||
unsigned char *priv,
|
unsigned char *priv,
|
||||||
size_t *len));
|
size_t *len));
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*get_pub_key) (const EVP_PKEY *pk,
|
int (*get_pub_key) (const EVP_PKEY *pk,
|
||||||
unsigned char *pub,
|
unsigned char *pub,
|
||||||
size_t *len));
|
size_t *len));
|
||||||
|
|
||||||
OSSL_DEPRECATEDIN_3_6
|
|
||||||
void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
|
void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
|
||||||
int (*pkey_security_bits) (const EVP_PKEY
|
int (*pkey_security_bits) (const EVP_PKEY
|
||||||
*pk));
|
*pk));
|
||||||
# endif /* OPENSSL_NO_DEPRECATED_3_6 */
|
|
||||||
|
|
||||||
int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
|
int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
|
||||||
int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
|
int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
|
||||||
@@ -2067,9 +2037,6 @@ int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer,
|
|||||||
int validate_peer);
|
int validate_peer);
|
||||||
int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer);
|
int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer);
|
||||||
int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
|
int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
|
||||||
EVP_SKEY *EVP_PKEY_derive_SKEY(EVP_PKEY_CTX *ctx, EVP_SKEYMGMT *mgmt,
|
|
||||||
const char *key_type, const char *propquery,
|
|
||||||
size_t keylen, const OSSL_PARAM params[]);
|
|
||||||
|
|
||||||
int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
|
int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
|
||||||
int EVP_PKEY_auth_encapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpriv,
|
int EVP_PKEY_auth_encapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpriv,
|
||||||
@@ -2325,8 +2292,6 @@ EVP_SKEY *EVP_SKEY_generate(OSSL_LIB_CTX *libctx, const char *skeymgmtname,
|
|||||||
EVP_SKEY *EVP_SKEY_import_raw_key(OSSL_LIB_CTX *libctx, const char *skeymgmtname,
|
EVP_SKEY *EVP_SKEY_import_raw_key(OSSL_LIB_CTX *libctx, const char *skeymgmtname,
|
||||||
unsigned char *key, size_t keylen,
|
unsigned char *key, size_t keylen,
|
||||||
const char *propquery);
|
const char *propquery);
|
||||||
EVP_SKEY *EVP_SKEY_import_SKEYMGMT(OSSL_LIB_CTX *libctx, EVP_SKEYMGMT *skeymgmt,
|
|
||||||
int selection, const OSSL_PARAM *params);
|
|
||||||
int EVP_SKEY_get0_raw_key(const EVP_SKEY *skey, const unsigned char **key,
|
int EVP_SKEY_get0_raw_key(const EVP_SKEY *skey, const unsigned char **key,
|
||||||
size_t *len);
|
size_t *len);
|
||||||
const char *EVP_SKEY_get0_key_id(const EVP_SKEY *skey);
|
const char *EVP_SKEY_get0_key_id(const EVP_SKEY *skey);
|
||||||
|
|||||||
+1
-5
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
* this file except in compliance with the License. You can obtain a copy
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@@ -43,10 +43,6 @@ void EVP_KDF_CTX_reset(EVP_KDF_CTX *ctx);
|
|||||||
size_t EVP_KDF_CTX_get_kdf_size(EVP_KDF_CTX *ctx);
|
size_t EVP_KDF_CTX_get_kdf_size(EVP_KDF_CTX *ctx);
|
||||||
int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen,
|
int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen,
|
||||||
const OSSL_PARAM params[]);
|
const OSSL_PARAM params[]);
|
||||||
int EVP_KDF_CTX_set_SKEY(EVP_KDF_CTX *ctx, EVP_SKEY *key, const char *paramname);
|
|
||||||
EVP_SKEY *EVP_KDF_derive_SKEY(EVP_KDF_CTX *ctx, EVP_SKEYMGMT *mgmt,
|
|
||||||
const char *key_type, const char *propquery,
|
|
||||||
size_t keylen, const OSSL_PARAM params[]);
|
|
||||||
int EVP_KDF_get_params(EVP_KDF *kdf, OSSL_PARAM params[]);
|
int EVP_KDF_get_params(EVP_KDF *kdf, OSSL_PARAM params[]);
|
||||||
int EVP_KDF_CTX_get_params(EVP_KDF_CTX *ctx, OSSL_PARAM params[]);
|
int EVP_KDF_CTX_get_params(EVP_KDF_CTX *ctx, OSSL_PARAM params[]);
|
||||||
int EVP_KDF_CTX_set_params(EVP_KDF_CTX *ctx, const OSSL_PARAM params[]);
|
int EVP_KDF_CTX_set_params(EVP_KDF_CTX *ctx, const OSSL_PARAM params[]);
|
||||||
|
|||||||
+1
-13
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
* this file except in compliance with the License. You can obtain a copy
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
@@ -169,7 +169,6 @@
|
|||||||
* 'no-deprecated'.
|
* 'no-deprecated'.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# undef OPENSSL_NO_DEPRECATED_3_6
|
|
||||||
# undef OPENSSL_NO_DEPRECATED_3_4
|
# undef OPENSSL_NO_DEPRECATED_3_4
|
||||||
# undef OPENSSL_NO_DEPRECATED_3_1
|
# undef OPENSSL_NO_DEPRECATED_3_1
|
||||||
# undef OPENSSL_NO_DEPRECATED_3_0
|
# undef OPENSSL_NO_DEPRECATED_3_0
|
||||||
@@ -180,17 +179,6 @@
|
|||||||
# undef OPENSSL_NO_DEPRECATED_1_0_0
|
# undef OPENSSL_NO_DEPRECATED_1_0_0
|
||||||
# undef OPENSSL_NO_DEPRECATED_0_9_8
|
# undef OPENSSL_NO_DEPRECATED_0_9_8
|
||||||
|
|
||||||
# if OPENSSL_API_LEVEL >= 30600
|
|
||||||
# ifndef OPENSSL_NO_DEPRECATED
|
|
||||||
# define OSSL_DEPRECATEDIN_3_6 OSSL_DEPRECATED(3.6)
|
|
||||||
# define OSSL_DEPRECATEDIN_3_6_FOR(msg) OSSL_DEPRECATED_FOR(3.6, msg)
|
|
||||||
# else
|
|
||||||
# define OPENSSL_NO_DEPRECATED_3_6
|
|
||||||
# endif
|
|
||||||
# else
|
|
||||||
# define OSSL_DEPRECATEDIN_3_6
|
|
||||||
# define OSSL_DEPRECATEDIN_3_6_FOR(msg)
|
|
||||||
# endif
|
|
||||||
# if OPENSSL_API_LEVEL >= 30500
|
# if OPENSSL_API_LEVEL >= 30500
|
||||||
# ifndef OPENSSL_NO_DEPRECATED
|
# ifndef OPENSSL_NO_DEPRECATED
|
||||||
# define OSSL_DEPRECATEDIN_3_5 OSSL_DEPRECATED(3.5)
|
# define OSSL_DEPRECATEDIN_3_5 OSSL_DEPRECATED(3.5)
|
||||||
|
|||||||
-59
@@ -778,10 +778,6 @@
|
|||||||
#define NID_id_smime_cti 195
|
#define NID_id_smime_cti 195
|
||||||
#define OBJ_id_smime_cti OBJ_SMIME,6L
|
#define OBJ_id_smime_cti OBJ_SMIME,6L
|
||||||
|
|
||||||
#define SN_id_smime_ori "id-smime-ori"
|
|
||||||
#define NID_id_smime_ori 1499
|
|
||||||
#define OBJ_id_smime_ori OBJ_SMIME,13L
|
|
||||||
|
|
||||||
#define SN_id_smime_mod_cms "id-smime-mod-cms"
|
#define SN_id_smime_mod_cms "id-smime-mod-cms"
|
||||||
#define NID_id_smime_mod_cms 196
|
#define NID_id_smime_mod_cms 196
|
||||||
#define OBJ_id_smime_mod_cms OBJ_id_smime_mod,1L
|
#define OBJ_id_smime_mod_cms OBJ_id_smime_mod,1L
|
||||||
@@ -1066,21 +1062,6 @@
|
|||||||
#define NID_id_alg_PWRI_KEK 893
|
#define NID_id_alg_PWRI_KEK 893
|
||||||
#define OBJ_id_alg_PWRI_KEK OBJ_id_smime_alg,9L
|
#define OBJ_id_alg_PWRI_KEK OBJ_id_smime_alg,9L
|
||||||
|
|
||||||
#define SN_HKDF_SHA256 "id-alg-hkdf-with-sha256"
|
|
||||||
#define LN_HKDF_SHA256 "HKDF-SHA256"
|
|
||||||
#define NID_HKDF_SHA256 1496
|
|
||||||
#define OBJ_HKDF_SHA256 OBJ_id_smime_alg,28L
|
|
||||||
|
|
||||||
#define SN_HKDF_SHA384 "id-alg-hkdf-with-sha384"
|
|
||||||
#define LN_HKDF_SHA384 "HKDF-SHA384"
|
|
||||||
#define NID_HKDF_SHA384 1497
|
|
||||||
#define OBJ_HKDF_SHA384 OBJ_id_smime_alg,29L
|
|
||||||
|
|
||||||
#define SN_HKDF_SHA512 "id-alg-hkdf-with-sha512"
|
|
||||||
#define LN_HKDF_SHA512 "HKDF-SHA512"
|
|
||||||
#define NID_HKDF_SHA512 1498
|
|
||||||
#define OBJ_HKDF_SHA512 OBJ_id_smime_alg,30L
|
|
||||||
|
|
||||||
#define SN_id_smime_cd_ldap "id-smime-cd-ldap"
|
#define SN_id_smime_cd_ldap "id-smime-cd-ldap"
|
||||||
#define NID_id_smime_cd_ldap 248
|
#define NID_id_smime_cd_ldap 248
|
||||||
#define OBJ_id_smime_cd_ldap OBJ_id_smime_cd,1L
|
#define OBJ_id_smime_cd_ldap OBJ_id_smime_cd,1L
|
||||||
@@ -1117,10 +1098,6 @@
|
|||||||
#define NID_id_smime_cti_ets_proofOfCreation 256
|
#define NID_id_smime_cti_ets_proofOfCreation 256
|
||||||
#define OBJ_id_smime_cti_ets_proofOfCreation OBJ_id_smime_cti,6L
|
#define OBJ_id_smime_cti_ets_proofOfCreation OBJ_id_smime_cti,6L
|
||||||
|
|
||||||
#define SN_id_smime_ori_kem "id-smime-ori-kem"
|
|
||||||
#define NID_id_smime_ori_kem 1500
|
|
||||||
#define OBJ_id_smime_ori_kem OBJ_id_smime_ori,3L
|
|
||||||
|
|
||||||
#define LN_friendlyName "friendlyName"
|
#define LN_friendlyName "friendlyName"
|
||||||
#define NID_friendlyName 156
|
#define NID_friendlyName 156
|
||||||
#define OBJ_friendlyName OBJ_pkcs9,20L
|
#define OBJ_friendlyName OBJ_pkcs9,20L
|
||||||
@@ -5481,42 +5458,6 @@
|
|||||||
#define LN_chacha20 "chacha20"
|
#define LN_chacha20 "chacha20"
|
||||||
#define NID_chacha20 1019
|
#define NID_chacha20 1019
|
||||||
|
|
||||||
#define SN_aes_128_cbc_hmac_sha1_etm "AES-128-CBC-HMAC-SHA1-ETM"
|
|
||||||
#define LN_aes_128_cbc_hmac_sha1_etm "aes-128-cbc-hmac-sha1-etm"
|
|
||||||
#define NID_aes_128_cbc_hmac_sha1_etm 1487
|
|
||||||
|
|
||||||
#define SN_aes_192_cbc_hmac_sha1_etm "AES-192-CBC-HMAC-SHA1-ETM"
|
|
||||||
#define LN_aes_192_cbc_hmac_sha1_etm "aes-192-cbc-hmac-sha1-etm"
|
|
||||||
#define NID_aes_192_cbc_hmac_sha1_etm 1488
|
|
||||||
|
|
||||||
#define SN_aes_256_cbc_hmac_sha1_etm "AES-256-CBC-HMAC-SHA1-ETM"
|
|
||||||
#define LN_aes_256_cbc_hmac_sha1_etm "aes-256-cbc-hmac-sha1-etm"
|
|
||||||
#define NID_aes_256_cbc_hmac_sha1_etm 1489
|
|
||||||
|
|
||||||
#define SN_aes_128_cbc_hmac_sha256_etm "AES-128-CBC-HMAC-SHA256-ETM"
|
|
||||||
#define LN_aes_128_cbc_hmac_sha256_etm "aes-128-cbc-hmac-sha256-etm"
|
|
||||||
#define NID_aes_128_cbc_hmac_sha256_etm 1490
|
|
||||||
|
|
||||||
#define SN_aes_192_cbc_hmac_sha256_etm "AES-192-CBC-HMAC-SHA256-ETM"
|
|
||||||
#define LN_aes_192_cbc_hmac_sha256_etm "aes-192-cbc-hmac-sha256-etm"
|
|
||||||
#define NID_aes_192_cbc_hmac_sha256_etm 1491
|
|
||||||
|
|
||||||
#define SN_aes_256_cbc_hmac_sha256_etm "AES-256-CBC-HMAC-SHA256-ETM"
|
|
||||||
#define LN_aes_256_cbc_hmac_sha256_etm "aes-256-cbc-hmac-sha256-etm"
|
|
||||||
#define NID_aes_256_cbc_hmac_sha256_etm 1492
|
|
||||||
|
|
||||||
#define SN_aes_128_cbc_hmac_sha512_etm "AES-128-CBC-HMAC-SHA512-ETM"
|
|
||||||
#define LN_aes_128_cbc_hmac_sha512_etm "aes-128-cbc-hmac-sha512-etm"
|
|
||||||
#define NID_aes_128_cbc_hmac_sha512_etm 1493
|
|
||||||
|
|
||||||
#define SN_aes_192_cbc_hmac_sha512_etm "AES-192-CBC-HMAC-SHA512-ETM"
|
|
||||||
#define LN_aes_192_cbc_hmac_sha512_etm "aes-192-cbc-hmac-sha512-etm"
|
|
||||||
#define NID_aes_192_cbc_hmac_sha512_etm 1494
|
|
||||||
|
|
||||||
#define SN_aes_256_cbc_hmac_sha512_etm "AES-256-CBC-HMAC-SHA512-ETM"
|
|
||||||
#define LN_aes_256_cbc_hmac_sha512_etm "aes-256-cbc-hmac-sha512-etm"
|
|
||||||
#define NID_aes_256_cbc_hmac_sha512_etm 1495
|
|
||||||
|
|
||||||
#define SN_dhpublicnumber "dhpublicnumber"
|
#define SN_dhpublicnumber "dhpublicnumber"
|
||||||
#define LN_dhpublicnumber "X9.42 DH"
|
#define LN_dhpublicnumber "X9.42 DH"
|
||||||
#define NID_dhpublicnumber 920
|
#define NID_dhpublicnumber 920
|
||||||
|
|||||||
+4
-4
@@ -107,7 +107,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OCSP_CERTID, OCSP_CERTID, OCSP_CERTID)
|
|||||||
#define sk_OCSP_CERTID_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OCSP_CERTID_sk_type(sk), ossl_check_OCSP_CERTID_type(ptr))
|
#define sk_OCSP_CERTID_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OCSP_CERTID_sk_type(sk), ossl_check_OCSP_CERTID_type(ptr))
|
||||||
#define sk_OCSP_CERTID_pop(sk) ((OCSP_CERTID *)OPENSSL_sk_pop(ossl_check_OCSP_CERTID_sk_type(sk)))
|
#define sk_OCSP_CERTID_pop(sk) ((OCSP_CERTID *)OPENSSL_sk_pop(ossl_check_OCSP_CERTID_sk_type(sk)))
|
||||||
#define sk_OCSP_CERTID_shift(sk) ((OCSP_CERTID *)OPENSSL_sk_shift(ossl_check_OCSP_CERTID_sk_type(sk)))
|
#define sk_OCSP_CERTID_shift(sk) ((OCSP_CERTID *)OPENSSL_sk_shift(ossl_check_OCSP_CERTID_sk_type(sk)))
|
||||||
#define sk_OCSP_CERTID_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OCSP_CERTID_sk_type(sk), ossl_check_OCSP_CERTID_freefunc_type(freefunc))
|
#define sk_OCSP_CERTID_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OCSP_CERTID_sk_type(sk),ossl_check_OCSP_CERTID_freefunc_type(freefunc))
|
||||||
#define sk_OCSP_CERTID_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OCSP_CERTID_sk_type(sk), ossl_check_OCSP_CERTID_type(ptr), (idx))
|
#define sk_OCSP_CERTID_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OCSP_CERTID_sk_type(sk), ossl_check_OCSP_CERTID_type(ptr), (idx))
|
||||||
#define sk_OCSP_CERTID_set(sk, idx, ptr) ((OCSP_CERTID *)OPENSSL_sk_set(ossl_check_OCSP_CERTID_sk_type(sk), (idx), ossl_check_OCSP_CERTID_type(ptr)))
|
#define sk_OCSP_CERTID_set(sk, idx, ptr) ((OCSP_CERTID *)OPENSSL_sk_set(ossl_check_OCSP_CERTID_sk_type(sk), (idx), ossl_check_OCSP_CERTID_type(ptr)))
|
||||||
#define sk_OCSP_CERTID_find(sk, ptr) OPENSSL_sk_find(ossl_check_OCSP_CERTID_sk_type(sk), ossl_check_OCSP_CERTID_type(ptr))
|
#define sk_OCSP_CERTID_find(sk, ptr) OPENSSL_sk_find(ossl_check_OCSP_CERTID_sk_type(sk), ossl_check_OCSP_CERTID_type(ptr))
|
||||||
@@ -133,7 +133,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OCSP_ONEREQ, OCSP_ONEREQ, OCSP_ONEREQ)
|
|||||||
#define sk_OCSP_ONEREQ_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OCSP_ONEREQ_sk_type(sk), ossl_check_OCSP_ONEREQ_type(ptr))
|
#define sk_OCSP_ONEREQ_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OCSP_ONEREQ_sk_type(sk), ossl_check_OCSP_ONEREQ_type(ptr))
|
||||||
#define sk_OCSP_ONEREQ_pop(sk) ((OCSP_ONEREQ *)OPENSSL_sk_pop(ossl_check_OCSP_ONEREQ_sk_type(sk)))
|
#define sk_OCSP_ONEREQ_pop(sk) ((OCSP_ONEREQ *)OPENSSL_sk_pop(ossl_check_OCSP_ONEREQ_sk_type(sk)))
|
||||||
#define sk_OCSP_ONEREQ_shift(sk) ((OCSP_ONEREQ *)OPENSSL_sk_shift(ossl_check_OCSP_ONEREQ_sk_type(sk)))
|
#define sk_OCSP_ONEREQ_shift(sk) ((OCSP_ONEREQ *)OPENSSL_sk_shift(ossl_check_OCSP_ONEREQ_sk_type(sk)))
|
||||||
#define sk_OCSP_ONEREQ_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OCSP_ONEREQ_sk_type(sk), ossl_check_OCSP_ONEREQ_freefunc_type(freefunc))
|
#define sk_OCSP_ONEREQ_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OCSP_ONEREQ_sk_type(sk),ossl_check_OCSP_ONEREQ_freefunc_type(freefunc))
|
||||||
#define sk_OCSP_ONEREQ_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OCSP_ONEREQ_sk_type(sk), ossl_check_OCSP_ONEREQ_type(ptr), (idx))
|
#define sk_OCSP_ONEREQ_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OCSP_ONEREQ_sk_type(sk), ossl_check_OCSP_ONEREQ_type(ptr), (idx))
|
||||||
#define sk_OCSP_ONEREQ_set(sk, idx, ptr) ((OCSP_ONEREQ *)OPENSSL_sk_set(ossl_check_OCSP_ONEREQ_sk_type(sk), (idx), ossl_check_OCSP_ONEREQ_type(ptr)))
|
#define sk_OCSP_ONEREQ_set(sk, idx, ptr) ((OCSP_ONEREQ *)OPENSSL_sk_set(ossl_check_OCSP_ONEREQ_sk_type(sk), (idx), ossl_check_OCSP_ONEREQ_type(ptr)))
|
||||||
#define sk_OCSP_ONEREQ_find(sk, ptr) OPENSSL_sk_find(ossl_check_OCSP_ONEREQ_sk_type(sk), ossl_check_OCSP_ONEREQ_type(ptr))
|
#define sk_OCSP_ONEREQ_find(sk, ptr) OPENSSL_sk_find(ossl_check_OCSP_ONEREQ_sk_type(sk), ossl_check_OCSP_ONEREQ_type(ptr))
|
||||||
@@ -173,7 +173,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OCSP_RESPID, OCSP_RESPID, OCSP_RESPID)
|
|||||||
#define sk_OCSP_RESPID_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OCSP_RESPID_sk_type(sk), ossl_check_OCSP_RESPID_type(ptr))
|
#define sk_OCSP_RESPID_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OCSP_RESPID_sk_type(sk), ossl_check_OCSP_RESPID_type(ptr))
|
||||||
#define sk_OCSP_RESPID_pop(sk) ((OCSP_RESPID *)OPENSSL_sk_pop(ossl_check_OCSP_RESPID_sk_type(sk)))
|
#define sk_OCSP_RESPID_pop(sk) ((OCSP_RESPID *)OPENSSL_sk_pop(ossl_check_OCSP_RESPID_sk_type(sk)))
|
||||||
#define sk_OCSP_RESPID_shift(sk) ((OCSP_RESPID *)OPENSSL_sk_shift(ossl_check_OCSP_RESPID_sk_type(sk)))
|
#define sk_OCSP_RESPID_shift(sk) ((OCSP_RESPID *)OPENSSL_sk_shift(ossl_check_OCSP_RESPID_sk_type(sk)))
|
||||||
#define sk_OCSP_RESPID_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OCSP_RESPID_sk_type(sk), ossl_check_OCSP_RESPID_freefunc_type(freefunc))
|
#define sk_OCSP_RESPID_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OCSP_RESPID_sk_type(sk),ossl_check_OCSP_RESPID_freefunc_type(freefunc))
|
||||||
#define sk_OCSP_RESPID_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OCSP_RESPID_sk_type(sk), ossl_check_OCSP_RESPID_type(ptr), (idx))
|
#define sk_OCSP_RESPID_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OCSP_RESPID_sk_type(sk), ossl_check_OCSP_RESPID_type(ptr), (idx))
|
||||||
#define sk_OCSP_RESPID_set(sk, idx, ptr) ((OCSP_RESPID *)OPENSSL_sk_set(ossl_check_OCSP_RESPID_sk_type(sk), (idx), ossl_check_OCSP_RESPID_type(ptr)))
|
#define sk_OCSP_RESPID_set(sk, idx, ptr) ((OCSP_RESPID *)OPENSSL_sk_set(ossl_check_OCSP_RESPID_sk_type(sk), (idx), ossl_check_OCSP_RESPID_type(ptr)))
|
||||||
#define sk_OCSP_RESPID_find(sk, ptr) OPENSSL_sk_find(ossl_check_OCSP_RESPID_sk_type(sk), ossl_check_OCSP_RESPID_type(ptr))
|
#define sk_OCSP_RESPID_find(sk, ptr) OPENSSL_sk_find(ossl_check_OCSP_RESPID_sk_type(sk), ossl_check_OCSP_RESPID_type(ptr))
|
||||||
@@ -210,7 +210,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(OCSP_SINGLERESP, OCSP_SINGLERESP, OCSP_SINGLERESP)
|
|||||||
#define sk_OCSP_SINGLERESP_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OCSP_SINGLERESP_sk_type(sk), ossl_check_OCSP_SINGLERESP_type(ptr))
|
#define sk_OCSP_SINGLERESP_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_OCSP_SINGLERESP_sk_type(sk), ossl_check_OCSP_SINGLERESP_type(ptr))
|
||||||
#define sk_OCSP_SINGLERESP_pop(sk) ((OCSP_SINGLERESP *)OPENSSL_sk_pop(ossl_check_OCSP_SINGLERESP_sk_type(sk)))
|
#define sk_OCSP_SINGLERESP_pop(sk) ((OCSP_SINGLERESP *)OPENSSL_sk_pop(ossl_check_OCSP_SINGLERESP_sk_type(sk)))
|
||||||
#define sk_OCSP_SINGLERESP_shift(sk) ((OCSP_SINGLERESP *)OPENSSL_sk_shift(ossl_check_OCSP_SINGLERESP_sk_type(sk)))
|
#define sk_OCSP_SINGLERESP_shift(sk) ((OCSP_SINGLERESP *)OPENSSL_sk_shift(ossl_check_OCSP_SINGLERESP_sk_type(sk)))
|
||||||
#define sk_OCSP_SINGLERESP_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OCSP_SINGLERESP_sk_type(sk), ossl_check_OCSP_SINGLERESP_freefunc_type(freefunc))
|
#define sk_OCSP_SINGLERESP_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_OCSP_SINGLERESP_sk_type(sk),ossl_check_OCSP_SINGLERESP_freefunc_type(freefunc))
|
||||||
#define sk_OCSP_SINGLERESP_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OCSP_SINGLERESP_sk_type(sk), ossl_check_OCSP_SINGLERESP_type(ptr), (idx))
|
#define sk_OCSP_SINGLERESP_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_OCSP_SINGLERESP_sk_type(sk), ossl_check_OCSP_SINGLERESP_type(ptr), (idx))
|
||||||
#define sk_OCSP_SINGLERESP_set(sk, idx, ptr) ((OCSP_SINGLERESP *)OPENSSL_sk_set(ossl_check_OCSP_SINGLERESP_sk_type(sk), (idx), ossl_check_OCSP_SINGLERESP_type(ptr)))
|
#define sk_OCSP_SINGLERESP_set(sk, idx, ptr) ((OCSP_SINGLERESP *)OPENSSL_sk_set(ossl_check_OCSP_SINGLERESP_sk_type(sk), (idx), ossl_check_OCSP_SINGLERESP_type(ptr)))
|
||||||
#define sk_OCSP_SINGLERESP_find(sk, ptr) OPENSSL_sk_find(ossl_check_OCSP_SINGLERESP_sk_type(sk), ossl_check_OCSP_SINGLERESP_type(ptr))
|
#define sk_OCSP_SINGLERESP_find(sk, ptr) OPENSSL_sk_find(ossl_check_OCSP_SINGLERESP_sk_type(sk), ossl_check_OCSP_SINGLERESP_type(ptr))
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user