Skip to content

Commit 16de987

Browse files
committed
Changes required for Android port
1 parent c0ed4e8 commit 16de987

18 files changed

+101
-231
lines changed

CoreFoundation/Base.subproj/CFPlatform.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131

3232
#endif
3333

34+
#if defined(__ANDROID__)
35+
#include <linux/prctl.h>
36+
#endif
37+
3438
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS
3539
#define kCFPlatformInterfaceStringEncoding kCFStringEncodingUTF8
3640
#else
@@ -1319,6 +1323,8 @@ _CFThreadRef _CFThreadCreate(const _CFThreadAttributes attrs, void *_Nullable (*
13191323
CF_SWIFT_EXPORT void _CFThreadSetName(const char *_Nullable name) {
13201324
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
13211325
pthread_setname_np(name);
1326+
#elif defined(__ANDROID__)
1327+
prctl(PR_SET_NAME, (unsigned long) name, 0, 0, 0);
13221328
#elif DEPLOYMENT_TARGET_LINUX
13231329
pthread_setname_np(pthread_self(), name);
13241330
#endif
@@ -1327,6 +1333,8 @@ CF_SWIFT_EXPORT void _CFThreadSetName(const char *_Nullable name) {
13271333
CF_SWIFT_EXPORT int _CFThreadGetName(char *buf, int length) {
13281334
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
13291335
return pthread_getname_np(pthread_self(), buf, length);
1336+
#elif defined(__ANDROID__)
1337+
prctl(PR_GET_NAME, (unsigned long) buf, 0, 0, 0);
13301338
#elif DEPLOYMENT_TARGET_LINUX
13311339
return pthread_getname_np(pthread_self(), buf, length);
13321340
#endif

CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
#include <CoreFoundation/ForFoundationOnly.h>
2828
#include <fts.h>
2929
#include <pthread.h>
30+
#ifndef __ANDROID__
3031
#include <execinfo.h>
32+
#endif
3133

3234
_CF_EXPORT_SCOPE_BEGIN
3335

CoreFoundation/URL.subproj/CFURL.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525
#include <unistd.h>
2626
#include <sys/stat.h>
2727
#include <sys/types.h>
28-
#if __has_include(<sys/syslog.h>)
29-
#include <sys/syslog.h>
30-
#else
28+
#if DEPLOYMENT_TARGET_ANDROID
3129
#include <syslog.h>
30+
#else
31+
#include <sys/syslog.h>
3232
#endif
3333
#include <CoreFoundation/CFURLPriv.h>
3434
#endif

CoreFoundation/URL.subproj/CFURLSessionInterface.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ static CFURLSessionMultiCode MakeMultiCode(CURLMcode value) {
3131
return (CFURLSessionMultiCode) { value };
3232
}
3333

34+
const char *CFURLSessionErrorDescription(int value) {
35+
return curl_easy_strerror(value);
36+
}
3437

3538
CFURLSessionEasyHandle _Nonnull CFURLSessionEasyHandleInit() {
3639
return curl_easy_init();

CoreFoundation/URL.subproj/CFURLSessionInterface.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ typedef struct CFURLSessionEasyCode {
4848
int value;
4949
} CFURLSessionEasyCode;
5050

51+
CF_EXPORT const char * _Nonnull CFURLSessionErrorDescription(int value);
52+
5153
/// CURLcode
5254
CF_EXPORT CFURLSessionEasyCode const CFURLSessionEasyCodeOK; // CURLE_OK
5355
CF_EXPORT CFURLSessionEasyCode const CFURLSessionEasyCodeUNSUPPORTED_PROTOCOL; // CURLE_UNSUPPORTED_PROTOCOL

Foundation/Host.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ open class Host: NSObject {
6565
}
6666

6767
internal func _resolveCurrent() {
68+
#if !os(Android)
6869
var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
6970
if getifaddrs(&ifaddr) != 0 {
7071
return
@@ -88,6 +89,7 @@ open class Host: NSObject {
8889
}
8990
ifa = ifaValue.ifa_next
9091
}
92+
#endif
9193
}
9294

9395
internal func _resolve() {
@@ -138,7 +140,7 @@ open class Host: NSObject {
138140
}
139141
let sa_len: socklen_t = socklen_t((family == AF_INET6) ? MemoryLayout<sockaddr_in6>.size : MemoryLayout<sockaddr_in>.size)
140142
let lookupInfo = { (content: inout [String], flags: Int32) in
141-
if getnameinfo(info.ai_addr, sa_len, host, socklen_t(NI_MAXHOST), nil, 0, flags) == 0 {
143+
if getnameinfo(info.ai_addr, sa_len, host, numericCast(NI_MAXHOST), nil, 0, flags) == 0 {
142144
content.append(String(cString: host))
143145
}
144146
}

Foundation/NSLog.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ public func NSLogv(_ format: String, _ args: CVaListPointer) {
3333
CFLog1(kCFLogLevelWarning, message._cfObject)
3434
#else
3535
CFLog1(Int32(kCFLogLevelWarning), message._cfObject)
36+
#if os(Android)
37+
print(message)
38+
#endif
3639
#endif
3740
}
3841

Foundation/Thread.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ open class Thread : NSObject {
250250
_cancelled = true
251251
}
252252

253-
253+
#if !os(Android)
254254
private class func backtraceAddresses<T>(_ body: (UnsafeMutablePointer<UnsafeMutableRawPointer?>, Int) -> [T]) -> [T] {
255255
// Same as swift/stdlib/public/runtime/Errors.cpp backtrace
256256
let maxSupportedStackDepth = 128;
@@ -284,6 +284,15 @@ open class Thread : NSObject {
284284
return symbols
285285
})
286286
}
287+
#else
288+
open class var callStackReturnAddresses: [NSNumber] {
289+
NSUnimplemented()
290+
}
291+
292+
open class var callStackSymbols: [String] {
293+
NSUnimplemented()
294+
}
295+
#endif
287296
}
288297

289298
extension NSNotification.Name {

Foundation/URLSession/URLSessionTask.swift

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ open class URLSessionTask : NSObject, NSCopying {
3333
internal var suspendCount = 1
3434
internal var session: URLSessionProtocol! //change to nil when task completes
3535
internal let body: _Body
36-
fileprivate var _protocol: URLProtocol! = nil
36+
fileprivate var _protocol: URLProtocol? = nil
3737
private let syncQ = DispatchQueue(label: "org.swift.URLSessionTask.SyncQ")
3838

3939
/// All operations must run on this queue.
@@ -178,8 +178,8 @@ open class URLSessionTask : NSObject, NSCopying {
178178
self.workQueue.async {
179179
let urlError = URLError(_nsError: NSError(domain: NSURLErrorDomain, code: NSURLErrorCancelled, userInfo: nil))
180180
self.error = urlError
181-
self._protocol.stopLoading()
182-
self._protocol.client?.urlProtocol(self._protocol, didFailWithError: urlError)
181+
self._protocol?.stopLoading()
182+
self._protocol?.client?.urlProtocol(self._protocol!, didFailWithError: urlError)
183183
}
184184
}
185185
}
@@ -235,7 +235,7 @@ open class URLSessionTask : NSObject, NSCopying {
235235

236236
if self.suspendCount == 1 {
237237
self.workQueue.async {
238-
self._protocol.stopLoading()
238+
self._protocol?.stopLoading()
239239
}
240240
}
241241
}
@@ -250,7 +250,21 @@ open class URLSessionTask : NSObject, NSCopying {
250250
self.updateTaskState()
251251
if self.suspendCount == 0 {
252252
self.workQueue.async {
253-
self._protocol.startLoading()
253+
if let _protocol = self._protocol {
254+
_protocol.startLoading()
255+
}
256+
else if self.error == nil {
257+
var userInfo: [String: Any] = [NSLocalizedDescriptionKey: "unsupported URL"]
258+
if let url = self.originalRequest?.url {
259+
userInfo[NSURLErrorFailingURLErrorKey] = url
260+
userInfo[NSURLErrorFailingURLStringErrorKey] = url.absoluteString
261+
}
262+
let urlError = URLError(_nsError: NSError(domain: NSURLErrorDomain,
263+
code: NSURLErrorUnsupportedURL,
264+
userInfo: userInfo))
265+
self.error = urlError
266+
_ProtocolClient().urlProtocol(task: self, didFailWithError: urlError)
267+
}
254268
}
255269
}
256270
}
@@ -547,6 +561,7 @@ extension _ProtocolClient : URLProtocolClient {
547561
session.taskRegistry.remove(task)
548562
}
549563
}
564+
task._protocol = nil
550565
}
551566

552567
func urlProtocol(_ protocol: URLProtocol, didCancel challenge: URLAuthenticationChallenge) {
@@ -574,6 +589,10 @@ extension _ProtocolClient : URLProtocolClient {
574589

575590
func urlProtocol(_ protocol: URLProtocol, didFailWithError error: Error) {
576591
guard let task = `protocol`.task else { fatalError() }
592+
urlProtocol(task: task, didFailWithError: error)
593+
}
594+
595+
func urlProtocol(task: URLSessionTask, didFailWithError error: Error) {
577596
guard let session = task.session as? URLSession else { fatalError() }
578597
switch session.behaviour(for: task) {
579598
case .taskDelegate(let delegate):
@@ -602,6 +621,7 @@ extension _ProtocolClient : URLProtocolClient {
602621
session.taskRegistry.remove(task)
603622
}
604623
}
624+
task._protocol = nil
605625
}
606626

607627
func urlProtocol(_ protocol: URLProtocol, cachedResponseIsValid cachedResponse: CachedURLResponse) {

Foundation/URLSession/http/EasyHandle.swift

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,7 @@ internal final class _EasyHandle {
5656
fileprivate var headerList: _CurlStringList?
5757
fileprivate var pauseState: _PauseState = []
5858
internal var timeoutTimer: _TimeoutSource!
59-
#if os(Android)
60-
static fileprivate var _CAInfoFile: UnsafeMutablePointer<Int8>?
61-
#endif
59+
private var errorBuffer = [UInt8](repeating: 0, count: 1000)
6260

6361
init(delegate: _EasyHandleDelegate) {
6462
self.delegate = delegate
@@ -89,8 +87,8 @@ extension _EasyHandle {
8987
}
9088

9189
internal extension _EasyHandle {
92-
func completedTransfer(withErrorCode errorCode: Int?) {
93-
delegate?.transferCompleted(withErrorCode: errorCode)
90+
func completedTransfer(withErrorInfo errorInfo: URLErrorInfo?) {
91+
delegate?.transferCompleted(withErrorInfo: errorInfo)
9492
}
9593
}
9694
internal protocol _EasyHandleDelegate: class {
@@ -107,7 +105,7 @@ internal protocol _EasyHandleDelegate: class {
107105
func fill(writeBuffer buffer: UnsafeMutableBufferPointer<Int8>) -> _EasyHandle._WriteBufferResult
108106
/// The transfer for this handle completed.
109107
/// - parameter errorCode: An NSURLError code, or `nil` if no error occured.
110-
func transferCompleted(withErrorCode errorCode: Int?)
108+
func transferCompleted(withErrorInfo errorInfo: URLErrorInfo?)
111109
/// Seek the input stream to the given position
112110
func seekInputStream(to position: UInt64) throws
113111
/// Gets called during the transfer to update progress.
@@ -170,20 +168,23 @@ extension _EasyHandle {
170168
let protocols = (CFURLSessionProtocolHTTP | CFURLSessionProtocolHTTPS)
171169
try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionPROTOCOLS, protocols).asError()
172170
try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionREDIR_PROTOCOLS, protocols).asError()
173-
#if os(Android)
174-
// See https://curl.haxx.se/docs/sslcerts.html
175-
// For SSL to work you need "cacert.pem" to be accessable
176-
// at the path pointed to by the URLSessionCAInfo env var.
177-
// Downloadable here: https://curl.haxx.se/ca/cacert.pem
178-
if let caInfo = _EasyHandle._CAInfoFile {
179-
if String(cString: caInfo) == "UNSAFE_SSL_NOVERIFY" {
180-
try! CFURLSession_easy_setopt_int(rawHandle, CFURLSessionOptionSSL_VERIFYPEER, 0).asError()
181-
}
182-
else {
183-
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionCAINFO, caInfo).asError()
184-
}
171+
errorBuffer.withUnsafeMutableBufferPointer {
172+
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionERRORBUFFER, $0.baseAddress).asError()
173+
}
174+
#if os(Android)
175+
// See https://curl.haxx.se/docs/sslcerts.html
176+
// For SSL on Android you need a "cacert.pem" to be
177+
// accessible at the path pointed to by this env var.
178+
// Downloadable here: https://curl.haxx.se/ca/cacert.pem
179+
if let caInfo = getenv("URLSessionCertificateAuthorityInfoFile") {
180+
if String(cString: caInfo) == "INSECURE_SSL_NO_VERIFY" {
181+
try! CFURLSession_easy_setopt_long(rawHandle, CFURLSessionOptionSSL_VERIFYPEER, 0).asError()
185182
}
186-
#endif
183+
else {
184+
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionCAINFO, caInfo).asError()
185+
}
186+
}
187+
#endif
187188
//TODO: Added in libcurl 7.45.0
188189
//TODO: Set default protocol for schemeless URLs
189190
//CURLOPT_DEFAULT_PROTOCOL available only in libcurl 7.45.0
@@ -630,19 +631,6 @@ extension _EasyHandle._CurlStringList {
630631
}
631632
}
632633

633-
#if os(Android)
634-
extension URLSession {
635-
636-
public static func setCAInfoFile(_ _CAInfoFile: String) {
637-
free(_EasyHandle._CAInfoFile)
638-
_CAInfoFile.withCString {
639-
_EasyHandle._CAInfoFile = strdup($0)
640-
}
641-
}
642-
643-
}
644-
#endif
645-
646634
extension CFURLSessionEasyCode : Equatable {
647635
public static func ==(lhs: CFURLSessionEasyCode, rhs: CFURLSessionEasyCode) -> Bool {
648636
return lhs.value == rhs.value

Foundation/URLSession/http/HTTPURLProtocol.swift

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,21 @@ import Dispatch
1313
internal class _HTTPURLProtocol: URLProtocol {
1414

1515
fileprivate var easyHandle: _EasyHandle!
16-
fileprivate var tempFileURL: URL
16+
fileprivate lazy var tempFileURL: URL = {
17+
let fileName = NSTemporaryDirectory() + NSUUID().uuidString + ".tmp"
18+
_ = FileManager.default.createFile(atPath: fileName, contents: nil)
19+
return URL(fileURLWithPath: fileName)
20+
}()
1721

1822
public required init(task: URLSessionTask, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) {
1923
self.internalState = _InternalState.initial
20-
let fileName = NSTemporaryDirectory() + NSUUID().uuidString + ".tmp"
21-
_ = FileManager.default.createFile(atPath: fileName, contents: nil)
22-
self.tempFileURL = URL(fileURLWithPath: fileName)
2324
super.init(request: task.originalRequest!, cachedResponse: cachedResponse, client: client)
2425
self.task = task
2526
self.easyHandle = _EasyHandle(delegate: self)
2627
}
2728

2829
public required init(request: URLRequest, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) {
2930
self.internalState = _InternalState.initial
30-
let fileName = NSTemporaryDirectory() + NSUUID().uuidString + ".tmp"
31-
_ = FileManager.default.createFile(atPath: fileName, contents: nil)
32-
self.tempFileURL = URL(fileURLWithPath: fileName)
3331
super.init(request: request, cachedResponse: cachedResponse, client: client)
3432
self.easyHandle = _EasyHandle(delegate: self)
3533
}
@@ -136,7 +134,7 @@ fileprivate extension _HTTPURLProtocol {
136134
// NSURLErrorNoPermissionsToReadFile
137135
// NSURLErrorFileDoesNotExist
138136
self.internalState = .transferFailed
139-
failWith(errorCode: errorCode(fileSystemError: e), request: request)
137+
failWith(errorCode: errorCode(fileSystemError: e), errorDescription: "File system error", request: request)
140138
return
141139
}
142140

@@ -330,12 +328,13 @@ internal extension _HTTPURLProtocol {
330328
case stream(InputStream)
331329
}
332330

333-
func failWith(errorCode: Int, request: URLRequest) {
331+
func failWith(errorCode: Int, errorDescription: String?, request: URLRequest) {
334332
//TODO: Error handling
335333
let userInfo: [String : Any]? = request.url.map {
336334
[
337335
NSURLErrorFailingURLErrorKey: $0,
338336
NSURLErrorFailingURLStringErrorKey: $0.absoluteString,
337+
NSLocalizedDescriptionKey: errorDescription ?? "Unknown http error",
339338
]
340339
}
341340
let error = URLError(_nsError: NSError(domain: NSURLErrorDomain, code: errorCode, userInfo: userInfo))
@@ -530,16 +529,16 @@ extension _HTTPURLProtocol: _EasyHandleDelegate {
530529
}
531530
}
532531

533-
func transferCompleted(withErrorCode errorCode: Int?) {
532+
func transferCompleted(withErrorInfo errorInfo: URLErrorInfo?) {
534533
// At this point the transfer is complete and we can decide what to do.
535534
// If everything went well, we will simply forward the resulting data
536535
// to the delegate. But in case of redirects etc. we might send another
537536
// request.
538537
guard case .transferInProgress(let ts) = internalState else { fatalError("Transfer completed, but it wasn't in progress.") }
539538
guard let request = task?.currentRequest else { fatalError("Transfer completed, but there's no current request.") }
540-
guard errorCode == nil else {
539+
guard errorInfo == nil else {
541540
internalState = .transferFailed
542-
failWith(errorCode: errorCode!, request: request)
541+
failWith(errorCode: errorInfo!.code, errorDescription: errorInfo!.description, request: request)
543542
return
544543
}
545544

@@ -557,7 +556,7 @@ extension _HTTPURLProtocol: _EasyHandleDelegate {
557556
completeTask()
558557
case .failWithError(let errorCode):
559558
internalState = .transferFailed
560-
failWith(errorCode: errorCode, request: request)
559+
failWith(errorCode: errorCode, errorDescription: "Completion failure", request: request)
561560
case .redirectWithRequest(let newRequest):
562561
redirectFor(request: newRequest)
563562
}
@@ -575,6 +574,10 @@ extension _HTTPURLProtocol: _EasyHandleDelegate {
575574
}
576575
}
577576

577+
internal struct URLErrorInfo {
578+
let code: Int, description: String?
579+
}
580+
578581
extension _HTTPURLProtocol {
579582
/// The is independent of the public `state: URLSessionTask.State`.
580583
enum _InternalState {

0 commit comments

Comments
 (0)