Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

Support for server push streams #136

Merged
merged 9 commits into from
Oct 30, 2015
Merged
106 changes: 59 additions & 47 deletions SPDY.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions SPDY/SPDYProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,20 @@
#import <Foundation/Foundation.h>
#import "SPDYLogger.h"


/**
NSNotification calls are posted using the NSURL loader thread. Care must be taken to
not block or delay the execution of this thread. Any substantive work should be done
on a different thread.
*/

// userInfo has a key "origin", value is an NSString
extern NSString *const SPDYOriginRegisteredNotification;
extern NSString *const SPDYOriginUnregisteredNotification;

// userInfo has a key "request", value is an NSURLRequest
extern NSString *const SPDYPushRequestReceivedNotification;

@class SPDYConfiguration;

@protocol SPDYTLSTrustEvaluator;
Expand Down
44 changes: 29 additions & 15 deletions SPDY/SPDYProtocol.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#import "SPDYMetadata+Utils.h"
#import "SPDYOrigin.h"
#import "SPDYProtocol+Project.h"
#import "SPDYPushStreamManager.h"
#import "SPDYSession.h"
#import "SPDYSessionManager.h"
#import "SPDYStream.h"
Expand All @@ -32,6 +33,7 @@
NSString *const SPDYSocketErrorDomain = @"SPDYSocketErrorDomain";
NSString *const SPDYOriginRegisteredNotification = @"SPDYOriginRegisteredNotification";
NSString *const SPDYOriginUnregisteredNotification = @"SPDYOriginUnregisteredNotification";
NSString *const SPDYPushRequestReceivedNotification = @"SPDYPushRequestReceivedNotification";

static char *const SPDYConfigQueue = "com.twitter.SPDYConfigQueue";

Expand All @@ -49,6 +51,7 @@ @interface SPDYAssertionHandler : NSAssertionHandler
@end

@interface SPDYProtocolContext : NSObject <SPDYProtocolContext>
- (void)associateWithStream:(SPDYStream *)stream;
@end

@implementation SPDYAssertionHandler
Expand Down Expand Up @@ -120,15 +123,13 @@ @implementation SPDYProtocolContext
SPDYMetadata *_metadata;
}

- (instancetype)initWithStream:(SPDYStream *)stream
- (void)associateWithStream:(SPDYStream *)stream
{
self = [super init];
if (self) {
_metadata = stream.metadata;
}
return self;
_metadata = stream.metadata;
}

#pragma mark SPDYProtocolContext protocol

- (SPDYMetadata *)metadata
{
return _metadata;
Expand Down Expand Up @@ -382,16 +383,14 @@ - (void)startLoading
origin = aliasedOrigin;
}

// Create the stream
_stream = [[SPDYStream alloc] initWithProtocol:self];
_context = [[SPDYProtocolContext alloc] initWithStream:_stream];
// Create the context, but delay stream creation (to allow for looking up push cache
// as late as possible). Must associate stream with this instance of the context then.
_context = [[SPDYProtocolContext alloc] init];

if (request.SPDYURLSession) {
[self detectSessionAndTaskThenContinueWithOrigin:origin];
} else {
// Start the stream
SPDYSessionManager *manager = [SPDYSessionManager localManagerForOrigin:origin];
[manager queueStream:_stream];
[self startStreamForOrigin:origin];
}
}

Expand Down Expand Up @@ -435,9 +434,7 @@ - (void)detectSessionAndTaskThenContinueWithOrigin:(SPDYOrigin *)origin
}
}

// Start the stream
SPDYSessionManager *manager = [SPDYSessionManager localManagerForOrigin:origin];
[manager queueStream:_stream];
[self startStreamForOrigin:origin];
}
};

Expand All @@ -447,10 +444,27 @@ - (void)detectSessionAndTaskThenContinueWithOrigin:(SPDYOrigin *)origin
}];
}

- (void)startStreamForOrigin:(SPDYOrigin *)origin
{
SPDYSessionManager *manager = [SPDYSessionManager localManagerForOrigin:origin];

// See if this is currently being pushed, and if so, hook it up, else create it
_stream = [manager.pushStreamManager streamForProtocol:self];
if (_stream != nil) {
SPDY_INFO(@"using in-progress push stream %@ for %@", _stream, self.request.URL.absoluteString);
} else {
_stream = [[SPDYStream alloc] initWithProtocol:self pushStreamManager:manager.pushStreamManager];
[manager queueStream:_stream];
}
[_context associateWithStream:_stream];
}

- (void)stopLoading
{
SPDY_INFO(@"stop loading %@", self.request.URL.absoluteString);

[_stream.pushStreamManager stopLoadingStream:_stream];

if (_stream && !_stream.closed) {
[_stream cancel];
}
Expand Down
25 changes: 25 additions & 0 deletions SPDY/SPDYPushStreamManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// SPDYPushStreamManager.h
// SPDY
//
// Copyright (c) 2014 Twitter, Inc. All rights reserved.
// Licensed under the Apache License v2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// Created by Kevin Goodier.
//

#import <Foundation/Foundation.h>

@class SPDYProtocol;
@class SPDYStream;

@interface SPDYPushStreamManager : NSObject

- (NSUInteger)pushStreamCount;
- (NSUInteger)associatedStreamCount;
- (SPDYStream *)streamForProtocol:(SPDYProtocol *)protocol;
- (void)addStream:(SPDYStream *)stream associatedWithStream:(SPDYStream *)associatedStream;
- (void)stopLoadingStream:(SPDYStream *)stream;

@end
Loading