From 8440605c277339770483a7daf31da7858bff2b38 Mon Sep 17 00:00:00 2001 From: Mark Slee Date: Tue, 20 Nov 2007 01:39:25 +0000 Subject: [PATCH] Cocoa Thrift binding patches from Andrew McGeachie Summary: Latest updates to the Cocoa bindings git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665354 13f79535-47bb-0310-9956-ffa450edef68 --- lib/cocoa/src/TApplicationException.h | 2 + lib/cocoa/src/TApplicationException.m | 27 +++++++++++ lib/cocoa/src/protocol/TBinaryProtocol.h | 4 ++ lib/cocoa/src/protocol/TBinaryProtocol.m | 20 ++++++++- lib/cocoa/src/server/TSocketServer.m | 45 ++++++++++++------- lib/cocoa/src/transport/THTTPClient.h | 2 + lib/cocoa/src/transport/THTTPClient.m | 29 ++++++++++-- .../src/transport/TNSFileHandleTransport.m | 8 ++-- lib/cocoa/src/transport/TNSStreamTransport.m | 22 ++++----- lib/cocoa/src/transport/TSocketClient.m | 6 ++- lib/cocoa/src/transport/TTransportException.h | 5 +++ lib/cocoa/src/transport/TTransportException.m | 20 +++++++++ 12 files changed, 151 insertions(+), 39 deletions(-) diff --git a/lib/cocoa/src/TApplicationException.h b/lib/cocoa/src/TApplicationException.h index 1fee06e4..90831f44 100644 --- a/lib/cocoa/src/TApplicationException.h +++ b/lib/cocoa/src/TApplicationException.h @@ -17,6 +17,8 @@ enum { + (TApplicationException *) read: (id ) protocol; +- (void) write: (id ) protocol; + + (TApplicationException *) exceptionWithType: (int) type reason: (NSString *) message; diff --git a/lib/cocoa/src/TApplicationException.m b/lib/cocoa/src/TApplicationException.m index 1f658de6..bace3606 100644 --- a/lib/cocoa/src/TApplicationException.m +++ b/lib/cocoa/src/TApplicationException.m @@ -6,6 +6,8 @@ - (id) initWithType: (int) type reason: (NSString *) reason { + mType = type; + NSString * name; switch (type) { case TApplicationException_UNKNOWN_METHOD: @@ -40,6 +42,8 @@ int fieldType; int fieldID; + [protocol readStructBeginReturningName: NULL]; + while (true) { [protocol readFieldBeginReturningName: NULL type: &fieldType @@ -74,6 +78,29 @@ } +- (void) write: (id ) protocol +{ + [protocol writeStructBeginWithName: @"TApplicationException"]; + + if ([self reason] != nil) { + [protocol writeFieldBeginWithName: @"message" + type: TType_STRING + fieldID: 1]; + [protocol writeString: [self reason]]; + [protocol writeFieldEnd]; + } + + [protocol writeFieldBeginWithName: @"type" + type: TType_I32 + fieldID: 2]; + [protocol writeI32: mType]; + [protocol writeFieldEnd]; + + [protocol writeFieldStop]; + [protocol writeStructEnd]; +} + + + (TApplicationException *) exceptionWithType: (int) type reason: (NSString *) reason { diff --git a/lib/cocoa/src/protocol/TBinaryProtocol.h b/lib/cocoa/src/protocol/TBinaryProtocol.h index 2c56740a..7e288fa0 100644 --- a/lib/cocoa/src/protocol/TBinaryProtocol.h +++ b/lib/cocoa/src/protocol/TBinaryProtocol.h @@ -7,6 +7,7 @@ id mTransport; BOOL mStrictRead; BOOL mStrictWrite; + int32_t mMessageSizeLimit; } - (id) initWithTransport: (id ) transport; @@ -15,6 +16,9 @@ strictRead: (BOOL) strictRead strictWrite: (BOOL) strictWrite; +- (int32_t) messageSizeLimit; +- (void) setMessageSizeLimit: (int32_t) sizeLimit; + @end; diff --git a/lib/cocoa/src/protocol/TBinaryProtocol.m b/lib/cocoa/src/protocol/TBinaryProtocol.m index 19db55f9..7564f5de 100644 --- a/lib/cocoa/src/protocol/TBinaryProtocol.m +++ b/lib/cocoa/src/protocol/TBinaryProtocol.m @@ -44,6 +44,18 @@ static TBinaryProtocolFactory * gSharedFactory = nil; } +- (int32_t) messageSizeLimit +{ + return mMessageSizeLimit; +} + + +- (void) setMessageSizeLimit: (int32_t) sizeLimit +{ + mMessageSizeLimit = sizeLimit; +} + + - (void) dealloc { [mTransport release]; @@ -70,7 +82,7 @@ static TBinaryProtocolFactory * gSharedFactory = nil; type: (int *) type sequenceID: (int *) sequenceID { - int size = [self readI32]; + int32_t size = [self readI32]; if (size < 0) { int version = size & VERSION_MASK; if (version != VERSION_1) { @@ -93,6 +105,12 @@ static TBinaryProtocolFactory * gSharedFactory = nil; @throw [TProtocolException exceptionWithName: @"TProtocolException" reason: @"Missing version in readMessageBegin, old client?"]; } + if ([self messageSizeLimit] > 0 && size > [self messageSizeLimit]) { + @throw [TProtocolException exceptionWithName: @"TProtocolException" + reason: [NSString stringWithFormat: @"Message too big. Size limit is: %d Message size is: %d", + mMessageSizeLimit, + size]]; + } NSString * messageName = [self readStringBody: size]; if (name != NULL) { *name = messageName; diff --git a/lib/cocoa/src/server/TSocketServer.m b/lib/cocoa/src/server/TSocketServer.m index a65d017b..d9d24e11 100644 --- a/lib/cocoa/src/server/TSocketServer.m +++ b/lib/cocoa/src/server/TSocketServer.m @@ -2,6 +2,7 @@ #import "TSocketServer.h" #import "TNSFileHandleTransport.h" #import "TProtocol.h" +#import "TTransportException.h" @implementation TSocketServer @@ -17,19 +18,28 @@ mProcessor = [processor retain]; // create a socket - mServerSocket = [[NSSocketPort alloc] initWithTCPPort: 8081]; - // wrap it in a file handle so we can get messages from it - mSocketFileHandle = [[NSFileHandle alloc] initWithFileDescriptor: [mServerSocket socket] - closeOnDealloc: YES]; - - // register for notifications of accepted incoming connections - [[NSNotificationCenter defaultCenter] addObserver: self - selector: @selector(connectionAccepted:) - name: NSFileHandleConnectionAcceptedNotification - object: mSocketFileHandle]; - - // tell socket to listen - [mSocketFileHandle acceptConnectionInBackgroundAndNotify]; + mServerSocket = [[NSSocketPort alloc] initWithTCPPort: port]; + // FIXME - move this separate start method and add method to close + // and cleanup any open ports + + if (mServerSocket == nil) { + NSLog(@"Unable to listen on TCP port %d", port); + } else { + NSLog(@"Listening on TCP port %d", port); + + // wrap it in a file handle so we can get messages from it + mSocketFileHandle = [[NSFileHandle alloc] initWithFileDescriptor: [mServerSocket socket] + closeOnDealloc: YES]; + + // register for notifications of accepted incoming connections + [[NSNotificationCenter defaultCenter] addObserver: self + selector: @selector(connectionAccepted:) + name: NSFileHandleConnectionAcceptedNotification + object: mSocketFileHandle]; + + // tell socket to listen + [mSocketFileHandle acceptConnectionInBackgroundAndNotify]; + } return self; } @@ -45,7 +55,7 @@ } -- (void) connentionAccepted: (NSNotification *) aNotification +- (void) connectionAccepted: (NSNotification *) aNotification { NSFileHandle * socket = [[aNotification userInfo] objectForKey: NSFileHandleNotificationFileHandleItem]; @@ -67,7 +77,12 @@ id inProtocol = [mInputProtocolFactory newProtocolOnTransport: transport]; id outProtocol = [mOutputProtocolFactory newProtocolOnTransport: transport]; - while ([mProcessor processOnInputProtocol: inProtocol outputProtocol: outProtocol]); + @try { + while ([mProcessor processOnInputProtocol: inProtocol outputProtocol: outProtocol]); + } + @catch (TTransportException * te) { + NSLog(@"%@", te); + } [pool release]; } diff --git a/lib/cocoa/src/transport/THTTPClient.h b/lib/cocoa/src/transport/THTTPClient.h index 98446cd4..802ff51e 100644 --- a/lib/cocoa/src/transport/THTTPClient.h +++ b/lib/cocoa/src/transport/THTTPClient.h @@ -14,5 +14,7 @@ - (id) initWithURL: (NSURL *) aURL timeout: (int) timeout; +- (void) setURL: (NSURL *) aURL; + @end diff --git a/lib/cocoa/src/transport/THTTPClient.m b/lib/cocoa/src/transport/THTTPClient.m index 45c0b80e..2e31a984 100644 --- a/lib/cocoa/src/transport/THTTPClient.m +++ b/lib/cocoa/src/transport/THTTPClient.m @@ -3,11 +3,13 @@ @implementation THTTPClient -- (id) initWithURL: (NSURL *) aURL -{ - self = [super init]; - mURL = [aURL retain]; +- (void) setupRequest +{ + if (mRequest != nil) { + [mRequest release]; + } + // set up our request object that we'll use for each request mRequest = [[NSMutableURLRequest alloc] initWithURL: mURL]; [mRequest setHTTPMethod: @"POST"]; @@ -15,6 +17,15 @@ [mRequest setValue: @"application/x-thrift" forHTTPHeaderField: @"Accept"]; [mRequest setValue: @"Cocoa/THTTPClient" forHTTPHeaderField: @"User-Agent"]; [mRequest setCachePolicy: NSURLRequestReloadIgnoringCacheData]; +} + + +- (id) initWithURL: (NSURL *) aURL +{ + self = [super init]; + mURL = [aURL retain]; + + [self setupRequest]; // create our request data buffer mRequestData = [[NSMutableData alloc] initWithCapacity: 1024]; @@ -34,6 +45,16 @@ } +- (void) setURL: (NSURL *) aURL +{ + [aURL retain]; + [mURL release]; + mURL = aURL; + + [self setupRequest]; +} + + - (void) dealloc { [mURL release]; diff --git a/lib/cocoa/src/transport/TNSFileHandleTransport.m b/lib/cocoa/src/transport/TNSFileHandleTransport.m index 7ad1ba7e..79a9e8d9 100644 --- a/lib/cocoa/src/transport/TNSFileHandleTransport.m +++ b/lib/cocoa/src/transport/TNSFileHandleTransport.m @@ -1,5 +1,6 @@ #import "TNSFileHandleTransport.h" +#import "TTransportException.h" @implementation TNSFileHandleTransport @@ -36,9 +37,8 @@ while (got < len) { NSData * d = [mInputFileHandle readDataOfLength: len-got]; if ([d length] == 0) { - @throw [NSException exceptionWithName: @"TTransportException" - reason: @"Cannot read. No more data." - userInfo: nil]; + @throw [TTransportException exceptionWithName: @"TTransportException" + reason: @"Cannot read. No more data."]; } [d getBytes: buf+got]; got += [d length]; @@ -62,7 +62,7 @@ - (void) flush { - [mOutputFileHandle synchronizeFile]; // ? + } @end diff --git a/lib/cocoa/src/transport/TNSStreamTransport.m b/lib/cocoa/src/transport/TNSStreamTransport.m index 8130a8b5..42a197e1 100644 --- a/lib/cocoa/src/transport/TNSStreamTransport.m +++ b/lib/cocoa/src/transport/TNSStreamTransport.m @@ -1,4 +1,6 @@ #import "TNSStreamTransport.h" +#import "TTransportException.h" + @implementation TNSStreamTransport @@ -29,9 +31,7 @@ while (got < len) { ret = [mInput read: buf+off+got maxLength: len-got]; if (ret <= 0) { - @throw [NSException exceptionWithName: @"TTransportException" - reason: @"Cannot read. Remote side has closed." - userInfo: nil]; + @throw [TTransportException exceptionWithReason: @"Cannot read. Remote side has closed."]; } got += ret; } @@ -39,23 +39,17 @@ } +// FIXME:geech:20071019 - make this write all - (void) write: (uint8_t *) data offset: (unsigned int) offset length: (unsigned int) length { int result = [mOutput write: data+offset maxLength: length]; if (result == -1) { - NSDictionary * errorInfo = [NSDictionary dictionaryWithObject: [mOutput streamError] - forKey: @"error"]; - @throw [NSException exceptionWithName: @"TTransportException" - reason: [NSString stringWithFormat: @"Error writing to transport output stream (%@).", [mOutput streamError]] - userInfo: errorInfo]; + @throw [TTransportException exceptionWithReason: @"Error writing to transport output stream." + error: [mOutput streamError]]; } else if (result == 0) { - @throw [NSException exceptionWithName: @"TTransportException" - reason: @"End of output stream." - userInfo: nil]; + @throw [TTransportException exceptionWithReason: @"End of output stream."]; } else if (result != length) { - @throw [NSException exceptionWithName: @"TTransportException" - reason: @"Output stream did not write all of our data." - userInfo: nil]; + @throw [TTransportException exceptionWithReason: @"Output stream did not write all of our data."]; } } diff --git a/lib/cocoa/src/transport/TSocketClient.m b/lib/cocoa/src/transport/TSocketClient.m index f3acc3bf..e8ae6e9e 100644 --- a/lib/cocoa/src/transport/TSocketClient.m +++ b/lib/cocoa/src/transport/TSocketClient.m @@ -14,7 +14,11 @@ inputStream: &input outputStream: &output]; - return [super initWithInputStream: input outputStream: output]; + self = [super initWithInputStream: input outputStream: output]; + [input open]; + [output open]; + + return self; } diff --git a/lib/cocoa/src/transport/TTransportException.h b/lib/cocoa/src/transport/TTransportException.h index 5d3802ba..7488ca52 100644 --- a/lib/cocoa/src/transport/TTransportException.h +++ b/lib/cocoa/src/transport/TTransportException.h @@ -3,4 +3,9 @@ @interface TTransportException : TException { } ++ (id) exceptionWithReason: (NSString *) reason + error: (NSError *) error; + ++ (id) exceptionWithReason: (NSString *) reason; + @end diff --git a/lib/cocoa/src/transport/TTransportException.m b/lib/cocoa/src/transport/TTransportException.m index e1102e21..3f829355 100644 --- a/lib/cocoa/src/transport/TTransportException.m +++ b/lib/cocoa/src/transport/TTransportException.m @@ -1,4 +1,24 @@ #import "TTransportException.h" @implementation TTransportException + ++ (id) exceptionWithReason: (NSString *) reason + error: (NSError *) error +{ + NSDictionary * userInfo = nil; + if (error != nil) { + userInfo = [NSDictionary dictionaryWithObject: error forKey: @"error"]; + } + + return [super exceptionWithName: @"TTransportException" + reason: reason + userInfo: userInfo]; +} + + ++ (id) exceptionWithReason: (NSString *) reason +{ + return [self exceptionWithReason: reason error: nil]; +} + @end -- 2.17.1