Changeset 3102

Show
Ignore:
Timestamp:
12/31/05 03:01:21 (3 years ago)
Author:
timothy
Message:

DCC fixes. Resume support when sending.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/cocoa-networking/Chat Core/MVIRCChatConnection.m

    r3101 r3102  
    14651465                        NSString *msg = [[NSString allocWithZone:nil] initWithData:arguments encoding:[self encoding]]; 
    14661466                        NSArray *parameters = [msg componentsSeparatedByString:@" "]; 
    1467                         [msg release]; 
    14681467 
    14691468                        if( [parameters count] >= 5 && [[parameters objectAtIndex:0] caseInsensitiveCompare:@"SEND"] == NSOrderedSame ) { 
     
    14821481 
    14831482                                MVIRCDownloadFileTransfer *transfer = [(MVIRCDownloadFileTransfer *)[MVIRCDownloadFileTransfer allocWithZone:nil] initWithUser:sender]; 
     1483                                if( port == 0 && [parameters count] >= 6 ) { 
     1484                                        BOOL turbo = ( [[parameters objectAtIndex:5] rangeOfString:@"T"].location != NSNotFound ); 
     1485                                        [transfer _setTurbo:turbo]; 
     1486                                        [transfer _setPassiveIdentifier:[[parameters objectAtIndex:5] intValue]]; 
     1487                                        [transfer _setPassive:YES]; 
     1488                                } else if( [parameters count] >= 6 ) { 
     1489                                        [transfer _setTurbo:[[parameters objectAtIndex:5] isEqualToString:@"T"]]; 
     1490                                } 
     1491 
    14841492                                [transfer _setOriginalFileName:[parameters objectAtIndex:1]]; 
    14851493                                [transfer _setFinalSize:(unsigned long long)size]; 
    14861494                                [transfer _setHost:host]; 
    14871495                                [transfer _setPort:port]; 
     1496 
    14881497                                [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVDownloadFileTransferOfferNotification object:transfer]; 
     1498 
    14891499                                [self _addFileTransfer:transfer]; 
    14901500                                [transfer release]; 
    14911501                        } else if( [parameters count] >= 4 && [[parameters objectAtIndex:0] caseInsensitiveCompare:@"ACCEPT"] == NSOrderedSame ) { 
     1502                                BOOL passive = NO; 
    14921503                                long long size = 0; 
    14931504                                unsigned int port = [[parameters objectAtIndex:2] intValue]; 
     
    14951506                                [scanner scanLongLong:&size]; 
    14961507 
     1508                                if( [parameters count] >= 5 ) { 
     1509                                        passive = YES; 
     1510                                        port = [[parameters objectAtIndex:4] intValue]; 
     1511                                } 
     1512 
    14971513                                @synchronized( _fileTransfers ) { 
    14981514                                        NSEnumerator *enumerator = [_fileTransfers objectEnumerator]; 
    14991515                                        MVFileTransfer *transfer = nil; 
    15001516                                        while( ( transfer = [enumerator nextObject] ) ) { 
    1501                                                 if( [transfer isDownload] && [[transfer user] isEqualToChatUser:sender] && [transfer port] == port ) { 
     1517                                                if( [transfer isDownload] && [transfer isPassive] == passive && [[transfer user] isEqualToChatUser:sender] && 
     1518                                                        ( ! passive ? [transfer port] == port : [(id)transfer _passiveIdentifier] == port ) ) { 
    15021519                                                        [transfer _setTransfered:(unsigned long long)size]; 
    15031520                                                        [transfer _setStartOffset:(unsigned long long)size]; 
     
    15061523                                        } 
    15071524                                } 
     1525                        } else if( [parameters count] >= 4 && [[parameters objectAtIndex:0] caseInsensitiveCompare:@"RESUME"] == NSOrderedSame ) { 
     1526                                BOOL passive = NO; 
     1527                                long long size = 0; 
     1528                                unsigned int port = [[parameters objectAtIndex:2] intValue]; 
     1529                                NSScanner *scanner = [NSScanner scannerWithString:[parameters objectAtIndex:3]]; 
     1530                                [scanner scanLongLong:&size]; 
     1531 
     1532                                if( [parameters count] >= 5 ) { 
     1533                                        passive = YES; 
     1534                                        port = [[parameters objectAtIndex:4] intValue]; 
     1535                                } 
     1536 
     1537                                @synchronized( _fileTransfers ) { 
     1538                                        NSEnumerator *enumerator = [_fileTransfers objectEnumerator]; 
     1539                                        MVFileTransfer *transfer = nil; 
     1540                                        while( ( transfer = [enumerator nextObject] ) ) { 
     1541                                                if( [transfer isUpload] && [transfer isPassive] == passive && [[transfer user] isEqualToChatUser:sender] && 
     1542                                                        ( ! passive ? [transfer port] == port : [(id)transfer _passiveIdentifier] == port ) ) { 
     1543                                                        [transfer _setTransfered:(unsigned long long)size]; 
     1544                                                        [transfer _setStartOffset:(unsigned long long)size]; 
     1545                                                        [sender sendSubcodeRequest:@"DCC ACCEPT" withArguments:[msg substringFromIndex:7]]; 
     1546                                                } 
     1547                                        } 
     1548                                } 
    15081549                        } 
     1550 
     1551                        [msg release]; 
    15091552                } else if( [command caseInsensitiveCompare:@"CLIENTINFO"] == NSOrderedSame ) { 
    15101553                        // make this extnesible later with a plugin registration method 
  • branches/cocoa-networking/Chat Core/MVIRCFileTransfer.h

    r3101 r3102  
    1111        NSFileHandle *_fileHandle; 
    1212        BOOL _fileNameQuoted; 
     13        BOOL _readData; 
     14        BOOL _doneSending; 
    1315        BOOL _done; 
    1416        unsigned int _passiveId; 
     
    1719- (void) _sendNextPacket; 
    1820- (void) _finish; 
     21- (unsigned int) _passiveIdentifier; 
    1922@end 
    2023 
     
    2730        BOOL _fileNameQuoted; 
    2831        BOOL _done; 
     32        BOOL _turbo; 
    2933        unsigned int _passiveId; 
    3034} 
    3135- (void) _setupAndStart; 
    3236- (void) _finish; 
     37- (void) _setTurbo:(BOOL) turbo; 
     38- (void) _setPassiveIdentifier:(unsigned int) identifier; 
     39- (unsigned int) _passiveIdentifier; 
    3340@end 
  • branches/cocoa-networking/Chat Core/MVIRCFileTransfer.m

    r3101 r3102  
    124124 
    125125- (void) dealloc { 
     126        NSLog(@"u/l dealloc" ); 
    126127        id old = _fileHandle; 
    127128        _fileHandle = nil; 
     
    137138        [self _setStatus:MVFileTransferStoppedStatus]; 
    138139 
    139         [self performSelector:@selector( _finish ) inThread:_connectionThread]; 
     140        _done = YES; // the thread will disconnect when it ends 
    140141 
    141142        id old = _fileHandle; 
     
    156157- (void) socket:(AsyncSocket *) sock willDisconnectWithError:(NSError *) error { 
    157158        NSLog(@"upload DCC willDisconnectWithError: %@", error ); 
    158         [self _setStatus:MVFileTransferErrorStatus]; 
     159        if( [self status] != MVFileTransferDoneStatus && [self status] != MVFileTransferStoppedStatus ) 
     160                [self _setStatus:MVFileTransferErrorStatus]; 
    159161} 
    160162 
     
    168170        [old release]; 
    169171 
    170         [self _finish]
     172        _done = YES
    171173} 
    172174 
     
    174176        [self _setStatus:MVFileTransferNormalStatus]; 
    175177        [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVFileTransferStartedNotification object:self]; 
     178 
    176179        [self _sendNextPacket]; 
     180        [_clientConnection readDataToLength:4 withTimeout:-1. tag:0]; 
    177181 
    178182        // now that we are connected deregister with the connection 
     
    182186 
    183187- (void) socket:(AsyncSocket *) sock didWriteDataWithTag:(long) tag { 
    184         unsigned long long progress = [self transfered] + tag; 
    185         [self _setTransfered:progress]; 
    186  
    187         [_clientConnection readDataToLength:4 withTimeout:-1. tag:( progress == [self finalSize] )]; 
    188         if( progress < [self finalSize] ) [self _sendNextPacket]; 
     188        if( ! _readData || [_fileHandle offsetInFile] > 0xffffffff ) { 
     189                unsigned long long progress = [self transfered] + tag; 
     190                [self _setTransfered:progress]; 
     191                if( progress == [self finalSize] ) { 
     192                        [self _setStatus:MVFileTransferDoneStatus]; 
     193                        [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVFileTransferFinishedNotification object:self]; 
     194                } 
     195        } 
     196 
     197        if( ! _doneSending ) [self _sendNextPacket]; 
    189198} 
    190199 
    191200- (void) socket:(AsyncSocket *) sock didReadData:(NSData *) data withTag:(long) tag { 
    192         if( tag ) { 
     201        unsigned long bytes = ntohl( *( (unsigned long *) [data bytes] ) ); 
     202 
     203        [self _setTransfered:bytes]; 
     204        [_clientConnection readDataToLength:4 withTimeout:-1. tag:0]; 
     205 
     206        if( bytes == ( [self finalSize] & 0xffffffff ) ) { 
    193207                [self _setStatus:MVFileTransferDoneStatus]; 
    194208                [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVFileTransferFinishedNotification object:self]; 
    195                 [self _finish]; 
    196         } 
     209                [_connection disconnectAfterWriting]; 
     210                _done = YES; 
     211        } 
     212 
     213        _readData = YES; 
    197214} 
    198215 
     
    200217 
    201218- (void) _setupAndStart { 
     219        if( _connectionThread ) return; 
     220 
    202221        BOOL directory = NO; 
    203222        BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[self source] isDirectory:&directory]; 
    204223        if( directory || ! fileExists ) return; 
    205224 
    206         id old = _fileHandle
     225        [_fileHandle release]
    207226        _fileHandle = [[NSFileHandle fileHandleForReadingAtPath:[self source]] retain]; 
    208         [old release]; 
    209  
    210227        if( ! _fileHandle ) return; 
    211228        [_fileHandle seekToFileOffset:[self startOffset]]; 
    212229 
    213         old = _connection; 
     230        [NSThread prepareForInterThreadMessages]; 
     231        [NSThread detachNewThreadSelector:@selector( _dccRunloop ) toTarget:self withObject:nil]; 
     232        while( ! _connectionThread ) sched_yield(); 
     233 
     234        if( ! [self isPassive] ) [self performSelector:@selector( _waitForConnection ) inThread:_connectionThread];      
     235
     236 
     237- (void) _waitForConnection { 
     238        [_connection release]; 
    214239        _connection = [[AsyncSocket allocWithZone:nil] initWithDelegate:self]; 
    215         [old release]; 
    216  
    217         if( ! _connectionThread ) { 
    218                 [NSThread prepareForInterThreadMessages]; 
    219                 [NSThread detachNewThreadSelector:@selector( _dccRunloop ) toTarget:self withObject:nil]; 
    220                 while( ! _connectionThread ) sched_yield(); 
    221         } 
    222  
    223         if( ! [self isPassive] ) [self performSelector:@selector( _waitForConnection ) inThread:_connectionThread];      
    224 
    225  
    226 - (void) _waitForConnection { 
     240 
    227241        unsigned int port = portRange.location; 
    228242        BOOL success = NO; 
     
    245259 
    246260                NSString *fileName = [[self source] lastPathComponent]; 
    247                 if( _fileNameQuoted ) [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"SEND \"%@\" %@ %hu %llu", fileName, address, [self port], [self finalSize]]]; 
    248                 else [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"SEND %@ %@ %hu %llu", fileName, address, [self port], [self finalSize]]]; 
    249         } 
     261                if( _fileNameQuoted ) [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"SEND \"%@\" %@ %hu %llu T", fileName, address, [self port], [self finalSize]]]; 
     262                else [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"SEND %@ %@ %hu %llu T", fileName, address, [self port], [self finalSize]]]; 
     263        } else _done = YES; 
    250264} 
    251265 
    252266- (void) _sendNextPacket { 
    253267        NSData *data = [_fileHandle readDataOfLength:DCCPacketSize]; 
    254  
    255         if( [data length] > 0 ) { 
    256                 [_clientConnection writeData:data withTimeout:-1 tag:[data length]]; 
    257         } else { 
    258                 [self _setStatus:MVFileTransferErrorStatus]; 
    259                 [self _finish]; 
    260         } 
     268        if( [data length] > 0 ) [_clientConnection writeData:data withTimeout:-1 tag:[data length]]; 
     269        else _doneSending = YES; 
    261270} 
    262271 
    263272- (void) _finish { 
     273        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector( _finish ) object:nil];        
     274 
    264275        id old = _connection; 
    265276        _connection = nil; 
    266277        [old setDelegate:nil]; 
     278        [old disconnect]; 
    267279        [old release]; 
    268280 
     
    270282        _clientConnection = nil; 
    271283        [old setDelegate:nil]; 
     284        [old disconnect]; 
    272285        [old release]; 
    273286 
     
    290303        } 
    291304 
    292         _connectionThread = nil; 
    293  
    294305        [self _finish]; 
    295306        [self release]; 
    296307 
     308        _connectionThread = nil; 
     309 
    297310        [pool release]; 
     311} 
     312 
     313- (unsigned int) _passiveIdentifier { 
     314        return _passiveId; 
     315} 
     316 
     317- (void) _setStartOffset:(unsigned long long) startOffset { 
     318        [_fileHandle seekToFileOffset:startOffset]; 
     319        [super _setStartOffset:startOffset]; 
    298320} 
    299321@end 
     
    309331 
    310332- (void) dealloc { 
     333        NSLog(@"d/l dealloc" ); 
    311334        id old = _fileHandle; 
    312335        _fileHandle = nil; 
     
    329352        [self _setStatus:MVFileTransferStoppedStatus]; 
    330353 
    331         [self performSelector:@selector( _finish ) inThread:_connectionThread]; 
     354        _done = YES; // the thread will disconnect when it ends 
    332355 
    333356        id old = _fileHandle; 
    334357        _fileHandle = nil; 
     358        [old synchronizeFile]; 
    335359        [old closeFile]; 
    336360        [old release]; 
     
    363387- (void) socket:(AsyncSocket *) sock willDisconnectWithError:(NSError *) error { 
    364388        NSLog(@"download DCC willDisconnectWithError: %@", error ); 
    365         [self _setStatus:MVFileTransferErrorStatus]; 
     389        if( [self status] != MVFileTransferDoneStatus && [self status] != MVFileTransferStoppedStatus ) 
     390                [self _setStatus:MVFileTransferErrorStatus]; 
    366391} 
    367392 
     
    384409        [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVFileTransferStartedNotification object:self]; 
    385410 
    386         unsigned long long progress = [self transfered]; 
    387         unsigned long long packet = DCCPacketSize; 
    388         if( ( progress + packet ) > [self finalSize] ) 
    389                 packet = [self finalSize] - progress; 
    390         [_connection readDataToLength:packet withTimeout:-1. tag:0]; 
     411        [_connection readDataWithTimeout:-1. tag:0]; 
    391412 
    392413        // now that we are connected deregister with the connection 
     
    399420        [self _setTransfered:progress]; 
    400421 
    401         // dcc only supports a 2 GB limit with these acknowledgment packets, we will acknowledge 
    402         // that we have all the bytes but keep reading if the file is over 2 GB 
    403         unsigned long progressToSend = htonl( progress & 0xffffffff ); 
    404         NSData *length = [[NSData allocWithZone:nil] initWithBytes:&progressToSend length:4]; 
    405         [_connection writeData:length withTimeout:-1 tag:0]; 
    406         [length release]; 
    407  
    408422        [_fileHandle writeData:data]; 
    409423 
    410         if( progress < [self finalSize] ) { 
    411                 unsigned long long packet = DCCPacketSize; 
    412                 if( ( progress + packet ) > [self finalSize] ) 
    413                         packet = [self finalSize] - progress; 
    414                 [_connection readDataToLength:packet withTimeout:-1. tag:0]; 
    415         } else { 
     424        if( ! _turbo ) { 
     425                // dcc only supports a 4 GB limit with these acknowledgment packets, we will acknowledge 
     426                // that we have all the bytes but keep reading if the file is over 4 GB 
     427                unsigned long progressToSend = htonl( progress & 0xffffffff ); 
     428                NSData *length = [[NSData allocWithZone:nil] initWithBytes:&progressToSend length:4]; 
     429                [_connection writeData:length withTimeout:-1 tag:0]; 
     430                [length release]; 
     431        } 
     432 
     433        if( progress == [self finalSize] ) { 
    416434                [self _setStatus:MVFileTransferDoneStatus]; 
    417435                [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVFileTransferFinishedNotification object:self]; 
    418                 [_connection disconnect]; 
     436                [_connection disconnectAfterWriting]; 
    419437                _done = YES; 
    420         } 
     438        } else [_connection readDataWithTimeout:-1. tag:0]; 
    421439} 
    422440 
     
    424442 
    425443- (void) _setupAndStart { 
     444        if( _connectionThread ) return; 
     445 
    426446        BOOL directory = NO; 
    427447        BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[self destination] isDirectory:&directory]; 
     
    431451        if( ! fileExists ) return; 
    432452 
    433         id old = _fileHandle
     453        [_fileHandle release]
    434454        _fileHandle = [[NSFileHandle fileHandleForWritingAtPath:[self destination]] retain]; 
    435         [old release]; 
    436  
    437455        if( ! _fileHandle ) return; 
    438456        [_fileHandle truncateFileAtOffset:[self startOffset]]; 
    439457 
    440         old = _connection; 
     458        [NSThread prepareForInterThreadMessages]; 
     459        [NSThread detachNewThreadSelector:@selector( _dccRunloop ) toTarget:self withObject:nil]; 
     460        while( ! _connectionThread ) sched_yield(); 
     461 
     462        [self performSelector:@selector( _connect ) inThread:_connectionThread];         
     463
     464 
     465- (void) _connect { 
    441466        _connection = [[AsyncSocket allocWithZone:nil] initWithDelegate:self]; 
    442         [old release]; 
    443  
    444         if( ! _connectionThread ) { 
    445                 [NSThread prepareForInterThreadMessages]; 
    446                 [NSThread detachNewThreadSelector:@selector( _dccRunloop ) toTarget:self withObject:nil]; 
    447                 while( ! _connectionThread ) sched_yield(); 
    448         } 
    449  
    450         [self performSelector:@selector( _connect ) inThread:_connectionThread];         
    451 
    452  
    453 - (void) _connect { 
     467 
    454468        if( ! [_connection connectToHost:[[self host] address] onPort:[self port] error:NULL] ) { 
    455469                NSLog(@"can't connect to DCC" ); 
     
    459473 
    460474- (void) _finish { 
     475        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector( _finish ) object:nil];        
     476 
    461477        id old = _connection; 
    462478        _connection = nil; 
    463479        [old setDelegate:nil]; 
     480        [old disconnect]; 
    464481        [old release]; 
    465482 
     
    482499        } 
    483500 
    484         _connectionThread = nil; 
    485  
    486501        [self _finish]; 
    487502        [self release]; 
    488503 
     504        _connectionThread = nil; 
     505 
    489506        [pool release]; 
    490507} 
     508 
     509- (void) _setTurbo:(BOOL) turbo { 
     510        _turbo = turbo; 
     511} 
     512 
     513- (void) _setPassiveIdentifier:(unsigned int) identifier { 
     514        _passiveId = identifier; 
     515} 
     516 
     517- (unsigned int) _passiveIdentifier { 
     518        return _passiveId; 
     519} 
    491520@end