mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +00:00
work in progress on keepalive and compression
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@27200 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
1d51e83998
commit
ca1b828428
2 changed files with 205 additions and 17 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
2008-12-02 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source/NSURLProtocol.m:
|
||||||
|
Add class for caching pairs of socket streams so we can eventually
|
||||||
|
implement connection keepalive.
|
||||||
|
|
||||||
2008-12-01 Richard Frith-Macdonald <rfm@gnu.org>
|
2008-12-01 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source/NSKeyValueCoding.m:
|
* Source/NSKeyValueCoding.m:
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#import <Foundation/NSError.h>
|
#import <Foundation/NSError.h>
|
||||||
#import <Foundation/NSHost.h>
|
#import <Foundation/NSHost.h>
|
||||||
|
#import <Foundation/NSNotification.h>
|
||||||
#import <Foundation/NSRunLoop.h>
|
#import <Foundation/NSRunLoop.h>
|
||||||
#import <Foundation/NSValue.h>
|
#import <Foundation/NSValue.h>
|
||||||
|
|
||||||
|
@ -32,20 +33,213 @@
|
||||||
#import "GSPrivate.h"
|
#import "GSPrivate.h"
|
||||||
#import "GSURLPrivate.h"
|
#import "GSURLPrivate.h"
|
||||||
|
|
||||||
|
/* Define to 1 for experimental (net yet working) compression support
|
||||||
|
*/
|
||||||
|
#ifdef USE_ZLIB
|
||||||
|
# undef USE_ZLIB
|
||||||
|
#endif
|
||||||
|
#define USE_ZLIB 0
|
||||||
|
|
||||||
|
#if USE_ZLIB
|
||||||
#if defined(HAVE_ZLIB_H)
|
#if defined(HAVE_ZLIB_H)
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
static void*
|
static void*
|
||||||
zalloc(void *opaque, size_t size)
|
zalloc(void *opaque, unsigned nitems, unsigned size)
|
||||||
{
|
{
|
||||||
return objc_malloc(size);
|
return objc_calloc(nitems, size);
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
zfree(void *opaque, void *mem)
|
zfree(void *opaque, void *mem)
|
||||||
{
|
{
|
||||||
objc_free(mem);
|
objc_free(mem);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
# undef USE_ZLIB
|
||||||
|
# define USE_ZLIB 0
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@interface GSSocketStreamPair : NSObject
|
||||||
|
{
|
||||||
|
NSInputStream *ip;
|
||||||
|
NSOutputStream *op;
|
||||||
|
NSHost *host;
|
||||||
|
uint16_t port;
|
||||||
|
NSDate *expires;
|
||||||
|
BOOL ssl;
|
||||||
|
}
|
||||||
|
+ (void) purge: (NSNotification*)n;
|
||||||
|
- (void) cache: (NSDate*)when;
|
||||||
|
- (NSDate*) expires;
|
||||||
|
- (id) initWithHost: (NSHost*)h port: (uint16_t)p forSSL: (BOOL)s;
|
||||||
|
- (NSInputStream*) inputStream;
|
||||||
|
- (NSOutputStream*) outputStream;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GSSocketStreamPair
|
||||||
|
|
||||||
|
static NSMutableDictionary *pairByHost = nil;
|
||||||
|
static NSLock *pairLock = nil;
|
||||||
|
static unsigned pairsCached = 0;
|
||||||
|
|
||||||
|
+ (void) initialize
|
||||||
|
{
|
||||||
|
if (pairByHost == nil)
|
||||||
|
{
|
||||||
|
pairByHost = [NSMutableDictionary new];
|
||||||
|
pairLock = [NSLock new];
|
||||||
|
/* Purge expired pairs at intervals.
|
||||||
|
*/
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||||
|
selector: @selector(purge:)
|
||||||
|
name: @"GSHousekeeping" object: nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void) purge: (NSNotification*)n
|
||||||
|
{
|
||||||
|
NSDate *now = [NSDate date];
|
||||||
|
NSEnumerator *enumerator;
|
||||||
|
NSHost *key;
|
||||||
|
|
||||||
|
[pairLock lock];
|
||||||
|
enumerator = [[pairByHost allKeys] objectEnumerator];
|
||||||
|
while ((key = [enumerator nextObject]) != nil)
|
||||||
|
{
|
||||||
|
NSMutableArray *items = [pairByHost objectForKey: key];
|
||||||
|
unsigned count = [items count];
|
||||||
|
|
||||||
|
while (count-- > 0)
|
||||||
|
{
|
||||||
|
GSSocketStreamPair *p = [items objectAtIndex: count];
|
||||||
|
|
||||||
|
if ([[p expires] timeIntervalSinceDate: now] <= 0.0)
|
||||||
|
{
|
||||||
|
[items removeObjectAtIndex: count];
|
||||||
|
pairsCached--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ([items count] == 0)
|
||||||
|
{
|
||||||
|
[pairByHost removeObjectForKey: key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[pairLock unlock];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) cache: (NSDate*)when
|
||||||
|
{
|
||||||
|
NSMutableArray *items;
|
||||||
|
|
||||||
|
ASSIGN(expires, when);
|
||||||
|
[pairLock lock];
|
||||||
|
items = [pairByHost objectForKey: host];
|
||||||
|
if (items == nil)
|
||||||
|
{
|
||||||
|
items = [NSMutableArray new];
|
||||||
|
[pairByHost setObject: items forKey: host];
|
||||||
|
[items release];
|
||||||
|
}
|
||||||
|
[items addObject: self];
|
||||||
|
pairsCached++;
|
||||||
|
[pairLock unlock];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[ip release];
|
||||||
|
[op release];
|
||||||
|
[host release];
|
||||||
|
[expires release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDate*) expires
|
||||||
|
{
|
||||||
|
return expires;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
[self release];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithHost: (NSHost*)h port: (uint16_t)p forSSL: (BOOL)s;
|
||||||
|
{
|
||||||
|
NSMutableArray *items;
|
||||||
|
unsigned count;
|
||||||
|
unsigned index;
|
||||||
|
NSDate *now;
|
||||||
|
|
||||||
|
now = [NSDate date];
|
||||||
|
[pairLock lock];
|
||||||
|
items = [pairByHost objectForKey: h];
|
||||||
|
count = [items count];
|
||||||
|
for (index = 0; index < count; index++)
|
||||||
|
{
|
||||||
|
GSSocketStreamPair *pair = [items objectAtIndex: count];
|
||||||
|
|
||||||
|
if ([pair->expires timeIntervalSinceDate: now] <= 0.0)
|
||||||
|
{
|
||||||
|
[items removeObjectAtIndex: index];
|
||||||
|
pairsCached--;
|
||||||
|
index--;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
else if (pair->port == p && pair->ssl == s)
|
||||||
|
{
|
||||||
|
/* Found a match ... remove from cache and return as self.
|
||||||
|
*/
|
||||||
|
[self release];
|
||||||
|
self = [pair retain];
|
||||||
|
[items removeObjectAtIndex: index];
|
||||||
|
pairsCached--;
|
||||||
|
[pairLock unlock];
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[pairLock unlock];
|
||||||
|
|
||||||
|
if ((self = [super init]) != nil)
|
||||||
|
{
|
||||||
|
[NSStream getStreamsToHost: host
|
||||||
|
port: port
|
||||||
|
inputStream: &ip
|
||||||
|
outputStream: &op];
|
||||||
|
if (ip == nil || op == nil)
|
||||||
|
{
|
||||||
|
[self release];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
ssl = s;
|
||||||
|
port = p;
|
||||||
|
host = [h retain];
|
||||||
|
[ip retain];
|
||||||
|
[op retain];
|
||||||
|
if (ssl == YES)
|
||||||
|
{
|
||||||
|
[ip setProperty: NSStreamSocketSecurityLevelNegotiatedSSL
|
||||||
|
forKey: NSStreamSocketSecurityLevelKey];
|
||||||
|
[op setProperty: NSStreamSocketSecurityLevelNegotiatedSSL
|
||||||
|
forKey: NSStreamSocketSecurityLevelKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSInputStream*) inputStream
|
||||||
|
{
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSOutputStream*) outputStream
|
||||||
|
{
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@interface _NSAboutURLProtocol : NSURLProtocol
|
@interface _NSAboutURLProtocol : NSURLProtocol
|
||||||
@end
|
@end
|
||||||
|
@ -88,7 +282,7 @@ typedef struct {
|
||||||
NSCachedURLResponse *cachedResponse;
|
NSCachedURLResponse *cachedResponse;
|
||||||
id <NSURLProtocolClient> client; // Not retained
|
id <NSURLProtocolClient> client; // Not retained
|
||||||
NSURLRequest *request;
|
NSURLRequest *request;
|
||||||
#if defined(HAVE_ZLIB_H)
|
#if USE_ZLIB
|
||||||
z_stream z; // context for decompress
|
z_stream z; // context for decompress
|
||||||
BOOL compressing; // are we compressing?
|
BOOL compressing; // are we compressing?
|
||||||
BOOL decompressing; // are we decompressing?
|
BOOL decompressing; // are we decompressing?
|
||||||
|
@ -201,7 +395,7 @@ static NSURLProtocol *placeholder = nil;
|
||||||
RELEASE(this->output);
|
RELEASE(this->output);
|
||||||
RELEASE(this->cachedResponse);
|
RELEASE(this->cachedResponse);
|
||||||
RELEASE(this->request);
|
RELEASE(this->request);
|
||||||
#if defined(HAVE_ZLIB_H)
|
#if USE_ZLIB
|
||||||
if (this->compressing == YES)
|
if (this->compressing == YES)
|
||||||
{
|
{
|
||||||
deflateEnd(&this->z);
|
deflateEnd(&this->z);
|
||||||
|
@ -347,11 +541,6 @@ static NSURLProtocol *placeholder = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) _didInitializeOutputStream: (NSOutputStream*)stream
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
[_parser release]; // received headers
|
[_parser release]; // received headers
|
||||||
|
@ -504,7 +693,6 @@ static NSURLProtocol *placeholder = nil;
|
||||||
}
|
}
|
||||||
RETAIN(this->input);
|
RETAIN(this->input);
|
||||||
RETAIN(this->output);
|
RETAIN(this->output);
|
||||||
[self _didInitializeOutputStream: this->output];
|
|
||||||
if ([[url scheme] isEqualToString: @"https"] == YES)
|
if ([[url scheme] isEqualToString: @"https"] == YES)
|
||||||
{
|
{
|
||||||
[this->input setProperty: NSStreamSocketSecurityLevelNegotiatedSSL
|
[this->input setProperty: NSStreamSocketSecurityLevelNegotiatedSSL
|
||||||
|
@ -731,7 +919,7 @@ static NSURLProtocol *placeholder = nil;
|
||||||
cacheStoragePolicy: policy];
|
cacheStoragePolicy: policy];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_ZLIB_H)
|
#if USE_ZLIB
|
||||||
s = [[document headerNamed: @"content-encoding"] value];
|
s = [[document headerNamed: @"content-encoding"] value];
|
||||||
if ([s isEqualToString: @"gzip"] || [s isEqualToString: @"x-gzip"])
|
if ([s isEqualToString: @"gzip"] || [s isEqualToString: @"x-gzip"])
|
||||||
{
|
{
|
||||||
|
@ -1250,12 +1438,6 @@ static NSURLProtocol *placeholder = nil;
|
||||||
return [[[request URL] scheme] isEqualToString: @"https"];
|
return [[[request URL] scheme] isEqualToString: @"https"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) _didInitializeOutputStream: (NSOutputStream *) stream
|
|
||||||
{
|
|
||||||
[stream setProperty: NSStreamSocketSecurityLevelNegotiatedSSL
|
|
||||||
forKey: NSStreamSocketSecurityLevelKey];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation _NSFTPURLProtocol
|
@implementation _NSFTPURLProtocol
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue