Ticket #1229: proxy.patch
| File proxy.patch, 9.3 KB (added by robclark, 4 years ago) |
|---|
-
Chat
14 14 #import <arpa/inet.h> 15 15 #import <netdb.h> 16 16 17 #import <SystemConfiguration/SystemConfiguration.h> 18 #include <fnmatch.h> 19 17 20 #pragma mark Declarations 18 21 19 22 #define READQUEUE_CAPACITY 5 /* Initial capacity. */ … … 38 41 kDisconnectSoon = 0x08 // If set, disconnect as soon as nothing is queued. 39 42 }; 40 43 44 45 static void writeFully( CFWriteStreamRef theWriteStream, UInt8 *buf, UInt16 n ) 46 { 47 while( n > 0 ) 48 { 49 int rc = CFWriteStreamWrite( theWriteStream, buf, n ); 50 NSLog(@"wrote: rc=%d", rc); 51 n -= rc; 52 buf += rc; 53 } 54 } 55 56 41 57 @interface AsyncSocket (Private) 42 58 - (BOOL) isSocketConnected; 43 59 - (BOOL) areStreamsConnected; … … 62 78 - (BOOL) configureStreamsAndReturnError:(NSError **)errPtr; 63 79 - (BOOL) openStreamsAndReturnError:(NSError **)errPtr; 64 80 - (void) doStreamOpen; 81 - (void) doStreamOpen_callDidConnectToHost; 65 82 - (void) closeWithError:(NSError *)err; 66 83 - (void) recoverUnreadData; 67 84 - (void) emptyQueues; … … 213 230 theContext.release = nil; 214 231 theContext.copyDescription = nil; 215 232 233 origHost = nil; 234 216 235 return self; 217 236 } 218 237 … … 544 563 // Creates the socket from a native socket. 545 564 - (BOOL) createStreamsFromNative:(CFSocketNativeHandle)native error:(NSError **)errPtr 546 565 { 566 /* 567 * NOT UPDATED FOR PROXIES... is this used? 568 */ 569 547 570 // Create the socket & streams. 548 571 CFStreamCreatePairWithSocket (kCFAllocatorDefault, native, &theReadStream, &theWriteStream); 549 572 if (theReadStream == NULL || theWriteStream == NULL) … … 557 580 return YES; 558 581 } 559 582 583 - (BOOL) getProxyInfoForHost:(NSString **)hostname onPort:(UInt16 *)port 584 { 585 // this function based on firetalk_use_proxy() from old version of Colloquy.. 586 587 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 588 NSDictionary *proxyDict = nil; 589 NSArray *exceptionList = nil; 590 NSEnumerator *enumerator = nil; 591 NSString *object = nil; 592 id val; 593 594 NSLog(@"orig host => %@:%d", *hostname, *port); 595 596 /* get proxy information */ 597 proxyDict = (NSDictionary *)SCDynamicStoreCopyProxies( NULL ); 598 [proxyDict autorelease]; 599 if( ! proxyDict ) { 600 [pool release]; 601 return NO; 602 } 603 604 /* check if it's an excepted host */ 605 exceptionList = [proxyDict objectForKey:(NSString *)kSCPropNetProxiesExceptionsList]; 606 enumerator = [exceptionList objectEnumerator]; 607 while( (object = [enumerator nextObject]) != nil ) { 608 if( [*hostname hasSuffix:object] ) { // should be case-insensitive? 609 [pool release]; 610 NSLog(@"excluded"); 611 return NO; 612 } 613 } 614 615 /* now check if it's SOCKS */ 616 val = [proxyDict objectForKey:(NSString *)kSCPropNetProxiesSOCKSEnable]; 617 if( val && ! [[NSNumber numberWithInt:0] isEqualToNumber:val] ) { 618 [pool release]; 619 NSLog(@"not implemented"); 620 return NO; 621 } 622 623 /* or if we should use HTTPS */ 624 val = [proxyDict objectForKey:(NSString *)kSCPropNetProxiesHTTPSEnable]; 625 if( ! [[NSNumber numberWithInt:0] isEqualToNumber:val] ) { 626 627 *hostname = [[proxyDict objectForKey:(NSString *)kSCPropNetProxiesHTTPSProxy] retain]; 628 *port = [[proxyDict objectForKey:(NSString *)kSCPropNetProxiesHTTPSPort] intValue]; 629 630 [pool release]; 631 632 NSLog(@"using proxy => %@:%d", *hostname, *port); 633 634 return YES; 635 } 636 637 [pool release]; 638 return NO; 639 } 640 641 560 642 - (BOOL) createStreamsToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr 561 643 { 644 origHost = hostname; 645 origPort = port; 646 647 if ( ! [self getProxyInfoForHost:&hostname onPort:&port] ) 648 { 649 // ok, we aren't using a proxy, so nil this back out: 650 origHost = nil; 651 } 652 562 653 // Create the socket & streams. 563 654 CFStreamCreatePairWithSocketToHost (kCFAllocatorDefault, (CFStringRef)hostname, port, &theReadStream, &theWriteStream); 564 655 if (theReadStream == NULL || theWriteStream == NULL) … … 623 714 NSError *err = [self getAbortError]; 624 715 if (errPtr) *errPtr = err; 625 716 return NO; 626 }; 717 }; 627 718 628 719 - (BOOL) openStreamsAndReturnError:(NSError **)errPtr 629 720 { … … 638 729 NSLog (@"AsyncSocket %p couldn't open write stream,", self); 639 730 goto Failed; 640 731 } 732 641 733 734 if (origHost != nil) 735 { 736 char buf[255]; 737 UInt16 n; 738 739 const char *host = [origHost UTF8String]; 740 741 // ok, we use a proxy... so we need to take care of interacting with 742 // proxy server now: 743 n = snprintf( buf, sizeof(buf), "CONNECT %s:%hu HTTP/1.1\nProxy-Connection: keep-alive\nConnection: keep-alive\nHost: %s\nUser-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_3; en-us) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.1 Safari/525.20\n\n", host, origPort, host ); 744 writeFully( theWriteStream, (UInt8 *)buf, n ); 745 printf("send: %s\n", buf ); 746 747 // for now, this is cheezy.. just look for \r\n without 748 // any error handling: 749 UInt8 lc, c = 0; 750 while(TRUE) 751 { 752 lc = c; 753 int n = CFReadStreamRead( theReadStream, &c, 1 ); 754 if(!n) 755 return NO; 756 if( (lc == '\r') && (c == '\n') ) 757 break; 758 printf("%c",c); 759 } 760 761 // this is skipped in doStreamOpen if we use a proxy, because the 762 // act of writing to the stream indirectly causes doStreamOpen to 763 // be called.. but we don't actually want to call the delegate until 764 // the above proxy communications are taken care of (otherwise the 765 // delegate could sneek in and write something before the "CONNECT ..." 766 // bit, which really confuses the proxy server: 767 [self doStreamOpen_callDidConnectToHost]; 768 } 769 642 770 return YES; 643 771 644 772 Failed:; … … 648 776 return NO; 649 777 } 650 778 779 - (void) doStreamOpen_callDidConnectToHost 780 { 781 // Call the delegate. 782 CFDataRef peer = CFSocketCopyPeerAddress (theSocket); 783 theFlags |= kDidCallConnectDeleg; 784 if ([theDelegate respondsToSelector:@selector(socket:didConnectToHost:port:)]) 785 [theDelegate socket:self 786 didConnectToHost:[self addressHost:peer] 787 port:[self addressPort:peer]]; 788 CFRelease (peer); 789 } 790 651 791 // Called when read or write streams open. When the socket is connected and both streams are open, consider the AsyncSocket instance to be ready. 652 792 - (void) doStreamOpen 653 793 { … … 661 801 [self closeWithError:err]; 662 802 } 663 803 804 // Immediately deal with any already-queued requests. 805 [self maybeDequeueRead]; 806 [self maybeDequeueWrite]; 807 664 808 // Schedule a poll timer to make up for lost ready-to-read/write notifications. This doesn't have to have a tight poll interval, since it is a backup system. 665 809 [thePollTimer invalidate]; 666 810 [thePollTimer release]; 667 811 thePollTimer = [[NSTimer scheduledTimerWithTimeInterval:POLL_INTERVAL target:self selector:@selector(doPoll:) userInfo:nil repeats:YES] retain]; 668 669 // Call the delegate. 670 CFDataRef peer = CFSocketCopyPeerAddress (theSocket); 671 theFlags |= kDidCallConnectDeleg; 672 if ([theDelegate respondsToSelector:@selector(socket:didConnectToHost:port:)]) 673 [theDelegate socket:self 674 didConnectToHost:[self addressHost:peer] 675 port:[self addressPort:peer]]; 676 CFRelease (peer); 677 678 // Immediately deal with any already-queued requests. 679 [self maybeDequeueRead]; 680 [self maybeDequeueWrite]; 812 813 if( origHost == nil ) 814 [self doStreamOpen_callDidConnectToHost]; 681 815 } 682 816 } 683 817 -
Chat
260 260 MVSafeCopyAssign( &_currentNickname, newNickname ); 261 261 262 262 if( connectiongOrConnected ) 263 { 264 printf("sending NICK (2)\n"); 263 265 [self sendRawMessageImmediatelyWithFormat:@"NICK %@", newNickname]; 264 266 } 267 } 265 268 266 269 - (NSString *) nickname { 267 270 return _currentNickname; … … 603 606 - (BOOL) socketWillConnect:(AsyncSocket *) sock { 604 607 MVAssertCorrectThreadRequired( _connectionThread ); 605 608 609 /* 610 * Now handled in AsyncSocket: 611 * 606 612 if( [[self proxyServer] length] && [self proxyServerPort] ) { 607 613 if( _proxy == MVChatConnectionHTTPSProxy || _proxy == MVChatConnectionHTTPProxy ) { 608 614 NSMutableDictionary *settings = [[NSMutableDictionary allocWithZone:nil] init]; … … 636 642 [settings release]; 637 643 } 638 644 } 645 * 646 * maybe following part should be handled in AsyncSocket too?? 647 */ 639 648 640 649 if( [self isSecure] ) { 641 650 CFReadStreamSetProperty( [sock getCFReadStream], kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL ); … … 716 725 MVAssertCorrectThreadRequired( _connectionThread ); 717 726 718 727 if( [[self password] length] ) [self sendRawMessageImmediatelyWithFormat:@"PASS %@", [self password]]; 728 printf("sending NICK\n"); 719 729 [self sendRawMessageImmediatelyWithFormat:@"NICK %@", [self preferredNickname]]; 720 730 [self sendRawMessageImmediatelyWithFormat:@"USER %@ 0 * :%@", ( [[self username] length] ? [self username] : @"anonymous" ), ( [[self realName] length] ? [self realName] : @"anonymous" )]; 721 731 -
Chat
78 78 NSTimer *thePollTimer; 79 79 id theDelegate; 80 80 Byte theFlags; 81 82 NSString *origHost; // nil if we aren't using a HTTPS proxy 83 UInt16 origPort; // not valid if we aren't using a HTTPS proxy 81 84 82 85 long theUserData; 83 86 }
