Skip to content

Commit d7c1668

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

19 files changed

+118
-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/NSTimeZone.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ open class NSTimeZone : NSObject, NSCopying, NSSecureCoding, NSCoding {
2929
}
3030

3131
public init?(name tzName: String, data aData: Data?) {
32+
#if os(Android)
33+
var tzName = tzName
34+
if tzName == "UTC" || tzName == "GMT" {
35+
tzName = "GMT+0000"
36+
}
37+
else if !(tzName.hasPrefix("GMT+") || tzName.hasPrefix("GMT-")) {
38+
NSLog("Time zone database not available on Android")
39+
}
40+
#endif
3241
super.init()
3342
if !_CFTimeZoneInit(_cfObject, tzName._cfObject, aData?._cfObject) {
3443
return nil
@@ -170,6 +179,14 @@ open class NSTimeZone : NSObject, NSCopying, NSSecureCoding, NSCoding {
170179
extension NSTimeZone {
171180

172181
open class var system: TimeZone {
182+
#if os(Android)
183+
var now = time(nil), info = tm()
184+
if localtime_r(&now, &info) != nil {
185+
// NOTE: this is not a real time zone but a fixed offset from GMT.
186+
// It will be incorrect outside the current daylight saving period.
187+
return TimeZone(reference: NSTimeZone(forSecondsFromGMT: info.tm_gmtoff))
188+
}
189+
#endif
173190
return CFTimeZoneCopySystem()._swiftObject
174191
}
175192

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

0 commit comments

Comments
 (0)