Skip to content

Revert "Parity: Networking: URLUploadTask and URLDownloadTask" #2461

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 49 additions & 13 deletions Foundation/URLSession/NativeProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,12 @@ internal class _NativeProtocol: URLProtocol, _EasyHandleDelegate {
}
}

func createTransferState(url: URL, body: _Body, workQueue: DispatchQueue) -> _TransferState {
func createTransferState(url: URL, workQueue: DispatchQueue) -> _TransferState {
let drain = createTransferBodyDataDrain()
switch body {
guard let t = task else {
fatalError("Cannot create transfer state")
}
switch t.body {
case .none:
return _TransferState(url: url, bodyDataDrain: drain)
case .data(let data):
Expand All @@ -355,19 +358,22 @@ internal class _NativeProtocol: URLProtocol, _EasyHandleDelegate {

/// Start a new transfer
func startNewTransfer(with request: URLRequest) {
let task = self.task!
task.currentRequest = request
guard let t = task else {
fatalError()
}
t.currentRequest = request
guard let url = request.url else {
fatalError("No URL in request.")
}

task.getBody { (body) in
self.internalState = .transferReady(self.createTransferState(url: url, body: body, workQueue: task.workQueue))
let request = task.authRequest ?? request
self.configureEasyHandle(for: request, body: body)
if (task.suspendCount) < 1 {
self.resume()
}
self.internalState = .transferReady(createTransferState(url: url, workQueue: t.workQueue))
if let authRequest = task?.authRequest {
configureEasyHandle(for: authRequest)
} else {
configureEasyHandle(for: request)
}
if (t.suspendCount) < 1 {
resume()
}
}

Expand Down Expand Up @@ -421,7 +427,7 @@ internal class _NativeProtocol: URLProtocol, _EasyHandleDelegate {
}
}

func configureEasyHandle(for request: URLRequest, body: _Body) {
func configureEasyHandle(for: URLRequest) {
NSRequiresConcreteImplementation()
}
}
Expand Down Expand Up @@ -618,7 +624,37 @@ extension _NativeProtocol._ResponseHeaderLines {
}

internal extension _NativeProtocol {
typealias _Body = URLSessionTask._Body
enum _Body {
case none
case data(DispatchData)
/// Body data is read from the given file URL
case file(URL)
case stream(InputStream)
}
}

fileprivate extension _NativeProtocol._Body {
enum _Error : Error {
case fileForBodyDataNotFound
}

/// - Returns: The body length, or `nil` for no body (e.g. `GET` request).
func getBodyLength() throws -> UInt64? {
switch self {
case .none:
return 0
case .data(let d):
return UInt64(d.count)
/// Body data is read from the given file URL
case .file(let fileURL):
guard let s = try FileManager.default.attributesOfItem(atPath: fileURL.path)[.size] as? NSNumber else {
throw _Error.fileForBodyDataNotFound
}
return s.uint64Value
case .stream:
return nil
}
}
}

extension _NativeProtocol {
Expand Down
30 changes: 4 additions & 26 deletions Foundation/URLSession/URLSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,7 @@ open class URLSession : NSObject {
}

/* Creates an upload task with the given request. The previously set body stream of the request (if any) is ignored and the URLSession:task:needNewBodyStream: delegate will be called when the body payload is required. */
open func uploadTask(withStreamedRequest request: URLRequest) -> URLSessionUploadTask {
let r = URLSession._Request(request)
return uploadTask(with: r, body: nil, behaviour: .callDelegate)
}
open func uploadTask(withStreamedRequest request: URLRequest) -> URLSessionUploadTask { NSUnimplemented() }

/* Creates a download task with the given request. */
open func downloadTask(with request: URLRequest) -> URLSessionDownloadTask {
Expand All @@ -450,9 +447,7 @@ open class URLSession : NSObject {
}

/* Creates a download task with the resume data. If the download cannot be successfully resumed, URLSession:task:didCompleteWithError: will be called. */
open func downloadTask(withResumeData resumeData: Data) -> URLSessionDownloadTask {
return invalidDownloadTask(behavior: .callDelegate)
}
open func downloadTask(withResumeData resumeData: Data) -> URLSessionDownloadTask { NSUnimplemented() }

/* Creates a bidirectional stream task to a given host and port.
*/
Expand Down Expand Up @@ -516,7 +511,7 @@ fileprivate extension URLSession {
/// Create an upload task.
///
/// All public methods funnel into this one.
func uploadTask(with request: _Request, body: URLSessionTask._Body?, behaviour: _TaskRegistry._Behaviour) -> URLSessionUploadTask {
func uploadTask(with request: _Request, body: URLSessionTask._Body, behaviour: _TaskRegistry._Behaviour) -> URLSessionUploadTask {
guard !self.invalidated else { fatalError("Session invalidated") }
let r = createConfiguredRequest(from: request)
let i = createNextTaskIdentifier()
Expand All @@ -538,21 +533,6 @@ fileprivate extension URLSession {
}
return task
}

/// Create a download task that is marked invalid.
func invalidDownloadTask(behavior: _TaskRegistry._Behaviour) -> URLSessionDownloadTask {
/* We do not support resume data in swift-corelibs-foundation, so whatever we are passed, we should just behave as Darwin does in the presence of invalid data. */

guard !self.invalidated else { fatalError("Session invalidated") }
let task = URLSessionDownloadTask()
task.createdFromInvalidResumeData = true
task.taskIdentifier = createNextTaskIdentifier()
task.session = self
workQueue.async {
self.taskRegistry.add(task, behaviour: behavior)
}
return task
}
}


Expand Down Expand Up @@ -608,9 +588,7 @@ extension URLSession {
return downloadTask(with: _Request(url), behavior: .downloadCompletionHandler(completionHandler))
}

open func downloadTask(withResumeData resumeData: Data, completionHandler: @escaping (URL?, URLResponse?, Error?) -> Void) -> URLSessionDownloadTask {
return invalidDownloadTask(behavior: .downloadCompletionHandler(completionHandler))
}
open func downloadTask(withResumeData resumeData: Data, completionHandler: @escaping (URL?, URLResponse?, Error?) -> Void) -> URLSessionDownloadTask { NSUnimplemented() }
}

internal extension URLSession {
Expand Down
47 changes: 7 additions & 40 deletions Foundation/URLSession/URLSessionTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ open class URLSessionTask : NSObject, NSCopying {

default:
let toBeSent: Int64?
if let bodyLength = try? self.knownBody?.getBodyLength() {
if let bodyLength = try? self.body.getBodyLength() {
toBeSent = Int64(clamping: bodyLength)
} else if self.countOfBytesExpectedToSend > 0 {
toBeSent = Int64(clamping: self.countOfBytesExpectedToSend)
Expand Down Expand Up @@ -95,10 +95,9 @@ open class URLSessionTask : NSObject, NSCopying {

/// How many times the task has been suspended, 0 indicating a running task.
internal var suspendCount = 1

internal var actualSession: URLSession? { return session as? URLSession }
internal var session: URLSessionProtocol! //change to nil when task completes

internal let body: _Body

fileprivate enum ProtocolState {
case toBeCreated
case awaitingCacheReply(Bag<(URLProtocol?) -> Void>)
Expand Down Expand Up @@ -194,27 +193,6 @@ open class URLSessionTask : NSObject, NSCopying {
}
}


internal let knownBody: _Body?
func getBody(completion: @escaping (_Body) -> Void) {
if let body = knownBody {
completion(body)
return
}

if let session = actualSession, let delegate = session.delegate as? URLSessionTaskDelegate {
delegate.urlSession(session, task: self) { (stream) in
if let stream = stream {
completion(.stream(stream))
} else {
completion(.none)
}
}
} else {
completion(.none)
}
}

private let syncQ = DispatchQueue(label: "org.swift.URLSessionTask.SyncQ")
private var hasTriggeredResume: Bool = false
internal var isSuspendedAfterResume: Bool {
Expand All @@ -234,7 +212,7 @@ open class URLSessionTask : NSObject, NSCopying {
session = _MissingURLSession()
taskIdentifier = 0
originalRequest = nil
knownBody = URLSessionTask._Body.none
body = .none
workQueue = DispatchQueue(label: "URLSessionTask.notused.0")
super.init()
}
Expand All @@ -248,13 +226,13 @@ open class URLSessionTask : NSObject, NSCopying {
self.init(session: session, request: request, taskIdentifier: taskIdentifier, body: .none)
}
}
internal init(session: URLSession, request: URLRequest, taskIdentifier: Int, body: _Body?) {
internal init(session: URLSession, request: URLRequest, taskIdentifier: Int, body: _Body) {
self.session = session
/* make sure we're actually having a serial queue as it's used for synchronization */
self.workQueue = DispatchQueue.init(label: "org.swift.URLSessionTask.WorkQueue", target: session.workQueue)
self.taskIdentifier = taskIdentifier
self.originalRequest = request
self.knownBody = body
self.body = body
super.init()
self.currentRequest = request
self.progress.cancellationHandler = { [weak self] in
Expand All @@ -274,7 +252,7 @@ open class URLSessionTask : NSObject, NSCopying {
}

/// An identifier for this task, assigned by and unique to the owning session
open internal(set) var taskIdentifier: Int
open private(set) var taskIdentifier: Int

/// May be nil if this is a stream task

Expand Down Expand Up @@ -611,17 +589,6 @@ open class URLSessionUploadTask : URLSessionDataTask {
*/
open class URLSessionDownloadTask : URLSessionTask {

var createdFromInvalidResumeData = false

// If a task is created from invalid resume data, prevent attempting creation of the protocol object.
override func _getProtocol(_ callback: @escaping (URLProtocol?) -> Void) {
if createdFromInvalidResumeData {
callback(nil)
} else {
super._getProtocol(callback)
}
}

internal var fileLength = -1.0

/* Cancel the download (and calls the superclass -cancel). If
Expand Down
6 changes: 3 additions & 3 deletions Foundation/URLSession/ftp/FTPURLProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,16 @@ internal class _FTPURLProtocol: _NativeProtocol {
}
}

override func configureEasyHandle(for request: URLRequest, body: _Body) {
override func configureEasyHandle(for request: URLRequest) {
easyHandle.set(verboseModeOn: enableLibcurlDebugOutput)
easyHandle.set(debugOutputOn: enableLibcurlDebugOutput, task: task!)
easyHandle.set(skipAllSignalHandling: true)
guard let url = request.url else { fatalError("No URL in request.") }
easyHandle.set(url: url)
easyHandle.set(preferredReceiveBufferSize: Int.max)
do {
switch (body, try body.getBodyLength()) {
case (.none, _):
switch (task?.body, try task?.body.getBodyLength()) {
case (.some(URLSessionTask._Body.none), _):
set(requestBodyLength: .noBody)
case (_, .some(let length)):
set(requestBodyLength: .length(length))
Expand Down
18 changes: 7 additions & 11 deletions Foundation/URLSession/http/HTTPURLProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ internal class _HTTPURLProtocol: _NativeProtocol {
/// Set options on the easy handle to match the given request.
///
/// This performs a series of `curl_easy_setopt()` calls.
override func configureEasyHandle(for request: URLRequest, body: _Body) {
override func configureEasyHandle(for request: URLRequest) {
// At this point we will call the equivalent of curl_easy_setopt()
// to configure everything on the handle. Since we might be re-using
// a handle, we must be sure to set everything and not rely on default
Expand Down Expand Up @@ -294,8 +294,8 @@ internal class _HTTPURLProtocol: _NativeProtocol {
easyHandle.setAllowedProtocolsToHTTPAndHTTPS()
easyHandle.set(preferredReceiveBufferSize: Int.max)
do {
switch (body, try body.getBodyLength()) {
case (.none, _):
switch (task?.body, try task?.body.getBodyLength()) {
case (nil, _):
set(requestBodyLength: .noBody)
case (_, let length?):
set(requestBodyLength: .length(length))
Expand Down Expand Up @@ -509,15 +509,11 @@ fileprivate extension _HTTPURLProtocol {
/// Any header values that should be removed from the ones set by libcurl
/// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_HTTPHEADER.html
var curlHeadersToRemove: [String] {
if let task = task {
if task.knownBody == nil {
return []
} else if case .some(.none) = task.knownBody {
return []
}
if task?.body == nil {
return []
} else {
return ["Expect"]
}

return ["Expect"]
}
}

Expand Down
Loading