HTTPSource now uses NSURLConnection.
parent
eedc659f84
commit
0091ccb447
|
@ -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
|
||||
|
|
|
@ -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"];
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue