Changeset 3543

Show
Ignore:
Timestamp:
01/07/07 17:09:41 (2 years ago)
Author:
timothy
Message:

Add support for passive DCC chat supported my some clients like mIRC.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/Chat Core/MVDirectChatConnection.h

    r3539 r3543  
    3030        NSHost *_host; 
    3131        BOOL _passive; 
     32        BOOL _localRequest; 
    3233        unsigned short _port; 
     34        unsigned int _passiveId; 
    3335        MVChatUser *_user; 
    3436        MVDirectChatConnectionStatus _status; 
    3537        NSError *_lastError; 
    3638        unsigned int _hash; 
     39        BOOL _releasing; 
    3740} 
    38 - (id) initWithUser:(MVChatUser *) user
     41+ (id) directChatConnectionWithUser:(MVChatUser *) user passively:(BOOL) passive
    3942 
    4043- (BOOL) isPassive; 
  • trunk/Chat Core/MVDirectChatConnection.m

    r3542 r3543  
    44#import "InterThreadMessaging.h" 
    55#import "MVDirectClientConnection.h" 
     6#import "MVIRCChatConnection.h" 
    67#import "MVFileTransfer.h" 
    78#import "MVChatUser.h" 
     
    2324 
    2425@implementation MVDirectChatConnection 
    25 - (id) initWithUser:(MVChatUser *) chatUser { 
    26         if( ( self = [super init] ) ) { 
    27                 _status = MVDirectChatConnectionHoldingStatus; 
    28                 _encoding = NSUTF8StringEncoding; 
    29                 _outgoingChatFormat = MVChatConnectionDefaultMessageFormat; 
    30                 _user = [chatUser retain]; 
    31                 _host = [[NSHost currentHost] retain]; 
    32                 _passive = YES; 
    33         } 
    34  
    35         return self; 
     26+ (id) directChatConnectionWithUser:(MVChatUser *) user passively:(BOOL) passive { 
     27        static unsigned passiveId = 0; 
     28 
     29        MVDirectChatConnection *ret = [(MVDirectChatConnection *)[MVDirectChatConnection allocWithZone:nil] initWithUser:user]; 
     30        [ret _setLocalRequest:YES]; 
     31        [ret _setPassive:passive]; 
     32 
     33        if( passive ) { 
     34                if( ++passiveId > 999 ) passiveId = 1; 
     35                [ret _setPassiveIdentifier:passiveId]; 
     36 
     37                // register with the main connection so the passive reply can find the original 
     38                [(MVIRCChatConnection *)[user connection] _addDirectClientConnection:ret]; 
     39 
     40                [user sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"CHAT chat 16843009 0 %lu", passiveId]]; 
     41        } else { 
     42                [ret initiate]; 
     43        } 
     44 
     45        return [ret autorelease]; 
     46
     47 
     48- (void) release { 
     49        if( ! _releasing && ( [self retainCount] - 1 ) == 1 ) { 
     50                _releasing = YES; 
     51                [(MVIRCChatConnection *)[[self user] connection] _removeDirectClientConnection:self]; 
     52        } 
     53 
     54        [super release]; 
    3655} 
    3756 
     
    91110        [_directClientConnection setDelegate:self]; 
    92111 
    93         if( [self isPassive] ) [_directClientConnection acceptConnectionOnFirstPortInRange:[MVFileTransfer fileTransferPortRange]]; 
    94         else [_directClientConnection connectToHost:[[self host] address] onPort:[self port]]; 
     112        if( _localRequest ) { 
     113                if( ! [self isPassive] ) [_directClientConnection acceptConnectionOnFirstPortInRange:[MVFileTransfer fileTransferPortRange]]; 
     114                else [_directClientConnection connectToHost:[[self host] address] onPort:[self port]]; 
     115        } else { 
     116                if( [self isPassive] ) [_directClientConnection acceptConnectionOnFirstPortInRange:[MVFileTransfer fileTransferPortRange]]; 
     117                else [_directClientConnection connectToHost:[[self host] address] onPort:[self port]]; 
     118        } 
    95119} 
    96120 
     
    176200 
    177201        [self _readNextMessage]; 
     202 
     203        // now that we are connected deregister with the connection 
     204        // do this last incase the connection is the last thing retaining us 
     205        [(MVIRCChatConnection *)[[self user] connection] _removeDirectClientConnection:self]; 
    178206} 
    179207 
     
    182210        [self _setPort:port]; 
    183211 
    184         [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"CHAT chat %@ %hu", address, [self port]]]; 
     212        if( [self isPassive] ) [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"CHAT chat %@ %hu %lu", address, [self port], [self _passiveIdentifier]]]; 
     213        else [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"CHAT chat %@ %hu", address, [self port]]]; 
    185214} 
    186215 
     
    241270 
    242271@implementation MVDirectChatConnection (MVDirectChatConnectionPrivate) 
     272- (id) initWithUser:(MVChatUser *) chatUser { 
     273        if( ( self = [super init] ) ) { 
     274                _status = MVDirectChatConnectionHoldingStatus; 
     275                _encoding = NSUTF8StringEncoding; 
     276                _outgoingChatFormat = MVChatConnectionDefaultMessageFormat; 
     277                _user = [chatUser retain]; 
     278                _host = [[NSHost currentHost] retain]; 
     279        } 
     280 
     281        return self; 
     282} 
     283 
    243284- (void) _writeMessage:(NSData *) message { 
    244285        MVAssertCorrectThreadRequired( [_directClientConnection connectionThread] ); 
     
    275316} 
    276317 
     318- (void) _setLocalRequest:(BOOL) localRequest { 
     319        _localRequest = localRequest; 
     320} 
     321 
     322- (void) _setPassiveIdentifier:(unsigned int) identifier { 
     323        _passiveId = identifier; 
     324} 
     325 
     326- (unsigned int) _passiveIdentifier { 
     327        return _passiveId; 
     328} 
     329 
    277330- (void) _postError:(NSError *) error { 
    278331        [self _setStatus:MVDirectChatConnectionErrorStatus]; 
  • trunk/Chat Core/MVDirectChatConnectionPrivate.h

    r3539 r3543  
    22 
    33@interface MVDirectChatConnection (MVDirectChatConnectionPrivate) 
     4- (id) initWithUser:(MVChatUser *) user; 
     5 
    46- (void) _writeMessage:(NSData *) message; 
    57- (void) _readNextMessage; 
     8 
    69- (void) _setStatus:(MVDirectChatConnectionStatus) status; 
    710- (void) _setStartDate:(NSDate *) startDate; 
     
    912- (void) _setPort:(unsigned short) port; 
    1013- (void) _setPassive:(BOOL) passive; 
     14- (void) _setLocalRequest:(BOOL) localRequest; 
     15- (void) _setPassiveIdentifier:(unsigned int) identifier; 
     16- (unsigned int) _passiveIdentifier; 
    1117- (void) _postError:(NSError *) error; 
    1218@end 
  • trunk/Chat Core/MVIRCChatConnection.h

    r3526 r3543  
    1717        NSMutableDictionary *_knownUsers; 
    1818        NSMutableSet *_pendingWhoisUsers; 
    19         NSMutableSet *_fileTransfers; 
     19        NSMutableSet *_directClientConnections; 
    2020        NSMutableSet *_supportedFeatures; 
    2121        NSMutableDictionary *_serverInformation; 
     
    5252- (void) _updateKnownUser:(MVChatUser *) user withNewNickname:(NSString *) nickname; 
    5353 
    54 - (void) _addFileTransfer:(MVFileTransfer *) transfer
    55 - (void) _removeFileTransfer:(MVFileTransfer *) transfer
     54- (void) _addDirectClientConnection:(id) connection
     55- (void) _removeDirectClientConnection:(id) connection
    5656 
    5757- (void) _setCurrentNickname:(NSString *) nickname; 
  • trunk/Chat Core/MVIRCChatConnection.m

    r3539 r3543  
    131131        [_chatConnection release]; 
    132132        [_knownUsers release]; 
    133         [_fileTransfers release]; 
     133        [_directClientConnections release]; 
    134134        [_server release]; 
    135135        [_currentNickname release]; 
     
    154154        _connectionThread = nil; 
    155155        _knownUsers = nil; 
    156         _fileTransfers = nil; 
     156        _directClientConnections = nil; 
    157157        _server = nil; 
    158158        _currentNickname = nil; 
     
    725725        const char *end = line + len - 2; // minus the line endings 
    726726 
    727         if( *( line + len - 2 ) != '\x0D' ) 
     727        if( *end != '\x0D' ) 
    728728                end = line + len - 1; // this server only uses \x0A for the message line ending, lets work with it 
    729729 
     
    10821082#pragma mark - 
    10831083 
    1084 - (void) _addFileTransfer:(MVFileTransfer *) transfer
    1085         if( ! _fileTransfers ) 
    1086                 _fileTransfers = [[NSMutableSet allocWithZone:nil] initWithCapacity:5]; 
    1087         @synchronized( _fileTransfers ) { 
    1088                 if( transfer ) [_fileTransfers addObject:transfer]; 
    1089         } 
    1090 } 
    1091  
    1092 - (void) _removeFileTransfer:(MVFileTransfer *) transfer
    1093         @synchronized( _fileTransfers ) { 
    1094                 if( transfer ) [_fileTransfers removeObject:transfer]; 
     1084- (void) _addDirectClientConnection:(id) connection
     1085        if( ! _directClientConnections ) 
     1086                _directClientConnections = [[NSMutableSet allocWithZone:nil] initWithCapacity:5]; 
     1087        @synchronized( _directClientConnections ) { 
     1088                if( connection ) [_directClientConnections addObject:connection]; 
     1089        } 
     1090} 
     1091 
     1092- (void) _removeDirectClientConnection:(id) connection
     1093        @synchronized( _directClientConnections ) { 
     1094                if( connection ) [_directClientConnections removeObject:connection]; 
    10951095        } 
    10961096} 
     
    16161616 
    16171617                        if( [subCommand isCaseInsensitiveEqualToString:@"SEND"] ) { 
     1618                                BOOL passive = NO; 
    16181619                                NSString *address = nil; 
    16191620                                int port = 0; 
     
    16241625                                [scanner scanInt:&port]; 
    16251626                                [scanner scanLongLong:&size]; 
     1627 
     1628                                if( [scanner scanLongLong:&passiveId] ) 
     1629                                        passive = YES; 
    16261630 
    16271631                                if( [address rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@".:"]].location == NSNotFound ) { 
     
    16311635                                } 
    16321636 
    1633                                 NSHost *host = [NSHost hostWithAddress:address]; 
    1634  
    1635                                 if( [scanner scanLongLong:&passiveId] && port > 0 ) { 
     1637                                if( passive && port > 0 ) { 
    16361638                                        // this is a passive reply, look up the original transfer 
    16371639                                        MVIRCUploadFileTransfer *transfer = nil; 
    16381640 
    1639                                         @synchronized( _fileTransfers ) { 
    1640                                                 NSEnumerator *enumerator = [_fileTransfers objectEnumerator]; 
     1641                                        @synchronized( _directClientConnections ) { 
     1642                                                NSEnumerator *enumerator = [_directClientConnections objectEnumerator]; 
    16411643                                                while( ( transfer = [enumerator nextObject] ) ) { 
    16421644                                                        if( ! [transfer isUpload] ) 
     
    16521654 
    16531655                                        if( transfer ) { 
    1654                                                 [transfer _setHost:host]; 
     1656                                                [transfer _setHost:[NSHost hostWithAddress:address]]; 
    16551657                                                [transfer _setPort:port]; 
    16561658                                                [transfer _setupAndStart]; 
     
    16591661                                        MVIRCDownloadFileTransfer *transfer = [(MVIRCDownloadFileTransfer *)[MVIRCDownloadFileTransfer allocWithZone:nil] initWithUser:sender]; 
    16601662 
    1661                                         if( port == 0 ) { 
     1663                                        if( port == 0 && passive ) { 
    16621664                                                [transfer _setPassiveIdentifier:passiveId]; 
    16631665                                                [transfer _setPassive:YES]; 
     1666                                        } else { 
     1667                                                [transfer _setHost:[NSHost hostWithAddress:address]]; 
     1668                                                [transfer _setPort:port]; 
    16641669                                        } 
    16651670 
     
    16681673                                        [transfer _setFileNameQuoted:quotedFileName]; 
    16691674                                        [transfer _setFinalSize:(unsigned long long)size]; 
    1670                                         [transfer _setHost:host]; 
    1671                                         [transfer _setPort:port]; 
    16721675 
    16731676                                        [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVDownloadFileTransferOfferNotification object:transfer]; 
    16741677 
    1675                                         [self _addFileTransfer:transfer]; 
     1678                                        [self _addDirectClientConnection:transfer]; 
    16761679                                        [transfer release]; 
    16771680                                } 
     
    16881691                                        passive = YES; 
    16891692 
    1690                                 @synchronized( _fileTransfers ) { 
    1691                                         NSEnumerator *enumerator = [_fileTransfers objectEnumerator]; 
     1693                                @synchronized( _directClientConnections ) { 
     1694                                        NSEnumerator *enumerator = [_directClientConnections objectEnumerator]; 
    16921695                                        MVIRCDownloadFileTransfer *transfer = nil; 
    16931696                                        while( ( transfer = [enumerator nextObject] ) ) { 
     
    17221725                                        passive = YES; 
    17231726 
    1724                                 @synchronized( _fileTransfers ) { 
    1725                                         NSEnumerator *enumerator = [_fileTransfers objectEnumerator]; 
     1727                                @synchronized( _directClientConnections ) { 
     1728                                        NSEnumerator *enumerator = [_directClientConnections objectEnumerator]; 
    17261729                                        MVIRCUploadFileTransfer *transfer = nil; 
    17271730                                        while( ( transfer = [enumerator nextObject] ) ) { 
     
    17451748                                } 
    17461749                        } else if( [subCommand isCaseInsensitiveEqualToString:@"CHAT"] ) { 
     1750                                BOOL passive = NO; 
    17471751                                NSString *address = nil; 
    17481752                                int port = 0; 
     1753                                long long passiveId = 0; 
    17491754 
    17501755                                [scanner scanUpToCharactersFromSet:whitespace intoString:&address]; 
    17511756                                [scanner scanInt:&port]; 
     1757 
     1758                                if( [scanner scanLongLong:&passiveId] ) 
     1759                                        passive = YES; 
    17521760 
    17531761                                if( [address rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@".:"]].location == NSNotFound ) { 
     
    17571765                                } 
    17581766 
    1759                                 NSHost *host = [NSHost hostWithAddress:address]; 
    1760  
    17611767                                if( [fileName isCaseInsensitiveEqualToString:@"CHAT"] || [fileName isCaseInsensitiveEqualToString:@"C H A T"] ) { 
    1762                                         MVDirectChatConnection *directChatConnection = [(MVDirectChatConnection *)[MVDirectChatConnection allocWithZone:nil] initWithUser:sender]; 
    1763                                         [directChatConnection _setPassive:NO]; 
    1764                                         [directChatConnection _setHost:host]; 
    1765                                         [directChatConnection _setPort:port]; 
    1766  
    1767                                         [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVDirectChatConnectionOfferNotification object:directChatConnection userInfo:[NSDictionary dictionaryWithObjectsAndKeys:sender, @"user", nil]]; 
    1768  
    1769                                         [directChatConnection release]; 
     1768                                        if( passive && port > 0 ) { 
     1769                                                // this is a passive reply, look up the original chat request 
     1770                                                MVDirectChatConnection *directChat = nil; 
     1771 
     1772                                                @synchronized( _directClientConnections ) { 
     1773                                                        NSEnumerator *enumerator = [_directClientConnections objectEnumerator]; 
     1774                                                        while( ( directChat = [enumerator nextObject] ) ) { 
     1775                                                                if( ! [directChat isPassive] ) 
     1776                                                                        continue; 
     1777                                                                if( ! [[directChat user] isEqualToChatUser:sender] ) 
     1778                                                                        continue; 
     1779                                                                if( [directChat _passiveIdentifier] == passiveId ) 
     1780                                                                        break; 
     1781                                                        } 
     1782                                                } 
     1783 
     1784                                                if( directChat ) { 
     1785                                                        [directChat _setHost:[NSHost hostWithAddress:address]]; 
     1786                                                        [directChat _setPort:port]; 
     1787                                                        [directChat initiate]; 
     1788                                                } 
     1789                                        } else { 
     1790                                                MVDirectChatConnection *directChatConnection = [(MVDirectChatConnection *)[MVDirectChatConnection allocWithZone:nil] initWithUser:sender]; 
     1791 
     1792                                                if( port == 0 && passive ) { 
     1793                                                        [directChatConnection _setPassiveIdentifier:passiveId]; 
     1794                                                        [directChatConnection _setPassive:YES]; 
     1795                                                } else { 
     1796                                                        [directChatConnection _setHost:[NSHost hostWithAddress:address]]; 
     1797                                                        [directChatConnection _setPort:port]; 
     1798                                                } 
     1799 
     1800                                                [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVDirectChatConnectionOfferNotification object:directChatConnection userInfo:[NSDictionary dictionaryWithObjectsAndKeys:sender, @"user", nil]]; 
     1801 
     1802                                                [self _addDirectClientConnection:directChatConnection]; 
     1803                                                [directChatConnection release]; 
     1804                                        } 
    17701805                                } 
    17711806                        } 
     
    18111846                                                passive = YES; 
    18121847 
    1813                                         @synchronized( _fileTransfers ) { 
    1814                                                 NSEnumerator *enumerator = [[[_fileTransfers copy] autorelease] objectEnumerator]; 
     1848                                        @synchronized( _directClientConnections ) { 
     1849                                                NSEnumerator *enumerator = [[[_directClientConnections copy] autorelease] objectEnumerator]; 
    18151850                                                MVIRCUploadFileTransfer *transfer = nil; 
    18161851                                                while( ( transfer = [enumerator nextObject] ) ) { 
  • trunk/Chat Core/MVIRCFileTransfer.m

    r3539 r3543  
    2828        [ret _setFileNameQuoted:( [fileName rangeOfString:@" "].location != NSNotFound )]; 
    2929 
    30         [(MVIRCChatConnection *)[user connection] _addFileTransfer:ret]; 
     30        [(MVIRCChatConnection *)[user connection] _addDirectClientConnection:ret]; 
    3131 
    3232        if( passive ) { 
     
    4848        if( ! _releasing && ( [self retainCount] - 1 ) == 1 ) { 
    4949                _releasing = YES; 
    50                 [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 
     50                [(MVIRCChatConnection *)[[self user] connection] _removeDirectClientConnection:self]; 
    5151        } 
    5252 
     
    7777 
    7878- (void) cancel { 
    79         [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 
    80  
    8179        [self _setStatus:MVFileTransferStoppedStatus]; 
    8280 
     
    8785        [old closeFile]; 
    8886        [old release]; 
     87 
     88        // do this last incase the connection is the last thing retaining us 
     89        [(MVIRCChatConnection *)[[self user] connection] _removeDirectClientConnection:self]; 
    8990} 
    9091 
     
    104105        // now that we are connected deregister with the connection 
    105106        // do this last incase the connection is the last thing retaining us 
    106         [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 
     107        [(MVIRCChatConnection *)[[self user] connection] _removeDirectClientConnection:self]; 
    107108} 
    108109 
     
    227228        if( ! _releasing && ( [self retainCount] - 1 ) == 1 ) { 
    228229                _releasing = YES; 
    229                 [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 
     230                [(MVIRCChatConnection *)[[self user] connection] _removeDirectClientConnection:self]; 
    230231        } 
    231232 
     
    283284        [old release]; 
    284285 
    285         [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 
     286        // do this last incase the connection is the last thing retaining us 
     287        [(MVIRCChatConnection *)[[self user] connection] _removeDirectClientConnection:self]; 
    286288} 
    287289 
     
    319321        // now that we are connected deregister with the connection 
    320322        // do this last incase the connection is the last thing retaining us 
    321         [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 
     323        [(MVIRCChatConnection *)[[self user] connection] _removeDirectClientConnection:self]; 
    322324} 
    323325 
  • trunk/Panels/MVChatUserAdditions.m

    r3539 r3543  
    116116- (IBAction) startDirectChat:(id) sender { 
    117117        if( [self isLocalUser] ) return; 
    118         MVDirectChatConnection *connection = [(MVDirectChatConnection *)[MVDirectChatConnection alloc] initWithUser:self]; 
     118 
     119        BOOL passive = [[NSUserDefaults standardUserDefaults] boolForKey:@"JVSendFilesPassively"]; 
     120        MVDirectChatConnection *connection = [MVDirectChatConnection directChatConnectionWithUser:self passively:passive]; 
    119121        [[JVChatController defaultController] chatViewControllerForDirectChatConnection:connection ifExists:NO]; 
    120         [connection initiate]; 
    121         [connection release]; 
    122122} 
    123123