Remove unused -[ProtocolClient shouldSendMessage].
[macgdbp.git] / Source / ProtocolClient.m
1 /*
2 * MacGDBp
3 * Copyright (c) 2013, Blue Static <http://www.bluestatic.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17 #import "ProtocolClient.h"
18
19 #import "AppDelegate.h"
20 #import "LoggingController.h"
21
22 @implementation ProtocolClient
23
24 - (id)initWithDelegate:(NSObject<ProtocolClientDelegate>*)delegate {
25 if ((self = [super init])) {
26 _delegate = delegate;
27 _delegateThread = [NSThread currentThread];
28 _lock = [[NSRecursiveLock alloc] init];
29 }
30 return self;
31 }
32
33 - (void)dealloc {
34 [_lock release];
35 [super dealloc];
36 }
37
38 - (BOOL)isConnected {
39 return [_messageQueue isConnected];
40 }
41
42 - (void)connectOnPort:(NSUInteger)port {
43 assert(!_messageQueue);
44 _messageQueue = [[MessageQueue alloc] initWithPort:port delegate:self];
45 [_messageQueue connect];
46 }
47
48 - (void)disconnect {
49 [_messageQueue disconnect];
50 }
51
52 - (NSNumber*)sendCommandWithFormat:(NSString*)format, ... {
53 // Collect varargs and format command.
54 va_list args;
55 va_start(args, format);
56 NSString* command = [[NSString alloc] initWithFormat:format arguments:args];
57 va_end(args);
58
59 NSNumber* callbackKey = [NSNumber numberWithInt:_nextID++];
60 NSString* taggedCommand = [NSString stringWithFormat:@"%@ -i %@", [command autorelease], callbackKey];
61
62 assert(_messageQueue);
63 [_messageQueue sendMessage:taggedCommand];
64 return callbackKey;
65 }
66
67 - (NSNumber*)sendCustomCommandWithFormat:(NSString*)format, ... {
68 // Collect varargs and format command.
69 va_list args;
70 va_start(args, format);
71 NSString* command = [[[NSString alloc] initWithFormat:format arguments:args] autorelease];
72 va_end(args);
73
74 NSNumber* callbackKey = [NSNumber numberWithInt:_nextID++];
75 NSString* taggedCommand = [command stringByReplacingOccurrencesOfString:@"{txn}"
76 withString:[callbackKey stringValue]];
77
78 [_messageQueue sendMessage:taggedCommand];
79 return callbackKey;
80 }
81
82 - (NSInteger)transactionIDFromResponse:(NSXMLDocument*)response {
83 return [[[[response rootElement] attributeForName:@"transaction_id"] stringValue] intValue];
84 }
85
86 - (NSInteger)transactionIDFromCommand:(NSString*)command {
87 NSRange occurrence = [command rangeOfString:@"-i "];
88 if (occurrence.location == NSNotFound)
89 return NSNotFound;
90 NSString* transaction = [command substringFromIndex:occurrence.location + occurrence.length];
91 return [transaction intValue];
92 }
93
94 + (NSString*)escapedFilePathURI:(NSString*)path {
95 // Custon GDBp paths are fine.
96 if ([[path substringToIndex:4] isEqualToString:@"gdbp"])
97 return path;
98
99 // Create a temporary URL that will escape all the nasty characters.
100 NSURL* url = [NSURL fileURLWithPath:path];
101 NSString* urlString = [url absoluteString];
102
103 // Remove the host because this is a file:// URL;
104 urlString = [urlString stringByReplacingOccurrencesOfString:[url host] withString:@""];
105
106 // Escape % for use in printf-style NSString formatters.
107 urlString = [urlString stringByReplacingOccurrencesOfString:@"%" withString:@"%%"];
108 return urlString;
109 }
110
111 // MessageQueueDelegate ////////////////////////////////////////////////////////
112
113 - (void)messageQueue:(MessageQueue*)queue error:(NSError*)error {
114 NSLog(@"error = %@", error);
115 }
116
117 - (void)messageQueueDidConnect:(MessageQueue*)queue {
118 [_lock lock];
119 _nextID = 0;
120 _lastReadID = 0;
121 _lastWrittenID = 0;
122 [_lock unlock];
123
124 [_delegate debuggerEngineConnected:self];
125 }
126
127 - (void)messageQueueDidDisconnect:(MessageQueue*)queue {
128 [_messageQueue release];
129 _messageQueue = nil;
130 [_delegate debuggerEngineDisconnected:self];
131 }
132
133 // Callback for when a message has been sent.
134 - (void)messageQueue:(MessageQueue*)queue didSendMessage:(NSString*)message
135 {
136 NSInteger tag = [self transactionIDFromCommand:message];
137 [_lock lock];
138 _lastWrittenID = tag;
139 [_lock unlock];
140
141 LoggingController* logger = [[AppDelegate instance] loggingController];
142 LogEntry* entry = [LogEntry newSendEntry:message];
143 entry.lastReadTransactionID = _lastReadID;
144 entry.lastWrittenTransactionID = _lastWrittenID;
145 [logger recordEntry:entry];
146 }
147
148 // Callback with the message content when one has been receieved.
149 - (void)messageQueue:(MessageQueue*)queue didReceiveMessage:(NSString*)message
150 {
151 LoggingController* logger = [[AppDelegate instance] loggingController];
152 LogEntry* entry = [LogEntry newReceiveEntry:message];
153 entry.lastReadTransactionID = _lastReadID;
154 entry.lastWrittenTransactionID = _lastWrittenID;
155 [logger recordEntry:entry];
156
157 // Test if we can convert it into an NSXMLDocument.
158 NSError* error = nil;
159 NSXMLDocument* xml = [[NSXMLDocument alloc] initWithXMLString:message
160 options:NSXMLDocumentTidyXML
161 error:&error];
162 if (error) {
163 [self messageQueue:queue error:error];
164 return;
165 }
166
167 // Validate the transaction.
168 NSInteger transaction = [self transactionIDFromResponse:xml];
169 if (transaction < _lastReadID) {
170 NSLog(@"Transaction #%d is out of date (lastRead = %d). Dropping packet: %@",
171 transaction, _lastReadID, message);
172 return;
173 }
174 if (transaction != _lastWrittenID) {
175 NSLog(@"Transaction #%d received out of order. lastRead = %d, lastWritten = %d. Continuing.",
176 transaction, _lastReadID, _lastWrittenID);
177 }
178
179 _lastReadID = transaction;
180 entry.lastReadTransactionID = _lastReadID;
181
182 [_delegate debuggerEngine:self receivedMessage:xml];
183 }
184
185 @end