Skip to content

Commit

Permalink
Added support for stream tasks in iOS 9+ and OSX 10.11+.
Browse files Browse the repository at this point in the history
  • Loading branch information
cnoon committed Aug 8, 2015
1 parent 61d6ddf commit f4a3a50
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Alamofire.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
4C812C641B535F6D0017E0BF /* root-ca-disig.cer in Resources */ = {isa = PBXBuildFile; fileRef = 4C812C5F1B535F6D0017E0BF /* root-ca-disig.cer */; };
4C812C651B535F6D0017E0BF /* testssl-expire.disig.sk.cer in Resources */ = {isa = PBXBuildFile; fileRef = 4C812C601B535F6D0017E0BF /* testssl-expire.disig.sk.cer */; };
4C812C661B535F6D0017E0BF /* testssl-expire.disig.sk.cer in Resources */ = {isa = PBXBuildFile; fileRef = 4C812C601B535F6D0017E0BF /* testssl-expire.disig.sk.cer */; };
4C83F41B1B749E0E00203445 /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C83F41A1B749E0E00203445 /* Stream.swift */; };
4C83F41C1B749E0E00203445 /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C83F41A1B749E0E00203445 /* Stream.swift */; };
4C83F41D1B749E0E00203445 /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C83F41A1B749E0E00203445 /* Stream.swift */; };
4CA028C51B7466C500C84163 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA028C41B7466C500C84163 /* ResultTests.swift */; };
4CA028C61B7466C500C84163 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA028C41B7466C500C84163 /* ResultTests.swift */; };
4CCFA79A1B2BE71600B6F460 /* URLProtocolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CCFA7991B2BE71600B6F460 /* URLProtocolTests.swift */; };
Expand Down Expand Up @@ -159,6 +162,7 @@
4C812C5E1B535F6D0017E0BF /* intermediate-ca-disig.cer */ = {isa = PBXFileReference; lastKnownFileType = file; name = "intermediate-ca-disig.cer"; path = "disig.sk/intermediate-ca-disig.cer"; sourceTree = "<group>"; };
4C812C5F1B535F6D0017E0BF /* root-ca-disig.cer */ = {isa = PBXFileReference; lastKnownFileType = file; name = "root-ca-disig.cer"; path = "disig.sk/root-ca-disig.cer"; sourceTree = "<group>"; };
4C812C601B535F6D0017E0BF /* testssl-expire.disig.sk.cer */ = {isa = PBXFileReference; lastKnownFileType = file; name = "testssl-expire.disig.sk.cer"; path = "disig.sk/testssl-expire.disig.sk.cer"; sourceTree = "<group>"; };
4C83F41A1B749E0E00203445 /* Stream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stream.swift; sourceTree = "<group>"; };
4CA028C41B7466C500C84163 /* ResultTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = "<group>"; };
4CCFA7991B2BE71600B6F460 /* URLProtocolTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLProtocolTests.swift; sourceTree = "<group>"; };
4CDE2C361AF8932A00BABAE5 /* Manager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Manager.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -374,6 +378,7 @@
4C23EB421B327C5B0090E0BC /* MultipartFormData.swift */,
4CDE2C451AF89FF300BABAE5 /* ResponseSerialization.swift */,
4C811F8C1B51856D00E0F59A /* ServerTrustPolicy.swift */,
4C83F41A1B749E0E00203445 /* Stream.swift */,
4CDE2C3F1AF89E0700BABAE5 /* Upload.swift */,
4CDE2C421AF89F0900BABAE5 /* Validation.swift */,
);
Expand Down Expand Up @@ -692,6 +697,7 @@
4DD67C251A5C590000ED2280 /* Alamofire.swift in Sources */,
4C23EB441B327C5B0090E0BC /* MultipartFormData.swift in Sources */,
4C811F8E1B51856D00E0F59A /* ServerTrustPolicy.swift in Sources */,
4C83F41C1B749E0E00203445 /* Stream.swift in Sources */,
4CDE2C3E1AF89D4900BABAE5 /* Download.swift in Sources */,
4CDE2C441AF89F0900BABAE5 /* Validation.swift in Sources */,
4C0E5BF91B673D3400816CCC /* Result.swift in Sources */,
Expand All @@ -711,6 +717,7 @@
4CEC605B1B745C9100E684F4 /* Result.swift in Sources */,
E4202FD41B667AA100C997FB /* Alamofire.swift in Sources */,
E4202FD51B667AA100C997FB /* MultipartFormData.swift in Sources */,
4C83F41D1B749E0E00203445 /* Stream.swift in Sources */,
E4202FD61B667AA100C997FB /* ServerTrustPolicy.swift in Sources */,
E4202FD71B667AA100C997FB /* Download.swift in Sources */,
E4202FD81B667AA100C997FB /* Validation.swift in Sources */,
Expand All @@ -730,6 +737,7 @@
F897FF4119AA800700AB5182 /* Alamofire.swift in Sources */,
4C23EB431B327C5B0090E0BC /* MultipartFormData.swift in Sources */,
4C811F8D1B51856D00E0F59A /* ServerTrustPolicy.swift in Sources */,
4C83F41B1B749E0E00203445 /* Stream.swift in Sources */,
4CDE2C3D1AF89D4900BABAE5 /* Download.swift in Sources */,
4CDE2C431AF89F0900BABAE5 /* Validation.swift in Sources */,
4C0E5BF81B673D3400816CCC /* Result.swift in Sources */,
Expand Down
7 changes: 7 additions & 0 deletions Source/Manager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -509,5 +509,12 @@ public class Manager {
)
}
}

