From 3cb3f116f49da699b11c48d4f6df48a636cb4bfd Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Mon, 31 May 2010 20:59:49 -0400 Subject: [PATCH] Finished enough of the basic refactoring to get things working. --- Source/DebuggerConnection.h | 31 ++++++++++-- Source/DebuggerConnection.m | 47 +++++++++++++++--- Source/DebuggerProcessor.h | 10 ++-- Source/DebuggerProcessor.m | 98 +++++++++++++------------------------ 4 files changed, 108 insertions(+), 78 deletions(-) diff --git a/Source/DebuggerConnection.h b/Source/DebuggerConnection.h index 1343d1f..7c5d526 100644 --- a/Source/DebuggerConnection.h +++ b/Source/DebuggerConnection.h @@ -16,15 +16,16 @@ #import +@protocol DebuggerConnectionDelegate; @class LoggingController; @interface DebuggerConnection : NSObject { // The port to connect on. - NSUInteger port; + NSUInteger port_; // If the connection to the debugger engine is currently active. - BOOL connected; + BOOL connected_; // The raw CFSocket on which the two streams are based. Strong. CFSocketRef socket_; @@ -67,9 +68,15 @@ int currentPacketIndex_; // The delegate. - id delegate_; + id delegate_; } +@property (readonly) NSUInteger port; +@property (readonly) BOOL connected; +@property (assign) id delegate; + +- (id)initWithPort:(NSUInteger)aPort; + - (void)connect; - (void)close; - (void)socketDidAccept; @@ -91,3 +98,21 @@ - (NSInteger)transactionIDFromCommand:(NSString*)command; @end + +// Delegate //////////////////////////////////////////////////////////////////// + +@protocol DebuggerConnectionDelegate + +@optional + +- (void)connectionDidAccept:(DebuggerConnection*)cx; +- (void)connectionDidCose:(DebuggerConnection*)cx; + +- (void)handleInitialResponse:(NSXMLDocument*)response; + +- (void)handleResponse:(NSXMLDocument*)response; + +- (void)errorEncountered:(NSString*)error; + +@end + diff --git a/Source/DebuggerConnection.m b/Source/DebuggerConnection.m index 190f15d..296c42b 100644 --- a/Source/DebuggerConnection.m +++ b/Source/DebuggerConnection.m @@ -171,6 +171,10 @@ void SocketAcceptCallback(CFSocketRef socket, @implementation DebuggerConnection +@synthesize port = port_; +@synthesize connected = connected_; +@synthesize delegate = delegate_; + @synthesize socket = socket_; @synthesize readStream = readStream_; @synthesize lastReadTransaction = lastReadTransaction_; @@ -179,6 +183,15 @@ void SocketAcceptCallback(CFSocketRef socket, @synthesize lastWrittenTransaction = lastWrittenTransaction_; @synthesize queuedWrites = queuedWrites_; +- (id)initWithPort:(NSUInteger)aPort +{ + if (self = [super init]) + { + port_ = aPort; + } + return self; +} + - (void)dealloc { self.currentPacket = nil; @@ -192,7 +205,7 @@ void SocketAcceptCallback(CFSocketRef socket, */ - (void)socketDidAccept { - connected = YES; + connected_ = YES; transactionID = 1; self.queuedWrites = [NSMutableArray array]; writeQueueLock_ = [NSRecursiveLock new]; @@ -225,7 +238,7 @@ void SocketAcceptCallback(CFSocketRef socket, memset(&address, 0, sizeof(address)); address.sin_len = sizeof(address); address.sin_family = AF_INET; - address.sin_port = htons(port); + address.sin_port = htons(port_); address.sin_addr.s_addr = htonl(INADDR_ANY); // Create the socket signature. @@ -275,7 +288,7 @@ void SocketAcceptCallback(CFSocketRef socket, - (void)socketDisconnected { [self close]; - [delegate_ debuggerDisconnected]; + [delegate_ connectionDidCose:self]; } /** @@ -503,7 +516,7 @@ void SocketAcceptCallback(CFSocketRef socket, if ([[[response rootElement] name] isEqualToString:@"init"]) { - [self initReceived:response]; + [delegate_ handleInitialResponse:response]; return; } @@ -511,7 +524,7 @@ void SocketAcceptCallback(CFSocketRef socket, if (callbackStr) { SEL callback = NSSelectorFromString(callbackStr); - [self performSelector:callback withObject:response]; + [delegate_ performSelector:callback withObject:response]; } [self sendQueuedWrites]; @@ -548,7 +561,7 @@ void SocketAcceptCallback(CFSocketRef socket, */ - (void)sendQueuedWrites { - if (!connected) + if (!connected_) return; [writeQueueLock_ lock]; @@ -590,4 +603,26 @@ void SocketAcceptCallback(CFSocketRef socket, return [transaction intValue]; } +/** + * Given a file path, this returns a file:// URI and escapes any spaces for the + * debugger engine. + */ +- (NSString*)escapedURIPath:(NSString*)path +{ + // Custon GDBp paths are fine. + if ([[path substringToIndex:4] isEqualToString:@"gdbp"]) + return path; + + // Create a temporary URL that will escape all the nasty characters. + NSURL* url = [NSURL fileURLWithPath:path]; + NSString* urlString = [url absoluteString]; + + // Remove the host because this is a file:// URL; + urlString = [urlString stringByReplacingOccurrencesOfString:[url host] withString:@""]; + + // Escape % for use in printf-style NSString formatters. + urlString = [urlString stringByReplacingOccurrencesOfString:@"%" withString:@"%%"]; + return urlString; +} + @end diff --git a/Source/DebuggerProcessor.h b/Source/DebuggerProcessor.h index edd027b..e5a4ca6 100644 --- a/Source/DebuggerProcessor.h +++ b/Source/DebuggerProcessor.h @@ -17,6 +17,7 @@ #import #import "Breakpoint.h" +#import "DebuggerConnection.h" #import "StackFrame.h" @protocol DebuggerProcessorDelegate; @@ -28,13 +29,10 @@ // primary unit that this class deals with is the StackFrame; clients should // maintain a stack structure and the Connection will inform the delegate when // a new frame is created or the stack should be destroyed. -@interface DebuggerProcessor : NSObject +@interface DebuggerProcessor : NSObject { - // The port to connect on. - NSUInteger port; - - // If the connection to the debugger engine is currently active. - BOOL connected; + // The connection to the debugger engine. + DebuggerConnection* connection_; // Human-readable status of the connection. NSString* status; diff --git a/Source/DebuggerProcessor.m b/Source/DebuggerProcessor.m index f4c68a7..5da5352 100644 --- a/Source/DebuggerProcessor.m +++ b/Source/DebuggerProcessor.m @@ -23,7 +23,6 @@ @interface DebuggerProcessor () @property (readwrite, copy) NSString* status; -- (void)initReceived:(NSXMLDocument*)response; - (void)updateStatus:(NSXMLDocument*)response; - (void)debuggerStep:(NSXMLDocument*)response; - (void)rebuildStack:(NSXMLDocument*)response; @@ -50,14 +49,13 @@ { if (self = [super init]) { - port = aPort; - connected = NO; - stackFrames_ = [[NSMutableDictionary alloc] init]; callbackContext_ = [NSMutableDictionary new]; [[BreakpointManager sharedManager] setConnection:self]; - [self connect]; + connection_ = [[DebuggerConnection alloc] initWithPort:aPort]; + connection_.delegate = self; + [connection_ connect]; } return self; } @@ -67,7 +65,7 @@ */ - (void)dealloc { - [self close]; + [connection_ close]; [stackFrames_ release]; [callbackContext_ release]; [super dealloc]; @@ -82,7 +80,7 @@ */ - (NSUInteger)port { - return port; + return [connection_ port]; } /** @@ -90,10 +88,9 @@ */ - (NSString*)remoteHost { - if (!connected) - { + if (![connection_ connected]) return @"(DISCONNECTED)"; - } + // TODO: Either impl or remove. return @""; } @@ -103,7 +100,7 @@ */ - (BOOL)isConnected { - return connected; + return [connection_ connected]; } // Commands //////////////////////////////////////////////////////////////////// @@ -115,9 +112,9 @@ */ - (void)reconnect { - [self close]; + [connection_ close]; self.status = @"Connecting"; - [self connect]; + [connection_ connect]; } /** @@ -125,7 +122,7 @@ */ - (void)run { - [self sendCommandWithCallback:@selector(debuggerStep:) format:@"run"]; + [connection_ sendCommandWithCallback:@selector(debuggerStep:) format:@"run"]; } /** @@ -133,7 +130,7 @@ */ - (void)stepIn { - [self sendCommandWithCallback:@selector(debuggerStep:) format:@"step_into"]; + [connection_ sendCommandWithCallback:@selector(debuggerStep:) format:@"step_into"]; } /** @@ -141,7 +138,7 @@ */ - (void)stepOut { - [self sendCommandWithCallback:@selector(debuggerStep:) format:@"step_out"]; + [connection_ sendCommandWithCallback:@selector(debuggerStep:) format:@"step_out"]; } /** @@ -149,7 +146,7 @@ */ - (void)stepOver { - [self sendCommandWithCallback:@selector(debuggerStep:) format:@"step_over"]; + [connection_ sendCommandWithCallback:@selector(debuggerStep:) format:@"step_over"]; } /** @@ -158,7 +155,7 @@ */ - (NSInteger)getProperty:(NSString*)property { - [self sendCommandWithCallback:@selector(propertiesReceived:) format:@"property_get -n \"%@\"", property]; + [connection_ sendCommandWithCallback:@selector(propertiesReceived:) format:@"property_get -n \"%@\"", property]; } // Breakpoint Management /////////////////////////////////////////////////////// @@ -169,11 +166,11 @@ */ - (void)addBreakpoint:(Breakpoint*)bp { - if (!connected) + if (![connection_ connected]) return; - NSString* file = [self escapedURIPath:[bp transformedPath]]; - NSNumber* transaction = [self sendCommandWithCallback:@selector(breakpointReceived:) + NSString* file = [connection_ escapedURIPath:[bp transformedPath]]; + NSNumber* transaction = [connection_ sendCommandWithCallback:@selector(breakpointReceived:) format:@"breakpoint_set -t line -f %@ -n %i", file, [bp line]]; [callbackContext_ setObject:bp forKey:transaction]; } @@ -183,12 +180,10 @@ */ - (void)removeBreakpoint:(Breakpoint*)bp { - if (!connected) - { + if (![connection_ connected]) return; - } - [self sendCommandWithCallback:nil format:@"breakpoint_remove -d %i", [bp debuggerId]]; + [connection_ sendCommandWithCallback:nil format:@"breakpoint_remove -d %i", [bp debuggerId]]; } // Specific Response Handlers ////////////////////////////////////////////////// @@ -197,7 +192,7 @@ /** * Initial packet received. We've started a brand-new connection to the engine. */ -- (void)initReceived:(NSXMLDocument*)response +- (void)handleInitialResponse:(NSXMLDocument*)response { // Register any breakpoints that exist offline. for (Breakpoint* bp in [[BreakpointManager sharedManager] breakpoints]) @@ -217,8 +212,7 @@ self.status = [[[[response rootElement] attributeForName:@"status"] stringValue] capitalizedString]; if (status == nil || [status isEqualToString:@"Stopped"] || [status isEqualToString:@"Stopping"]) { - connected = NO; - [self close]; + [connection_ close]; [delegate debuggerDisconnected]; self.status = @"Stopped"; @@ -232,7 +226,7 @@ - (void)debuggerStep:(NSXMLDocument*)response { [self updateStatus:response]; - if (!connected) + if (![connection_ connected]) return; // If this is the run command, tell the delegate that a bunch of updates @@ -244,7 +238,7 @@ if ([delegate respondsToSelector:@selector(clobberStack)]) [delegate clobberStack]; [stackFrames_ removeAllObjects]; - stackFirstTransactionID_ = [[self sendCommandWithCallback:@selector(rebuildStack:) format:@"stack_depth"] intValue]; + stackFirstTransactionID_ = [[connection_ sendCommandWithCallback:@selector(rebuildStack:) format:@"stack_depth"] intValue]; } } @@ -256,7 +250,7 @@ { NSInteger depth = [[[[response rootElement] attributeForName:@"depth"] stringValue] intValue]; - if (stackFirstTransactionID_ == [self transactionIDFromResponse:response]) + if (stackFirstTransactionID_ == [connection_ transactionIDFromResponse:response]) stackDepth_ = depth; // We now need to alloc a bunch of stack frames and get the basic information @@ -264,7 +258,7 @@ for (NSInteger i = 0; i < depth; i++) { // Use the transaction ID to create a routing path. - NSNumber* routingID = [self sendCommandWithCallback:@selector(getStackFrame:) format:@"stack_get -d %d", i]; + NSNumber* routingID = [connection_ sendCommandWithCallback:@selector(getStackFrame:) format:@"stack_get -d %d", i]; [stackFrames_ setObject:[StackFrame alloc] forKey:routingID]; } } @@ -276,7 +270,7 @@ - (void)getStackFrame:(NSXMLDocument*)response { // Get the routing information. - NSInteger routingID = [self transactionIDFromResponse:response]; + NSInteger routingID = [connection_ transactionIDFromResponse:response]; if (routingID < stackFirstTransactionID_) return; NSNumber* routingNumber = [NSNumber numberWithInt:routingID]; @@ -298,11 +292,11 @@ // Get the source code of the file. Escape % in URL chars. NSString* escapedFilename = [frame.filename stringByReplacingOccurrencesOfString:@"%" withString:@"%%"]; - NSNumber* transaction = [self sendCommandWithCallback:@selector(setSource:) format:@"source -f %@", escapedFilename]; + NSNumber* transaction = [connection_ sendCommandWithCallback:@selector(setSource:) format:@"source -f %@", escapedFilename]; [callbackContext_ setObject:routingNumber forKey:transaction]; // Get the names of all the contexts. - transaction = [self sendCommandWithCallback:@selector(contextsReceived:) format:@"context_names -d %d", frame.index]; + transaction = [connection_ sendCommandWithCallback:@selector(contextsReceived:) format:@"context_names -d %d", frame.index]; [callbackContext_ setObject:routingNumber forKey:transaction]; if ([delegate respondsToSelector:@selector(newStackFrame:)]) @@ -315,7 +309,7 @@ */ - (void)setSource:(NSXMLDocument*)response { - NSNumber* transaction = [NSNumber numberWithInt:[self transactionIDFromResponse:response]]; + NSNumber* transaction = [NSNumber numberWithInt:[connection_ transactionIDFromResponse:response]]; if ([transaction intValue] < stackFirstTransactionID_) return; NSNumber* routingNumber = [callbackContext_ objectForKey:transaction]; @@ -340,7 +334,7 @@ - (void)contextsReceived:(NSXMLDocument*)response { // Get the stack frame's routing ID and use it again. - NSNumber* receivedTransaction = [NSNumber numberWithInt:[self transactionIDFromResponse:response]]; + NSNumber* receivedTransaction = [NSNumber numberWithInt:[connection_ transactionIDFromResponse:response]]; if ([receivedTransaction intValue] < stackFirstTransactionID_) return; NSNumber* routingID = [callbackContext_ objectForKey:receivedTransaction]; @@ -356,7 +350,7 @@ NSInteger cid = [[[context attributeForName:@"id"] stringValue] intValue]; // Fetch each context's variables. - NSNumber* transaction = [self sendCommandWithCallback:@selector(variablesReceived:) + NSNumber* transaction = [connection_ sendCommandWithCallback:@selector(variablesReceived:) format:@"context_get -d %d -c %d", frame.index, cid]; [callbackContext_ setObject:routingID forKey:transaction]; } @@ -368,7 +362,7 @@ - (void)variablesReceived:(NSXMLDocument*)response { // Get the stack frame's routing ID and use it again. - NSInteger transaction = [self transactionIDFromResponse:response]; + NSInteger transaction = [connection_ transactionIDFromResponse:response]; if (transaction < stackFirstTransactionID_) return; NSNumber* receivedTransaction = [NSNumber numberWithInt:transaction]; @@ -398,7 +392,7 @@ */ - (void)propertiesReceived:(NSXMLDocument*)response { - NSInteger transaction = [self transactionIDFromResponse:response]; + NSInteger transaction = [connection_ transactionIDFromResponse:response]; /* @@ -421,7 +415,7 @@ */ - (void)breakpointReceived:(NSXMLDocument*)response { - NSNumber* transaction = [NSNumber numberWithInt:[self transactionIDFromResponse:response]]; + NSNumber* transaction = [NSNumber numberWithInt:[connection_ transactionIDFromResponse:response]]; Breakpoint* bp = [callbackContext_ objectForKey:transaction]; if (!bp) return; @@ -430,26 +424,4 @@ [bp setDebuggerId:[[[[response rootElement] attributeForName:@"id"] stringValue] intValue]]; } -/** - * Given a file path, this returns a file:// URI and escapes any spaces for the - * debugger engine. - */ -- (NSString*)escapedURIPath:(NSString*)path -{ - // Custon GDBp paths are fine. - if ([[path substringToIndex:4] isEqualToString:@"gdbp"]) - return path; - - // Create a temporary URL that will escape all the nasty characters. - NSURL* url = [NSURL fileURLWithPath:path]; - NSString* urlString = [url absoluteString]; - - // Remove the host because this is a file:// URL; - urlString = [urlString stringByReplacingOccurrencesOfString:[url host] withString:@""]; - - // Escape % for use in printf-style NSString formatters. - urlString = [urlString stringByReplacingOccurrencesOfString:@"%" withString:@"%%"]; - return urlString; -} - @end -- 2.43.5