LCOV - code coverage report
Current view: top level - Core/Debug - OODebugTCPConsoleClient.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 34 0.0 %
Date: 2025-05-28 07:50:54 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : OODebugTCPConsoleClient.m
       4             : 
       5             : 
       6             : Oolite Debug Support
       7             : 
       8             : Copyright (C) 2009-2013 Jens Ayton and contributors
       9             : 
      10             : Permission is hereby granted, free of charge, to any person obtaining a copy
      11             : of this software and associated documentation files (the "Software"), to deal
      12             : in the Software without restriction, including without limitation the rights
      13             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      14             : copies of the Software, and to permit persons to whom the Software is
      15             : furnished to do so, subject to the following conditions:
      16             : 
      17             : The above copyright notice and this permission notice shall be included in all
      18             : copies or substantial portions of the Software.
      19             : 
      20             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      21             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      23             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      25             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      26             : SOFTWARE.
      27             : 
      28             : */
      29             : 
      30             : #ifndef OO_EXCLUDE_DEBUG_SUPPORT
      31             : 
      32             : 
      33             : #import "OODebugTCPConsoleClient.h"
      34             : #import "OODebugTCPConsoleProtocol.h"
      35             : #import "OODebugMonitor.h"
      36             : #import "OOFunctionAttributes.h"
      37             : #import "OOLogging.h"
      38             : #include <stdint.h>
      39             : #import "NSDictionaryOOExtensions.h"
      40             : 
      41             : #if OOLITE_WINDOWS
      42             : #include <winsock2.h>
      43             : #else
      44             : #include <arpa/inet.h>    // For htonl
      45             : #endif
      46             : 
      47             : #import "OOCollectionExtractors.h"
      48             : #import "OOTCPStreamDecoder.h"
      49             : 
      50             : 
      51             : #ifdef OO_LOG_DEBUG_PROTOCOL_PACKETS
      52             : static void LogSendPacket(NSDictionary *packet);
      53             : #else
      54           0 : #define LogSendPacket(packet) do {} while (0)
      55             : #endif
      56             : 
      57             : 
      58             : static void DecoderPacket(void *cbInfo, OOALStringRef packetType, OOALDictionaryRef packet);
      59             : static void DecoderError(void *cbInfo, OOALStringRef errorDesc);
      60             : 
      61             : 
      62           0 : OOINLINE BOOL StatusIsSendable(OOTCPClientConnectionStatus status)
      63             : {
      64             :         return status == kOOTCPClientStartedConnectionStage1 || status == kOOTCPClientStartedConnectionStage2 || status == kOOTCPClientConnected;
      65             : }
      66             : 
      67             : 
      68             : @interface OODebugTCPConsoleClient (OOPrivate)
      69             : 
      70           0 : - (void) closeConnection;
      71             : 
      72           0 : - (BOOL) sendBytes:(const void *)bytes count:(size_t)count;
      73           0 : - (void) sendDictionary:(NSDictionary *)dictionary;
      74             : 
      75           0 : - (void) sendPacket:(NSString *)packetType
      76             :          withParameters:(NSDictionary *)parameters;
      77             : 
      78           0 : - (void) sendPacket:(NSString *)packetType
      79             :                   withValue:(id)value
      80             :            forParameter:(NSString *)paramKey;
      81             : 
      82           0 : - (void) readData;
      83           0 : - (void) dispatchPacket:(NSDictionary *)packet ofType:(NSString *)packetType;
      84             : 
      85           0 : - (void) handleApproveConnectionPacket:(NSDictionary *)packet;
      86           0 : - (void) handleRejectConnectionPacket:(NSDictionary *)packet;
      87           0 : - (void) handleCloseConnectionPacket:(NSDictionary *)packet;
      88           0 : - (void) handleNoteConfigurationChangePacket:(NSDictionary *)packet;
      89           0 : - (void) handlePerformCommandPacket:(NSDictionary *)packet;
      90           0 : - (void) handleRequestConfigurationValuePacket:(NSDictionary *)packet;
      91           0 : - (void) handlePingPacket:(NSDictionary *)packet;
      92           0 : - (void) handlePongPacket:(NSDictionary *)packet;
      93             : 
      94           0 : - (void) disconnectFromServerWithMessage:(NSString *)message;
      95           0 : - (void) breakConnectionWithMessage:(NSString *)message;
      96           0 : - (void) breakConnectionWithBadStream:(NSStream *)stream;
      97             : 
      98             : @end
      99             : 
     100             : 
     101             : @implementation OODebugTCPConsoleClient
     102             : 
     103           0 : - (id) init
     104             : {
     105             :         return [self initWithAddress:nil port:0];
     106             : }
     107             : 
     108             : 
     109             : - (id) initWithAddress:(NSString *)address port:(uint16_t)port
     110             : {
     111             :         BOOL                                    OK = NO;
     112             :         NSDictionary                    *parameters = nil;
     113             :         
     114             :         if (address == nil)  address = @"127.0.0.1";
     115             :         if (port == 0)  port = kOOTCPConsolePort;
     116             :         
     117             :         self = [super init];
     118             :         if (self != nil)
     119             :         {
     120             :                 _host = [NSHost hostWithName:address];
     121             :                 if (_host != nil)
     122             :                 {
     123             :                         [_host retain];
     124             :                         [NSStream getStreamsToHost:_host
     125             :                                                                   port:port
     126             :                                                    inputStream:&_inStream
     127             :                                                   outputStream:&_outStream];
     128             :                 }
     129             :                 
     130             :                 if (_inStream != nil && _outStream != nil)
     131             :                 {
     132             :                         [_inStream retain];
     133             :                         [_outStream retain];
     134             :                         [_inStream setDelegate:self];
     135             :                         [_outStream setDelegate:self];
     136             :                         [_inStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
     137             :                         [_outStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
     138             :                         [_inStream open];
     139             :                         [_outStream open];
     140             :                         
     141             :                         // Need to wait for the streams to reach open status before we can send packets
     142             :                         // TODO: Might be neater to use the handleEvent callback to flag this.. - Micha 20090425
     143             :                         NSRunLoop * myRunLoop = [NSRunLoop currentRunLoop];
     144             :                         NSDate * timeOut = [NSDate dateWithTimeIntervalSinceNow:3]; // Wait up to 3 seconds
     145             :                         while( _host != nil && ([_inStream streamStatus] < 2 || [_outStream streamStatus] < 2) &&
     146             :                                         [myRunLoop runMode:NSDefaultRunLoopMode beforeDate:timeOut] )
     147             :                                 ; // Wait
     148             : 
     149             :                         _decoder = OOTCPStreamDecoderCreate(DecoderPacket, DecoderError, NULL, self);
     150             :                 }
     151             :                 
     152             :                 if (_decoder != NULL)
     153             :                 {
     154             :                         OK = YES;
     155             :                         _status = kOOTCPClientStartedConnectionStage1;
     156             :                         
     157             :                         
     158             :                         // Attempt to connect
     159             :                         parameters = [NSDictionary dictionaryWithObjectsAndKeys:
     160             :                                                         [NSNumber numberWithUnsignedInt:kOOTCPProtocolVersion_1_1_0], kOOTCPProtocolVersion,
     161             :                                                         [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"], kOOTCPOoliteVersion,
     162             :                                                         nil];
     163             :                         [self sendPacket:kOOTCPPacket_RequestConnection
     164             :                            withParameters:parameters];
     165             :                         
     166             :                         if (_status == kOOTCPClientStartedConnectionStage1)  _status = kOOTCPClientStartedConnectionStage2;
     167             :                         else  OK = NO;  // Connection failed.
     168             :                 }
     169             :                 
     170             :                 if (!OK)
     171             :                 {
     172             :                         OOLog(@"debugTCP.connect.failed", @"Failed to connect to debug console at address %@:%i.", address, port);
     173             :                         [self release];
     174             :                         self = nil;
     175             :                 }
     176             :         }
     177             :         
     178             :         return self;
     179             : }
     180             : 
     181             : 
     182           0 : - (void) dealloc
     183             : {
     184             :         if (StatusIsSendable(_status))
     185             :         {
     186             :                 [self disconnectFromServerWithMessage:@"TCP console bridge unexpectedly released while active."];
     187             :         }
     188             :         if (_monitor)
     189             :         {
     190             :                 [_monitor disconnectDebugger:self message:@"TCP console bridge unexpectedly released while active."];
     191             :         }
     192             :         
     193             :         
     194             :         [self closeConnection];
     195             :         
     196             :         OOTCPStreamDecoderDestroy(_decoder);
     197             :         _decoder = NULL;
     198             :         
     199             :         [super dealloc];
     200             : }
     201             : 
     202             : 
     203           0 : - (BOOL)connectDebugMonitor:(in OODebugMonitor *)debugMonitor
     204             :                            errorMessage:(out NSString **)message
     205             : {
     206             :         if (_status == kOOTCPClientConnectionRefused)
     207             :         {
     208             :                 if (message != NULL)  *message = @"Connection refused.";
     209             :                 return NO;
     210             :         }
     211             :         if (_status == kOOTCPClientDisconnected)
     212             :         {
     213             :                 if (message != NULL)  *message = @"Cannot reconnect after disconnecting.";
     214             :                 return NO;
     215             :         }
     216             :         
     217             :         _monitor = debugMonitor;
     218             :         
     219             :         return YES;
     220             : }
     221             : 
     222             : 
     223           0 : - (void)disconnectDebugMonitor:(in OODebugMonitor *)debugMonitor
     224             :                                            message:(in NSString *)message
     225             : {
     226             :         [self disconnectFromServerWithMessage:message];
     227             :         _monitor = nil;
     228             : }
     229             : 
     230             : 
     231           0 : - (oneway void)debugMonitor:(in OODebugMonitor *)debugMonitor
     232             :                         jsConsoleOutput:(in NSString *)output
     233             :                                    colorKey:(in NSString *)colorKey
     234             :                           emphasisRange:(in NSRange)emphasisRange
     235             : {
     236             :         NSMutableDictionary                     *parameters = nil;
     237             :         NSArray                                         *range = nil;
     238             :         
     239             :         parameters = [NSMutableDictionary dictionaryWithCapacity:3];
     240             :         [parameters setObject:output forKey:kOOTCPMessage];
     241             :         [parameters setObject:colorKey ? colorKey : (NSString *)@"general" forKey:kOOTCPColorKey];
     242             :         if (emphasisRange.length != 0)
     243             :         {
     244             :                 range = [NSArray arrayWithObjects:
     245             :                                                 [NSNumber numberWithUnsignedInteger:emphasisRange.location],
     246             :                                                 [NSNumber numberWithUnsignedInteger:emphasisRange.length],
     247             :                                                 nil];
     248             :                 [parameters setObject:range forKey:kOOTCPEmphasisRanges];
     249             :         }
     250             :         
     251             :         [self sendPacket:kOOTCPPacket_ConsoleOutput
     252             :            withParameters:parameters];
     253             : }
     254             : 
     255             : 
     256           0 : - (oneway void)debugMonitorClearConsole:(in OODebugMonitor *)debugMonitor
     257             : {
     258             :         [self sendPacket:kOOTCPPacket_ClearConsole
     259             :            withParameters:nil];
     260             : }
     261             : 
     262             : 
     263           0 : - (oneway void)debugMonitorShowConsole:(in OODebugMonitor *)debugMonitor
     264             : {
     265             :         [self sendPacket:kOOTCPPacket_ShowConsole
     266             :            withParameters:nil];
     267             : }
     268             : 
     269             : 
     270           0 : - (oneway void)debugMonitor:(in OODebugMonitor *)debugMonitor
     271             :                   noteConfiguration:(in NSDictionary *)configuration
     272             : {
     273             :         [self sendPacket:kOOTCPPacket_NoteConfiguration
     274             :                         withValue:configuration
     275             :                  forParameter:kOOTCPConfiguration];
     276             : }
     277             : 
     278             : 
     279           0 : - (oneway void)debugMonitor:(in OODebugMonitor *)debugMonitor
     280             : noteChangedConfigrationValue:(in id)newValue
     281             :                                          forKey:(in NSString *)key
     282             : {
     283             :         if (newValue != nil)
     284             :         {
     285             :                 [self sendPacket:kOOTCPPacket_NoteConfiguration
     286             :                                 withValue:[NSDictionary dictionaryWithObject:newValue forKey:key]
     287             :                          forParameter:kOOTCPConfiguration];
     288             :         }
     289             :         else
     290             :         {
     291             :                 [self sendPacket:kOOTCPPacket_NoteConfiguration
     292             :                                 withValue:[NSArray arrayWithObject:key]
     293             :                          forParameter:kOOTCPRemovedConfigurationKeys];
     294             :         }
     295             : }
     296             : 
     297             : 
     298           0 : - (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
     299             : {
     300             :         if (_status > kOOTCPClientConnected)  return;
     301             :         
     302             :         if (stream == _inStream && eventCode == NSStreamEventHasBytesAvailable)
     303             :         {
     304             :                 [self readData];
     305             :         }
     306             :         else if (eventCode == NSStreamEventErrorOccurred)
     307             :         {
     308             :                 [self breakConnectionWithBadStream:stream];
     309             :         }
     310             :         else if (eventCode == NSStreamEventErrorOccurred)
     311             :         {
     312             :                 [self breakConnectionWithMessage:[NSString stringWithFormat:
     313             :                    @"Console closed the connection."]];
     314             :         }
     315             : }
     316             : 
     317             : @end
     318             : 
     319             : 
     320             : @implementation OODebugTCPConsoleClient (OOPrivate)
     321             : 
     322             : - (void) closeConnection
     323             : {
     324             :         [_inStream close];
     325             :         [_inStream setDelegate:nil];
     326             :         [_inStream release];
     327             :         _inStream = nil;
     328             :         
     329             :         [_outStream close];
     330             :         [_outStream setDelegate:nil];
     331             :         [_outStream release];
     332             :         _outStream = nil;
     333             :         
     334             :         [_host release];
     335             :         _host = nil;
     336             : }
     337             : 
     338             : 
     339             : - (BOOL) sendBytes:(const void *)bytes count:(size_t)count
     340             : {
     341             :         if (bytes == NULL || count == 0)  return YES;
     342             :         if (!StatusIsSendable(_status) || _outStream == nil)  return NO;
     343             :         
     344             :         do
     345             :         {
     346             :                 NSInteger written = [_outStream write:bytes maxLength:count];
     347             :                 if (written < 1)  return NO;
     348             :                 
     349             :                 count -= written;
     350             :                 bytes += written;
     351             :         }
     352             :         while (count > 0);
     353             :         
     354             :         return YES;
     355             : }
     356             : 
     357             : 
     358             : - (void) sendDictionary:(NSDictionary *)dictionary
     359             : {
     360             :         NSData                                  *data = nil;
     361             :         NSString                                *errorDesc = NULL;
     362             :         size_t                                  count;
     363             :         const uint8_t                   *bytes = NULL;
     364             :         uint32_t                                header;
     365             :         bool                                    sentOK = YES;
     366             :         
     367             :         if (dictionary == nil || !StatusIsSendable(_status))  return;
     368             :         
     369             :         data = [NSPropertyListSerialization dataFromPropertyList:dictionary
     370             :                                                                                                           format:NSPropertyListXMLFormat_v1_0
     371             :                                                                                         errorDescription:&errorDesc];
     372             :         
     373             :         if (data == nil)
     374             :         {
     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
     377             :                 [errorDesc autorelease];
     378             : #endif
     379             :                 return;
     380             :         }
     381             :         
     382             :         LogSendPacket(dictionary);
     383             :         
     384             :         count = [data length];
     385             :         if (count == 0)  return;
     386             :         header = htonl(count);
     387             :         
     388             :         bytes = [data bytes];
     389             :         
     390             :         /*      In testing, all bad stream errors were caused by the python console
     391             :                 rejecting headers. Made the protocol a bit more fault tolerant.
     392             :                 -- Kaks 2012.03.24
     393             :         */
     394             :         if (![self sendBytes:&header count:sizeof header])
     395             :         {
     396             :                 OOLog(@"debugTCP.send.warning", @"%@", @"Error sending packet header, retrying.");
     397             :                 // wait 8 milliseconds, resend the header
     398             :                 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:.008]];
     399             :                 if (![self sendBytes:&header count:sizeof header])
     400             :                 {
     401             :                         //OOLog(@"debugTCP.send.warning", @"Error sending packet header, retrying one more time.");
     402             :                         // wait 16 milliseconds, try to resend the header one last time!
     403             :                         [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:.016]];
     404             :                         if (![self sendBytes:&header count:sizeof header])
     405             :                         {
     406             :                                 sentOK = NO;
     407             :                         }
     408             :                 }
     409             :         }
     410             :         
     411             :         if(sentOK && ![self sendBytes:bytes count:count])
     412             :         {
     413             :                 OOLog(@"debugTCP.send.warning", @"%@", @"Error sending packet body, retrying.");
     414             :                 // wait 8 milliseconds, try again.
     415             :                 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:.008]];
     416             :                 if(![self sendBytes:bytes count:count])
     417             :                 {
     418             :                         sentOK = NO;
     419             :                 }
     420             :         }
     421             :         
     422             :         if (!sentOK)
     423             :         {
     424             :                 OOLog(@"debugTCP.send.error", @"The following packet could not be sent: %@", dictionary);
     425             :                 if(![[OODebugMonitor sharedDebugMonitor] TCPIgnoresDroppedPackets])
     426             :                 {
     427             :                         [self breakConnectionWithBadStream:_outStream];
     428             :                 }
     429             :         }
     430             : }
     431             : 
     432             : 
     433             : - (void) sendPacket:(NSString *)packetType
     434             :          withParameters:(NSDictionary *)parameters
     435             : {
     436             :         NSDictionary            *dict = nil;
     437             :         
     438             :         if (packetType == nil)  return;
     439             :         
     440             :         if (parameters != nil)
     441             :         {
     442             :                 dict = [parameters dictionaryByAddingObject:packetType forKey:kOOTCPPacketType];
     443             :         }
     444             :         else
     445             :         {
     446             :                 dict = [NSDictionary dictionaryWithObjectsAndKeys:packetType, kOOTCPPacketType, nil];
     447             :         }
     448             :         
     449             :         [self sendDictionary:dict];
     450             : }
     451             : 
     452             : 
     453             : - (void) sendPacket:(NSString *)packetType
     454             :                   withValue:(id)value
     455             :            forParameter:(NSString *)paramKey
     456             : {
     457             :         if (packetType == nil)  return;
     458             :         if (paramKey == nil)  value = nil;
     459             :         
     460             :         [self sendDictionary:[NSDictionary dictionaryWithObjectsAndKeys:
     461             :                 packetType, kOOTCPPacketType,
     462             :                 value, paramKey,
     463             :                 nil]];
     464             : }
     465             : 
     466             : 
     467             : - (void) readData
     468             : {
     469             :         enum { kBufferSize = 16 << 10 };
     470             :         
     471             :         uint8_t                                                 buffer[kBufferSize];
     472             :         NSInteger                                               length;
     473             :         NSData                                                  *data;
     474             :         
     475             :         length = [_inStream read:buffer maxLength:kBufferSize];
     476             :         while (length > 0)
     477             :         {
     478             :                 data = [NSData dataWithBytesNoCopy:buffer length:length freeWhenDone:NO];
     479             :                 OOTCPStreamDecoderReceiveData(_decoder, data);
     480             :                 length = [_inStream read:buffer maxLength:kBufferSize];
     481             :         }
     482             : }
     483             : 
     484             : 
     485             : - (void) dispatchPacket:(NSDictionary *)packet ofType:(NSString *)packetType
     486             : {
     487             :         if (packet == nil || packetType == nil)  return;
     488             :         
     489           0 : #define PACKET_CASE(x) else if ([packetType isEqualToString:kOOTCPPacket_##x])  { [self handle##x##Packet:packet]; }
     490             :         
     491             :         if (0) {}
     492             :         PACKET_CASE(ApproveConnection)
     493             :         PACKET_CASE(RejectConnection)
     494             :         PACKET_CASE(CloseConnection)
     495             :         PACKET_CASE(NoteConfigurationChange)
     496             :         PACKET_CASE(PerformCommand)
     497             :         PACKET_CASE(RequestConfigurationValue)
     498             :         PACKET_CASE(Ping)
     499             :         PACKET_CASE(Pong)
     500             :         else
     501             :         {
     502             :                 OOLog(@"debugTCP.protocolError.unknownPacketType", @"Unhandled packet type %@.", packetType);
     503             :         }
     504             : }
     505             : 
     506             : 
     507             : - (void) handleApproveConnectionPacket:(NSDictionary *)packet
     508             : {
     509             :         NSMutableString                 *connectedMessage = nil;
     510             :         NSString                                *consoleIdentity = nil;
     511             :         NSString                                *hostName = nil;
     512             :         
     513             :         if (_status == kOOTCPClientStartedConnectionStage2)
     514             :         {
     515             :                 _status = kOOTCPClientConnected;
     516             :                 
     517             :                 // Build "Connected..." message with two optional parts, console identity and host name.
     518             :                 connectedMessage = [NSMutableString stringWithString:@"Connected to debug console"];
     519             :                 
     520             :                 consoleIdentity = [packet oo_stringForKey:kOOTCPConsoleIdentity];
     521             :                 if (consoleIdentity != nil)  [connectedMessage appendFormat:@" \"%@\"", consoleIdentity];
     522             :                 
     523             :                 hostName = [_host name];
     524             :                 if ([hostName length] != 0 &&
     525             :                         ![hostName isEqual:@"localhost"] &&
     526             :                         ![hostName isEqual:@"127.0.0.1"] &&
     527             :                         ![hostName isEqual:@"::1"])
     528             :                 {
     529             :                         [connectedMessage appendFormat:@" at %@", hostName];
     530             :                 }
     531             :                 
     532             :                 OOLog(@"debugTCP.connected", @"%@.", connectedMessage);
     533             :         }
     534             :         else
     535             :         {
     536             :                 OOLog(@"debugTCP.protocolError.outOfOrder", @"Got %@ packet from debug console in wrong context.", kOOTCPPacket_ApproveConnection);
     537             :         }       
     538             : }
     539             : 
     540             : 
     541             : - (void) handleRejectConnectionPacket:(NSDictionary *)packet
     542             : {
     543             :         NSString                                *message = nil;
     544             :         
     545             :         if (_status == kOOTCPClientStartedConnectionStage2)
     546             :         {
     547             :                 _status = kOOTCPClientConnectionRefused;
     548             :         }
     549             :         else
     550             :         {
     551             :                 OOLog(@"debugTCP.protocolError.outOfOrder", @"Got %@ packet from debug console in wrong context.", kOOTCPPacket_RejectConnection);
     552             :         }
     553             :         
     554             :         message = [packet oo_stringForKey:kOOTCPMessage];
     555             :         if (message == nil)  message = @"Console refused connection.";
     556             :         [self breakConnectionWithMessage:message];
     557             : }
     558             : 
     559             : 
     560             : - (void) handleCloseConnectionPacket:(NSDictionary *)packet
     561             : {
     562             :         NSString                                *message = nil;
     563             :         
     564             :         if (!StatusIsSendable(_status))
     565             :         {
     566             :                 OOLog(@"debugTCP.protocolError.outOfOrder", @"Got %@ packet from debug console in wrong context.", kOOTCPPacket_CloseConnection);
     567             :         }
     568             :         message = [packet oo_stringForKey:kOOTCPMessage];
     569             :         if (message == nil)  message = @"Console closed connection.";
     570             :         [self breakConnectionWithMessage:message];
     571             : }
     572             : 
     573             : 
     574             : - (void) handleNoteConfigurationChangePacket:(NSDictionary *)packet
     575             : {
     576             :         NSDictionary                    *configuration = nil;
     577             :         NSArray                                 *removed = nil;
     578             :         NSEnumerator                    *keyEnum = nil;
     579             :         NSString                                *key = nil;
     580             :         id                                              value = nil;
     581             :         
     582             :         if (_monitor == nil)  return;
     583             :         
     584             :         configuration = [packet oo_dictionaryForKey:kOOTCPConfiguration];
     585             :         if (configuration != nil)
     586             :         {
     587             :                 for (keyEnum = [configuration keyEnumerator]; (key = [keyEnum nextObject]); )
     588             :                 {
     589             :                         value = [configuration objectForKey:key];
     590             :                         [_monitor setConfigurationValue:value forKey:key];
     591             :                 }
     592             :         }
     593             :         
     594             :         removed = [configuration oo_arrayForKey:kOOTCPRemovedConfigurationKeys];
     595             :         for (keyEnum = [removed objectEnumerator]; (key = [keyEnum nextObject]); )
     596             :         {
     597             :                 [_monitor setConfigurationValue:nil forKey:key];
     598             :         }
     599             : }
     600             : 
     601             : 
     602             : - (void) handlePerformCommandPacket:(NSDictionary *)packet
     603             : {
     604             :         NSString                                *message = nil;
     605             :         
     606             :         message = [packet oo_stringForKey:kOOTCPMessage];
     607             :         if (message != nil)  [_monitor performJSConsoleCommand:message];
     608             : }
     609             : 
     610             : 
     611             : - (void) handleRequestConfigurationValuePacket:(NSDictionary *)packet
     612             : {
     613             :         NSString                                *key = nil;
     614             :         id                                              value = nil;
     615             :         
     616             :         key = [packet oo_stringForKey:kOOTCPConfigurationKey];
     617             :         if (key != nil)
     618             :         {
     619             :                 value = [_monitor configurationValueForKey:key];
     620             :                 [self debugMonitor:_monitor
     621             :  noteChangedConfigrationValue:value
     622             :                                         forKey:key];
     623             :         }
     624             : }
     625             : 
     626             : 
     627             : - (void) handlePingPacket:(NSDictionary *)packet
     628             : {
     629             :         id                                              message = nil;
     630             :         
     631             :         message = [packet objectForKey:kOOTCPMessage];
     632             :         [self sendPacket:kOOTCPPacket_Pong
     633             :                         withValue:message
     634             :                  forParameter:kOOTCPMessage];
     635             : }
     636             : 
     637             : 
     638             : - (void) handlePongPacket:(NSDictionary *)packet
     639             : {
     640             :         // Do nothing; we don't currently send pings.
     641             : }
     642             : 
     643             : 
     644             : - (void) disconnectFromServerWithMessage:(NSString *)message
     645             : {
     646             :         if (StatusIsSendable(_status))
     647             :         {
     648             :                 [self sendPacket:kOOTCPPacket_CloseConnection
     649             :                                 withValue:message
     650             :                          forParameter:kOOTCPMessage];
     651             :         }
     652             :         [self closeConnection];
     653             :         
     654             :         _status = kOOTCPClientDisconnected;
     655             : }
     656             : 
     657             : 
     658             : - (void) breakConnectionWithMessage:(NSString *)message
     659             : {
     660             :         [self closeConnection];
     661             :         
     662             :         if (_status != kOOTCPClientConnectionRefused)  _status = kOOTCPClientDisconnected;
     663             :         
     664             :         if ([message length] > 0)
     665             :         {
     666             :                 OOLog(@"debugTCP.disconnect", @"No connection to debug console: \"%@\"", message);
     667             :         }
     668             :         else
     669             :         {
     670             :                 OOLog(@"debugTCP.disconnect", @"%@", @"Debug console not connected.");    
     671             :         }
     672             :         
     673             : #if 0
     674             :         // Disconnecting causes crashiness for reasons I don't understand, and isn't very important anyway.
     675             :         [_monitor disconnectDebugger:self message:message];
     676             :         _monitor = nil;
     677             : #endif
     678             : }
     679             : 
     680             : 
     681             : - (void) breakConnectionWithBadStream:(NSStream *)stream
     682             : {
     683             :         NSString                                *errorDesc = nil;
     684             :         NSError                                 *error = nil;
     685             :         
     686             :         error = [stream streamError];
     687             :         errorDesc = [error localizedDescription];
     688             :         if (errorDesc == nil)  errorDesc = [error description];
     689             :         if (errorDesc == nil)  errorDesc = @"bad stream.";
     690             :         [self breakConnectionWithMessage:[NSString stringWithFormat:
     691             :            @"Connection to debug console failed: '%@' (outStream status: %li, inStream status: %li).",
     692             :                 errorDesc, [_outStream streamStatus], [_inStream streamStatus]]];
     693             : }
     694             : 
     695             : @end
     696             : 
     697             : 
     698           0 : static void DecoderPacket(void *cbInfo, OOALStringRef packetType, OOALDictionaryRef packet)
     699             : {
     700             :         [(OODebugTCPConsoleClient *)cbInfo dispatchPacket:packet ofType:packetType];
     701             : }
     702             : 
     703             : 
     704           0 : static void DecoderError(void *cbInfo, OOALStringRef errorDesc)
     705             : {
     706             :         [(OODebugTCPConsoleClient *)cbInfo breakConnectionWithMessage:errorDesc];
     707             : }
     708             : 
     709             : 
     710             : #ifdef OO_LOG_DEBUG_PROTOCOL_PACKETS
     711             : void LogOOTCPStreamDecoderPacket(NSDictionary *packet)
     712             : {
     713             :         NSData                                  *data = nil;
     714             :         NSString                                *xml = nil;
     715             :         
     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);
     719             : }
     720             : 
     721             : 
     722             : static void LogSendPacket(NSDictionary *packet)
     723             : {
     724             :         NSData                                  *data = nil;
     725             :         NSString                                *xml = nil;
     726             :         
     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);
     730             : }
     731             : #endif
     732             : 
     733             : #endif /* OO_EXCLUDE_DEBUG_SUPPORT */

Generated by: LCOV version 1.14