30#ifndef OO_EXCLUDE_DEBUG_SUPPORT
51#ifdef OO_LOG_DEBUG_PROTOCOL_PACKETS
54#define LogSendPacket(packet) do {} while (0)
68@interface OODebugTCPConsoleClient (OOPrivate)
72- (BOOL) sendBytes:(const
void *)bytes count:(
size_t)count;
73- (void) sendDictionary:(NSDictionary *)dictionary;
75- (void) sendPacket:(NSString *)packetType
76 withParameters:(NSDictionary *)parameters;
78- (void) sendPacket:(NSString *)packetType
80 forParameter:(NSString *)paramKey;
83- (void) dispatchPacket:(NSDictionary *)packet ofType:(NSString *)packetType;
85- (void) handleApproveConnectionPacket:(NSDictionary *)packet;
86- (void) handleRejectConnectionPacket:(NSDictionary *)packet;
87- (void) handleCloseConnectionPacket:(NSDictionary *)packet;
88- (void) handleNoteConfigurationChangePacket:(NSDictionary *)packet;
89- (void) handlePerformCommandPacket:(NSDictionary *)packet;
90- (void) handleRequestConfigurationValuePacket:(NSDictionary *)packet;
91- (void) handlePingPacket:(NSDictionary *)packet;
92- (void) handlePongPacket:(NSDictionary *)packet;
94- (void) disconnectFromServerWithMessage:(NSString *)message;
95- (void) breakConnectionWithMessage:(NSString *)message;
96- (void) breakConnectionWithBadStream:(NSStream *)stream;
109- (id) initWithAddress:(NSString *)address port:(uint16_t)port
112 NSDictionary *parameters =
nil;
114 if (address ==
nil) address =
@"127.0.0.1";
126 inputStream:&_inStream
127 outputStream:&_outStream];
134 [_inStream setDelegate:
self];
135 [_outStream setDelegate:
self];
136 [_inStream scheduleInRunLoop:[
NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
137 [_outStream scheduleInRunLoop:[
NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
143 NSRunLoop * myRunLoop = [
NSRunLoop currentRunLoop];
144 NSDate * timeOut = [
NSDate dateWithTimeIntervalSinceNow:3];
146 [myRunLoop runMode:NSDefaultRunLoopMode beforeDate:timeOut] )
159 parameters = [
NSDictionary dictionaryWithObjectsAndKeys:
160 [
NSNumber numberWithUnsignedInt:kOOTCPProtocolVersion_1_1_0], kOOTCPProtocolVersion,
161 [[[
NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"], kOOTCPOoliteVersion,
163 [
self sendPacket:kOOTCPPacket_RequestConnection
172 OOLog(
@"debugTCP.connect.failed",
@"Failed to connect to debug console at address %@:%i.", address, port);
109- (id) initWithAddress:(NSString *)address port:(uint16_t)port {
…}
204 errorMessage:(out NSString **)message
208 if (message != NULL) *message =
@"Connection refused.";
213 if (message != NULL) *message =
@"Cannot reconnect after disconnecting.";
224 message:(in NSString *)message
232 jsConsoleOutput:(in NSString *)output
233 colorKey:(in NSString *)colorKey
234 emphasisRange:(in NSRange)emphasisRange
236 NSMutableDictionary *parameters =
nil;
237 NSArray *range =
nil;
240 [
parameters setObject:output forKey:kOOTCPMessage];
241 [
parameters setObject:colorKey ? colorKey : (NSString *)@"general" forKey:kOOTCPColorKey];
242 if (emphasisRange.length != 0)
244 range = [
NSArray arrayWithObjects:
245 [
NSNumber numberWithUnsignedInteger:emphasisRange.location],
246 [
NSNumber numberWithUnsignedInteger:emphasisRange.length],
248 [
parameters setObject:range forKey:kOOTCPEmphasisRanges];
271 noteConfiguration:(in NSDictionary *)configuration
273 [
self sendPacket:kOOTCPPacket_NoteConfiguration
280noteChangedConfigrationValue:(in
id)newValue
281 forKey:(in NSString *)key
285 [
self sendPacket:kOOTCPPacket_NoteConfiguration
291 [
self sendPacket:kOOTCPPacket_NoteConfiguration
298- (void)
stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
302 if (
stream ==
_inStream && eventCode == NSStreamEventHasBytesAvailable)
306 else if (eventCode == NSStreamEventErrorOccurred)
310 else if (eventCode == NSStreamEventErrorOccurred)
313 @"Console closed the connection."]];
298- (void)
stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
…}
320@implementation OODebugTCPConsoleClient (OOPrivate)
339- (BOOL) sendBytes:(const
void *)bytes count:(
size_t)count
341 if (bytes == NULL ||
count == 0)
return YES;
346 NSInteger written = [
_outStream write:bytes maxLength:count];
347 if (written < 1)
return NO;
339- (BOOL) sendBytes:(const
void *)bytes count:(
size_t)count {
…}
358- (void) sendDictionary:(NSDictionary *)dictionary
361 NSString *errorDesc = NULL;
363 const uint8_t *bytes = NULL;
370 format:NSPropertyListXMLFormat_v1_0
371 errorDescription:&errorDesc];
375 OOLog(
@"debugTCP.conversionFailure",
@"Could not convert dictionary to data for transmission to debug console: %@", errorDesc != NULL ? errorDesc : (NSString *)
@"unknown error.");
376#if OOLITE_RELEASE_PLIST_ERROR_STRINGS
385 if (
count == 0)
return;
386 header = htonl(
count);
388 bytes = [
data bytes];
394 if (![
self sendBytes:&header
count:
sizeof header])
396 OOLog(
@"debugTCP.send.warning",
@"%@",
@"Error sending packet header, retrying.");
398 [[
NSRunLoop currentRunLoop] runUntilDate:[
NSDate dateWithTimeIntervalSinceNow:.008]];
399 if (![
self sendBytes:&header
count:
sizeof header])
403 [[
NSRunLoop currentRunLoop] runUntilDate:[
NSDate dateWithTimeIntervalSinceNow:.016]];
404 if (![
self sendBytes:&header
count:
sizeof header])
411 if(sentOK && ![
self sendBytes:bytes
count:
count])
413 OOLog(
@"debugTCP.send.warning",
@"%@",
@"Error sending packet body, retrying.");
415 [[
NSRunLoop currentRunLoop] runUntilDate:[
NSDate dateWithTimeIntervalSinceNow:.008]];
424 OOLog(
@"debugTCP.send.error",
@"The following packet could not be sent: %@", dictionary);
425 if(![[
OODebugMonitor sharedDebugMonitor] TCPIgnoresDroppedPackets])
358- (void) sendDictionary:(NSDictionary *)dictionary {
…}
433- (void) sendPacket:(NSString *)packetType
434 withParameters:(NSDictionary *)parameters
436 NSDictionary *dict =
nil;
438 if (packetType ==
nil)
return;
440 if (parameters !=
nil)
442 dict = [
parameters dictionaryByAddingObject:packetType forKey:kOOTCPPacketType];
446 dict = [
NSDictionary dictionaryWithObjectsAndKeys:packetType, kOOTCPPacketType, nil];
433- (void) sendPacket:(NSString *)packetType {
…}
453- (void) sendPacket:(NSString *)packetType
455 forParameter:(NSString *)paramKey
457 if (packetType ==
nil)
return;
458 if (paramKey ==
nil) value =
nil;
461 packetType, kOOTCPPacketType,
453- (void) sendPacket:(NSString *)packetType {
…}
469 enum { kBufferSize = 16 << 10 };
475 length = [
_inStream read:buffer maxLength:kBufferSize];
478 data = [
NSData dataWithBytesNoCopy:buffer length:length freeWhenDone:NO];
480 length = [
_inStream read:buffer maxLength:kBufferSize];
485- (void) dispatchPacket:(NSDictionary *)packet ofType:(NSString *)packetType
487 if (packet ==
nil || packetType ==
nil)
return;
489#define PACKET_CASE(x) else if ([packetType isEqualToString:kOOTCPPacket_##x]) { [self handle##x##Packet:packet]; }
502 OOLog(
@"debugTCP.protocolError.unknownPacketType",
@"Unhandled packet type %@.", packetType);
485- (void) dispatchPacket:(NSDictionary *)packet ofType:(NSString *)packetType {
…}
507- (void) handleApproveConnectionPacket:(NSDictionary *)packet
509 NSMutableString *connectedMessage =
nil;
510 NSString *consoleIdentity =
nil;
511 NSString *hostName =
nil;
518 connectedMessage = [
NSMutableString stringWithString:@"Connected to debug console"];
520 consoleIdentity = [
packet oo_stringForKey:kOOTCPConsoleIdentity];
523 hostName = [
_host name];
524 if ([hostName length] != 0 &&
525 ![hostName isEqual:
@"localhost"] &&
526 ![hostName isEqual:
@"127.0.0.1"] &&
527 ![hostName isEqual:
@"::1"])
532 OOLog(
@"debugTCP.connected",
@"%@.", connectedMessage);
507- (void) handleApproveConnectionPacket:(NSDictionary *)packet {
…}
541- (void) handleRejectConnectionPacket:(NSDictionary *)packet
543 NSString *message =
nil;
554 message = [
packet oo_stringForKey:kOOTCPMessage];
555 if (message ==
nil) message =
@"Console refused connection.";
541- (void) handleRejectConnectionPacket:(NSDictionary *)packet {
…}
560- (void) handleCloseConnectionPacket:(NSDictionary *)packet
562 NSString *message =
nil;
568 message = [
packet oo_stringForKey:kOOTCPMessage];
569 if (message ==
nil) message =
@"Console closed connection.";
560- (void) handleCloseConnectionPacket:(NSDictionary *)packet {
…}
574- (void) handleNoteConfigurationChangePacket:(NSDictionary *)packet
576 NSDictionary *configuration =
nil;
577 NSArray *removed =
nil;
578 NSEnumerator *keyEnum =
nil;
582 if (_monitor ==
nil)
return;
584 configuration = [
packet oo_dictionaryForKey:kOOTCPConfiguration];
585 if (configuration !=
nil)
587 for (keyEnum = [configuration keyEnumerator]; (key = [
keyEnum nextObject]); )
590 [
_monitor setConfigurationValue:value forKey:key];
594 removed = [
configuration oo_arrayForKey:kOOTCPRemovedConfigurationKeys];
595 for (keyEnum = [removed objectEnumerator]; (key = [
keyEnum nextObject]); )
597 [
_monitor setConfigurationValue:nil forKey:key];
574- (void) handleNoteConfigurationChangePacket:(NSDictionary *)packet {
…}
602- (void) handlePerformCommandPacket:(NSDictionary *)packet
604 NSString *message =
nil;
606 message = [
packet oo_stringForKey:kOOTCPMessage];
607 if (message !=
nil) [
_monitor performJSConsoleCommand:message];
602- (void) handlePerformCommandPacket:(NSDictionary *)packet {
…}
611- (void) handleRequestConfigurationValuePacket:(NSDictionary *)packet
616 key = [
packet oo_stringForKey:kOOTCPConfigurationKey];
619 value = [
_monitor configurationValueForKey:key];
611- (void) handleRequestConfigurationValuePacket:(NSDictionary *)packet {
…}
627- (void) handlePingPacket:(NSDictionary *)packet
631 message = [
packet objectForKey:kOOTCPMessage];
627- (void) handlePingPacket:(NSDictionary *)packet {
…}
638- (void) handlePongPacket:(NSDictionary *)packet
638- (void) handlePongPacket:(NSDictionary *)packet {
…}
644- (void) disconnectFromServerWithMessage:(NSString *)message
644- (void) disconnectFromServerWithMessage:(NSString *)message {
…}
658- (void) breakConnectionWithMessage:(NSString *)message
664 if ([message length] > 0)
666 OOLog(
@"debugTCP.disconnect",
@"No connection to debug console: \"%@\
"", message);
670 OOLog(
@"debugTCP.disconnect",
@"%@",
@"Debug console not connected.");
675 [
_monitor disconnectDebugger:
self message:message];
658- (void) breakConnectionWithMessage:(NSString *)message {
…}
681- (void) breakConnectionWithBadStream:(NSStream *)stream
683 NSString *errorDesc =
nil;
684 NSError *error =
nil;
686 error = [stream streamError];
687 errorDesc = [
error localizedDescription];
688 if (errorDesc ==
nil) errorDesc = [
error description];
689 if (errorDesc ==
nil) errorDesc =
@"bad stream.";
691 @"Connection to debug console failed: '%@' (outStream status: %li, inStream status: %li).",
681- (void) breakConnectionWithBadStream:(NSStream *)stream {
…}
710#ifdef OO_LOG_DEBUG_PROTOCOL_PACKETS
716 data = [NSPropertyListSerialization dataFromPropertyList:packet format:NSPropertyListXMLFormat_v1_0 errorDescription:NULL];
717 xml = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
718 OOLog(
@"debugTCP.receive",
@"Received packet:\n%@", xml);
727 data = [NSPropertyListSerialization dataFromPropertyList:packet format:NSPropertyListXMLFormat_v1_0 errorDescription:NULL];
728 xml = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
729 OOLog(
@"debugTCP.send",
@"Sent packet:\n%@", xml);
OOTCPClientConnectionStatus
@ kOOTCPClientStartedConnectionStage2
@ kOOTCPClientStartedConnectionStage1
@ kOOTCPClientConnectionRefused
@ kOOTCPClientDisconnected
#define LogSendPacket(packet)
OOINLINE BOOL StatusIsSendable(OOTCPClientConnectionStatus status)
static void DecoderPacket(void *cbInfo, OOALStringRef packetType, OOALDictionaryRef packet)
static void DecoderError(void *cbInfo, OOALStringRef errorDesc)
#define kOOTCPPacket_ApproveConnection
#define kOOTCPPacket_RejectConnection
#define kOOTCPPacket_CloseConnection
#define OOLog(class, format,...)
const struct NSString * OOALStringRef
const struct NSDictionary * OOALDictionaryRef
OOTCPStreamDecoderRef OOTCPStreamDecoderCreate(OOTCPStreamDecoderPacketCallback packetCB, OOTCPStreamDecoderErrorCallback errorCB, OOTCPStreamDecoderFinalizeCallback finalizeCB, void *cbInfo)
void OOTCPStreamDecoderDestroy(OOTCPStreamDecoderRef decoder)
void OOTCPStreamDecoderReceiveData(OOTCPStreamDecoderRef decoder, OOALDataRef data)
#define LogOOTCPStreamDecoderPacket(packet)
void disconnectDebugger:message:(in id< OODebuggerInterface > debugger, [message] in NSString *message)
OOTCPClientConnectionStatus _status
void sendPacket:withParameters:(NSString *packetType,[withParameters] NSDictionary *parameters)
void disconnectFromServerWithMessage:(NSString *message)
NSOutputStream * _outStream
struct OOTCPStreamDecoder * _decoder
id initWithAddress:port:(NSString *address,[port] uint16_t port)
oneway void debugMonitor:noteChangedConfigrationValue:forKey:(in OODebugMonitor *debugMonitor, [noteChangedConfigrationValue] in id newValue, [forKey] in NSString *key)
void sendPacket:withValue:forParameter:(NSString *packetType,[withValue] id value,[forParameter] NSString *paramKey)
OODebugMonitor * _monitor
void breakConnectionWithBadStream:(NSStream *stream)
void sendDictionary:(NSDictionary *dictionary)
void breakConnectionWithMessage:(NSString *message)
void dispatchPacket:ofType:(NSDictionary *packet,[ofType] NSString *packetType)
NSInputStream * _inStream