Ticket #1229: proxy-2.patch

File proxy-2.patch, 9.3 KB (added by robclark, 4 years ago)

updated patch which doesn't break non-proxy case ;-)

  • Chat

     
    1414#import <arpa/inet.h> 
    1515#import <netdb.h> 
    1616 
     17#import <SystemConfiguration/SystemConfiguration.h> 
     18#include <fnmatch.h> 
     19 
    1720#pragma mark Declarations 
    1821 
    1922#define READQUEUE_CAPACITY  5           /* Initial capacity. */ 
     
    3841    kDisconnectSoon = 0x08          // If set, disconnect as soon as nothing is queued. 
    3942}; 
    4043 
     44 
     45static 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 
    4157@interface AsyncSocket (Private) 
    4258- (BOOL) isSocketConnected; 
    4359- (BOOL) areStreamsConnected; 
     
    6278- (BOOL) configureStreamsAndReturnError:(NSError **)errPtr; 
    6379- (BOOL) openStreamsAndReturnError:(NSError **)errPtr; 
    6480- (void) doStreamOpen; 
     81- (void) doStreamOpen_callDidConnectToHost; 
    6582- (void) closeWithError:(NSError *)err; 
    6683- (void) recoverUnreadData; 
    6784- (void) emptyQueues; 
     
    213230    theContext.release = nil; 
    214231    theContext.copyDescription = nil; 
    215232 
     233  origHost = nil; 
     234 
    216235    return self; 
    217236} 
    218237 
     
    544563// Creates the socket from a native socket. 
    545564- (BOOL) createStreamsFromNative:(CFSocketNativeHandle)native error:(NSError **)errPtr 
    546565{ 
     566  /*  
     567   * NOT UPDATED FOR PROXIES... is this used? 
     568   */ 
     569 
    547570    // Create the socket & streams. 
    548571    CFStreamCreatePairWithSocket (kCFAllocatorDefault, native, &theReadStream, &theWriteStream); 
    549572    if (theReadStream == NULL || theWriteStream == NULL) 
     
    557580    return YES; 
    558581} 
    559582 
     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 *exceptions = 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  exceptions = [exceptionList objectEnumerator]; 
     607    while( (object = [exceptions nextObject]) != nil ) { 
     608    if( [*hostname rangeOfString: object].location != NSNotFound ) {  // should be case-insensitive? 
     609//    if( [*hostname hasSuffix:object] ) { 
     610     
     611            [pool release]; 
     612      NSLog(@"excluded"); 
     613            return NO; 
     614        } 
     615    } 
     616 
     617    /* now check if it's SOCKS */ 
     618  val = [proxyDict objectForKey:(NSString *)kSCPropNetProxiesSOCKSEnable]; 
     619    if( val && ! [[NSNumber numberWithInt:0] isEqualToNumber:val] ) { 
     620        [pool release]; 
     621    NSLog(@"not implemented"); 
     622        return NO; 
     623    } 
     624 
     625    /* or if we should use HTTPS */ 
     626  val = [proxyDict objectForKey:(NSString *)kSCPropNetProxiesHTTPSEnable]; 
     627    if( val && ! [[NSNumber numberWithInt:0] isEqualToNumber:val] ) { 
     628     
     629    *hostname = [[proxyDict objectForKey:(NSString *)kSCPropNetProxiesHTTPSProxy] retain]; 
     630    *port     = [[proxyDict objectForKey:(NSString *)kSCPropNetProxiesHTTPSPort] intValue]; 
     631     
     632        [pool release]; 
     633     
     634    NSLog(@"using proxy => %@:%d", *hostname, *port); 
     635     
     636        return YES; 
     637    } 
     638 
     639    [pool release]; 
     640    return NO; 
     641} 
     642 
     643 
    560644- (BOOL) createStreamsToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr 
    561645{ 
     646  origHost = hostname; 
     647  origPort = port; 
     648   
     649  if ( ! [self getProxyInfoForHost:&hostname onPort:&port] ) 
     650  { 
     651    // ok, we aren't using a proxy, so nil this back out: 
     652    origHost = nil; 
     653  } 
     654   
    562655    // Create the socket & streams. 
    563656    CFStreamCreatePairWithSocketToHost (kCFAllocatorDefault, (CFStringRef)hostname, port, &theReadStream, &theWriteStream); 
    564657    if (theReadStream == NULL || theWriteStream == NULL) 
     
    623716    NSError *err = [self getAbortError]; 
    624717    if (errPtr) *errPtr = err; 
    625718    return NO; 
    626 };   
     719}; 
    627720 
    628721- (BOOL) openStreamsAndReturnError:(NSError **)errPtr 
    629722{ 
     
    638731        NSLog (@"AsyncSocket %p couldn't open write stream,", self); 
    639732        goto Failed; 
    640733    } 
     734   
    641735     
     736  if (origHost != nil) 
     737  { 
     738    char buf[255]; 
     739    UInt16 n; 
     740     
     741    const char *host = [origHost UTF8String]; 
     742     
     743    // ok, we use a proxy... so we need to take care of interacting with 
     744    // proxy server now: 
     745    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 ); 
     746    writeFully( theWriteStream, (UInt8 *)buf, n ); 
     747printf("send: %s\n", buf ); 
     748     
     749    // for now, this is cheezy.. just look for \r\n without 
     750    // any error handling: 
     751    UInt8 lc, c = 0; 
     752    while(TRUE) 
     753    { 
     754      lc = c; 
     755      int n = CFReadStreamRead( theReadStream, &c, 1 ); 
     756      if(!n) 
     757        return NO; 
     758      if( (lc == '\r') && (c == '\n') ) 
     759        break; 
     760printf("%c",c); 
     761    } 
     762     
     763    // this is skipped in doStreamOpen if we use a proxy, because the 
     764    // act of writing to the stream indirectly causes doStreamOpen to 
     765    // be called.. but we don't actually want to call the delegate until 
     766    // the above proxy communications are taken care of (otherwise the 
     767    // delegate could sneek in and write something before the "CONNECT ..." 
     768    // bit, which really confuses the proxy server: 
     769    [self doStreamOpen_callDidConnectToHost]; 
     770  } 
     771   
    642772    return YES; 
    643773     
    644774Failed:; 
     
    648778    return NO; 
    649779} 
    650780 
     781- (void) doStreamOpen_callDidConnectToHost 
     782{ 
     783  // Call the delegate. 
     784    CFDataRef peer = CFSocketCopyPeerAddress (theSocket); 
     785    theFlags |= kDidCallConnectDeleg; 
     786    if ([theDelegate respondsToSelector:@selector(socket:didConnectToHost:port:)]) 
     787        [theDelegate socket:self 
     788             didConnectToHost:[self addressHost:peer] 
     789            port:[self addressPort:peer]]; 
     790    CFRelease (peer);   
     791} 
     792 
    651793// Called when read or write streams open. When the socket is connected and both streams are open, consider the AsyncSocket instance to be ready. 
    652794- (void) doStreamOpen 
    653795{ 
     
    661803            [self closeWithError:err]; 
    662804        } 
    663805         
     806        // Immediately deal with any already-queued requests. 
     807        [self maybeDequeueRead]; 
     808        [self maybeDequeueWrite]; 
     809         
    664810        // 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. 
    665811        [thePollTimer invalidate]; 
    666812        [thePollTimer release]; 
    667813        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]; 
     814     
     815    if( origHost == nil ) 
     816      [self doStreamOpen_callDidConnectToHost]; 
    681817    } 
    682818} 
    683819 
  • Chat

     
    260260        MVSafeCopyAssign( &_currentNickname, newNickname ); 
    261261 
    262262    if( connectiongOrConnected ) 
     263{ 
     264printf("sending NICK (2)\n"); 
    263265        [self sendRawMessageImmediatelyWithFormat:@"NICK %@", newNickname]; 
    264266} 
     267} 
    265268 
    266269- (NSString *) nickname { 
    267270    return _currentNickname; 
     
    603606- (BOOL) socketWillConnect:(AsyncSocket *) sock { 
    604607    MVAssertCorrectThreadRequired( _connectionThread ); 
    605608 
     609/*  
     610 * Now handled in AsyncSocket: 
     611 *  
    606612    if( [[self proxyServer] length] && [self proxyServerPort] ) { 
    607613        if( _proxy == MVChatConnectionHTTPSProxy || _proxy == MVChatConnectionHTTPProxy ) { 
    608614            NSMutableDictionary *settings = [[NSMutableDictionary allocWithZone:nil] init]; 
     
    636642            [settings release]; 
    637643        } 
    638644    } 
     645 *  
     646 * maybe following part should be handled in AsyncSocket too?? 
     647 */ 
    639648 
    640649    if( [self isSecure] ) { 
    641650        CFReadStreamSetProperty( [sock getCFReadStream], kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL ); 
     
    716725    MVAssertCorrectThreadRequired( _connectionThread ); 
    717726 
    718727    if( [[self password] length] ) [self sendRawMessageImmediatelyWithFormat:@"PASS %@", [self password]]; 
     728printf("sending NICK\n"); 
    719729    [self sendRawMessageImmediatelyWithFormat:@"NICK %@", [self preferredNickname]]; 
    720730    [self sendRawMessageImmediatelyWithFormat:@"USER %@ 0 * :%@", ( [[self username] length] ? [self username] : @"anonymous" ), ( [[self realName] length] ? [self realName] : @"anonymous" )]; 
    721731 
  • Chat

     
    7878    NSTimer *thePollTimer; 
    7979    id theDelegate; 
    8080    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 
    8184 
    8285    long theUserData; 
    8386}