Changeset 3101
- Timestamp:
- 12/30/05 06:05:58 (3 years ago)
- Files:
-
- branches/cocoa-networking/Chat Core/MVIRCChatConnection.h (modified) (1 diff)
- branches/cocoa-networking/Chat Core/MVIRCChatConnection.m (modified) (3 diffs)
- branches/cocoa-networking/Chat Core/MVIRCFileTransfer.h (modified) (2 diffs)
- branches/cocoa-networking/Chat Core/MVIRCFileTransfer.m (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/cocoa-networking/Chat Core/MVIRCChatConnection.h
r3099 r3101 30 30 31 31 @interface MVChatConnection (MVIRCChatConnectionPrivate) 32 - (AsyncSocket *) _chatConnection; 32 33 - (void) _readNextMessageFromServer; 33 34 branches/cocoa-networking/Chat Core/MVIRCChatConnection.m
r3099 r3101 516 516 [self disconnect]; 517 517 518 [_chatConnection setDelegate:nil]; 519 518 520 [_chatConnection release]; 519 521 [_knownUsers release]; … … 948 950 949 951 @implementation MVIRCChatConnection (MVIRCChatConnectionPrivate) 952 - (AsyncSocket *) _chatConnection { 953 return _chatConnection; 954 } 955 950 956 - (void) _connect { 951 957 [_chatConnection disconnect]; … … 1475 1481 NSHost *host = [NSHost hostWithAddress:address]; 1476 1482 1477 MVIRCDownloadFileTransfer *transfer = [ [MVIRCDownloadFileTransfer allocWithZone:nil] initWithUser:sender];1483 MVIRCDownloadFileTransfer *transfer = [(MVIRCDownloadFileTransfer *)[MVIRCDownloadFileTransfer allocWithZone:nil] initWithUser:sender]; 1478 1484 [transfer _setOriginalFileName:[parameters objectAtIndex:1]]; 1479 1485 [transfer _setFinalSize:(unsigned long long)size]; branches/cocoa-networking/Chat Core/MVIRCFileTransfer.h
r3099 r3101 7 7 @interface MVIRCUploadFileTransfer : MVUploadFileTransfer { 8 8 AsyncSocket *_connection; 9 AsyncSocket *_clientConnection; 9 10 NSThread *_connectionThread; 11 NSFileHandle *_fileHandle; 12 BOOL _fileNameQuoted; 13 BOOL _done; 14 unsigned int _passiveId; 10 15 } 16 - (void) _setupAndStart; 17 - (void) _sendNextPacket; 18 - (void) _finish; 11 19 @end 12 20 … … 18 26 NSFileHandle *_fileHandle; 19 27 BOOL _fileNameQuoted; 28 BOOL _done; 20 29 unsigned int _passiveId; 21 30 } 22 31 - (void) _setupAndStart; 32 - (void) _finish; 23 33 @end branches/cocoa-networking/Chat Core/MVIRCFileTransfer.m
r3099 r3101 1 1 #import <sched.h> 2 #import <arpa/inet.h> 2 3 3 4 #import "MVIRCFileTransfer.h" … … 83 84 } */ 84 85 85 #pragma mark - 86 static NSRange portRange; 86 87 87 88 @implementation MVIRCUploadFileTransfer 89 + (void) initialize { 90 portRange = NSMakeRange( 1024, 20 ); 91 } 92 88 93 + (id) transferWithSourceFile:(NSString *) path toUser:(MVChatUser *) user passively:(BOOL) passive { 89 NSURL *url = [NSURL URLWithString:@"http://colloquy.info/ip.php"]; 90 NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:3.]; 91 NSMutableData *result = [[NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:NULL] mutableCopyWithZone:nil]; 92 [result appendBytes:"\0" length:1]; 93 94 [result release]; 95 96 MVIRCUploadFileTransfer *ret = [[MVIRCUploadFileTransfer allocWithZone:nil] initWithUser:user]; 94 static unsigned passiveId = 0; 95 96 MVIRCUploadFileTransfer *ret = [(MVIRCUploadFileTransfer *)[MVIRCUploadFileTransfer allocWithZone:nil] initWithUser:user]; 97 [(MVIRCChatConnection *)[user connection] _addFileTransfer:ret]; 97 98 [ret _setSource:path]; 99 [ret _setPassive:passive]; 100 101 NSNumber *size = [[[NSFileManager defaultManager] fileAttributesAtPath:[ret source] traverseLink:YES] objectForKey:NSFileSize]; 102 [ret _setFinalSize:[size unsignedLongLongValue]]; 103 104 NSString *fileName = [[ret source] lastPathComponent]; 105 ret->_fileNameQuoted = ( [fileName rangeOfString:@" "].location != NSNotFound ); 106 107 if( passive ) { 108 passiveId++; 109 if( passiveId > 1000 ) 110 passiveId = 1; 111 ret->_passiveId = passiveId; 112 } else { 113 [ret _setupAndStart]; 114 } 98 115 99 116 return [ret autorelease]; 117 } 118 119 - (void) release { 120 if( ( [self retainCount] - 1 ) == 1 ) 121 [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 122 [super release]; 123 } 124 125 - (void) dealloc { 126 id old = _fileHandle; 127 _fileHandle = nil; 128 [old closeFile]; 129 [old release]; 130 131 _connectionThread = nil; 132 133 [super dealloc]; 100 134 } 101 135 102 136 - (void) cancel { 103 137 [self _setStatus:MVFileTransferStoppedStatus]; 104 [_connection release]; 138 139 [self performSelector:@selector( _finish ) inThread:_connectionThread]; 140 141 id old = _fileHandle; 142 _fileHandle = nil; 143 [old closeFile]; 144 [old release]; 145 146 [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 147 } 148 149 #pragma mark - 150 151 - (void) socket:(AsyncSocket *) sock didAcceptNewSocket:(AsyncSocket *) newSocket { 152 if( ! _clientConnection ) _clientConnection = [newSocket retain]; 153 else [newSocket disconnect]; 154 } 155 156 - (void) socket:(AsyncSocket *) sock willDisconnectWithError:(NSError *) error { 157 NSLog(@"upload DCC willDisconnectWithError: %@", error ); 158 [self _setStatus:MVFileTransferErrorStatus]; 159 } 160 161 - (void) socketDidDisconnect:(AsyncSocket *) sock { 162 if( [self status] != MVFileTransferDoneStatus && [self status] != MVFileTransferStoppedStatus ) 163 [self _setStatus:MVFileTransferErrorStatus]; 164 165 id old = _fileHandle; 166 _fileHandle = nil; 167 [old closeFile]; 168 [old release]; 169 170 [self _finish]; 171 } 172 173 - (void) socket:(AsyncSocket *) sock didConnectToHost:(NSString *) host port:(UInt16) port { 174 [self _setStatus:MVFileTransferNormalStatus]; 175 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVFileTransferStartedNotification object:self]; 176 [self _sendNextPacket]; 177 178 // now that we are connected deregister with the connection 179 // do this last incase the connection is the last thing retaining us 180 [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 181 } 182 183 - (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]; 189 } 190 191 - (void) socket:(AsyncSocket *) sock didReadData:(NSData *) data withTag:(long) tag { 192 if( tag ) { 193 [self _setStatus:MVFileTransferDoneStatus]; 194 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVFileTransferFinishedNotification object:self]; 195 [self _finish]; 196 } 197 } 198 199 #pragma mark - 200 201 - (void) _setupAndStart { 202 BOOL directory = NO; 203 BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[self source] isDirectory:&directory]; 204 if( directory || ! fileExists ) return; 205 206 id old = _fileHandle; 207 _fileHandle = [[NSFileHandle fileHandleForReadingAtPath:[self source]] retain]; 208 [old release]; 209 210 if( ! _fileHandle ) return; 211 [_fileHandle seekToFileOffset:[self startOffset]]; 212 213 old = _connection; 214 _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 { 227 unsigned int port = portRange.location; 228 BOOL success = NO; 229 while( ! success ) { 230 if( [_connection acceptOnPort:port error:NULL] ) { 231 success = YES; 232 break; 233 } else { 234 [_connection disconnect]; 235 if( ++port > NSMaxRange( portRange ) ) 236 port = 0; // just use a random port since the user defined range is in use 237 } 238 } 239 240 if( success ) { 241 id address = [[(MVIRCChatConnection *)[[self user] connection] _chatConnection] localHost]; 242 if( [address rangeOfString:@"."].location != NSNotFound ) 243 address = [NSNumber numberWithUnsignedLong:ntohl( inet_addr( [address UTF8String] ) )]; 244 [self _setPort:[_connection localPort]]; 245 246 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 } 250 } 251 252 - (void) _sendNextPacket { 253 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 } 261 } 262 263 - (void) _finish { 264 id old = _connection; 105 265 _connection = nil; 266 [old setDelegate:nil]; 267 [old release]; 268 269 old = _clientConnection; 270 _clientConnection = nil; 271 [old setDelegate:nil]; 272 [old release]; 273 274 _done = YES; 275 } 276 277 - (oneway void) _dccRunloop { 278 NSAutoreleasePool *pool = [[NSAutoreleasePool allocWithZone:nil] init]; 279 [self retain]; 280 281 _connectionThread = [NSThread currentThread]; 282 [NSThread prepareForInterThreadMessages]; 283 [NSThread setThreadPriority:0.75]; 284 285 BOOL active = YES; 286 while( active && ! _done ) { 287 NSDate *timeout = [[NSDate allocWithZone:nil] initWithTimeIntervalSinceNow:5.]; 288 active = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeout]; 289 [timeout release]; 290 } 291 292 _connectionThread = nil; 293 294 [self _finish]; 295 [self release]; 296 297 [pool release]; 106 298 } 107 299 @end … … 110 302 111 303 @implementation MVIRCDownloadFileTransfer 304 - (void) release { 305 if( ( [self retainCount] - 1 ) == 1 ) 306 [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 307 [super release]; 308 } 309 112 310 - (void) dealloc { 113 [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 114 115 [_fileHandle synchronizeFile]; 116 [_fileHandle closeFile]; 117 118 [_connection release]; 119 [_fileHandle release]; 120 121 _connection = nil; 311 id old = _fileHandle; 312 _fileHandle = nil; 313 [old synchronizeFile]; 314 [old closeFile]; 315 [old release]; 316 122 317 _connectionThread = nil; 123 _fileHandle = nil;124 318 125 319 [super dealloc]; … … 129 323 if( _fileNameQuoted ) [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"REJECT \"%@\"", [self originalFileName]]]; 130 324 else [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"REJECT %@", [self originalFileName]]]; 325 [self cancel]; 131 326 } 132 327 133 328 - (void) cancel { 134 329 [self _setStatus:MVFileTransferStoppedStatus]; 135 [_connection release]; 136 _connection = nil; 330 331 [self performSelector:@selector( _finish ) inThread:_connectionThread]; 332 333 id old = _fileHandle; 334 _fileHandle = nil; 335 [old closeFile]; 336 [old release]; 337 338 [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 137 339 } 138 340 … … 147 349 else [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"RESUME %@ 0 %llu %lu", [self originalFileName], [size unsignedLongLongValue], _passiveId]]; 148 350 } else { 149 if( _fileNameQuoted ) [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"RESUME \"%@\" % lu %llu", [self originalFileName], [self port], [size unsignedLongLongValue]]];150 else [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"RESUME %@ % lu %llu", [self originalFileName], [self port], [size unsignedLongLongValue]]];351 if( _fileNameQuoted ) [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"RESUME \"%@\" %hu %llu", [self originalFileName], [self port], [size unsignedLongLongValue]]]; 352 else [[self user] sendSubcodeRequest:@"DCC" withArguments:[NSString stringWithFormat:@"RESUME %@ %hu %llu", [self originalFileName], [self port], [size unsignedLongLongValue]]]; 151 353 } 152 354 return; // we need to wait until we get an ACCEPT reply … … 160 362 161 363 - (void) socket:(AsyncSocket *) sock willDisconnectWithError:(NSError *) error { 162 NSLog(@" DCC willDisconnectWithError: %@", error );364 NSLog(@"download DCC willDisconnectWithError: %@", error ); 163 365 [self _setStatus:MVFileTransferErrorStatus]; 164 366 } 165 367 166 368 - (void) socketDidDisconnect:(AsyncSocket *) sock { 167 if( [self status] != MVFileTransferDoneStatus )369 if( [self status] != MVFileTransferDoneStatus && [self status] != MVFileTransferStoppedStatus ) 168 370 [self _setStatus:MVFileTransferErrorStatus]; 169 371 170 [_fileHandle synchronizeFile]; 171 [_fileHandle closeFile]; 172 [_fileHandle release]; 173 _fileHandle = nil; 372 id old = _fileHandle; 373 _fileHandle = nil; 374 [old synchronizeFile]; 375 [old closeFile]; 376 [old release]; 377 378 _done = YES; 174 379 } 175 380 … … 184 389 packet = [self finalSize] - progress; 185 390 [_connection readDataToLength:packet withTimeout:-1. tag:0]; 391 392 // now that we are connected deregister with the connection 393 // do this last incase the connection is the last thing retaining us 394 [(MVIRCChatConnection *)[[self user] connection] _removeFileTransfer:self]; 186 395 } 187 396 … … 208 417 [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:MVFileTransferFinishedNotification object:self]; 209 418 [_connection disconnect]; 419 _done = YES; 210 420 } 211 421 } … … 221 431 if( ! fileExists ) return; 222 432 223 [_fileHandle release];433 id old = _fileHandle; 224 434 _fileHandle = [[NSFileHandle fileHandleForWritingAtPath:[self destination]] retain]; 435 [old release]; 436 225 437 if( ! _fileHandle ) return; 226 438 [_fileHandle truncateFileAtOffset:[self startOffset]]; 227 439 228 [_connection release];440 old = _connection; 229 441 _connection = [[AsyncSocket allocWithZone:nil] initWithDelegate:self]; 442 [old release]; 230 443 231 444 if( ! _connectionThread ) { … … 245 458 } 246 459 460 - (void) _finish { 461 id old = _connection; 462 _connection = nil; 463 [old setDelegate:nil]; 464 [old release]; 465 466 _done = YES; 467 } 468 247 469 - (oneway void) _dccRunloop { 248 470 NSAutoreleasePool *pool = [[NSAutoreleasePool allocWithZone:nil] init]; 471 [self retain]; 249 472 250 473 _connectionThread = [NSThread currentThread]; … … 253 476 254 477 BOOL active = YES; 255 while( active && ( [self status] == MVFileTransferNormalStatus || [self status] == MVFileTransferHoldingStatus ) ) 256 active = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 257 258 if( [NSThread currentThread] == _connectionThread ) 259 _connectionThread = nil; 478 while( active && ! _done ) { 479 NSDate *timeout = [[NSDate allocWithZone:nil] initWithTimeIntervalSinceNow:5.]; 480 active = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeout]; 481 [timeout release]; 482 } 483 484 _connectionThread = nil; 485 486 [self _finish]; 487 [self release]; 260 488 261 489 [pool release];
