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

Commit

Permalink
Use separate session pool for cellular connections -- resolves #11
Browse files Browse the repository at this point in the history
  • Loading branch information
goaway authored and Jeff Pinner committed Mar 26, 2014
1 parent c6a9e4f commit 0fd11b8
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 19 deletions.
9 changes: 8 additions & 1 deletion SPDY/SPDYSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,17 @@
@class SPDYOrigin;

@interface SPDYSession : NSObject

@property (nonatomic, readonly) SPDYOrigin *origin;
@property (nonatomic, readonly) bool isCellular;
@property (nonatomic, readonly) bool isOpen;
- (id)initWithOrigin:(SPDYOrigin *)origin configuration:(SPDYConfiguration *)configuration error:(NSError **)pError;

- (id)initWithOrigin:(SPDYOrigin *)origin
configuration:(SPDYConfiguration *)configuration
cellular:(bool)cellular
error:(NSError **)pError;
- (void)issueRequest:(SPDYProtocol *)protocol;
- (void)cancelRequest:(SPDYProtocol *)protocol;
- (void)close;

@end
14 changes: 13 additions & 1 deletion SPDY/SPDYSession.m
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,13 @@ @implementation SPDYSession
bool _enableSettingsMinorVersion;
bool _receivedGoAwayFrame;
bool _sentGoAwayFrame;
bool _cellular;
}

- (id)initWithOrigin:(SPDYOrigin *)origin configuration:(SPDYConfiguration *)configuration error:(NSError **)pError
- (id)initWithOrigin:(SPDYOrigin *)origin
configuration:(SPDYConfiguration *)configuration
cellular:(bool)cellular
error:(NSError **)pError
{
NSParameterAssert(origin != nil);

Expand All @@ -98,6 +102,9 @@ - (id)initWithOrigin:(SPDYOrigin *)origin configuration:(SPDYConfiguration *)con
_origin = origin;
SPDY_INFO(@"session connecting to %@", _origin);

// TODO: for accuracy confirm this later from the socket
_cellular = cellular;

if ([_origin.scheme isEqualToString:@"https"]) {
SPDY_DEBUG(@"session using TLS");
[_socket secureWithTLS:configuration.tlsSettings];
Expand Down Expand Up @@ -221,6 +228,11 @@ - (void)dealloc
[_socket disconnect];
}

- (bool)isCellular
{
return _cellular;
}

- (bool)isOpen
{
return (!_receivedGoAwayFrame && !_sentGoAwayFrame);
Expand Down
4 changes: 3 additions & 1 deletion SPDY/SPDYSessionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
@class SPDYSession;

@interface SPDYSessionManager : NSObject
+ (void)setConfiguration:(SPDYConfiguration *)configuration;

+ (SPDYSession *)sessionForURL:(NSURL *)url error:(NSError **)pError;
+ (void)sessionClosed:(SPDYSession *)session;
+ (void)setConfiguration:(SPDYConfiguration *)configuration;

@end
78 changes: 65 additions & 13 deletions SPDY/SPDYSessionManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,59 @@
#error "This file requires ARC support."
#endif

#import <SystemConfiguration/SystemConfiguration.h>
#import <arpa/inet.h>
#import "SPDYCommonLogger.h"
#import "SPDYOrigin.h"
#import "SPDYSessionManager.h"
#import "SPDYProtocol.h"
#import "SPDYSession.h"
#import "SPDYSessionManager.h"

@interface SPDYSessionManager ()
+ (NSMutableDictionary *)activeSessions;
+ (NSMutableDictionary *)_sessionPool:(bool)network;
@end

static NSString *const SPDYSessionManagerKey = @"com.twitter.SPDYSessionManager";
static SPDYConfiguration *currentConfiguration;
static volatile bool reachabilityIsWWAN;

#if TARGET_OS_IPHONE
static char *const SPDYReachabilityQueue = "com.twitter.SPDYReachabilityQueue";

static SCNetworkReachabilityRef reachabilityRef;
static dispatch_queue_t reachabilityQueue;

static void SPDYReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info);
#endif

@implementation SPDYSessionManager

+ (void)initialize
{
currentConfiguration = [SPDYConfiguration defaultConfiguration];
}
reachabilityIsWWAN = NO;

+ (NSMutableDictionary *)activeSessions
{
NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary;
NSMutableDictionary *activeSessions = threadDictionary[SPDYSessionManagerKey];
if (!activeSessions) {
activeSessions = [NSMutableDictionary new];
threadDictionary[SPDYSessionManagerKey] = activeSessions;
#if TARGET_OS_IPHONE
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = (uint8_t)sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;

SCNetworkReachabilityContext context = {0, NULL, NULL, NULL, NULL};
reachabilityRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress);

if (SCNetworkReachabilitySetCallback(reachabilityRef, SPDYReachabilityCallback, &context)) {
reachabilityQueue = dispatch_queue_create(SPDYReachabilityQueue, DISPATCH_QUEUE_SERIAL);
SCNetworkReachabilitySetDispatchQueue(reachabilityRef, reachabilityQueue);
}
return activeSessions;

dispatch_async(reachabilityQueue, ^{
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) {
SPDYReachabilityCallback(reachabilityRef, flags, NULL);
}
});
#endif
}

