// // Conversation.m // // Created by Eric Baur on Thu Jul 08 2004. // Copyright (c) 2004 Eric Shore Baur. All rights reserved. // #import "Conversation.h" @implementation Conversation static BOOL requireSyn; static BOOL capturesData; + (void)initialize { // update flags [self setKeys:[NSArray arrayWithObject:@"flags"] triggerChangeNotificationsForDependentKey:@"flagsArray"]; [self setKeys:[NSArray arrayWithObject:@"flags"] triggerChangeNotificationsForDependentKey:@"flagsAsAttributedString"]; [self setKeys:[NSArray arrayWithObject:@"sflags"] triggerChangeNotificationsForDependentKey:@"sourceFlagsAsAttributedString"]; [self setKeys:[NSArray arrayWithObject:@"dflags"] triggerChangeNotificationsForDependentKey:@"destinationFlagsAsAttributedString"]; // update sequence numbers [self setKeys:[NSArray arrayWithObject:@"seq"] triggerChangeNotificationsForDependentKey:@"sequenceArray"]; // update acknowledgements [self setKeys:[NSArray arrayWithObject:@"ack"] triggerChangeNotificationsForDependentKey:@"acknowledgementArray"]; // update windows [self setKeys:[NSArray arrayWithObject:@"win"] triggerChangeNotificationsForDependentKey:@"windowArray"]; // update length [self setKeys:[NSArray arrayWithObject:@"bytes"] triggerChangeNotificationsForDependentKey:@"lengthArray"]; // update timestamp [self setKeys:[NSArray arrayWithObject:@"timestamp"] triggerChangeNotificationsForDependentKey:@"timestampArray"]; //update payload [self setKeys:[NSArray arrayWithObjects:@"payloadArray", @"representation", @"displayCount", @"bytes", nil] triggerChangeNotificationsForDependentKey:@"payloadAsAttributedString"]; [self setKeys:[NSArray arrayWithObjects:@"representation", @"sbytes", nil] triggerChangeNotificationsForDependentKey:@"clientPayloadAsAttributedString"]; [self setKeys:[NSArray arrayWithObjects:@"representation", @"dbytes", nil] triggerChangeNotificationsForDependentKey:@"serverPayloadAsAttributedString"]; // not sure if @"representation" needs to be here... [self setKeys:[NSArray arrayWithObjects:@"representation", @"displayCount", @"clientPayloadAsAttributedString", nil] triggerChangeNotificationsForDependentKey:@"clientPayloadAsRTFData"]; [self setKeys:[NSArray arrayWithObjects:@"representation", @"serverPayloadAsAttributedString", nil] triggerChangeNotificationsForDependentKey:@"serverPayloadAsRTFData"]; [self setKeys:[NSArray arrayWithObjects:@"representation", @"payloadAsAttributedString", nil] triggerChangeNotificationsForDependentKey:@"payloadAsRTFData"]; [self setKeys:[NSArray arrayWithObjects: @"flagsArray", @"sequenceArray", @"acknowledgementArray", @"windowArray", @"lengthArray", @"timestampArray", nil ] triggerChangeNotificationsForDependentKey:@"history"]; [self setKeys:[NSArray arrayWithObjects: @"flagsArray", @"sequenceArray", @"acknowledgementArray", @"windowArray", @"lengthArray", @"timestampArray", nil ] triggerChangeNotificationsForDependentKey:@"historyDataSet"]; [self setKeys:[NSArray arrayWithObjects: @"flagsArray", @"sequenceArray", @"acknowledgementArray", @"windowArray", @"lengthArray", @"timestampArray", nil ] triggerChangeNotificationsForDependentKey:@"myself"]; [ColorizationRules sharedRulesWithDictionary:[[NSDictionary alloc] initWithObjectsAndKeys: [NSColor greenColor], @"-S------", [NSColor yellowColor], @"-S--A---", [NSColor brownColor], @"----A---", [NSColor blueColor], @"---PA---", [NSColor blackColor], @"F---A---", [NSColor blackColor], @"F-------", [NSColor magentaColor], @"--R-A---", [NSColor redColor], @"--R-----", [NSColor grayColor], @"--------", nil ] ]; requireSyn = NO; } + (BOOL)requiresSyn { return requireSyn; } + (void)setRequiresSyn:(BOOL)synFirst { requireSyn = synFirst; } + (BOOL)capturesData { return capturesData; } + (void)setCapturesData:(BOOL)dataCapture { capturesData = dataCapture; } + (NSString *)calculateIDFromSource:(NSString *)src port:(int)srcp destination:(NSString *)dst port:(int)dstp { if (srcp>dstp) { return [NSString stringWithFormat:@"%@:%d-%@:%d", src, srcp, dst, dstp ]; } else { return [NSString stringWithFormat:@"%@:%d-%@:%d", dst, dstp, src, srcp ]; } } + (id)blankConversation { return [[[Conversation alloc] initWithOrderingNumber:0 source:@"127.0.0.1" port:0 destination:@"255.255.255.255" port:65535 flags:@"--------" sequence:0 acknowledgment:0 window:0 length:0 timestamp:0.0 payload:[NSData data] ] autorelease ]; } #pragma mark "Global" methods - (id)myself { return self; } - (id)initWithOrderNumber:(int)number packet:(NSDictionary *)origPacket { return [self initWithOrderingNumber:number source: [origPacket objectForKey:@"source"] port: [[origPacket objectForKey:@"sport"] intValue] destination: [origPacket objectForKey:@"destination"] port: [[origPacket objectForKey:@"dport"] intValue] flags: [origPacket objectForKey:@"flags"] sequence: [[origPacket objectForKey:@"sequence"] unsignedLongLongValue] acknowledgment: [[origPacket objectForKey:@"acknowledgement"] unsignedLongLongValue] window: [[origPacket objectForKey:@"window"] intValue] length: [[origPacket objectForKey:@"length"] intValue] timestamp: [[origPacket objectForKey:@"timestamp"] doubleValue] payload: [origPacket objectForKey:@"payload"] ]; } - (id)initWithOrderingNumber:(int)number source:(NSString *)origSource port:(int)sourcePort destination:(NSString *)origDestination port:(int)destinationPort flags:(NSString *)origFlags sequence:(unsigned long long)origSequence acknowledgment:(unsigned long long)origAcknowledgment window:(int)origWindow length:(int)origLength timestamp:(double)origTimestamp payload:(NSData *)origPayload { // if (requireSyn && ![origFlags isEqual:@"-S------"]) // return nil; self = [super init]; if (self) { ordering_number = number; [self setSource:origSource]; [self setSourcePort:sourcePort]; [self setDestination:origDestination]; [self setDestinationPort:destinationPort]; if (requireSyn && ![origFlags isEqual:@"-S------"]) hidden = YES; else hidden = NO; representation = 0; bytes = 0; sbytes = 0; dbytes = 0; count = 1; scount = 1; dcount = 0; flagsArray = [[NSMutableArray array] retain]; [self addFlags:origFlags withSource:origSource]; sequenceArray = [[NSMutableArray array] retain]; [self addSequenceAsULL:origSequence]; acknowledgementArray = [[NSMutableArray array] retain]; [self addAcknowledgementAsULL:origAcknowledgment]; windowArray = [[NSMutableArray array] retain]; [self addWindowAsInt:origWindow]; lengthArray = [[NSMutableArray array] retain]; [self addLengthAsInt:origLength]; timestampArray = [[NSMutableArray array] retain]; [self addTimestampAsDouble:origTimestamp]; sflags = origFlags; [sflags retain]; dflags = [NSString stringWithString:@"--------"]; [dflags retain]; flags = origFlags; [flags retain]; timestamp = origTimestamp; if (capturesData) payloadArray = [[NSMutableArray array] retain]; else payloadArray = nil; [self addPayload:origPayload withSource:source]; colorizationRules = [[ColorizationRules sharedRules] retain]; } return self; } - (void)addPacket:(NSDictionary *)newPacket { [self addPacketWithSource: [newPacket objectForKey:@"source"] flags: [newPacket objectForKey:@"flags"] sequence: [[newPacket objectForKey:@"sequence"] unsignedLongLongValue] acknowledgement: [[newPacket objectForKey:@"acknowledgement"] unsignedLongLongValue] window: [[newPacket objectForKey:@"window"] intValue] length: [[newPacket objectForKey:@"length"] intValue] timestamp: [[newPacket objectForKey:@"timestamp"] doubleValue] payload: [newPacket objectForKey:@"payload"] ]; } - (void)addPacketWithSource:(NSString *)packetSource flags:(NSString *)packetFlags sequence:(unsigned long long)packetSeq acknowledgement:(unsigned long long)packetAck window:(int)packetWindow length:(int)packetLength timestamp:(double)packetTimestamp payload:(NSData *)packetPayload { [self addFlags:packetFlags withSource:packetSource]; [self addSequenceAsULL:packetSeq]; [self addAcknowledgementAsULL:packetAck]; [self addWindowAsInt:packetWindow]; [self addLengthAsInt:packetLength]; [self addTimestampAsDouble:packetTimestamp]; [self addPayload:packetPayload withSource:packetSource]; if ([packetSource isEqual:source]) { scount++; sbytes += packetLength; } else if ([packetSource isEqual:destination]) { dcount++; dbytes += packetLength; } count++; bytes += packetLength; if (historyController) [historyController addObject:[self dictionaryForHistoryIndex:(count-1)] ]; } #pragma mark simple accessor methods - (void)addFlags:(NSString *)newFlags withSource:(NSString *)theSource { [flags release]; if ([theSource isEqual:source]) { flags = [NSString stringWithFormat:@" %@>",newFlags]; [sflags release]; sflags = newFlags; [sflags retain]; } else if ([theSource isEqual:destination]) { flags = [NSString stringWithFormat:@"<%@ ",newFlags]; [dflags release]; dflags = newFlags; [dflags retain]; } else { flags = @"-xxxxxxxx-"; } [flagsArray addObject:flags]; [flags retain]; } - (void)addSequence:(NSNumber *)newSequence { sequence = [newSequence unsignedLongLongValue]; [sequenceArray addObject:newSequence]; } - (void)addSequenceAsULL:(unsigned long long)newSequence { sequence = newSequence; [sequenceArray addObject:[NSNumber numberWithUnsignedLongLong:sequence]]; } - (void)addAcknowledgement:(NSNumber *)newAcknowledgement { acknowledgement = [newAcknowledgement unsignedLongLongValue]; [acknowledgementArray addObject:newAcknowledgement]; } - (void)addAcknowledgementAsULL:(unsigned long long)newAcknowledgement { acknowledgement = newAcknowledgement; [acknowledgementArray addObject:[NSNumber numberWithUnsignedLongLong:acknowledgement]]; } - (void)addWindow:(NSNumber *)newWindow { window = [newWindow intValue]; [windowArray addObject:newWindow]; } - (void)addWindowAsInt:(int)newWindow { window = newWindow; [windowArray addObject:[NSNumber numberWithInt:window]]; } - (void)addLength:(NSNumber *)newLength { [lengthArray addObject:newLength]; } - (void)addLengthAsInt:(int)newLength { [lengthArray addObject:[NSNumber numberWithInt:newLength] ]; } - (void)addTimestampAsDouble:(double)newTimestamp { if (newTimestamp) [timestampArray addObject:[NSDate dateWithTimeIntervalSince1970:newTimestamp] ]; else [timestampArray addObject:[NSDate dateWithTimeIntervalSinceNow:0]]; timestamp = newTimestamp; } - (void)addPayload:(NSData *)newPayload withSource:(NSString *)theSource { if ( ! capturesData ) { return; } //NSLog(@"addPayload:%@ withSource:%@",[newPayload description],theSource); [payloadArray addObject:[NSDictionary dictionaryWithObjectsAndKeys: newPayload, @"payload", theSource, @"source", nil ] ]; } - (double)lastTimestamp { return timestamp; } - (double)timelength { return (timestamp - [[timestampArray objectAtIndex:0] timeIntervalSince1970]); } - (double)starttime { return [[timestampArray objectAtIndex:0] timeIntervalSince1970]; } - (NSString *)source { return source; } - (NSString *)destination { return destination; } - (int)sourcePort { return sport; } - (int)destinationPort { return dport; } #pragma mark complex accessor methods - (NSAttributedString *)flagsAsAttributedString { return [colorizationRules colorize:flags]; } - (NSAttributedString *)sourceFlagsAsAttributedString { return [colorizationRules colorize:sflags]; } - (NSAttributedString *)destinationFlagsAsAttributedString { return [colorizationRules colorize:dflags]; } - (NSArray *)payloadArrayBySource { //NSEnumerator *en = [payloadArray objectEnumerator]; NSDictionary *tempDict; NSData *testData; NSMutableData *tempData = nil; NSMutableArray *returnArray = [NSMutableArray array]; unsigned int payloadCount = 0; unsigned int payloadBytes = 0; unsigned int payloadOrder = 0; int startingIndex = 0; id currentSource = nil; int i; int packetCount = [payloadArray count]; for (i=0; i2 || representation<0) { //this line needs to change is more types are added NSLog( @"No valid representation specified: using CONVERSATION_ASCII" ); representation = CONVERSATION_ASCII; } /* CONVERSATION_ASCII calculations */ if (representation==CONVERSATION_ASCII) { ENTRY(NSLog( @"processing CONVERSATION_ASCII" );) outputLen = bufferLen; output = malloc( outputLen ); for (i=0; i 128 || buffer[i] < 32 ) { if ( !(buffer[i]==9 || buffer[i]==10 || buffer[i]==12 || buffer[i]==13 ) ) output[i] = '.'; else output[i] = buffer[i]; } else { output[i] = buffer[i]; } } /* CONVERSATION_HEX calculations */ } else if (representation==CONVERSATION_HEX) { ENTRY(NSLog( @"processing CONVERSATION_HEX" );) outputLen = 51 * ( bufferLen/16 + 1 ); output = malloc( outputLen ); j = 0; //index for output for (i=0; i>4) & 0xF ]; output[j++] = hexDigits[ buffer[i] & 0xF ]; } for ( ; j 128 || buffer[k] < 32 ) output[j++] = '.'; else output[j++] = buffer[k]; } } output[j++] = newline; } else if (i%8==0) { output[j++] = space; } output[j++] = space; output[j++] = hexDigits[ (buffer[i]>>4) & 0xF ]; output[j++] = hexDigits[ buffer[i] & 0xF ]; } //fill up the hex spaces unsigned int roundOff = 16*(i/16+1); // We don't add to much space if line if full (i%16==0) if (!(i%16==0)) { for (k=i; k 128 || buffer[k] < 32 ) output[j++] = '.'; else output[j++] = buffer[k]; } output[j++] = newline; for ( ; j8) { //this is an arbitrary restriction, do I need it? for (i=0; i=0) return [searchData subdataWithRange:NSMakeRange(start,len-start)]; else return nil; } #pragma mark more accessor methods - (void)setSource:(NSString *)newSource { if (newSource==nil) return; [source release]; source = newSource; [source retain]; idChanged = YES; } - (void)setDestination:(NSString *)newDestination { if (newDestination==nil) return; [destination release]; destination = newDestination; [destination retain]; idChanged = YES; } - (void)setSourcePort:(int)newSourcePort { if ( newSourcePort >= 0 && newSourcePort <= 65535 ) { sport = newSourcePort; idChanged = YES; } } - (void)setDestinationPort:(int)newDestinationPort { if ( newDestinationPort >= 0 && newDestinationPort <= 65535 ) { dport = newDestinationPort; idChanged = YES; } } - (BOOL)isHidden { //NSLog( @"check hidden state" ); return hidden; } - (void)setHidden:(BOOL)state { hidden = state; } #pragma mark intersting statistics - (NSArray *)waitTimes { NSMutableArray *tempArray = [NSMutableArray array]; int i; int myCount = [timestampArray count]; for (i=0; i maxTime) maxTime = tempTime; } return maxTime; } - (double)serverMaxWaitTime { double maxTime = -1; double tempTime; int i; int myCount = [payloadArray count]; for ( i=0; i maxTime) maxTime = tempTime; } } return maxTime; } - (double)clientMaxWaitTime { double maxTime = -1; double tempTime; int i; int myCount = [payloadArray count]; for ( i=0; i maxTime) maxTime = tempTime; } } return maxTime; } - (double)connectWaitTime { //bail if the first packet is not a SYN packet if ( ! [[flagsArray objectAtIndex:0] isEqualToString:@" -S------>"] ) { return 0; } //check the next few packets to see if any is a SYN/ACK int i; int myCount = [flagsArray count]; for (i=1; i<6 && i"] ) { [tempDict setObject:[NSNumber numberWithInt:0] forKey:@"flagNums"]; } else if ( [tempString isEqualToString:@"<-S--A--- "] || [tempString isEqualToString:@" -S--A--->"] ) { [tempDict setObject:[NSNumber numberWithInt:1] forKey:@"flagNums"]; } else if ( [tempString isEqualToString:@"<----A--- "] || [tempString isEqualToString:@" ----A--->"] ) { [tempDict setObject:[NSNumber numberWithInt:2] forKey:@"flagNums"]; } else if ( [tempString isEqualToString:@"<---PA--- "] || [tempString isEqualToString:@" ---PA--->"] ) { [tempDict setObject:[NSNumber numberWithInt:3] forKey:@"flagNums"]; } else if ( [tempString isEqualToString:@""] ) { [tempDict setObject:[NSNumber numberWithInt:4] forKey:@"flagNums"]; } else if ( [tempString isEqualToString:@""] ) { [tempDict setObject:[NSNumber numberWithInt:5] forKey:@"flagNums"]; } else if ( [tempString isEqualToString:@"<--R-A--- "] || [tempString isEqualToString:@" --R-A--->"] ) { [tempDict setObject:[NSNumber numberWithInt:6] forKey:@"flagNums"]; } else if ( [tempString isEqualToString:@"<--R----- "] || [tempString isEqualToString:@" --R----->"] ) { [tempDict setObject:[NSNumber numberWithInt:7] forKey:@"flagNums"]; } else if ( [tempString isEqualToString:@"<-------- "] || [tempString isEqualToString:@" -------->"] ) { [tempDict setObject:[NSNumber numberWithInt:8] forKey:@"flagNums"]; } else { //will get here with uncommon flag combinations [tempDict setObject:[NSNumber numberWithInt:-1] forKey:@"flagNums"]; } } int gvCounter; for (gvCounter=0; gvCounter