Ticket #1229: proxy.patch

File proxy.patch, 9.3 KB (added by robclark, 4 years ago)
  • 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 *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 
    560642- (BOOL) createStreamsToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr 
    561643{ 
     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   
    562653    // Create the socket & streams. 
    563654    CFStreamCreatePairWithSocketToHost (kCFAllocatorDefault, (CFStringRef)hostname, port, &theReadStream, &theWriteStream); 
    564655    if (theReadStream == NULL || theWriteStream == NULL) 
     
    623714    NSError *err = [self getAbortError]; 
    624715    if (errPtr) *errPtr = err; 
    625716    return NO; 
    626 };   
     717}; 
    627718 
    628719- (BOOL) openStreamsAndReturnError:(NSError **)errPtr 
    629720{ 
     
    638729        NSLog (@"AsyncSocket %p couldn't open write stream,", self); 
    639730        goto Failed; 
    640731    } 
     732   
    641733     
     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 ); 
     745printf("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; 
     758printf("%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   
    642770    return YES; 
    643771     
    644772Failed:; 
     
    648776    return NO; 
    649777} 
    650778 
     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 
    651791// Called when read or write streams open. When the socket is connected and both streams are open, consider the AsyncSocket instance to be ready. 
    652792- (void) doStreamOpen 
    653793{ 
     
    661801            [self closeWithError:err]; 
    662802        } 
    663803         
     804        // Immediately deal with any already-queued requests. 
     805        [self maybeDequeueRead]; 
     806        [self maybeDequeueWrite]; 
     807         
    664808        // 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. 
    665809        [thePollTimer invalidate]; 
    666810        [thePollTimer release]; 
    667811        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]; 
    681815    } 
    682816} 
    683817 
  • 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}