+ (void)setConfiguration:(SPDYConfiguration *)configuration
Expand All @@ -51,11 +76,12 @@ + (void)setConfiguration:(SPDYConfiguration *)configuration
+ (SPDYSession *)sessionForURL:(NSURL *)url error:(NSError **)pError
{
SPDYOrigin *origin = [[SPDYOrigin alloc] initWithURL:url error:pError];
NSMutableDictionary *activeSessions = [SPDYSessionManager activeSessions];
NSMutableDictionary *activeSessions = [SPDYSessionManager _sessionPool:reachabilityIsWWAN];
SPDYSession *session = activeSessions[origin];
if (!session || !session.isOpen) {
session = [[SPDYSession alloc] initWithOrigin:origin
configuration:currentConfiguration
cellular:reachabilityIsWWAN
error:pError];
if (session) {
activeSessions[origin] = session;
Expand All @@ -67,10 +93,36 @@ + (SPDYSession *)sessionForURL:(NSURL *)url error:(NSError **)pError
+ (void)sessionClosed:(SPDYSession *)session
{
SPDYOrigin *origin = session.origin;
NSMutableDictionary *activeSessions = [SPDYSessionManager activeSessions];
NSMutableDictionary *activeSessions = [SPDYSessionManager _sessionPool:session.isCellular];
if (activeSessions[origin] == session) {
[activeSessions removeObjectForKey:origin];
}
}

+ (NSMutableDictionary *)_sessionPool:(bool)cellular
{
NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary;
NSArray *sessionPools = threadDictionary[SPDYSessionManagerKey];
if (!sessionPools) {
threadDictionary[SPDYSessionManagerKey] = @[
[NSMutableDictionary new],
[NSMutableDictionary new] // WWAN
];
}

SPDY_DEBUG(@"using %@ session pool", cellular ? @"cellular" : @"standard");
return sessionPools[cellular ? 1 : 0];
}

@end

#if TARGET_OS_IPHONE
static void SPDYReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
{
// Only update if the network is actually reachable
if (flags & kSCNetworkReachabilityFlagsReachable) {
reachabilityIsWWAN = (flags & kSCNetworkReachabilityFlagsIsWWAN) != 0;
SPDY_DEBUG(@"reachability updated: %@", reachabilityIsWWAN ? @"WWAN" : @"WLAN");
}
}
#endif
6 changes: 3 additions & 3 deletions SPDY/SPDYSocket.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
#error "This file requires ARC support."
#endif

#import <arpa/inet.h>
#import <netinet/in.h>
#import <sys/socket.h>
#import "SPDYSocket.h"
#import "SPDYCommonLogger.h"
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>

#pragma mark Declarations

Expand Down

0 comments on commit 0fd11b8

Please sign in to comment.