Oolite 1.91.0.7646-241128-10e222e
Loading...
Searching...
No Matches
OODebugTCPConsoleClient.m
Go to the documentation of this file.
1/*
2
3OODebugTCPConsoleClient.m
4
5
6Oolite Debug Support
7
8Copyright (C) 2009-2013 Jens Ayton and contributors
9
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files (the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions:
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27
28*/
29
30#ifndef OO_EXCLUDE_DEBUG_SUPPORT
31
32
35#import "OODebugMonitor.h"
37#import "OOLogging.h"
38#include <stdint.h>
40
41#if OOLITE_WINDOWS
42#include <winsock2.h>
43#else
44#include <arpa/inet.h> // For htonl
45#endif
46
49
50
51#ifdef OO_LOG_DEBUG_PROTOCOL_PACKETS
52static void LogSendPacket(NSDictionary *packet);
53#else
54#define LogSendPacket(packet) do {} while (0)
55#endif
56
57
58static void DecoderPacket(void *cbInfo, OOALStringRef packetType, OOALDictionaryRef packet);
59static void DecoderError(void *cbInfo, OOALStringRef errorDesc);
60
61
66
67
68@interface OODebugTCPConsoleClient (OOPrivate)
69
70- (void) closeConnection;
71
72- (BOOL) sendBytes:(const void *)bytes count:(size_t)count;
73- (void) sendDictionary:(NSDictionary *)dictionary;
74
75- (void) sendPacket:(NSString *)packetType
76 withParameters:(NSDictionary *)parameters;
77
78- (void) sendPacket:(NSString *)packetType
79 withValue:(id)value
80 forParameter:(NSString *)paramKey;
81
82- (void) readData;
83- (void) dispatchPacket:(NSDictionary *)packet ofType:(NSString *)packetType;
84
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;
93
94- (void) disconnectFromServerWithMessage:(NSString *)message;
95- (void) breakConnectionWithMessage:(NSString *)message;
96- (void) breakConnectionWithBadStream:(NSStream *)stream;
97
98@end
99
100
101@implementation OODebugTCPConsoleClient
102
103- (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;
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
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- (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
197 _decoder = NULL;
198
199 [super dealloc];
200}
201
202
203- (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- (void)disconnectDebugMonitor:(in OODebugMonitor *)debugMonitor
224 message:(in NSString *)message
225{
226 [self disconnectFromServerWithMessage:message];
227 _monitor = nil;
228}
229
230
231- (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- (oneway void)debugMonitorClearConsole:(in OODebugMonitor *)debugMonitor
257{
258 [self sendPacket:kOOTCPPacket_ClearConsole
259 withParameters:nil];
260}
261
262
263- (oneway void)debugMonitorShowConsole:(in OODebugMonitor *)debugMonitor
264{
265 [self sendPacket:kOOTCPPacket_ShowConsole
266 withParameters:nil];
267}
268
269
270- (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- (oneway void)debugMonitor:(in OODebugMonitor *)debugMonitor
280noteChangedConfigrationValue:(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- (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#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
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
546 {
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
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
698static void DecoderPacket(void *cbInfo, OOALStringRef packetType, OOALDictionaryRef packet)
699{
700 [(OODebugTCPConsoleClient *)cbInfo dispatchPacket:packet ofType:packetType];
701}
702
703
704static void DecoderError(void *cbInfo, OOALStringRef errorDesc)
705{
706 [(OODebugTCPConsoleClient *)cbInfo breakConnectionWithMessage:errorDesc];
707}
708
709
710#ifdef OO_LOG_DEBUG_PROTOCOL_PACKETS
711void 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
722static 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 */
OOTCPClientConnectionStatus
@ kOOTCPClientStartedConnectionStage2
@ kOOTCPClientConnected
@ kOOTCPClientStartedConnectionStage1
@ kOOTCPClientConnectionRefused
@ kOOTCPClientDisconnected
#define LogSendPacket(packet)
OOINLINE BOOL StatusIsSendable(OOTCPClientConnectionStatus status)
#define PACKET_CASE(x)
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 OOINLINE
#define OOLog(class, format,...)
Definition OOLogging.h:88
unsigned count
return nil
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)
id initWithAddress:port:(NSString *address,[port] uint16_t port)
voidpf stream
Definition ioapi.h:134