tweaks for url loading

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@25142 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2007-05-11 15:47:06 +00:00
parent 7c633ab823
commit 1d562005d1
9 changed files with 259 additions and 240 deletions

View file

@ -5,9 +5,11 @@
* Source/win32/NSStreamWin32.m: * Source/win32/NSStreamWin32.m:
* Headers/Foundation/NSStream.h: * Headers/Foundation/NSStream.h:
First hack at extensions to get address and port properties for First hack at extensions to get address and port properties for
network streams. network streams. Use localhost if no host is given for connect.
* Source/GSFFIInvocation.m: * Source/GSFFIInvocation.m:
Attempt to use forward2 if available. Attempt to use forward2 if available.
* Source/NSURLProtocol.m:
Fixup some problems with incorporation of code from mySTEP.
2007-05-11 Richard Frith-Macdonald <rfm@gnu.org> 2007-05-11 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -442,6 +442,7 @@ extern "C" {
#include <Foundation/NSURLHandle.h> #include <Foundation/NSURLHandle.h>
#include <Foundation/NSURLConnection.h>
@class NSArray; @class NSArray;
@class NSDictionary; @class NSDictionary;
@ -504,13 +505,10 @@ extern "C" {
@interface GSXMLRPC : NSObject <NSURLHandleClient> @interface GSXMLRPC : NSObject <NSURLHandleClient>
{ {
@private @private
#ifdef GNUSTEP
NSURLHandle *handle; NSURLHandle *handle;
#else
NSString *connectionURL; NSString *connectionURL;
NSURLConnection *connection; NSURLConnection *connection;
NSMutableData *response; NSMutableData *response;
#endif
NSTimer *timer; NSTimer *timer;
id result; id result;
id delegate; // Not retained. id delegate; // Not retained.

View file

@ -72,7 +72,7 @@ extern "C" {
/** <init /> /** <init />
* Initialises the receiver with the specified request (performing * Initialises the receiver with the specified request (performing
* a deep copy so that ithe request does not change during loading) * a deep copy so that the request does not change during loading)
* and delegate.<br /> * and delegate.<br />
* This automatically initiates an asynchronous load for the request.<br /> * This automatically initiates an asynchronous load for the request.<br />
* Processing of the request is done in the thread which calls this * Processing of the request is done in the thread which calls this

View file

@ -52,29 +52,7 @@
#include "GNUstepBase/GSMime.h" #include "GNUstepBase/GSMime.h"
#include "GNUstepBase/GSXML.h" #include "GNUstepBase/GSXML.h"
#ifndef NeXT_Foundation_LIBRARY
#include <Foundation/NSArray.h>
#include <Foundation/NSBundle.h>
#include <Foundation/NSCalendarDate.h>
#include <Foundation/NSCharacterSet.h>
#include <Foundation/NSData.h>
#include <Foundation/NSDate.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSException.h>
#include <Foundation/NSFileManager.h>
#include <Foundation/NSHashTable.h>
#include <Foundation/NSInvocation.h>
#include <Foundation/NSMapTable.h>
#include <Foundation/NSRunLoop.h>
#include <Foundation/NSString.h>
#include <Foundation/NSTimeZone.h>
#include <Foundation/NSTimer.h>
#include <Foundation/NSURL.h>
#include <Foundation/NSURLHandle.h>
#include <Foundation/NSValue.h>
#else
#include <Foundation/Foundation.h> #include <Foundation/Foundation.h>
#endif
/* libxml headers */ /* libxml headers */
#include <libxml/tree.h> #include <libxml/tree.h>

View file

@ -74,16 +74,27 @@ typedef struct {
static NSMutableArray *registered = nil; static NSMutableArray *registered = nil;
static NSLock *regLock = nil; static NSLock *regLock = nil;
static Class abstractClass = nil;
static NSURLProtocol *placeholder = nil;
@implementation NSURLProtocol @implementation NSURLProtocol
+ (id) allocWithZone: (NSZone*)z + (id) allocWithZone: (NSZone*)z
{ {
NSURLProtocol *o = [super allocWithZone: z]; NSURLProtocol *o;
if (o != nil) if ((self == abstractClass) && (z == 0 || z == NSDefaultMallocZone()))
{ {
o->_NSURLProtocolInternal = NSZoneCalloc(z, 1, sizeof(Internal)); /* Return a default placeholder instance to avoid the overhead of
* creating and destroying instances of the abstract class.
*/
o = placeholder;
}
else
{
/* Create and return an instance of the concrete subclass.
*/
o = (NSURLProtocol*)NSAllocateObject(self, 0, z);
} }
return o; return o;
} }
@ -92,6 +103,9 @@ static NSLock *regLock = nil;
{ {
if (registered == nil) if (registered == nil)
{ {
abstractClass = [NSURLProtocol class];
placeholder = (NSURLProtocol*)NSAllocateObject(abstractClass, 0,
NSDefaultMallocZone());
registered = [NSMutableArray new]; registered = [NSMutableArray new];
regLock = [NSLock new]; regLock = [NSLock new];
[self registerClass: [_NSHTTPURLProtocol class]]; [self registerClass: [_NSHTTPURLProtocol class]];
@ -145,6 +159,11 @@ static NSLock *regLock = nil;
- (void) dealloc - (void) dealloc
{ {
if (self == placeholder)
{
[self retain];
return;
}
if (this != 0) if (this != 0)
{ {
[self stopLoading]; [self stopLoading];
@ -153,6 +172,7 @@ static NSLock *regLock = nil;
RELEASE(this->cachedResponse); RELEASE(this->cachedResponse);
RELEASE(this->request); RELEASE(this->request);
NSZoneFree([self zone], this); NSZoneFree([self zone], this);
_NSURLProtocolInternal = 0;
} }
[super dealloc]; [super dealloc];
} }
@ -160,14 +180,27 @@ static NSLock *regLock = nil;
- (NSString*) description - (NSString*) description
{ {
return [NSString stringWithFormat:@"%@ %@", return [NSString stringWithFormat:@"%@ %@",
[super description], this->request]; [super description], this ? (id)this->request : nil];
}
- (id) init
{
if ((self = [super init]) != nil)
{
if (isa != abstractClass)
{
_NSURLProtocolInternal = NSZoneCalloc(GSObjCZone(self),
1, sizeof(Internal));
}
}
return self;
} }
- (id) initWithRequest: (NSURLRequest *)request - (id) initWithRequest: (NSURLRequest *)request
cachedResponse: (NSCachedURLResponse *)cachedResponse cachedResponse: (NSCachedURLResponse *)cachedResponse
client: (id <NSURLProtocolClient>)client client: (id <NSURLProtocolClient>)client
{ {
if (isa == [NSURLProtocol class]) if (isa == abstractClass)
{ {
unsigned count; unsigned count;
@ -189,7 +222,7 @@ static NSLock *regLock = nil;
cachedResponse: cachedResponse cachedResponse: cachedResponse
client: client]; client: client];
} }
if ((self = [super init]) != nil) if ((self = [self init]) != nil)
{ {
this->request = [request copy]; this->request = [request copy];
this->cachedResponse = RETAIN(cachedResponse); this->cachedResponse = RETAIN(cachedResponse);
@ -390,7 +423,7 @@ static NSLock *regLock = nil;
{ // process header line { // process header line
unsigned char *c, *end; unsigned char *c, *end;
NSString *key, *val; NSString *key, *val;
#if 0 #if 1
NSLog(@"process header line len=%d", len); NSLog(@"process header line len=%d", len);
#endif #endif
// if it begins with ' ' or '\t' it is a continuation line to the previous header field // if it begins with ' ' or '\t' it is a continuation line to the previous header field
@ -442,6 +475,7 @@ static NSLock *regLock = nil;
*/ */
if ([self isKindOfClass: [_NSHTTPSURLProtocol class]]) if ([self isKindOfClass: [_NSHTTPSURLProtocol class]])
policy=NSURLCacheStorageNotAllowed; // never policy=NSURLCacheStorageNotAllowed; // never
NSLog(@"Received");
[this->client URLProtocol: self didReceiveResponse: response cacheStoragePolicy: policy]; [this->client URLProtocol: self didReceiveResponse: response cacheStoragePolicy: policy];
} }
return YES; return YES;
@ -465,7 +499,7 @@ static NSLock *regLock = nil;
- (void) _processHeader: (unsigned char *) buffer length: (int) len - (void) _processHeader: (unsigned char *) buffer length: (int) len
{ // next header fragment received { // next header fragment received
unsigned char *ptr, *end; unsigned char *ptr, *end;
#if 0 #if 1
NSLog(@"received %d bytes", len); NSLog(@"received %d bytes", len);
#endif #endif
if (len <= 0) if (len <= 0)
@ -536,12 +570,18 @@ static NSLock *regLock = nil;
#endif #endif
if (stream == this->input) if (stream == this->input)
{ {
#if 1
NSLog(@"input stream handleEvent: %x for: %@", event, self);
#endif
switch(event) switch(event)
{ {
case NSStreamEventHasBytesAvailable: case NSStreamEventHasBytesAvailable:
{ {
unsigned char buffer[512]; unsigned char buffer[512];
int len=[(NSInputStream *) stream read: buffer maxLength: sizeof(buffer)]; int len;
len = [(NSInputStream *)stream read: buffer
maxLength: sizeof(buffer)];
if (len < 0) if (len < 0)
{ {
#if 1 #if 1
@ -559,7 +599,7 @@ static NSLock *regLock = nil;
} }
case NSStreamEventEndEncountered: // can this occur in parallel to NSStreamEventHasBytesAvailable??? case NSStreamEventEndEncountered: // can this occur in parallel to NSStreamEventHasBytesAvailable???
{ {
#if 0 #if 1
NSLog(@"end of response"); NSLog(@"end of response");
#endif #endif
if (!_readingBody) if (!_readingBody)
@ -571,7 +611,7 @@ static NSLock *regLock = nil;
} }
case NSStreamEventOpenCompleted: case NSStreamEventOpenCompleted:
{ // prepare to receive header { // prepare to receive header
#if 0 #if 1
NSLog(@"HTTP input stream opened"); NSLog(@"HTTP input stream opened");
#endif #endif
return; return;
@ -583,6 +623,7 @@ static NSLock *regLock = nil;
else if (stream == this->output) else if (stream == this->output)
{ {
unsigned char *msg; unsigned char *msg;
#if 0 #if 0
NSLog(@"An event occurred on the output stream."); NSLog(@"An event occurred on the output stream.");
#endif #endif
@ -594,6 +635,7 @@ static NSLock *regLock = nil;
search=Katzen&go=Artikel <- body search=Katzen&go=Artikel <- body
*/ */
switch(event) switch(event)
{ {
case NSStreamEventOpenCompleted: case NSStreamEventOpenCompleted:
@ -601,15 +643,16 @@ static NSLock *regLock = nil;
#if 0 #if 0
NSLog(@"HTTP output stream opened"); NSLog(@"HTTP output stream opened");
#endif #endif
msg=(unsigned char *) [[NSString stringWithFormat: @"%@ %@ HTTP/1.1\r\n", msg = (unsigned char *)[[NSString stringWithFormat:
@"%@ %@ HTTP/1.1\r\n",
[this->request HTTPMethod], [this->request HTTPMethod],
[[this->request URL] absoluteString] [[this->request URL] absoluteString]] UTF8String];
] cString]; // FIXME: UTF8??? [(NSOutputStream *) stream write: msg
[(NSOutputStream *) stream write: msg maxLength: strlen((char *) msg)]; maxLength: strlen((char *) msg)];
#if 1 #if 0
NSLog(@"sent %s", msg); NSLog(@"sent %s", msg);
#endif #endif
_headerEnumerator=[[[this->request allHTTPHeaderFields] objectEnumerator] retain]; _headerEnumerator = [[[this->request allHTTPHeaderFields] keyEnumerator] retain];
return; return;
} }
case NSStreamEventHasSpaceAvailable: case NSStreamEventHasSpaceAvailable:
@ -621,7 +664,7 @@ static NSLock *regLock = nil;
key = [_headerEnumerator nextObject]; key = [_headerEnumerator nextObject];
if (key) if (key)
{ {
#if 1 #if 0
NSLog(@"sending %@: %@", key, [this->request valueForHTTPHeaderField: key]); NSLog(@"sending %@: %@", key, [this->request valueForHTTPHeaderField: key]);
#endif #endif
msg=(unsigned char *)[[NSString stringWithFormat: @"%@: %@\r\n", key, [this->request valueForHTTPHeaderField: key]] UTF8String]; msg=(unsigned char *)[[NSString stringWithFormat: @"%@: %@\r\n", key, [this->request valueForHTTPHeaderField: key]] UTF8String];
@ -637,7 +680,7 @@ static NSLock *regLock = nil;
[_body open]; [_body open];
} }
[(NSOutputStream *) stream write: msg maxLength: strlen((char *) msg)]; // NOTE: we might block here if header value is too long [(NSOutputStream *) stream write: msg maxLength: strlen((char *) msg)]; // NOTE: we might block here if header value is too long
#if 1 #if 0
NSLog(@"sent %s", msg); NSLog(@"sent %s", msg);
#endif #endif
return; return;

View file

@ -399,6 +399,5 @@ static const NSMapTableKeyCallBacks headerKeyCallBacks =
{ {
return this->statusCode; return this->statusCode;
} }
@end @end

View file

@ -1268,7 +1268,7 @@ static void setNonblocking(int fd)
inputStream: (NSInputStream **)inputStream inputStream: (NSInputStream **)inputStream
outputStream: (NSOutputStream **)outputStream outputStream: (NSOutputStream **)outputStream
{ {
NSString *address = [host address]; NSString *address = host ? (id)[host address] : (id)@"127.0.0.1";
GSSocketInputStream *ins = nil; GSSocketInputStream *ins = nil;
GSSocketOutputStream *outs = nil; GSSocketOutputStream *outs = nil;
int sock; int sock;
@ -1281,10 +1281,10 @@ static void setNonblocking(int fd)
if (!ins) if (!ins)
{ {
#if defined(PF_INET6) #if defined(PF_INET6)
ins = [[GSInet6InputStream alloc] initToAddr: address ins = AUTORELEASE([[GSInet6InputStream alloc]
port: port]; initToAddr: address port: port]);
outs = [[GSInet6OutputStream alloc] initToAddr: address outs = AUTORELEASE([[GSInet6OutputStream alloc]
port: port]; initToAddr: address port: port]);
sock = socket(PF_INET6, SOCK_STREAM, 0); sock = socket(PF_INET6, SOCK_STREAM, 0);
#else #else
sock = -1; sock = -1;
@ -1308,7 +1308,6 @@ static void setNonblocking(int fd)
[outs setSibling: ins]; [outs setSibling: ins];
*outputStream = outs; *outputStream = outs;
} }
return;
} }
+ (void) getLocalStreamsToPath: (NSString *)path + (void) getLocalStreamsToPath: (NSString *)path

View file

@ -1926,7 +1926,7 @@ static id propertyForInet6Stream(int descriptor, NSString *key)
inputStream: (NSInputStream **)inputStream inputStream: (NSInputStream **)inputStream
outputStream: (NSOutputStream **)outputStream outputStream: (NSOutputStream **)outputStream
{ {
NSString *address = [host address]; NSString *address = host ? (id)[host address] : (id)@"127.0.0.1";
GSSocketInputStream *ins = nil; GSSocketInputStream *ins = nil;
GSSocketOutputStream *outs = nil; GSSocketOutputStream *outs = nil;
int sock; int sock;