From fc479ea3baa9d15d7e37c87360820c073f2e3019 Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Wed, 1 Jan 2014 21:50:10 -0500 Subject: [PATCH] Remove the thin layer around ProtocolClient that is NetworkConnection. --- MacGDBp.xcodeproj/project.pbxproj | 8 +- Source/DebuggerBackEnd.h | 7 +- Source/DebuggerBackEnd.m | 128 +++++++++++++++----------- Source/NetworkConnection.h | 70 --------------- Source/NetworkConnection.m | 143 ------------------------------ Source/ProtocolClient.h | 4 + Source/ProtocolClient.m | 17 ++++ 7 files changed, 105 insertions(+), 272 deletions(-) delete mode 100644 Source/NetworkConnection.h delete mode 100644 Source/NetworkConnection.m diff --git a/MacGDBp.xcodeproj/project.pbxproj b/MacGDBp.xcodeproj/project.pbxproj index 330a3ca..8457284 100644 --- a/MacGDBp.xcodeproj/project.pbxproj +++ b/MacGDBp.xcodeproj/project.pbxproj @@ -48,7 +48,6 @@ 1EEBFD090D3599E8008F835B /* BSSplitView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EEBFD070D3599E8008F835B /* BSSplitView.m */; }; 1EEBFD120D359A9F008F835B /* dimple.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EEBFD110D359A9F008F835B /* dimple.png */; }; 1EEE875D0D9DE4B4009CBA7C /* MacGDBp.icns in Resources */ = {isa = PBXBuildFile; fileRef = 1EEE875C0D9DE4B4009CBA7C /* MacGDBp.icns */; }; - 1EFBE63012C515C200F96D6E /* NetworkConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EFBE62F12C515C200F96D6E /* NetworkConnection.m */; }; 1EFF70C30DFDC018006B9D33 /* BreakpointController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EFF70C20DFDC018006B9D33 /* BreakpointController.m */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; @@ -80,7 +79,6 @@ 1E02C5700C610158006F1752 /* DebuggerBackEnd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DebuggerBackEnd.m; path = Source/DebuggerBackEnd.m; sourceTree = ""; }; 1E02C5F40C610724006F1752 /* DebuggerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DebuggerController.h; path = Source/DebuggerController.h; sourceTree = ""; }; 1E02C5F50C610724006F1752 /* DebuggerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DebuggerController.m; path = Source/DebuggerController.m; sourceTree = ""; }; - 1E0724E111B47BCC0017AD3C /* NetworkConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkConnection.h; path = Source/NetworkConnection.h; sourceTree = ""; }; 1E0AFBB80FC2518700C67031 /* HUDIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = HUDIcon.png; path = Icons/HUDIcon.png; sourceTree = ""; }; 1E108E3E136CC8B9002E34E0 /* EvalController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EvalController.h; path = Source/EvalController.h; sourceTree = ""; }; 1E108E3F136CC8B9002E34E0 /* EvalController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EvalController.m; path = Source/EvalController.m; sourceTree = ""; }; @@ -136,7 +134,6 @@ 1EEBFD080D3599E8008F835B /* BSSplitView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BSSplitView.h; path = Source/BSSplitView.h; sourceTree = ""; }; 1EEBFD110D359A9F008F835B /* dimple.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = dimple.png; sourceTree = ""; }; 1EEE875C0D9DE4B4009CBA7C /* MacGDBp.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = MacGDBp.icns; path = Icons/MacGDBp.icns; sourceTree = ""; }; - 1EFBE62F12C515C200F96D6E /* NetworkConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NetworkConnection.m; path = Source/NetworkConnection.m; sourceTree = ""; }; 1EFF70C10DFDC018006B9D33 /* BreakpointController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointController.h; path = Source/BreakpointController.h; sourceTree = ""; }; 1EFF70C20DFDC018006B9D33 /* BreakpointController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BreakpointController.m; path = Source/BreakpointController.m; sourceTree = ""; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; @@ -232,8 +229,6 @@ 1E1E52C10DF9B1FB00D334F9 /* Connection */ = { isa = PBXGroup; children = ( - 1E0724E111B47BCC0017AD3C /* NetworkConnection.h */, - 1EFBE62F12C515C200F96D6E /* NetworkConnection.m */, 1E02C56F0C610158006F1752 /* DebuggerBackEnd.h */, 1E02C5700C610158006F1752 /* DebuggerBackEnd.m */, 1E35FFB00C65A74C0030F527 /* NSXMLElementAdditions.h */, @@ -399,6 +394,8 @@ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; + attributes = { + }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MacGDBp" */; compatibilityVersion = "Xcode 3.1"; developmentRegion = English; @@ -484,7 +481,6 @@ 1E6B5947116106FE001189D2 /* LoggingController.m in Sources */, 1EC1337E127DBB00007946FC /* VariableNode.m in Sources */, 1EC6965812BBC6A700A8D984 /* modp_b64.cc in Sources */, - 1EFBE63012C515C200F96D6E /* NetworkConnection.m in Sources */, 1EDA9CF812DD13B300596211 /* BSLineNumberRulerView.mm in Sources */, 1E11814A1319805E003BFEF1 /* BSSourceViewTextView.m in Sources */, 1E108E40136CC8B9002E34E0 /* EvalController.m in Sources */, diff --git a/Source/DebuggerBackEnd.h b/Source/DebuggerBackEnd.h index 25d7851..55963a3 100644 --- a/Source/DebuggerBackEnd.h +++ b/Source/DebuggerBackEnd.h @@ -17,7 +17,7 @@ #import #import "Breakpoint.h" -#import "NetworkConnection.h" +#import "ProtocolClient.h" #import "StackFrame.h" @protocol DebuggerBackEndDelegate; @@ -30,10 +30,11 @@ // primary unit that this class deals with is the StackFrame; clients should // maintain a stack structure and the BackEnd will inform the delegate when // a new frame is created or the stack should be destroyed. -@interface DebuggerBackEnd : NSObject +@interface DebuggerBackEnd : NSObject { // The connection to the debugger engine. - NetworkConnection* connection_; + NSUInteger port_; + ProtocolClient* client_; // Human-readable status of the connection. NSString* status; diff --git a/Source/DebuggerBackEnd.m b/Source/DebuggerBackEnd.m index 4ce0c08..64a21d9 100644 --- a/Source/DebuggerBackEnd.m +++ b/Source/DebuggerBackEnd.m @@ -60,13 +60,13 @@ callTable_ = [NSMutableDictionary new]; [[BreakpointManager sharedManager] setConnection:self]; - connection_ = [[NetworkConnection alloc] initWithPort:aPort]; - connection_.delegate = self; + port_ = aPort; + client_ = [[ProtocolClient alloc] initWithDelegate:self]; attached_ = [[NSUserDefaults standardUserDefaults] boolForKey:@"DebuggerAttached"]; if (self.attached) - [connection_ connect]; + [client_ connectOnPort:port_]; } return self; } @@ -76,7 +76,7 @@ */ - (void)dealloc { - [connection_ close]; + [client_ release]; [stackFrames_ release]; [callTable_ release]; [callbackContext_ release]; @@ -92,7 +92,7 @@ */ - (NSUInteger)port { - return [connection_ port]; + return port_; } /** @@ -100,7 +100,7 @@ */ - (BOOL)isConnected { - return [connection_ connected] && active_; + return active_; } /** @@ -110,9 +110,9 @@ - (void)setAttached:(BOOL)attached { if (attached != attached_) { if (!attached) - [connection_ close]; + [client_ connectOnPort:port_]; else - [connection_ connect]; + [client_ disconnect]; } attached_ = attached; } @@ -125,7 +125,7 @@ */ - (void)run { - NSNumber* tx = [connection_ sendCommandWithFormat:@"run"]; + NSNumber* tx = [client_ sendCommandWithFormat:@"run"]; [self recordCallback:@selector(debuggerStep:) forTransaction:tx]; } @@ -134,7 +134,7 @@ */ - (void)stepIn { - NSNumber* tx = [connection_ sendCommandWithFormat:@"step_into"]; + NSNumber* tx = [client_ sendCommandWithFormat:@"step_into"]; [self recordCallback:@selector(debuggerStep:) forTransaction:tx]; } @@ -143,7 +143,7 @@ */ - (void)stepOut { - NSNumber* tx = [connection_ sendCommandWithFormat:@"step_out"]; + NSNumber* tx = [client_ sendCommandWithFormat:@"step_out"]; [self recordCallback:@selector(debuggerStep:) forTransaction:tx]; } @@ -152,7 +152,7 @@ */ - (void)stepOver { - NSNumber* tx = [connection_ sendCommandWithFormat:@"step_over"]; + NSNumber* tx = [client_ sendCommandWithFormat:@"step_over"]; [self recordCallback:@selector(debuggerStep:) forTransaction:tx]; } @@ -161,7 +161,7 @@ */ - (void)stop { - [connection_ close]; + [client_ disconnect]; active_ = NO; self.status = @"Stopped"; } @@ -171,7 +171,7 @@ */ - (void)detach { - [connection_ sendCommandWithFormat:@"detach"]; + [client_ sendCommandWithFormat:@"detach"]; active_ = NO; self.status = @"Stopped"; } @@ -182,7 +182,7 @@ */ - (NSInteger)getChildrenOfProperty:(VariableNode*)property atDepth:(NSInteger)depth; { - NSNumber* tx = [connection_ sendCommandWithFormat:@"property_get -d %d -n %@", depth, [property fullName]]; + NSNumber* tx = [client_ sendCommandWithFormat:@"property_get -d %d -n %@", depth, [property fullName]]; [self recordCallback:@selector(propertiesReceived:) forTransaction:tx]; return [tx intValue]; } @@ -198,13 +198,13 @@ // Get the source code of the file. Escape % in URL chars. if ([frame.filename length]) { NSString* escapedFilename = [frame.filename stringByReplacingOccurrencesOfString:@"%" withString:@"%%"]; - transaction = [connection_ sendCommandWithFormat:@"source -f %@", escapedFilename]; + transaction = [client_ sendCommandWithFormat:@"source -f %@", escapedFilename]; [self recordCallback:@selector(setSource:) forTransaction:transaction]; [callbackContext_ setObject:routingNumber forKey:transaction]; } // Get the names of all the contexts. - transaction = [connection_ sendCommandWithFormat:@"context_names -d %d", frame.index]; + transaction = [client_ sendCommandWithFormat:@"context_names -d %d", frame.index]; [self recordCallback:@selector(contextsReceived:) forTransaction:transaction]; [callbackContext_ setObject:routingNumber forKey:transaction]; @@ -220,11 +220,11 @@ */ - (void)addBreakpoint:(Breakpoint*)bp { - if (![connection_ connected]) + if (!active_) return; - NSString* file = [connection_ escapedURIPath:[bp transformedPath]]; - NSNumber* tx = [connection_ sendCommandWithFormat:@"breakpoint_set -t line -f %@ -n %i", file, [bp line]]; + NSString* file = [ProtocolClient escapedFilePathURI:[bp transformedPath]]; + NSNumber* tx = [client_ sendCommandWithFormat:@"breakpoint_set -t line -f %@ -n %i", file, [bp line]]; [self recordCallback:@selector(breakpointReceived:) forTransaction:tx]; [callbackContext_ setObject:bp forKey:tx]; } @@ -234,10 +234,10 @@ */ - (void)removeBreakpoint:(Breakpoint*)bp { - if (![connection_ connected]) + if (!active_) return; - [connection_ sendCommandWithFormat:@"breakpoint_remove -d %i", [bp debuggerId]]; + [client_ sendCommandWithFormat:@"breakpoint_remove -d %i", [bp debuggerId]]; } /** @@ -245,17 +245,58 @@ */ - (void)evalScript:(NSString*)str { - if (![connection_ connected]) + if (!active_) return; char* encodedString = malloc(modp_b64_encode_len([str length])); modp_b64_encode(encodedString, [str UTF8String], [str length]); - NSNumber* tx = [connection_ sendCustomCommandWithFormat:@"eval -i {txn} -- %s", encodedString]; + NSNumber* tx = [client_ sendCustomCommandWithFormat:@"eval -i {txn} -- %s", encodedString]; free(encodedString); [self recordCallback:@selector(evalScriptReceived:) forTransaction:tx]; } +// Protocol Client Delegate //////////////////////////////////////////////////// +#pragma mark Protocol Client Delegate + +- (void)debuggerEngineConnected:(ProtocolClient*)client +{ + active_ = YES; +} + +/** + * Called when the connection is finally closed. This will reopen the listening + * socket if the debugger remains attached. + */ +- (void)debuggerEngineDisconnected:(ProtocolClient*)client +{ + active_ = NO; + + if ([delegate respondsToSelector:@selector(debuggerDisconnected)]) + [delegate debuggerDisconnected]; + + if (self.attached) + [client_ connectOnPort:port_]; +} + +- (void)debuggerEngine:(ProtocolClient*)client receivedMessage:(NSXMLDocument*)message +{ + // Check and see if there's an error. + NSArray* error = [[message rootElement] elementsForName:@"error"]; + if ([error count] > 0) { + NSLog(@"Xdebug error: %@", error); + NSString* errorMessage = [[[[error objectAtIndex:0] children] objectAtIndex:0] stringValue]; + [self errorEncountered:errorMessage]; + } + + if ([[[message rootElement] name] isEqualToString:@"init"]) { + [self handleInitialResponse:message]; + return; + } + + [self handleResponse:message]; +} + // Specific Response Handlers ////////////////////////////////////////////////// #pragma mark Response Handlers @@ -270,7 +311,7 @@ - (void)handleInitialResponse:(NSXMLDocument*)response { if (!self.attached) { - [connection_ sendCommandWithFormat:@"detach"]; + [client_ sendCommandWithFormat:@"detach"]; return; } @@ -286,22 +327,9 @@ // TODO: update the status. } -/** - * Called when the connection is finally closed. This will reopen the listening - * socket if the debugger remains attached. - */ -- (void)connectionDidClose:(NetworkConnection*)connection -{ - if ([delegate respondsToSelector:@selector(debuggerDisconnected)]) - [delegate debuggerDisconnected]; - - if (self.attached) - [connection_ connect]; -} - - (void)handleResponse:(NSXMLDocument*)response { - NSInteger transactionID = [connection_ transactionIDFromResponse:response]; + NSInteger transactionID = [client_ transactionIDFromResponse:response]; NSNumber* key = [NSNumber numberWithInt:transactionID]; NSString* callbackStr = [callTable_ objectForKey:key]; if (callbackStr) @@ -323,7 +351,7 @@ [delegate debuggerDisconnected]; active_ = NO; } else if ([status isEqualToString:@"Stopping"]) { - [connection_ sendCommandWithFormat:@"stop"]; + [client_ sendCommandWithFormat:@"stop"]; active_ = NO; } } @@ -343,7 +371,7 @@ if ([delegate respondsToSelector:@selector(clobberStack)]) [delegate clobberStack]; [stackFrames_ removeAllObjects]; - NSNumber* tx = [connection_ sendCommandWithFormat:@"stack_depth"]; + NSNumber* tx = [client_ sendCommandWithFormat:@"stack_depth"]; [self recordCallback:@selector(rebuildStack:) forTransaction:tx]; stackFirstTransactionID_ = [tx intValue]; } @@ -356,7 +384,7 @@ { NSInteger depth = [[[[response rootElement] attributeForName:@"depth"] stringValue] intValue]; - if (stackFirstTransactionID_ == [connection_ transactionIDFromResponse:response]) + if (stackFirstTransactionID_ == [client_ transactionIDFromResponse:response]) stackDepth_ = depth; // We now need to alloc a bunch of stack frames and get the basic information @@ -364,7 +392,7 @@ for (NSInteger i = 0; i < depth; i++) { // Use the transaction ID to create a routing path. - NSNumber* routingID = [connection_ sendCommandWithFormat:@"stack_get -d %d", i]; + NSNumber* routingID = [client_ sendCommandWithFormat:@"stack_get -d %d", i]; [self recordCallback:@selector(getStackFrame:) forTransaction:routingID]; [stackFrames_ setObject:[[StackFrame new] autorelease] forKey:routingID]; } @@ -377,7 +405,7 @@ - (void)getStackFrame:(NSXMLDocument*)response { // Get the routing information. - NSInteger routingID = [connection_ transactionIDFromResponse:response]; + NSInteger routingID = [client_ transactionIDFromResponse:response]; if (routingID < stackFirstTransactionID_) return; NSNumber* routingNumber = [NSNumber numberWithInt:routingID]; @@ -412,7 +440,7 @@ */ - (void)setSource:(NSXMLDocument*)response { - NSNumber* transaction = [NSNumber numberWithInt:[connection_ transactionIDFromResponse:response]]; + NSNumber* transaction = [NSNumber numberWithInt:[client_ transactionIDFromResponse:response]]; if ([transaction intValue] < stackFirstTransactionID_) return; NSNumber* routingNumber = [callbackContext_ objectForKey:transaction]; @@ -437,7 +465,7 @@ - (void)contextsReceived:(NSXMLDocument*)response { // Get the stack frame's routing ID and use it again. - NSNumber* receivedTransaction = [NSNumber numberWithInt:[connection_ transactionIDFromResponse:response]]; + NSNumber* receivedTransaction = [NSNumber numberWithInt:[client_ transactionIDFromResponse:response]]; if ([receivedTransaction intValue] < stackFirstTransactionID_) return; NSNumber* routingID = [callbackContext_ objectForKey:receivedTransaction]; @@ -453,7 +481,7 @@ NSInteger cid = [[[context attributeForName:@"id"] stringValue] intValue]; // Fetch each context's variables. - NSNumber* tx = [connection_ sendCommandWithFormat:@"context_get -d %d -c %d", frame.index, cid]; + NSNumber* tx = [client_ sendCommandWithFormat:@"context_get -d %d -c %d", frame.index, cid]; [self recordCallback:@selector(variablesReceived:) forTransaction:tx]; [callbackContext_ setObject:routingID forKey:tx]; } @@ -465,7 +493,7 @@ - (void)variablesReceived:(NSXMLDocument*)response { // Get the stack frame's routing ID and use it again. - NSInteger transaction = [connection_ transactionIDFromResponse:response]; + NSInteger transaction = [client_ transactionIDFromResponse:response]; if (transaction < stackFirstTransactionID_) return; NSNumber* receivedTransaction = [NSNumber numberWithInt:transaction]; @@ -499,7 +527,7 @@ */ - (void)propertiesReceived:(NSXMLDocument*)response { - NSInteger transaction = [connection_ transactionIDFromResponse:response]; + NSInteger transaction = [client_ transactionIDFromResponse:response]; /* @@ -532,7 +560,7 @@ */ - (void)breakpointReceived:(NSXMLDocument*)response { - NSNumber* transaction = [NSNumber numberWithInt:[connection_ transactionIDFromResponse:response]]; + NSNumber* transaction = [NSNumber numberWithInt:[client_ transactionIDFromResponse:response]]; Breakpoint* bp = [callbackContext_ objectForKey:transaction]; if (!bp) return; diff --git a/Source/NetworkConnection.h b/Source/NetworkConnection.h deleted file mode 100644 index 74c5ed6..0000000 --- a/Source/NetworkConnection.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * MacGDBp - * Copyright (c) 2007 - 2011, Blue Static - * - * This program is free software; you can redistribute it and/or modify it under the terms of the GNU - * General Public License as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if not, - * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#import - -#import "ProtocolClient.h" - -@protocol NetworkConnectionDelegate; -@class LoggingController; - -// This class is the lowest level component to the network. It deals with all -// the intricacies of network and stream programming. Almost all the work this -// class does is on a background thread, which is created when the connection is -// asked to connect and shutdown when asked to close. -@interface NetworkConnection : ProtocolClient -{ - // The port to connect on. - NSUInteger port_; - - ProtocolClient* _ideClient; - - // If the connection to the debugger engine is currently active. - BOOL connected_; - - // The delegate. All methods are executed on the main thread. - NSObject* delegate_; -} - -@property (readonly) NSUInteger port; -@property (readonly) BOOL connected; -@property (assign) id delegate; - -- (id)initWithPort:(NSUInteger)aPort; - -- (void)connect; -- (void)close; - -- (NSString*)escapedURIPath:(NSString*)path; - -@end - -// Delegate //////////////////////////////////////////////////////////////////// - -@protocol NetworkConnectionDelegate - -@optional - -- (void)connectionDidAccept:(NetworkConnection*)cx; -- (void)connectionDidClose:(NetworkConnection*)cx; - -- (void)handleInitialResponse:(NSXMLDocument*)response; - -- (void)handleResponse:(NSXMLDocument*)response; - -- (void)errorEncountered:(NSString*)error; - -@end diff --git a/Source/NetworkConnection.m b/Source/NetworkConnection.m deleted file mode 100644 index b1cfa0d..0000000 --- a/Source/NetworkConnection.m +++ /dev/null @@ -1,143 +0,0 @@ -/* - * MacGDBp - * Copyright (c) 2007 - 2011, Blue Static - * - * This program is free software; you can redistribute it and/or modify it under the terms of the GNU - * General Public License as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if not, - * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#import "NetworkConnection.h" - -// This is the private interface for the NetworkConnection class. This is shared -// by the C++ NetworkCallbackController to communicate. -@interface NetworkConnection (Private) - -- (void)handleResponse:(NSXMLDocument*)response; - -// Threadsafe wrappers for the delegate's methods. -- (void)errorEncountered:(NSString*)error; - -@end - - -//////////////////////////////////////////////////////////////////////////////// - -@implementation NetworkConnection - -@synthesize port = port_; -@synthesize connected = connected_; -@synthesize delegate = delegate_; - -- (id)initWithPort:(NSUInteger)aPort -{ - if (self = [super initWithDelegate:self]) { - port_ = aPort; - _ideClient = self; - } - return self; -} - -/** - * Kicks off the socket on another thread. - */ -- (void)connect -{ - [_ideClient connectOnPort:port_]; -} - -- (void)close -{ - [_ideClient disconnect]; -} - -- (void)debuggerEngineConnected:(ProtocolClient*)client -{ - if ([delegate_ respondsToSelector:@selector(connectionDidAccept:)]) - [delegate_ connectionDidAccept:self]; -} - -- (void)debuggerEngineDisconnected:(ProtocolClient*)client -{ - if ([delegate_ respondsToSelector:@selector(connectionDidClose:)]) - [delegate_ connectionDidClose:self]; -} - -- (void)debuggerEngine:(ProtocolClient*)client receivedMessage:(NSXMLDocument*)message -{ - [self handleResponse:message]; -} - -- (void)dealloc -{ - [_ideClient release]; - [super dealloc]; -} - -/** - * 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; -} - -// Private ///////////////////////////////////////////////////////////////////// -#pragma mark Private - -// Delegate Thread-Safe Wrappers /////////////////////////////////////////////// - -/** - * Receives errors from the SocketWrapper and updates the display - */ -- (void)errorEncountered:(NSString*)error -{ - if (![delegate_ respondsToSelector:@selector(errorEncountered:)]) - return; - [delegate_ performSelectorOnMainThread:@selector(errorEncountered:) - withObject:error - waitUntilDone:NO]; -} - -- (void)handleResponse:(NSXMLDocument*)response -{ - // Check and see if there's an error. - NSArray* error = [[response rootElement] elementsForName:@"error"]; - if ([error count] > 0) { - NSLog(@"Xdebug error: %@", error); - NSString* errorMessage = [[[[error objectAtIndex:0] children] objectAtIndex:0] stringValue]; - [self errorEncountered:errorMessage]; - } - - if ([[[response rootElement] name] isEqualToString:@"init"]) { - connected_ = YES; - [delegate_ handleInitialResponse:response]; - return; - } - - if ([delegate_ respondsToSelector:@selector(handleResponse:)]) - [delegate_ handleResponse:response]; -} - -@end diff --git a/Source/ProtocolClient.h b/Source/ProtocolClient.h index b0158fa..a2eb7e5 100644 --- a/Source/ProtocolClient.h +++ b/Source/ProtocolClient.h @@ -56,6 +56,10 @@ - (NSInteger)transactionIDFromResponse:(NSXMLDocument*)response; - (NSInteger)transactionIDFromCommand:(NSString*)command; +// Given a path to a file, creates a URI for it that is suitable for sending to +// the debugger engine. ++ (NSString*)escapedFilePathURI:(NSString*)path; + @end // Delegate //////////////////////////////////////////////////////////////////// diff --git a/Source/ProtocolClient.m b/Source/ProtocolClient.m index 9fe62cb..0136bfe 100644 --- a/Source/ProtocolClient.m +++ b/Source/ProtocolClient.m @@ -91,6 +91,23 @@ return [transaction intValue]; } ++ (NSString*)escapedFilePathURI:(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; +} + // MessageQueueDelegate //////////////////////////////////////////////////////// - (void)messageQueue:(MessageQueue*)queue error:(NSError*)error { -- 2.22.5