Refine request padding.

pull/2/head
Matthew Chen 6 years ago
parent a44712ec3d
commit 415526fc9b

@ -3,6 +3,7 @@
// //
import Foundation import Foundation
import SignalCoreKit
@objc @objc
public class ContentProxy: NSObject { public class ContentProxy: NSObject {
@ -102,56 +103,25 @@ public class ContentProxy: NSObject {
} }
public class func padRequestSize(request: inout URLRequest) { public class func padRequestSize(request: inout URLRequest) {
guard let sizeEstimate: UInt = estimateRequestSize(request: request) else { // Generate 1-64 chars of padding.
owsFailDebug("Could not estimate request size.") let paddingLength: Int = 1 + Int(arc4random_uniform(64))
return let padding = self.padding(withLength: paddingLength)
} assert(padding.count == paddingLength)
// We pad the estimated size to an even multiple of paddingQuantum (plus the
// extra ": " and "\r\n"). The exact size doesn't matter so long as the
// padding is consistent.
let paddingQuantum: UInt = 1024
let paddingSize = paddingQuantum - (sizeEstimate % paddingQuantum)
let padding = String(repeating: ".", count: Int(paddingSize))
request.addValue(padding, forHTTPHeaderField: "X-SignalPadding") request.addValue(padding, forHTTPHeaderField: "X-SignalPadding")
} }
private class func estimateRequestSize(request: URLRequest) -> UInt? { private class func padding(withLength length: Int) -> String {
// iOS doesn't offer an exact way to measure request sizes on the wire, // Pick a random ASCII char in the range 48-122
// but we can reliably estimate request sizes using the "knowns", e.g. var result = ""
// HTTP method, path, querystring, headers. The "unknowns" should be // Min and max values, inclusive.
// consistent between requests. let minValue: UInt32 = 48
let maxValue: UInt32 = 122
guard let url = request.url?.absoluteString else { for _ in 1...length {
owsFailDebug("Request missing URL.") let value = minValue + arc4random_uniform(maxValue - minValue + 1)
return nil assert(value >= minValue)
} assert(value <= maxValue)
guard let components = URLComponents(string: url) else { result += String(UnicodeScalar(UInt8(value)))
owsFailDebug("Request has invalid URL.")
return nil
}
var result: Int = 0
if let httpMethod = request.httpMethod {
result += httpMethod.count
}
result += components.percentEncodedPath.count
if let percentEncodedQuery = components.percentEncodedQuery {
result += percentEncodedQuery.count
} }
if let allHTTPHeaderFields = request.allHTTPHeaderFields { return result
for (key, value) in allHTTPHeaderFields { }
// Each header has 4 extra bytes: }
//
// * Two for the key/value separator ": "
// * Two for "\r\n", the line break in the HTTP protocol spec.
result += key.count + value.count + 4
}
} else {
owsFailDebug("Request has no headers.")
}
if let httpBody = request.httpBody {
result += httpBody.count
}
return UInt(result)
}}

Loading…
Cancel
Save