HTTPSource now uses NSURLConnection.

CQTexperiment
vspader 2007-10-14 16:29:49 +00:00
parent eedc659f84
commit 0091ccb447
5 changed files with 146 additions and 197 deletions

View File

@ -8,20 +8,20 @@
#import <Cocoa/Cocoa.h>
#import "Socket.h"
#import "Semaphore.h"
#import "Plugin.h"
@interface HTTPSource : NSObject <CogSource>
{
Socket *_socket;
NSURLConnection *_connection;
long _byteCount;
BOOL _connectionFinished;
NSMutableData *_data;
Semaphore *_sem;
NSURL *_url;
BOOL pastHeader;
long byteCount;
}
- (void)setURL:(NSURL *)url;
@end

View File

@ -11,29 +11,32 @@
@implementation HTTPSource
- (BOOL)buffered
{
return NO;
}
- (BOOL)open:(NSURL *)url
{
[self setURL:url];
unsigned int port = [[url port] unsignedIntValue];
if (!port)
port = 80;
_socket = [[Socket alloc] initWithHost:[url host] port:port];
NSLog(@"SOCKET?");
if (_socket) {
NSLog(@"WE HAVE A SOCKET!");
NSData *request = [[NSString stringWithFormat:@"GET %@ HTTP/1.0\nHOST: %@\n\n",[url path],[url host]] dataUsingEncoding:NSUTF8StringEncoding];
[_socket send:(void *)[request bytes] amount:[request length]];
pastHeader = NO;
}
_url = [url copy];
_connectionFinished = NO;
_byteCount = 0;
_data = [[NSMutableData alloc] init];
_sem = [[Semaphore alloc] init];
[NSThread detachNewThreadSelector:@selector(makeConnection) toTarget:self withObject:nil];
NSLog(@"Connection opened!");
return YES;
}
- (void)makeConnection
{
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:_url];
_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[request release];
[[NSRunLoop currentRunLoop] run];
return (_socket != nil);
}
- (NSDictionary *)properties
@ -53,74 +56,125 @@
- (long)tell
{
return byteCount;
return _byteCount;
}
- (int)read:(void *)buffer amount:(int)amount
{
NSLog(@"READING DATA: %i", amount);
if (!pastHeader) {
const int delimeter_size = 4; //\r\n\r\n
// FILE *testFout = fopen("/Users/vspader/header.raw", "w");
int l = [_socket receive:buffer amount:amount];
NSLog(@"Received data: %i", l);
uint8_t *f;
while(NULL == (f = (uint8_t *)strnstr((const char *)buffer, "\r\n\r\n", l))) {
// fwrite(buffer, 1,l, testFout);
//Need to check for boundary conditions
memmove(buffer, (uint8_t *)buffer + (l - delimeter_size), delimeter_size);
l = delimeter_size + [_socket receive:((uint8_t *)buffer + delimeter_size) amount:(amount - delimeter_size)];
}
pastHeader = YES;
uint8_t *bufferOffset = f + delimeter_size;
uint8_t *bufferEnd = (uint8_t *)buffer + l;
int amountRemaining = bufferEnd - bufferOffset;
//For testing only
// fwrite(buffer, 1, bufferOffset - (uint8_t *)buffer, testFout);
// fclose(testFout);
// testFout = fopen("/Users/vspader/test.raw", "w");
// fwrite(bufferOffset, 1, amountRemaining, testFout);
// fclose(testFout);
memmove(buffer,bufferOffset, amountRemaining);
return amountRemaining + [self read:((uint8_t *)buffer + amountRemaining) amount:(amount - amountRemaining)];
while (amount > [_data length] && !_connectionFinished) {
NSLog(@"Waiting: %@", [NSThread currentThread]);
[_sem timedWait: 2];
}
else {
int l = [_socket receive:buffer amount:amount];
NSLog(@"Read called!");
if (amount > [_data length])
amount = [_data length];
[_data getBytes:buffer length:amount];
//FOR TESTING ONLY
// FILE *testFout = fopen("/Users/vspader/test.raw", "a");
// fwrite(buffer, 1, l, testFout);
// fclose(testFout);
if (l > 0)
byteCount += l;
//Remove the bytes
[_data replaceBytesInRange:NSMakeRange(0, amount) withBytes:NULL length:0];
_byteCount += amount;
return l;
}
return amount;
}
//Only called from thread.
- (void)cancel
{
NSLog(@"CANCEL!");
[_connection cancel];
_connectionFinished = YES;
[_sem signal];
[NSThread exit];
}
- (void)close
{
[_socket close];
[_connection cancel];
[_connection release];
_connection = nil;
[_data release];
_data = nil;
[_url release];
_url = nil;
[_sem release];
_sem = nil;
}
- (void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSLog(@"Authentication cancelled");
[self cancel];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"Connection failed: %@", error);
[self cancel];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSLog(@"Received authentication challenge. Canceling.");
[self cancel];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
//May be called more than once. Mime-type may change. Will be called before didReceiveData
NSLog(@"Received response: %@", response);
[_data release];
_data = [[NSMutableData alloc] init];
}
-(NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
NSLog(@"Received cache request");
//No caching an HTTP stream
return nil;
}
-(NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
{
NSLog(@"Received redirect");
//Redirect away
return request;
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"Connection finished loading.");
_connectionFinished = YES;
[_sem signal];
[NSThread exit];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(@"Connection received data.");
[_data appendData:data];
[_sem signal];
}
- (void)dealloc
{
[self setURL:nil];
[_socket release];
[_url release];
[self close];
[super dealloc];
}
@ -130,13 +184,6 @@
return _url;
}
- (void)setURL:(NSURL *)url
{
[url retain];
[_url release];
_url = url;
}
+ (NSArray *)schemes
{
return [NSArray arrayWithObject:@"http"];

View File

@ -7,7 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
17ADB60B0B97A73B00257CA2 /* Socket.m in Sources */ = {isa = PBXBuildFile; fileRef = 17ADB60A0B97A73B00257CA2 /* Socket.m */; };
176A6E470CC272E8000F60DE /* Semaphore.m in Sources */ = {isa = PBXBuildFile; fileRef = 176A6E450CC272E8000F60DE /* Semaphore.m */; };
17ADB6100B97A74800257CA2 /* HTTPSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 17ADB60D0B97A74800257CA2 /* HTTPSource.m */; };
17ADB6110B97A74800257CA2 /* HTTPSourcePlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 17ADB60F0B97A74800257CA2 /* HTTPSourcePlugin.m */; };
8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
@ -17,8 +17,8 @@
089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
17ADB6090B97A73B00257CA2 /* Socket.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Socket.h; sourceTree = "<group>"; };
17ADB60A0B97A73B00257CA2 /* Socket.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = Socket.m; sourceTree = "<group>"; };
176A6E440CC272E8000F60DE /* Semaphore.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Semaphore.h; sourceTree = "<group>"; };
176A6E450CC272E8000F60DE /* Semaphore.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = Semaphore.m; sourceTree = "<group>"; };
17ADB60C0B97A74800257CA2 /* HTTPSource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HTTPSource.h; sourceTree = "<group>"; };
17ADB60D0B97A74800257CA2 /* HTTPSource.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = HTTPSource.m; sourceTree = "<group>"; };
17ADB60E0B97A74800257CA2 /* HTTPSourcePlugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HTTPSourcePlugin.h; sourceTree = "<group>"; };
@ -79,7 +79,7 @@
17ADB60D0B97A74800257CA2 /* HTTPSource.m */,
17ADB60E0B97A74800257CA2 /* HTTPSourcePlugin.h */,
17ADB60F0B97A74800257CA2 /* HTTPSourcePlugin.m */,
17ADB6080B97A73B00257CA2 /* Utils */,
176A6E410CC272E8000F60DE /* Utils */,
);
name = Classes;
sourceTree = "<group>";
@ -102,14 +102,15 @@
name = "Other Frameworks";
sourceTree = "<group>";
};
17ADB6080B97A73B00257CA2 /* Utils */ = {
176A6E410CC272E8000F60DE /* Utils */ = {
isa = PBXGroup;
children = (
17ADB6090B97A73B00257CA2 /* Socket.h */,
17ADB60A0B97A73B00257CA2 /* Socket.m */,
176A6E440CC272E8000F60DE /* Semaphore.h */,
176A6E450CC272E8000F60DE /* Semaphore.m */,
);
path = Utils;
sourceTree = "<group>";
name = Utils;
path = ../../Audio/Utils;
sourceTree = SOURCE_ROOT;
};
19C28FB8FE9D52D311CA2CBB /* Products */ = {
isa = PBXGroup;
@ -178,9 +179,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
17ADB60B0B97A73B00257CA2 /* Socket.m in Sources */,
17ADB6100B97A74800257CA2 /* HTTPSource.m in Sources */,
17ADB6110B97A74800257CA2 /* HTTPSourcePlugin.m in Sources */,
176A6E470CC272E8000F60DE /* Semaphore.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -1,23 +0,0 @@
//
// Socket.h
// Cog
//
// Created by Vincent Spader on 2/28/07.
// Copyright 2007 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
//Rediculously simple socket wrapper
@interface Socket : NSObject {
int _fd;
}
+ (id)socketWithHost:(NSString *)host port:(unsigned int) port;
- (id)initWithHost:(NSString *)host port:(unsigned int)port;
- (int)send:(const void *)data amount:(unsigned int)amount;
- (int)receive:(void *)data amount:(unsigned int)amount;
- (void)close;
@end

View File

@ -1,76 +0,0 @@
//
// Socket.m
// Cog
//
// Created by Vincent Spader on 2/28/07.
// Copyright 2007 __MyCompanyName__. All rights reserved.
//
#import "Socket.h"
#import <netdb.h>
@implementation Socket
+ (id)socketWithHost:(NSString *)host port:(unsigned int)port
{
return [[[Socket alloc] initWithHost:host port:port] autorelease];
}
- (id)initWithHost:(NSString *)host port:(unsigned int) port
{
self = [super init];
if (self)
{
_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in sin;
struct hostent *he;
if (_fd < 0) {
return nil;
}
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
he = gethostbyname([host UTF8String]);
if (!he) {
NSLog(@"Socket error.");
close(_fd);
return nil;
}
memcpy(&sin.sin_addr, he->h_addr, 4);
if (connect(_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
NSLog(@"Error: %s\n", strerror(errno));
close(_fd);
return nil;
}
}
return self;
}
- (int)send:(const void *)data amount:(unsigned int)amount
{
return send(_fd, data, amount, 0);
}
- (int)receive:(void *)data amount:(unsigned int)amount
{
return recv(_fd, data, amount, 0);
}
- (void)close
{
close(_fd);
}
- (void)dealloc
{
[self close];
[super dealloc];
}
@end