1EEBFD120D359A9F008F835B /* dimple.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EEBFD110D359A9F008F835B /* dimple.png */; };
1EEE875D0D9DE4B4009CBA7C /* MacGDBp.icns in Resources */ = {isa = PBXBuildFile; fileRef = 1EEE875C0D9DE4B4009CBA7C /* MacGDBp.icns */; };
1EFBE63012C515C200F96D6E /* NetworkConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1EFBE62F12C515C200F96D6E /* NetworkConnection.mm */; };
+ 1EFBE66B12C51E3900F96D6E /* NetworkCallbackController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1EFBE66A12C51E3900F96D6E /* NetworkCallbackController.mm */; };
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 = (); }; };
1EEBFD110D359A9F008F835B /* dimple.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = dimple.png; sourceTree = "<group>"; };
1EEE875C0D9DE4B4009CBA7C /* MacGDBp.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = MacGDBp.icns; path = Icons/MacGDBp.icns; sourceTree = "<group>"; };
1EFBE62F12C515C200F96D6E /* NetworkConnection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NetworkConnection.mm; path = Source/NetworkConnection.mm; sourceTree = "<group>"; };
+ 1EFBE66912C51E3900F96D6E /* NetworkCallbackController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkCallbackController.h; path = Source/NetworkCallbackController.h; sourceTree = "<group>"; };
+ 1EFBE66A12C51E3900F96D6E /* NetworkCallbackController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NetworkCallbackController.mm; path = Source/NetworkCallbackController.mm; sourceTree = "<group>"; };
+ 1EFBE66C12C51EFA00F96D6E /* NetworkConnectionPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkConnectionPrivate.h; path = Source/NetworkConnectionPrivate.h; sourceTree = "<group>"; };
1EFF70C10DFDC018006B9D33 /* BreakpointController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointController.h; path = Source/BreakpointController.h; sourceTree = "<group>"; };
1EFF70C20DFDC018006B9D33 /* BreakpointController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BreakpointController.m; path = Source/BreakpointController.m; sourceTree = "<group>"; };
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
isa = PBXGroup;
children = (
1E0724E111B47BCC0017AD3C /* NetworkConnection.h */,
+ 1EFBE66C12C51EFA00F96D6E /* NetworkConnectionPrivate.h */,
1EFBE62F12C515C200F96D6E /* NetworkConnection.mm */,
+ 1EFBE66912C51E3900F96D6E /* NetworkCallbackController.h */,
+ 1EFBE66A12C51E3900F96D6E /* NetworkCallbackController.mm */,
1E02C56F0C610158006F1752 /* DebuggerBackEnd.h */,
1E02C5700C610158006F1752 /* DebuggerBackEnd.m */,
1E35FFB00C65A74C0030F527 /* NSXMLElementAdditions.h */,
1EC1337E127DBB00007946FC /* VariableNode.m in Sources */,
1EC6965812BBC6A700A8D984 /* modp_b64.cc in Sources */,
1EFBE63012C515C200F96D6E /* NetworkConnection.mm in Sources */,
+ 1EFBE66B12C51E3900F96D6E /* NetworkCallbackController.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
--- /dev/null
+/*
+ * MacGDBp
+ * Copyright (c) 2007 - 2010, Blue Static <http://www.bluestatic.org>
+ *
+ * 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 <CoreFoundation/CoreFoundation.h>
+
+@class NetworkConnection;
+
+// This class is used for the CFNetwork callbacks. It is a private class and
+// the instance is owned by the NewtorkConnection instance. This class can be
+// considered an extension of NetworkConnection.
+class NetworkCallbackController
+{
+ public:
+ // This object should be constructed on the thread which the streams are
+ // to be scheduled on. It will hold a weak reference to the run loop on that
+ // thread.
+ NetworkCallbackController(NetworkConnection* connection);
+
+ // 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,
+ CFSocketCallBackType callbackType,
+ CFDataRef address,
+ const void* data,
+ void* self);
+ static void ReadStreamCallback(CFReadStreamRef stream,
+ CFStreamEventType eventType,
+ void* self);
+ static void WriteStreamCallback(CFWriteStreamRef stream,
+ CFStreamEventType eventType,
+ void* self);
+
+ private:
+ void OnSocketAccept(CFSocketRef socket,
+ CFDataRef address,
+ const void* data);
+ void OnReadStreamEvent(CFReadStreamRef stream, CFStreamEventType eventType);
+ void OnWriteStreamEvent(CFWriteStreamRef stream, CFStreamEventType eventType);
+
+ // Removes the read or write stream from the run loop, closes the stream,
+ // releases the reference.
+ void UnscheduleReadStream();
+ void UnscheduleWriteStream();
+
+ // Messages the NetworkConnection's delegate and takes ownership of |error|.
+ void ReportError(CFErrorRef error);
+
+ NetworkConnection* connection_; // Weak, owns this.
+ CFRunLoopRef runLoop_; // Weak.
+};
+
--- /dev/null
+/*
+ * MacGDBp
+ * Copyright (c) 2007 - 2010, Blue Static <http://www.bluestatic.org>
+ *
+ * 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 "NetworkCallbackController.h"
+
+#import "NetworkConnection.h"
+#import "NetworkConnectionPrivate.h"
+
+NetworkCallbackController::NetworkCallbackController(NetworkConnection* connection)
+ : connection_(connection),
+ runLoop_(CFRunLoopGetCurrent())
+{
+}
+
+// Static Methods //////////////////////////////////////////////////////////////
+
+void NetworkCallbackController::SocketAcceptCallback(CFSocketRef socket,
+ CFSocketCallBackType callbackType,
+ CFDataRef address,
+ const void* data,
+ void* self)
+{
+ assert(callbackType == kCFSocketAcceptCallBack);
+ static_cast<NetworkCallbackController*>(self)->OnSocketAccept(socket, address, data);
+}
+
+void NetworkCallbackController::ReadStreamCallback(CFReadStreamRef stream,
+ CFStreamEventType eventType,
+ void* self)
+{
+ static_cast<NetworkCallbackController*>(self)->OnReadStreamEvent(stream, eventType);
+}
+
+void NetworkCallbackController::WriteStreamCallback(CFWriteStreamRef stream,
+ CFStreamEventType eventType,
+ void* self)
+{
+ static_cast<NetworkCallbackController*>(self)->OnWriteStreamEvent(stream, eventType);
+}
+
+
+// Private Instance Methods ////////////////////////////////////////////////////
+
+void NetworkCallbackController::OnSocketAccept(CFSocketRef socket,
+ CFDataRef address,
+ const void* data)
+{
+ CFReadStreamRef readStream;
+ CFWriteStreamRef writeStream;
+
+ // Create the streams on the socket.
+ CFStreamCreatePairWithSocket(kCFAllocatorDefault,
+ *(CFSocketNativeHandle*)data, // Socket handle.
+ &readStream, // Read stream in-pointer.
+ &writeStream); // Write stream in-pointer.
+
+ // Create struct to register callbacks for the stream.
+ CFStreamClientContext context = { 0 };
+ context.info = this;
+
+ // Set the client of the read stream.
+ CFOptionFlags readFlags = kCFStreamEventOpenCompleted |
+ kCFStreamEventHasBytesAvailable |
+ kCFStreamEventErrorOccurred |
+ kCFStreamEventEndEncountered;
+ if (CFReadStreamSetClient(readStream, readFlags, &NetworkCallbackController::ReadStreamCallback, &context))
+ // Schedule in run loop to do asynchronous communication with the engine.
+ CFReadStreamScheduleWithRunLoop(readStream, runLoop_, kCFRunLoopCommonModes);
+ else
+ return;
+
+ // Open the stream now that it's scheduled on the run loop.
+ if (!CFReadStreamOpen(readStream)) {
+ ReportError(CFReadStreamCopyError(readStream));
+ return;
+ }
+
+ // Set the client of the write stream.
+ CFOptionFlags writeFlags = kCFStreamEventOpenCompleted |
+ kCFStreamEventCanAcceptBytes |
+ kCFStreamEventErrorOccurred |
+ kCFStreamEventEndEncountered;
+ if (CFWriteStreamSetClient(writeStream, writeFlags, &NetworkCallbackController::WriteStreamCallback, &context))
+ // Schedule it in the run loop to receive error information.
+ CFWriteStreamScheduleWithRunLoop(writeStream, runLoop_, kCFRunLoopCommonModes);
+ else
+ return;
+
+ // Open the write stream.
+ if (!CFWriteStreamOpen(writeStream)) {
+ ReportError(CFWriteStreamCopyError(writeStream));
+ return;
+ }
+
+ connection_.readStream = readStream;
+ connection_.writeStream = writeStream;
+ [connection_ socketDidAccept];
+}
+
+void NetworkCallbackController::OnReadStreamEvent(CFReadStreamRef stream,
+ CFStreamEventType eventType)
+{
+ switch (eventType)
+ {
+ case kCFStreamEventHasBytesAvailable:
+ [connection_ readStreamHasData];
+ break;
+
+ case kCFStreamEventErrorOccurred:
+ {
+ ReportError(CFReadStreamCopyError(stream));
+ UnscheduleReadStream();
+ break;
+ }
+
+ case kCFStreamEventEndEncountered:
+ UnscheduleReadStream();
+ [connection_ socketDisconnected];
+ break;
+ };
+}
+
+void NetworkCallbackController::OnWriteStreamEvent(CFWriteStreamRef stream,
+ CFStreamEventType eventType)
+{
+ switch (eventType)
+ {
+ case kCFStreamEventCanAcceptBytes:
+ [connection_ sendQueuedWrites];
+ break;
+
+ case kCFStreamEventErrorOccurred:
+ {
+ ReportError(CFWriteStreamCopyError(stream));
+ UnscheduleWriteStream();
+ break;
+ }
+
+ case kCFStreamEventEndEncountered:
+ UnscheduleReadStream();
+ [connection_ socketDisconnected];
+ break;
+ }
+}
+
+void NetworkCallbackController::UnscheduleReadStream()
+{
+ CFReadStreamUnscheduleFromRunLoop(connection_.readStream, runLoop_, kCFRunLoopCommonModes);
+ CFReadStreamClose(connection_.readStream);
+ CFRelease(connection_.readStream);
+ connection_.readStream = NULL;
+}
+
+void NetworkCallbackController::UnscheduleWriteStream()
+{
+ CFWriteStreamUnscheduleFromRunLoop(connection_.writeStream, runLoop_, kCFRunLoopCommonModes);
+ CFWriteStreamClose(connection_.writeStream);
+ CFRelease(connection_.writeStream);
+ connection_.writeStream = NULL;
+}
+
+void NetworkCallbackController::ReportError(CFErrorRef error)
+{
+ [connection_ errorEncountered:[(NSError*)error description]];
+ CFRelease(error);
+}
// The write stream. Weak.
CFWriteStreamRef writeStream_;
- // Run loop source used to quit the thread.
+ // Run loop source used to quit the thread. Strong.
CFRunLoopSourceRef quitSource_;
// An ever-increasing integer that gives each transaction a unique ID for the
*/
#import "NetworkConnection.h"
+#import "NetworkConnectionPrivate.h"
#import <sys/socket.h>
#import <netinet/in.h>
#import "AppDelegate.h"
#import "LoggingController.h"
-
-// NetworkConnection (Private) /////////////////////////////////////////////////
-
-@interface NetworkConnection ()
-
-@property (assign) CFSocketRef socket;
-@property (assign) CFReadStreamRef readStream;
-@property NSUInteger lastReadTransaction;
-@property (retain) NSMutableString* currentPacket;
-@property (assign) CFWriteStreamRef writeStream;
-@property NSUInteger lastWrittenTransaction;
-@property (retain) NSMutableArray* queuedWrites;
-
-- (void)runNetworkThread;
-
-- (void)socketDidAccept;
-- (void)socketDisconnected;
-- (void)readStreamHasData;
-
-// These methods MUST be called on the network thread as they are not threadsafe.
-- (void)send:(NSString*)command;
-- (void)performSend:(NSString*)command;
-- (void)sendQueuedWrites;
-
-- (void)performQuitSignal;
-
-- (void)handleResponse:(NSXMLDocument*)response;
-- (void)handlePacket:(NSString*)packet;
-
-// Threadsafe wrappers for the delegate's methods.
-- (void)errorEncountered:(NSString*)error;
-- (LogEntry*)recordSend:(NSString*)command;
-- (LogEntry*)recordReceive:(NSString*)command;
-
-@end
-
-// CFNetwork Callbacks /////////////////////////////////////////////////////////
-
-class NetworkCallbackController
-{
- public:
- NetworkCallbackController(NetworkConnection* connection)
- : connection_(connection),
- runLoop_(CFRunLoopGetCurrent())
- {
- }
-
- static void SocketAcceptCallback(CFSocketRef socket,
- CFSocketCallBackType callbackType,
- CFDataRef address,
- const void* data,
- void* self)
- {
- assert(callbackType == kCFSocketAcceptCallBack);
- static_cast<NetworkCallbackController*>(self)->OnSocketAccept(socket, address, data);
- }
-
- void OnSocketAccept(CFSocketRef socket,
- CFDataRef address,
- const void* data)
- {
- CFReadStreamRef readStream;
- CFWriteStreamRef writeStream;
-
- // Create the streams on the socket.
- CFStreamCreatePairWithSocket(kCFAllocatorDefault,
- *(CFSocketNativeHandle*)data, // Socket handle.
- &readStream, // Read stream in-pointer.
- &writeStream); // Write stream in-pointer.
-
- // Create struct to register callbacks for the stream.
- CFStreamClientContext context = { 0 };
- context.info = this;
-
- // Set the client of the read stream.
- CFOptionFlags readFlags = kCFStreamEventOpenCompleted |
- kCFStreamEventHasBytesAvailable |
- kCFStreamEventErrorOccurred |
- kCFStreamEventEndEncountered;
- if (CFReadStreamSetClient(readStream, readFlags, &NetworkCallbackController::ReadStreamCallback, &context))
- // Schedule in run loop to do asynchronous communication with the engine.
- CFReadStreamScheduleWithRunLoop(readStream, runLoop_, kCFRunLoopCommonModes);
- else
- return;
-
- // Open the stream now that it's scheduled on the run loop.
- if (!CFReadStreamOpen(readStream)) {
- ReportError(CFReadStreamCopyError(readStream));
- return;
- }
-
- // Set the client of the write stream.
- CFOptionFlags writeFlags = kCFStreamEventOpenCompleted |
- kCFStreamEventCanAcceptBytes |
- kCFStreamEventErrorOccurred |
- kCFStreamEventEndEncountered;
- if (CFWriteStreamSetClient(writeStream, writeFlags, &NetworkCallbackController::WriteStreamCallback, &context))
- // Schedule it in the run loop to receive error information.
- CFWriteStreamScheduleWithRunLoop(writeStream, runLoop_, kCFRunLoopCommonModes);
- else
- return;
-
- // Open the write stream.
- if (!CFWriteStreamOpen(writeStream)) {
- ReportError(CFWriteStreamCopyError(writeStream));
- return;
- }
-
- connection_.readStream = readStream;
- connection_.writeStream = writeStream;
- [connection_ socketDidAccept];
- }
-
- static void ReadStreamCallback(CFReadStreamRef stream,
- CFStreamEventType eventType,
- void* self)
- {
- static_cast<NetworkCallbackController*>(self)->OnReadStreamEvent(stream, eventType);
- }
-
- void OnReadStreamEvent(CFReadStreamRef stream, CFStreamEventType eventType)
- {
- switch (eventType)
- {
- case kCFStreamEventHasBytesAvailable:
- [connection_ readStreamHasData];
- break;
-
- case kCFStreamEventErrorOccurred:
- {
- ReportError(CFReadStreamCopyError(stream));
- UnscheduleReadStream();
- break;
- }
-
- case kCFStreamEventEndEncountered:
- UnscheduleReadStream();
- [connection_ socketDisconnected];
- break;
- };
- }
-
- void UnscheduleReadStream()
- {
- CFReadStreamUnscheduleFromRunLoop(connection_.readStream, runLoop_, kCFRunLoopCommonModes);
- CFReadStreamClose(connection_.readStream);
- CFRelease(connection_.readStream);
- connection_.readStream = NULL;
- }
-
- static void WriteStreamCallback(CFWriteStreamRef stream,
- CFStreamEventType eventType,
- void* self)
- {
- static_cast<NetworkCallbackController*>(self)->OnWriteStreamEvent(stream, eventType);
- }
-
- void OnWriteStreamEvent(CFWriteStreamRef stream, CFStreamEventType eventType)
- {
- switch (eventType)
- {
- case kCFStreamEventCanAcceptBytes:
- [connection_ sendQueuedWrites];
- break;
-
- case kCFStreamEventErrorOccurred:
- {
- ReportError(CFWriteStreamCopyError(stream));
- UnscheduleWriteStream();
- break;
- }
-
- case kCFStreamEventEndEncountered:
- UnscheduleReadStream();
- [connection_ socketDisconnected];
- break;
- }
- }
- void UnscheduleWriteStream()
- {
- CFWriteStreamUnscheduleFromRunLoop(connection_.writeStream, runLoop_, kCFRunLoopCommonModes);
- CFWriteStreamClose(connection_.writeStream);
- CFRelease(connection_.writeStream);
- connection_.writeStream = NULL;
- }
-
- private:
- void ReportError(CFErrorRef error)
- {
- [connection_ errorEncountered:[(NSError*)error description]];
- CFRelease(error);
- }
-
- NetworkConnection* connection_; // Weak, owns this.
- CFRunLoopRef runLoop_; // Weak.
-};
+#include "NetworkCallbackController.h"
// Other Run Loop Callbacks ////////////////////////////////////////////////////
--- /dev/null
+/*
+ * MacGDBp
+ * Copyright (c) 2007 - 2010, Blue Static <http://www.bluestatic.org>
+ *
+ * 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
+ */
+
+@class LogEntry;
+
+@interface NetworkConnection ()
+
+@property (assign) CFSocketRef socket;
+@property (assign) CFReadStreamRef readStream;
+@property NSUInteger lastReadTransaction;
+@property (retain) NSMutableString* currentPacket;
+@property (assign) CFWriteStreamRef writeStream;
+@property NSUInteger lastWrittenTransaction;
+@property (retain) NSMutableArray* queuedWrites;
+
+- (void)runNetworkThread;
+
+- (void)socketDidAccept;
+- (void)socketDisconnected;
+- (void)readStreamHasData;
+
+// These methods MUST be called on the network thread as they are not threadsafe.
+- (void)send:(NSString*)command;
+- (void)performSend:(NSString*)command;
+- (void)sendQueuedWrites;
+
+- (void)performQuitSignal;
+
+- (void)handleResponse:(NSXMLDocument*)response;
+- (void)handlePacket:(NSString*)packet;
+
+// Threadsafe wrappers for the delegate's methods.
+- (void)errorEncountered:(NSString*)error;
+- (LogEntry*)recordSend:(NSString*)command;
+- (LogEntry*)recordReceive:(NSString*)command;
+
+@end