Changeset 3144
- Timestamp:
- 02/21/06 02:06:24 (3 years ago)
- Files:
-
- branches/cocoa-networking/Chat Core/MVChatConnection.h (modified) (1 diff)
- branches/cocoa-networking/Chat Core/MVChatConnection.m (modified) (2 diffs)
- branches/cocoa-networking/Chat Core/MVIRCChatConnection.h (modified) (2 diffs)
- branches/cocoa-networking/Chat Core/MVIRCChatConnection.m (modified) (21 diffs)
- branches/cocoa-networking/Chat Core/MVIRCChatRoom.m (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/cocoa-networking/Chat Core/MVChatConnection.h
r3128 r3144 220 220 - (void) sendRawMessage:(id) raw immediately:(BOOL) now; 221 221 - (void) sendRawMessageWithFormat:(NSString *) format, ...; 222 - (void) sendRawMessageImmediatelyWithFormat:(NSString *) format, ...; 222 223 - (void) sendRawMessageWithComponents:(id) firstComponent, ...; 224 - (void) sendRawMessageImmediatelyWithComponents:(id) firstComponent, ...; 223 225 224 226 #pragma mark - branches/cocoa-networking/Chat Core/MVChatConnection.m
r3139 r3144 531 531 } 532 532 533 - (void) sendRawMessageImmediatelyWithFormat:(NSString *) format, ... { 534 NSParameterAssert( format != nil ); 535 536 va_list ap; 537 va_start( ap, format ); 538 539 NSString *command = [[NSString allocWithZone:nil] initWithFormat:format arguments:ap]; 540 541 va_end( ap ); 542 543 [self sendRawMessage:command immediately:YES]; 544 [command release]; 545 } 546 533 547 - (void) sendRawMessageWithComponents:(id) firstComponent, ... { 534 548 NSParameterAssert( firstComponent != nil ); … … 555 569 556 570 [self sendRawMessage:data immediately:NO]; 571 [data release]; 572 } 573 574 - (void) sendRawMessageImmediatelyWithComponents:(id) firstComponent, ... { 575 NSParameterAssert( firstComponent != nil ); 576 577 NSMutableData *data = [[NSMutableData allocWithZone:nil] initWithCapacity:512]; 578 id object = firstComponent; 579 580 va_list ap; 581 va_start( ap, firstComponent ); 582 583 do { 584 if( [object isKindOfClass:[NSData class]] ) { 585 [data appendData:object]; 586 } else if( [firstComponent isKindOfClass:[NSString class]] ) { 587 NSData *stringData = [object dataUsingEncoding:[self encoding] allowLossyConversion:YES]; 588 [data appendData:stringData]; 589 } else { 590 NSData *stringData = [[object description] dataUsingEncoding:[self encoding] allowLossyConversion:YES]; 591 [data appendData:stringData]; 592 } 593 } while( object = va_arg( ap, void * ) ); 594 595 va_end( ap ); 596 597 [self sendRawMessage:data immediately:YES]; 557 598 [data release]; 558 599 } branches/cocoa-networking/Chat Core/MVIRCChatConnection.h
r3142 r3144 12 12 NSTimer *_periodicCleanUpTimer; 13 13 NSThread *_connectionThread; 14 NSDate *_queueWait; 15 NSDate *_lastCommand; 16 NSMutableArray *_sendQueue; 17 NSTimer *_sendQueueTimer; 14 18 NSMutableDictionary *_knownUsers; 15 19 NSMutableSet *_fileTransfers; … … 47 51 48 52 - (void) _periodicCleanUp; 53 - (void) _startQueueTimer; 54 - (void) _stopSendQueueTimer; 49 55 @end branches/cocoa-networking/Chat Core/MVIRCChatConnection.m
r3142 r3144 14 14 #import "NSStringAdditions.h" 15 15 #import "NSDataAdditions.h" 16 17 #define JVMaximumCommandsSentAtOnce 5 16 18 17 19 static const NSStringEncoding supportedEncodings[] = { … … 197 199 [_realName release]; 198 200 [_threadWaitLock release]; 201 [_periodicCleanUpTimer release]; 202 [_sendQueue release]; 203 [_sendQueueTimer release]; 204 [_queueWait release]; 205 [_lastCommand release]; 199 206 200 207 _chatConnection = nil; … … 209 216 _realName = nil; 210 217 _threadWaitLock = nil; 218 _periodicCleanUpTimer = nil; 219 _sendQueue = nil; 220 _sendQueueTimer = nil; 221 _queueWait = nil; 222 _lastCommand = nil; 211 223 212 224 [super dealloc]; … … 240 252 [old release]; 241 253 254 old = _queueWait; 255 _queueWait = [[NSDate dateWithTimeIntervalSinceNow:120.] retain]; 256 [old release]; 257 242 258 [self _willConnect]; // call early so other code has a chance to change our info 243 259 … … 254 270 - (void) disconnectWithReason:(NSAttributedString *) reason { 255 271 [self cancelPendingReconnectAttempts]; 272 if( _sendQueueTimer ) [self performSelector:@selector( _stopSendQueueTimer ) withObject:nil inThread:_connectionThread]; 256 273 257 274 if( _status == MVChatConnectionConnectedStatus ) { 258 275 if( [[reason string] length] ) { 259 276 NSData *msg = [[self class] _flattenedIRCDataForMessage:reason withEncoding:[self encoding] andChatFormat:[self outgoingChatFormat]]; 260 [self sendRawMessage WithComponents:@"QUIT :", msg, nil];261 } else [self sendRawMessage:@"QUIT" ];277 [self sendRawMessageImmediatelyWithComponents:@"QUIT :", msg, nil]; 278 } else [self sendRawMessage:@"QUIT" immediately:YES]; 262 279 } 263 280 … … 300 317 301 318 if( [self isConnected] ) 302 [self sendRawMessage WithFormat:@"NICK %@", nickname];319 [self sendRawMessageImmediatelyWithFormat:@"NICK %@", nickname]; 303 320 } 304 321 … … 315 332 - (void) setNicknamePassword:(NSString *) password { 316 333 if( ! [[self localUser] isIdentified] && password && [self isConnected] ) 317 [self sendRawMessage WithFormat:@"NickServ IDENTIFY %@", password];334 [self sendRawMessageImmediatelyWithFormat:@"NickServ IDENTIFY %@", password]; 318 335 [super setNicknamePassword:password]; 319 336 } … … 377 394 NSParameterAssert( [raw isKindOfClass:[NSData class]] || [raw isKindOfClass:[NSString class]] ); 378 395 379 NSMutableData *data = nil; 380 NSString *string = nil; 381 382 if( [raw isKindOfClass:[NSMutableData class]] ) { 383 data = [raw retain]; 384 string = [[NSString allocWithZone:nil] initWithData:data encoding:[self encoding]]; 385 } else if( [raw isKindOfClass:[NSData class]] ) { 386 data = [raw mutableCopyWithZone:nil]; 387 string = [[NSString allocWithZone:nil] initWithData:data encoding:[self encoding]]; 388 } else if( [raw isKindOfClass:[NSString class]] ) { 389 data = [[raw dataUsingEncoding:[self encoding] allowLossyConversion:YES] mutableCopyWithZone:nil]; 390 string = [raw retain]; 391 } 392 393 // IRC messages are always lines of characters terminated with a CR-LF 394 // (Carriage Return - Line Feed) pair, and these messages SHALL NOT 395 // exceed 512 characters in length, counting all characters including 396 // the trailing CR-LF. Thus, there are 510 characters maximum allowed 397 // for the command and its parameters. 398 399 if( [data length] > 510 ) [data setLength:510]; 400 [data appendBytes:"\x0D\x0A" length:2]; 401 402 [self performSelector:@selector( _writeDataToServer: ) withObject:data inThread:_connectionThread]; 403 404 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVChatConnectionGotRawMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:string, @"message", [NSNumber numberWithBool:YES], @"outbound", nil]]; 405 406 [string release]; 407 [data release]; 396 if( ! now ) { 397 @synchronized( _sendQueue ) { 398 now = ! [_sendQueue count]; 399 } 400 401 if( now ) now = ( ! _queueWait || [_queueWait timeIntervalSinceNow] <= 0. ); 402 if( now ) now = ( ! _lastCommand || [_lastCommand timeIntervalSinceNow] <= -0.2 ); 403 } 404 405 if( now ) { 406 [self performSelector:@selector( _writeDataToServer: ) withObject:raw inThread:_connectionThread]; 407 408 id old = _lastCommand; 409 _lastCommand = [[NSDate allocWithZone:nil] init]; 410 [old release]; 411 } else { 412 if( ! _sendQueue ) _sendQueue = [[NSMutableArray allocWithZone:nil] initWithCapacity:20]; 413 414 @synchronized( _sendQueue ) { 415 [_sendQueue addObject:raw]; 416 } 417 418 if( ! _sendQueueTimer ) 419 [self performSelector:@selector( _startQueueTimer ) withObject:nil inThread:_connectionThread]; 420 } 408 421 } 409 422 … … 507 520 if( ! _cachedDate || ABS( [_cachedDate timeIntervalSinceNow] ) > 300. ) { 508 521 [self sendRawMessage:@"LIST"]; 509 [_cachedDate release]; 522 523 id old = _cachedDate; 510 524 _cachedDate = [[NSDate allocWithZone:nil] init]; 525 [old release]; 511 526 } 512 527 } … … 514 529 - (void) stopFetchingChatRoomList { 515 530 if( _cachedDate && ABS( [_cachedDate timeIntervalSinceNow] ) < 600. ) 516 [self sendRawMessage:@"LIST STOP" ];531 [self sendRawMessage:@"LIST STOP" immediately:YES]; 517 532 } 518 533 … … 529 544 530 545 NSData *msg = [[self class] _flattenedIRCDataForMessage:message withEncoding:[self encoding] andChatFormat:[self outgoingChatFormat]]; 531 [self sendRawMessage WithComponents:@"AWAY :", msg, nil];546 [self sendRawMessageImmediatelyWithComponents:@"AWAY :", msg, nil]; 532 547 } else { 533 548 [[self localUser] _setStatus:MVChatUserAvailableStatus]; 534 [self sendRawMessage:@"AWAY" ];549 [self sendRawMessage:@"AWAY" immediately:YES]; 535 550 } 536 551 } … … 566 581 567 582 BOOL active = YES; 568 while( active && ( _status == MVChatConnectionConnectedStatus || _status == MVChatConnectionConnectingStatus ) )583 while( active && ( _status == MVChatConnectionConnectedStatus || _status == MVChatConnectionConnectingStatus || [_chatConnection isConnected] ) ) 569 584 active = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 585 586 // make sure the connection has sent all the delegate calls it has scheduled 587 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1.]]; 570 588 571 589 if( [NSThread currentThread] == _connectionThread ) … … 579 597 580 598 - (void) _didDisconnect { 581 [_knownUsers removeAllObjects];582 583 599 if( _status == MVChatConnectionServerDisconnectedStatus ) { 584 600 if( ABS( [_lastConnectAttempt timeIntervalSinceNow] ) > 300. ) … … 636 652 637 653 - (void) socketDidDisconnect:(AsyncSocket *) sock { 638 id old = _localUser; 639 _localUser = nil; 654 if( sock != _chatConnection ) return; 655 656 id old = _chatConnection; 657 _chatConnection = nil; 658 [old setDelegate:nil]; 640 659 [old release]; 641 660 642 [self _periodicCleanUp]; 661 NSLog(@"socketDidDisconnect" ); 662 663 [self _stopSendQueueTimer]; 664 665 @synchronized( _sendQueue ) { 666 [_sendQueue removeAllObjects]; 667 } 668 669 old = _lastCommand; 670 _lastCommand = nil; 671 [old release]; 672 673 old = _queueWait; 674 _queueWait = nil; 675 [old release]; 676 677 @synchronized( _knownUsers ) { 678 [_knownUsers removeAllObjects]; 679 } 680 643 681 [_periodicCleanUpTimer invalidate]; 644 682 [_periodicCleanUpTimer release]; … … 649 687 650 688 - (void) socket:(AsyncSocket *) sock didConnectToHost:(NSString *) host port:(UInt16) port { 651 if( [[self password] length] ) [self sendRawMessage WithFormat:@"PASS %@", [self password]];652 [self sendRawMessage WithFormat:@"NICK %@", [self nickname]];653 [self sendRawMessage WithFormat:@"USER %@ 0 * :%@", [self username], [self realName]];689 if( [[self password] length] ) [self sendRawMessageImmediatelyWithFormat:@"PASS %@", [self password]]; 690 [self sendRawMessageImmediatelyWithFormat:@"NICK %@", [self nickname]]; 691 [self sendRawMessageImmediatelyWithFormat:@"USER %@ 0 * :%@", [self username], [self realName]]; 654 692 655 693 id old = _localUser; … … 801 839 #pragma mark - 802 840 803 - (void) _writeDataToServer:(NSData *) data { 841 - (void) _writeDataToServer:(id) raw { 842 NSMutableData *data = nil; 843 NSString *string = nil; 844 845 if( [raw isKindOfClass:[NSMutableData class]] ) { 846 data = [raw retain]; 847 string = [[NSString allocWithZone:nil] initWithData:data encoding:[self encoding]]; 848 } else if( [raw isKindOfClass:[NSData class]] ) { 849 data = [raw mutableCopyWithZone:nil]; 850 string = [[NSString allocWithZone:nil] initWithData:data encoding:[self encoding]]; 851 } else if( [raw isKindOfClass:[NSString class]] ) { 852 data = [[raw dataUsingEncoding:[self encoding] allowLossyConversion:YES] mutableCopyWithZone:nil]; 853 string = [raw retain]; 854 } 855 856 // IRC messages are always lines of characters terminated with a CR-LF 857 // (Carriage Return - Line Feed) pair, and these messages SHALL NOT 858 // exceed 512 characters in length, counting all characters including 859 // the trailing CR-LF. Thus, there are 510 characters maximum allowed 860 // for the command and its parameters. 861 862 if( [data length] > 510 ) [data setLength:510]; 863 [data appendBytes:"\x0D\x0A" length:2]; 864 804 865 [_chatConnection writeData:data withTimeout:-1. tag:0]; 866 867 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVChatConnectionGotRawMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:string, @"message", [NSNumber numberWithBool:YES], @"outbound", nil]]; 868 869 [string release]; 870 [data release]; 805 871 } 806 872 … … 914 980 } 915 981 982 - (void) _startQueueTimer { 983 if( _sendQueueTimer ) return; 984 _sendQueueTimer = [[NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector( _sendQueue ) userInfo:nil repeats:YES] retain]; 985 } 986 987 - (void) _stopSendQueueTimer { 988 id old = _sendQueueTimer; 989 _sendQueueTimer = nil; 990 [old invalidate]; 991 [old release]; 992 } 993 994 - (void) _sendQueue { 995 @synchronized( _sendQueue ) { 996 if( ! [_sendQueue count] ) { 997 [self _stopSendQueueTimer]; 998 return; 999 } 1000 } 1001 1002 if( _queueWait && [_queueWait timeIntervalSinceNow] > 0. ) return; 1003 1004 NSData *data = nil; 1005 @synchronized( _sendQueue ) { 1006 data = [[_sendQueue objectAtIndex:0] retain]; 1007 [_sendQueue removeObjectAtIndex:0]; 1008 } 1009 1010 [self _writeDataToServer:data]; 1011 [data release]; 1012 1013 id old = _lastCommand; 1014 _lastCommand = [[NSDate allocWithZone:nil] init]; 1015 [old release]; 1016 } 1017 916 1018 #pragma mark - 917 1019 … … 936 1038 937 1039 - (void) _handle001WithParameters:(NSArray *) parameters fromSender:(MVChatUser *) sender { 1040 id old = _queueWait; 1041 _queueWait = [[NSDate dateWithTimeIntervalSinceNow:0.5] retain]; 1042 [old release]; 1043 938 1044 [self performSelectorOnMainThread:@selector( _didConnect ) withObject:nil waitUntilDone:NO]; 939 1045 // Identify if we have a user password 940 1046 if( [[self nicknamePassword] length] ) 941 [self sendRawMessage WithFormat:@"NickServ IDENTIFY %@", [self nicknamePassword]];1047 [self sendRawMessageImmediatelyWithFormat:@"NickServ IDENTIFY %@", [self nicknamePassword]]; 942 1048 if( [parameters count] >= 1 ) { 943 1049 NSString *nickname = [parameters objectAtIndex:0]; … … 1036 1142 if( ! [self nicknamePassword] ) { 1037 1143 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVChatConnectionNeedNicknamePasswordNotification object:self userInfo:nil]; 1038 } else [self sendRawMessage WithFormat:@"NickServ IDENTIFY %@", [self nicknamePassword]];1144 } else [self sendRawMessageImmediatelyWithFormat:@"NickServ IDENTIFY %@", [self nicknamePassword]]; 1039 1145 } else if( [msg rangeOfString:@"Password accepted"].location != NSNotFound ) { 1040 1146 [[self localUser] _setIdentified:YES]; … … 1249 1355 [room _clearBannedUsers]; 1250 1356 1251 [self sendRawMessage WithFormat:@"WHO %@", name];1252 [self sendRawMessage WithFormat:@"MODE %@ b", name];1357 [self sendRawMessageImmediatelyWithFormat:@"WHO %@", name]; 1358 [self sendRawMessageImmediatelyWithFormat:@"MODE %@ b", name]; 1253 1359 } else { 1254 1360 if( [sender status] != MVChatUserAwayStatus ) [sender _setStatus:MVChatUserAvailableStatus]; … … 1459 1565 - (void) _handlePingWithParameters:(NSArray *) parameters fromSender:(MVChatUser *) sender { 1460 1566 if( [parameters count] >= 1 ) { 1461 if( [parameters count] == 1 ) [self sendRawMessage WithComponents:@"PONG :", [parameters objectAtIndex:0], nil];1462 else [self sendRawMessage WithComponents:@"PONG ", [parameters objectAtIndex:1], @" :", [parameters objectAtIndex:0], nil];1567 if( [parameters count] == 1 ) [self sendRawMessageImmediatelyWithComponents:@"PONG :", [parameters objectAtIndex:0], nil]; 1568 else [self sendRawMessageImmediatelyWithComponents:@"PONG ", [parameters objectAtIndex:1], @" :", [parameters objectAtIndex:0], nil]; 1463 1569 } 1464 1570 } branches/cocoa-networking/Chat Core/MVIRCChatRoom.m
r3137 r3144 35 35 - (void) partWithReason:(NSAttributedString *) reason { 36 36 if( ! [self isJoined] ) return; 37 if( ! [reason length] ) [[self connection] sendRawMessage :[NSString stringWithFormat:@"PART %@", [self name]] immediately:YES];38 else [[self connection] sendRawMessage :[NSString stringWithFormat:@"PART %@ :%@", [self name], [reason string]] immediately:YES];37 if( ! [reason length] ) [[self connection] sendRawMessageImmediatelyWithFormat:@"PART %@", [self name]]; 38 else [[self connection] sendRawMessageImmediatelyWithFormat:@"PART %@ :%@", [self name], [reason string]]; 39 39 [self _setDateParted:[NSDate date]]; 40 40 } … … 221 221 NSData *msg = [MVIRCChatConnection _flattenedIRCDataForMessage:reason withEncoding:[self encoding] andChatFormat:[[self connection] outgoingChatFormat]]; 222 222 NSString *prefix = [[NSString allocWithZone:nil] initWithFormat:@"KICK %@ %@ :", [self name], [user nickname]]; 223 [[self connection] sendRawMessage WithComponents:prefix, msg, nil];223 [[self connection] sendRawMessageImmediatelyWithComponents:prefix, msg, nil]; 224 224 [prefix release]; 225 } else [[self connection] sendRawMessage WithFormat:@"KICK %@ %@", [self name], [user nickname]];225 } else [[self connection] sendRawMessageImmediatelyWithFormat:@"KICK %@ %@", [self name], [user nickname]]; 226 226 } 227 227 228 228 - (void) addBanForUser:(MVChatUser *) user { 229 229 [super addBanForUser:user]; 230 [[self connection] sendRawMessage WithFormat:@"MODE %@ +b %@!%@@%@", [self name], ( [user nickname] ? [user nickname] : @"*" ), ( [user username] ? [user username] : @"*" ), ( [user address] ? [user address] : @"*" )];230 [[self connection] sendRawMessageImmediatelyWithFormat:@"MODE %@ +b %@!%@@%@", [self name], ( [user nickname] ? [user nickname] : @"*" ), ( [user username] ? [user username] : @"*" ), ( [user address] ? [user address] : @"*" )]; 231 231 } 232 232 233 233 - (void) removeBanForUser:(MVChatUser *) user { 234 234 [super removeBanForUser:user]; 235 [[self connection] sendRawMessage WithFormat:@"MODE %@ -b %@!%@@%@", [self name], ( [user nickname] ? [user nickname] : @"*" ), ( [user username] ? [user username] : @"*" ), ( [user address] ? [user address] : @"*" )];235 [[self connection] sendRawMessageImmediatelyWithFormat:@"MODE %@ -b %@!%@@%@", [self name], ( [user nickname] ? [user nickname] : @"*" ), ( [user username] ? [user username] : @"*" ), ( [user address] ? [user address] : @"*" )]; 236 236 } 237 237 @end
