From 6df06684267cc4dc13cac807b8d9706496a7f3b1 Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Sat, 19 Feb 2011 12:40:42 -0500 Subject: [PATCH] Move dealing with the socket into NetworkCallbackController. --- Source/DebuggerBackEnd.h | 1 + Source/DebuggerBackEnd.m | 12 ++++++ Source/DebuggerController.m | 2 +- Source/NetworkCallbackController.h | 14 ++++++- Source/NetworkCallbackController.mm | 65 ++++++++++++++++++++++++++++- Source/NetworkConnection.h | 3 -- Source/NetworkConnection.mm | 57 ++----------------------- Source/NetworkConnectionPrivate.h | 1 - 8 files changed, 94 insertions(+), 61 deletions(-) diff --git a/Source/DebuggerBackEnd.h b/Source/DebuggerBackEnd.h index f95a4ed..255b585 100644 --- a/Source/DebuggerBackEnd.h +++ b/Source/DebuggerBackEnd.h @@ -80,6 +80,7 @@ - (void)stepIn; - (void)stepOut; - (void)stepOver; +- (void)stop; - (void)detach; // Breakpoint management. diff --git a/Source/DebuggerBackEnd.m b/Source/DebuggerBackEnd.m index 96ca92b..92cd9d5 100644 --- a/Source/DebuggerBackEnd.m +++ b/Source/DebuggerBackEnd.m @@ -138,6 +138,18 @@ [self recordCallback:@selector(debuggerStep:) forTransaction:tx]; } +/** + * Halts execution of the script. + */ +- (void)stop +{ + [connection_ close]; + active_ = NO; + self.status = @"Stopped"; + if ([delegate respondsToSelector:@selector(debuggerDisconnected)]) + [delegate debuggerDisconnected]; +} + /** * Ends the current debugging session. */ diff --git a/Source/DebuggerController.m b/Source/DebuggerController.m index efd037e..db02575 100644 --- a/Source/DebuggerController.m +++ b/Source/DebuggerController.m @@ -209,7 +209,7 @@ */ - (IBAction)stop:(id)sender { - [connection detach]; + [connection stop]; } - (void)fetchChildProperties:(VariableNode*)node diff --git a/Source/NetworkCallbackController.h b/Source/NetworkCallbackController.h index d8da7d5..de6cc32 100644 --- a/Source/NetworkCallbackController.h +++ b/Source/NetworkCallbackController.h @@ -15,6 +15,7 @@ */ #import +#import @class NetworkConnection; @@ -29,6 +30,13 @@ class NetworkCallbackController // thread. NetworkCallbackController(NetworkConnection* connection); + // Creates a socket and schedules it on the current run loop. + void OpenConnection(NSUInteger port); + + // Closes down the read/write streams. + void CloseConnection(); + + private: // These static methods forward an invocation to the instance methods. The // last void pointer, named |self|, is the instance of this class. static void SocketAcceptCallback(CFSocketRef socket, @@ -43,7 +51,6 @@ class NetworkCallbackController CFStreamEventType eventType, void* self); - private: void OnSocketAccept(CFSocketRef socket, CFDataRef address, const void* data); @@ -57,7 +64,10 @@ class NetworkCallbackController // Messages the NetworkConnection's delegate and takes ownership of |error|. void ReportError(CFErrorRef error); - + + // The actual socket. + CFSocketRef socket_; // Strong. + NetworkConnection* connection_; // Weak, owns this. CFRunLoopRef runLoop_; // Weak. }; diff --git a/Source/NetworkCallbackController.mm b/Source/NetworkCallbackController.mm index 28958ed..b2d79f2 100644 --- a/Source/NetworkCallbackController.mm +++ b/Source/NetworkCallbackController.mm @@ -16,6 +16,9 @@ #import "NetworkCallbackController.h" +#import +#import + #import "NetworkConnection.h" #import "NetworkConnectionPrivate.h" @@ -25,6 +28,63 @@ NetworkCallbackController::NetworkCallbackController(NetworkConnection* connecti { } +void NetworkCallbackController::OpenConnection(NSUInteger port) +{ + // Pass ourselves to the callback so we don't have to use ugly globals. + CFSocketContext context = { 0 }; + context.info = this; + + // Create the address structure. + struct sockaddr_in address; + memset(&address, 0, sizeof(address)); + address.sin_len = sizeof(address); + address.sin_family = AF_INET; + address.sin_port = htons(port); + address.sin_addr.s_addr = htonl(INADDR_ANY); + + // Create the socket signature. + CFSocketSignature signature; + signature.protocolFamily = PF_INET; + signature.socketType = SOCK_STREAM; + signature.protocol = IPPROTO_TCP; + signature.address = (CFDataRef)[NSData dataWithBytes:&address length:sizeof(address)]; + + do { + socket_ = CFSocketCreateWithSocketSignature(kCFAllocatorDefault, + &signature, // Socket signature. + kCFSocketAcceptCallBack, // Callback types. + &NetworkCallbackController::SocketAcceptCallback, // Callout function pointer. + &context); // Context to pass to callout. + if (!socket_) { + [connection_ errorEncountered:@"Could not open socket."]; + sleep(1); + } + } while (!socket_); + + // Allow old, yet-to-be recycled sockets to be reused. + BOOL yes = YES; + setsockopt(CFSocketGetNative(socket_), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(BOOL)); + setsockopt(CFSocketGetNative(socket_), SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(BOOL)); + + // Schedule the socket on the run loop. + CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket_, 0); + CFRunLoopAddSource(runLoop_, source, kCFRunLoopCommonModes); + CFRelease(source); +} + +void NetworkCallbackController::CloseConnection() +{ + if (socket_) { + NSLog(@"invalidating socket %d", close(CFSocketGetNative(socket_))); + CFSocketInvalidate(socket_); + NSLog(@"socket is valid %d", CFSocketIsValid(socket_)); + CFRelease(socket_); + socket_ = NULL; + } + UnscheduleReadStream(); + UnscheduleWriteStream(); +} + // Static Methods ////////////////////////////////////////////////////////////// void NetworkCallbackController::SocketAcceptCallback(CFSocketRef socket, @@ -116,15 +176,18 @@ void NetworkCallbackController::OnReadStreamEvent(CFReadStreamRef stream, switch (eventType) { case kCFStreamEventHasBytesAvailable: - [connection_ readStreamHasData]; + if (connection_.readStream) + [connection_ readStreamHasData]; break; case kCFStreamEventErrorOccurred: + NSLog(@"%s error", __PRETTY_FUNCTION__); ReportError(CFReadStreamCopyError(stream)); UnscheduleReadStream(); break; case kCFStreamEventEndEncountered: + NSLog(@"%s end", __PRETTY_FUNCTION__); UnscheduleReadStream(); [connection_ socketDisconnected]; break; diff --git a/Source/NetworkConnection.h b/Source/NetworkConnection.h index efd0163..d34d7ce 100644 --- a/Source/NetworkConnection.h +++ b/Source/NetworkConnection.h @@ -46,9 +46,6 @@ class NetworkCallbackController; // Internal class that manages CFNetwork callbacks. Strong. NetworkCallbackController* callbackController_; - // The raw CFSocket on which the two streams are based. Strong. - CFSocketRef socket_; - // The read stream that is scheduled on the main run loop. Weak. CFReadStreamRef readStream_; diff --git a/Source/NetworkConnection.mm b/Source/NetworkConnection.mm index 41227d3..894b1d7 100644 --- a/Source/NetworkConnection.mm +++ b/Source/NetworkConnection.mm @@ -17,9 +17,6 @@ #import "NetworkConnection.h" #import "NetworkConnectionPrivate.h" -#import -#import - #import "AppDelegate.h" #import "LoggingController.h" #include "NetworkCallbackController.h" @@ -40,7 +37,6 @@ void PerformQuitSignal(void* info) @synthesize connected = connected_; @synthesize delegate = delegate_; -@synthesize socket = socket_; @synthesize readStream = readStream_; @synthesize lastReadTransaction = lastReadTransaction_; @synthesize currentPacket = currentPacket_; @@ -88,47 +84,6 @@ void PerformQuitSignal(void* info) runLoop_ = [NSRunLoop currentRunLoop]; callbackController_ = new NetworkCallbackController(self); - // Pass ourselves to the callback so we don't have to use ugly globals. - CFSocketContext context = { 0 }; - context.info = callbackController_; - - // Create the address structure. - struct sockaddr_in address; - memset(&address, 0, sizeof(address)); - address.sin_len = sizeof(address); - address.sin_family = AF_INET; - address.sin_port = htons(port_); - address.sin_addr.s_addr = htonl(INADDR_ANY); - - // Create the socket signature. - CFSocketSignature signature; - signature.protocolFamily = PF_INET; - signature.socketType = SOCK_STREAM; - signature.protocol = IPPROTO_TCP; - signature.address = (CFDataRef)[NSData dataWithBytes:&address length:sizeof(address)]; - - do { - socket_ = CFSocketCreateWithSocketSignature(kCFAllocatorDefault, - &signature, // Socket signature. - kCFSocketAcceptCallBack, // Callback types. - &NetworkCallbackController::SocketAcceptCallback, // Callout function pointer. - &context); // Context to pass to callout. - if (!socket_) { - [self errorEncountered:@"Could not open socket."]; - sleep(1); - } - } while (!socket_); - - // Allow old, yet-to-be recycled sockets to be reused. - BOOL yes = YES; - setsockopt(CFSocketGetNative(socket_), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(BOOL)); - setsockopt(CFSocketGetNative(socket_), SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(BOOL)); - - // Schedule the socket on the run loop. - CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket_, 0); - CFRunLoopAddSource([runLoop_ getCFRunLoop], source, kCFRunLoopCommonModes); - CFRelease(source); - // Create a source that is used to quit. CFRunLoopSourceContext quitContext = { 0 }; quitContext.info = self; @@ -136,6 +91,8 @@ void PerformQuitSignal(void* info) quitSource_ = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &quitContext); CFRunLoopAddSource([runLoop_ getCFRunLoop], quitSource_, kCFRunLoopCommonModes); + callbackController_->OpenConnection(port_); + CFRunLoopRun(); thread_ = nil; @@ -195,14 +152,8 @@ void PerformQuitSignal(void* info) if (runLoop_) { CFRunLoopStop([runLoop_ getCFRunLoop]); } - - // The socket goes down, so do the streams, which clean themselves up. - if (socket_) { - NSLog(@"invalidating socket"); - CFSocketInvalidate(socket_); - CFRelease(socket_); - socket_ = NULL; - } + + callbackController_->CloseConnection(); } /** diff --git a/Source/NetworkConnectionPrivate.h b/Source/NetworkConnectionPrivate.h index 5cf9070..3b8f7f4 100644 --- a/Source/NetworkConnectionPrivate.h +++ b/Source/NetworkConnectionPrivate.h @@ -20,7 +20,6 @@ // by the C++ NetworkCallbackController to communicate. @interface NetworkConnection () -@property (assign) CFSocketRef socket; @property (assign) CFReadStreamRef readStream; @property NSUInteger lastReadTransaction; @property (retain) NSMutableString* currentPacket; -- 2.22.5