// MARK: - NSURLSessionStreamDelegate

var _streamTaskReadClosed: Any?
var _streamTaskWriteClosed: Any?
var _streamTaskBetterRouteDiscovered: Any?
var _streamTaskDidBecomeInputStream: Any?
}
}
180 changes: 180 additions & 0 deletions Source/Stream.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// Stream.swift
//
// Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import Foundation

#if !os(watchOS)

@available(iOS 9.0, OSX 10.11, *)
extension Manager {
private enum Streamable {
case Stream(String, Int)
case NetService(NSNetService)
}

private func stream(streamable: Streamable) -> Request {
var streamTask: NSURLSessionStreamTask!

switch streamable {
case .Stream(let hostName, let port):
dispatch_sync(queue) {
streamTask = self.session.streamTaskWithHostName(hostName, port: port)
}
case .NetService(let netService):
dispatch_sync(queue) {
streamTask = self.session.streamTaskWithNetService(netService)
}
}

let request = Request(session: session, task: streamTask)

delegate[request.delegate.task] = request.delegate

if startRequestsImmediately {
request.resume()
}

return request
}

/**
Creates a request for bidirectional streaming with the given hostname and port.

- parameter hostName: The hostname of the server to connect to.
- parameter port: The port of the server to connect to.

:returns: The created stream request.
*/
public func stream(hostName hostName: String, port: Int) -> Request {
return stream(.Stream(hostName, port))
}

/**
Creates a request for bidirectional streaming with the given `NSNetService`.

- parameter netService: The net service used to identify the endpoint.

- returns: The created stream request.
*/
public func stream(netService netService: NSNetService) -> Request {
return stream(.NetService(netService))
}
}

// MARK: -

@available(iOS 9.0, OSX 10.11, *)
extension Manager.SessionDelegate: NSURLSessionStreamDelegate {

// MARK: Override Closures

/// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:readClosedForStreamTask:`.
public var streamTaskReadClosed: ((NSURLSession, NSURLSessionStreamTask) -> Void)? {
get {
return _streamTaskReadClosed as? (NSURLSession, NSURLSessionStreamTask) -> Void
}
set {
_streamTaskReadClosed = newValue
}
}

/// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:writeClosedForStreamTask:`.
public var streamTaskWriteClosed: ((NSURLSession, NSURLSessionStreamTask) -> Void)? {
get {
return _streamTaskWriteClosed as? (NSURLSession, NSURLSessionStreamTask) -> Void
}
set {
_streamTaskWriteClosed = newValue
}
}

/// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:betterRouteDiscoveredForStreamTask:`.
public var streamTaskBetterRouteDiscovered: ((NSURLSession, NSURLSessionStreamTask) -> Void)? {
get {
return _streamTaskBetterRouteDiscovered as? (NSURLSession, NSURLSessionStreamTask) -> Void
}
set {
_streamTaskBetterRouteDiscovered = newValue
}
}

/// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:streamTask:didBecomeInputStream:outputStream:`.
public var streamTaskDidBecomeInputStream: ((NSURLSession, NSURLSessionStreamTask, NSInputStream, NSOutputStream) -> Void)? {
get {
return _streamTaskDidBecomeInputStream as? (NSURLSession, NSURLSessionStreamTask, NSInputStream, NSOutputStream) -> Void
}
set {
_streamTaskDidBecomeInputStream = newValue
}
}

// MARK: Delegate Methods

/**
Tells the delegate that the read side of the connection has been closed.

- parameter session: The session.
- parameter streamTask: The stream task.
*/
public func URLSession(session: NSURLSession, readClosedForStreamTask streamTask: NSURLSessionStreamTask) {
streamTaskReadClosed?(session, streamTask)
}

/**
Tells the delegate that the write side of the connection has been closed.

- parameter session: The session.
- parameter streamTask: The stream task.
*/
public func URLSession(session: NSURLSession, writeClosedForStreamTask streamTask: NSURLSessionStreamTask) {
streamTaskWriteClosed?(session, streamTask)
}

/**
Tells the delegate that the system has determined that a better route to the host is available.

- parameter session: The session.
- parameter streamTask: The stream task.
*/
public func URLSession(session: NSURLSession, betterRouteDiscoveredForStreamTask streamTask: NSURLSessionStreamTask) {
streamTaskBetterRouteDiscovered?(session, streamTask)
}

/**
Tells the delegate that the stream task has been completed and provides the unopened stream objects.

- parameter session: The session.
- parameter streamTask: The stream task.
- parameter inputStream: The new input stream.
- parameter outputStream: The new output stream.
*/
public func URLSession(
session: NSURLSession,
streamTask: NSURLSessionStreamTask,
didBecomeInputStream inputStream: NSInputStream,
outputStream: NSOutputStream)
{
streamTaskDidBecomeInputStream?(session, streamTask, inputStream, outputStream)
}
}

#endif

0 comments on commit f4a3a50

Please sign in to comment.