mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 08:41:03 +00:00
Added Ibadinov's socks parsing code, modified to build without warnings/errors
on more systems. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@36828 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
aca76da0ef
commit
9c1209f421
10 changed files with 1003 additions and 0 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
||||||
|
2013-07-04 Ibadinov Marat <ibadinov@me.com>
|
||||||
|
|
||||||
|
* GSSocksParser/GSSocks5Parser.m:
|
||||||
|
* GSSocksParser/GSSocks5Parser.h:
|
||||||
|
* GSSocksParser/GSSocksParserPrivate.h:
|
||||||
|
* GSSocksParser/GSSocksParser.m:
|
||||||
|
* GSSocksParser/GSSocksParserPrivate.m:
|
||||||
|
* GSSocksParser/GSSocksParser.h:
|
||||||
|
* GSSocksParser/GSSocks4Parser.m:
|
||||||
|
* GSSocksParser/GSSocks4Parser.h:
|
||||||
|
Parsing code for SOCKS versions 4 and 5.
|
||||||
|
|
||||||
2013-07-03 Sebastian Reitenbach <sebastia@l00-bugdead-prods.de>
|
2013-07-03 Sebastian Reitenbach <sebastia@l00-bugdead-prods.de>
|
||||||
|
|
||||||
* Source/Additions/GSMime.m
|
* Source/Additions/GSMime.m
|
||||||
|
|
|
@ -174,6 +174,10 @@ GSString.m \
|
||||||
GSTimSort.m \
|
GSTimSort.m \
|
||||||
GSTLS.m \
|
GSTLS.m \
|
||||||
GSValue.m \
|
GSValue.m \
|
||||||
|
GSSocksParser/GSSocksParser.m \
|
||||||
|
GSSocksParser/GSSocksParserPrivate.m \
|
||||||
|
GSSocksParser/GSSocks4Parser.m \
|
||||||
|
GSSocksParser/GSSocks5Parser.m \
|
||||||
NSAffineTransform.m \
|
NSAffineTransform.m \
|
||||||
NSArchiver.m \
|
NSArchiver.m \
|
||||||
NSArray.m \
|
NSArray.m \
|
||||||
|
|
34
Source/GSSocksParser/GSSocks4Parser.h
Normal file
34
Source/GSSocksParser/GSSocks4Parser.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Parsers of SOCKS protocol messages
|
||||||
|
* Copyright (C) 2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Written by Marat Ibadinov <ibadinov@me.com>
|
||||||
|
* Date: 2013
|
||||||
|
*
|
||||||
|
* This file is part of the GNUstep Base Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110 USA.
|
||||||
|
*
|
||||||
|
* $Date$ $Revision$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "GSSocksParser.h"
|
||||||
|
|
||||||
|
@interface GSSocks4Parser : GSSocksParser {
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
170
Source/GSSocksParser/GSSocks4Parser.m
Normal file
170
Source/GSSocksParser/GSSocks4Parser.m
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* Parsers of SOCKS protocol messages
|
||||||
|
* Copyright (C) 2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Written by Marat Ibadinov <ibadinov@me.com>
|
||||||
|
* Date: 2013
|
||||||
|
*
|
||||||
|
* This file is part of the GNUstep Base Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110 USA.
|
||||||
|
*
|
||||||
|
* $Date$ $Revision$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "GSSocks4Parser.h"
|
||||||
|
#import "GSSocksParserPrivate.h"
|
||||||
|
#import <arpa/inet.h>
|
||||||
|
|
||||||
|
typedef enum GSSocks4InternalError {
|
||||||
|
GSSocks4InternalErrorIPv6 = 0x4a
|
||||||
|
} GSSocks4InternalError;
|
||||||
|
|
||||||
|
typedef enum GSSocks4ResponseStatus {
|
||||||
|
GSSocks4ResponseStatusAccessGranted = 0x5a,
|
||||||
|
GSSocks4ResponseStatusRequestRejected = 0x5b,
|
||||||
|
GSSocks4ResponseStatusIdentdFailed = 0x5c,
|
||||||
|
GSSocks4ResponseStatusUserNotConfirmed = 0x5d,
|
||||||
|
} GSSocks4ResponseStatus;
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@implementation GSSocks4Parser
|
||||||
|
|
||||||
|
- (id) initWithConfiguration: (NSDictionary *)aConfiguration
|
||||||
|
address: (NSString *)anAddress
|
||||||
|
port: (NSUInteger)aPort
|
||||||
|
{
|
||||||
|
if (nil != (self = [super init]))
|
||||||
|
{
|
||||||
|
configuration = [aConfiguration retain];
|
||||||
|
address = [anAddress retain];
|
||||||
|
port = aPort;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) start
|
||||||
|
{
|
||||||
|
NSMutableData *data;
|
||||||
|
uint8_t *bytes;
|
||||||
|
uint8_t zero;
|
||||||
|
NSString *user;
|
||||||
|
GSSocksAddressType addressType;
|
||||||
|
|
||||||
|
addressType = [self addressType];
|
||||||
|
if (addressType == GSSocksAddressTypeIPv6)
|
||||||
|
{
|
||||||
|
NSError *error;
|
||||||
|
|
||||||
|
error = [self errorWithCode: GSSocks4InternalErrorIPv6
|
||||||
|
description: @"IPv6 addresses are not supported by SOCKS4 proxies"];
|
||||||
|
[delegate parser: self encounteredError: error];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = [NSMutableData dataWithLength: 8];
|
||||||
|
bytes = [data mutableBytes];
|
||||||
|
bytes[0] = 0x4;
|
||||||
|
bytes[1] = 0x1;
|
||||||
|
*(uint16_t *)(bytes + 2) = htons((uint16_t)port);
|
||||||
|
if (addressType == GSSocksAddressTypeDomain)
|
||||||
|
{
|
||||||
|
bytes[4] = bytes[5] = bytes[6] = 0;
|
||||||
|
bytes[7] = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const uint32_t *addressBytes = [[self addressData] bytes];
|
||||||
|
|
||||||
|
*(uint32_t *)(bytes + 4) = htonl(*addressBytes);
|
||||||
|
}
|
||||||
|
zero = 0x0;
|
||||||
|
user = [configuration objectForKey: NSStreamSOCKSProxyUserKey];
|
||||||
|
if (user)
|
||||||
|
{
|
||||||
|
[data appendData: [user dataUsingEncoding: NSUTF8StringEncoding]];
|
||||||
|
[data appendBytes: &zero length: 1];
|
||||||
|
}
|
||||||
|
if (addressType == GSSocksAddressTypeDomain)
|
||||||
|
{
|
||||||
|
[data appendData: [address dataUsingEncoding: NSUTF8StringEncoding]];
|
||||||
|
[data appendBytes: &zero length: 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
[delegate parser: self formedRequest: data];
|
||||||
|
[delegate parser: self needsMoreBytes: 8];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSError *) errorWithResponseStatus: (NSInteger)aStatus
|
||||||
|
{
|
||||||
|
NSString *description;
|
||||||
|
|
||||||
|
switch ((GSSocks4ResponseStatus)aStatus)
|
||||||
|
{
|
||||||
|
case GSSocks4ResponseStatusRequestRejected:
|
||||||
|
description = @"request was rejected or the server failed to fulfil it";
|
||||||
|
break;
|
||||||
|
case GSSocks4ResponseStatusIdentdFailed:
|
||||||
|
description = @"identd is not running or not reachable from the server";
|
||||||
|
break;
|
||||||
|
case GSSocks4ResponseStatusUserNotConfirmed:
|
||||||
|
description = @"identd could not confirm the user ID string in the request";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
description = @"unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
description = [NSString stringWithFormat:
|
||||||
|
@"SOCKS4 connnection failed, reason: %@", description];
|
||||||
|
return [self errorWithCode: aStatus description: description];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) parseNextChunk: (NSData *)aChunk
|
||||||
|
{
|
||||||
|
NSUInteger bndPort;
|
||||||
|
uint32_t addressBytes;
|
||||||
|
NSData *addressData;
|
||||||
|
NSString *bndAddress;
|
||||||
|
const uint8_t *bytes;
|
||||||
|
|
||||||
|
bytes = [aChunk bytes];
|
||||||
|
if (bytes[1] != GSSocks4ResponseStatusAccessGranted)
|
||||||
|
{
|
||||||
|
NSError *error = [self errorWithResponseStatus:bytes[1]];
|
||||||
|
[delegate parser:self encounteredError:error];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bndPort = ntohs(*(uint16_t *)(bytes + 2));
|
||||||
|
addressBytes = ntohl(*(uint32_t *)(bytes + 4));
|
||||||
|
addressData = [NSData dataWithBytesNoCopy: &addressBytes
|
||||||
|
length: 4
|
||||||
|
freeWhenDone: NO];
|
||||||
|
bndAddress = [self addressFromData: addressData
|
||||||
|
withType :GSSocksAddressTypeIPv4];
|
||||||
|
|
||||||
|
[delegate parser: self finishedWithAddress: bndAddress port: bndPort];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
38
Source/GSSocksParser/GSSocks5Parser.h
Normal file
38
Source/GSSocksParser/GSSocks5Parser.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Parsers of SOCKS protocol messages
|
||||||
|
* Copyright (C) 2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Written by Marat Ibadinov <ibadinov@me.com>
|
||||||
|
* Date: 2013
|
||||||
|
*
|
||||||
|
* This file is part of the GNUstep Base Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110 USA.
|
||||||
|
*
|
||||||
|
* $Date$ $Revision$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "GSSocksParser.h"
|
||||||
|
|
||||||
|
@interface GSSocks5Parser : GSSocksParser {
|
||||||
|
NSUInteger state;
|
||||||
|
NSUInteger addressSize;
|
||||||
|
uint8_t addressType;
|
||||||
|
BOOL stopped;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
283
Source/GSSocksParser/GSSocks5Parser.m
Normal file
283
Source/GSSocksParser/GSSocks5Parser.m
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
/*
|
||||||
|
* Parsers of SOCKS protocol messages
|
||||||
|
* Copyright (C) 2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Written by Marat Ibadinov <ibadinov@me.com>
|
||||||
|
* Date: 2013
|
||||||
|
*
|
||||||
|
* This file is part of the GNUstep Base Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110 USA.
|
||||||
|
*
|
||||||
|
* $Date$ $Revision$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "GSSocks5Parser.h"
|
||||||
|
#import "GSSocksParserPrivate.h"
|
||||||
|
#import <arpa/inet.h>
|
||||||
|
|
||||||
|
typedef enum GSSocks5ParserState {
|
||||||
|
GSSocks5ParserStateHandshake,
|
||||||
|
GSSocks5ParserStateAuthenticationRequest,
|
||||||
|
GSSocks5ParserStateAuthenticationResponse,
|
||||||
|
GSSocks5ParserStateRequest,
|
||||||
|
GSSocks5ParserStateResponse,
|
||||||
|
GSSocks5ParserStateResponseAddressLength,
|
||||||
|
GSSocks5ParserStateResponseAddressAndPort,
|
||||||
|
} GSSocks5ParserState;
|
||||||
|
|
||||||
|
typedef enum GSSocks5AuthenticationMethod {
|
||||||
|
GSSocks5AuthenticationMethodNone = 0x00,
|
||||||
|
GSSocks5AuthenticationMethodGSSAPI = 0x01,
|
||||||
|
GSSocks5AuthenticationMethodPassword = 0x02,
|
||||||
|
GSSocks5AuthenticationMethodNoAcceptable = 0xFF,
|
||||||
|
} GSSocks5AuthenticationMethod;
|
||||||
|
|
||||||
|
typedef enum GSSocks5ResponseStatus {
|
||||||
|
GSSocks5ResponseStatusSuccess = 0x0,
|
||||||
|
GSSocks5ResponseStatusGeneralFailure = 0x1,
|
||||||
|
GSSocks5ResponseStatusConnectionNotAllowed = 0x2,
|
||||||
|
GSSocks5ResponseStatusNetworkUnreachable = 0x3,
|
||||||
|
GSSocks5ResponseStatusHostUnreachable = 0x4,
|
||||||
|
GSSocks5ResponseStatusConnectionRefused = 0x5,
|
||||||
|
GSSocks5ResponseStatusTTLExpired = 0x6,
|
||||||
|
GSSocks5ResponseStatusCommandNotSupported = 0x7,
|
||||||
|
GSSocks5ResponseStatusAddressTypeNotSupported = 0x8,
|
||||||
|
} GSSocks5ResponseStatus;
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@implementation GSSocks5Parser
|
||||||
|
|
||||||
|
- (id) initWithConfiguration: (NSDictionary *)aConfiguration
|
||||||
|
address: (NSString *)anAddress
|
||||||
|
port: (NSUInteger)aPort
|
||||||
|
{
|
||||||
|
if (nil != (self = [super init]))
|
||||||
|
{
|
||||||
|
configuration = [aConfiguration retain];
|
||||||
|
address = [anAddress retain];
|
||||||
|
port = aPort;
|
||||||
|
stopped = YES;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) start
|
||||||
|
{
|
||||||
|
uint8_t bytes[3] = {0x5, 0x1, GSSocks5AuthenticationMethodNone};
|
||||||
|
|
||||||
|
state = GSSocks5ParserStateHandshake;
|
||||||
|
stopped = NO;
|
||||||
|
|
||||||
|
if ([configuration objectForKey: NSStreamSOCKSProxyUserKey])
|
||||||
|
{
|
||||||
|
bytes[2] = GSSocks5AuthenticationMethodPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
[delegate parser: self
|
||||||
|
formedRequest: [NSData dataWithBytes: bytes length: 3]];
|
||||||
|
[delegate parser: self needsMoreBytes: 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSError *) errorWithResponseStatus: (NSInteger)aStatus
|
||||||
|
{
|
||||||
|
NSString *description;
|
||||||
|
|
||||||
|
switch ((GSSocks5ResponseStatus)aStatus)
|
||||||
|
{
|
||||||
|
case GSSocks5ResponseStatusGeneralFailure:
|
||||||
|
description = @"general server failure";
|
||||||
|
break;
|
||||||
|
case GSSocks5ResponseStatusConnectionNotAllowed:
|
||||||
|
description = @"connection is not allowed by a ruleset";
|
||||||
|
break;
|
||||||
|
case GSSocks5ResponseStatusNetworkUnreachable:
|
||||||
|
description = @"destination network is unreachable";
|
||||||
|
break;
|
||||||
|
case GSSocks5ResponseStatusHostUnreachable:
|
||||||
|
description = @"destination host is unreachable";
|
||||||
|
break;
|
||||||
|
case GSSocks5ResponseStatusConnectionRefused:
|
||||||
|
description = @"connection has been refused";
|
||||||
|
break;
|
||||||
|
case GSSocks5ResponseStatusTTLExpired:
|
||||||
|
description = @"connection has timed out";
|
||||||
|
break;
|
||||||
|
case GSSocks5ResponseStatusCommandNotSupported:
|
||||||
|
description = @"command is not supported";
|
||||||
|
break;
|
||||||
|
case GSSocks5ResponseStatusAddressTypeNotSupported:
|
||||||
|
description = @"address type is not supported";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
description = @"unkown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
description = [NSString stringWithFormat:
|
||||||
|
@"SOCKS5 server failed to fulfil request, reason: %@", description];
|
||||||
|
return [self errorWithCode: aStatus description: description];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) reportError: (NSError *)anError
|
||||||
|
{
|
||||||
|
stopped = YES;
|
||||||
|
[delegate parser: self encounteredError: anError];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) parseNextChunk: (NSData *)aChunk
|
||||||
|
{
|
||||||
|
const uint8_t *bytes;
|
||||||
|
if (stopped)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bytes = [aChunk bytes];
|
||||||
|
switch ((GSSocks5ParserState)state)
|
||||||
|
{
|
||||||
|
case GSSocks5ParserStateHandshake:
|
||||||
|
{
|
||||||
|
if (bytes[1] == GSSocks5AuthenticationMethodNoAcceptable)
|
||||||
|
{
|
||||||
|
NSError *error;
|
||||||
|
|
||||||
|
error = [self
|
||||||
|
errorWithCode: GSSocks5AuthenticationMethodNoAcceptable
|
||||||
|
description: @"SOCKS server does not support"
|
||||||
|
@" requested authentication method"];
|
||||||
|
[self reportError:error];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (![configuration objectForKey: NSStreamSOCKSProxyUserKey])
|
||||||
|
{
|
||||||
|
state = GSSocks5ParserStateRequest;
|
||||||
|
goto GSSocks5ParserStateRequest;
|
||||||
|
}
|
||||||
|
state = GSSocks5ParserStateAuthenticationRequest;
|
||||||
|
}
|
||||||
|
case GSSocks5ParserStateAuthenticationRequest:
|
||||||
|
{
|
||||||
|
NSString *username
|
||||||
|
= [configuration objectForKey: NSStreamSOCKSProxyUserKey];
|
||||||
|
NSString *password
|
||||||
|
= [configuration objectForKey: NSStreamSOCKSProxyPasswordKey];
|
||||||
|
uint8_t bytes[3] = {
|
||||||
|
0x5, (uint8_t)[username length], (uint8_t)[password length]};
|
||||||
|
NSMutableData *request
|
||||||
|
= [NSMutableData dataWithCapacity:bytes[1] + bytes[2] + 3];
|
||||||
|
|
||||||
|
[request appendBytes: bytes length: 2];
|
||||||
|
[request appendBytes: [username UTF8String] length: bytes[1]];
|
||||||
|
[request appendBytes: &bytes[2] length: 1];
|
||||||
|
[request appendBytes: [password UTF8String] length: bytes[2]];
|
||||||
|
|
||||||
|
state = GSSocks5ParserStateAuthenticationResponse;
|
||||||
|
[delegate parser: self formedRequest: request];
|
||||||
|
[delegate parser: self needsMoreBytes: 2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GSSocks5ParserStateAuthenticationResponse:
|
||||||
|
{
|
||||||
|
if (bytes[1])
|
||||||
|
{
|
||||||
|
NSError *error;
|
||||||
|
|
||||||
|
error = [self errorWithCode: 0xFF + bytes[1]
|
||||||
|
description: @"SOCKS authentication failed"];
|
||||||
|
[self reportError: error];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = GSSocks5ParserStateRequest;
|
||||||
|
}
|
||||||
|
GSSocks5ParserStateRequest:
|
||||||
|
case GSSocks5ParserStateRequest:
|
||||||
|
{
|
||||||
|
GSSocksAddressType type = [self addressType];
|
||||||
|
uint8_t request[4] = {
|
||||||
|
0x5, 0x1, 0x0, type
|
||||||
|
};
|
||||||
|
uint16_t portWithNetworkEndianness;
|
||||||
|
NSMutableData *data = [NSMutableData dataWithBytes:request length:4];
|
||||||
|
NSData *addressData = [self addressData];
|
||||||
|
|
||||||
|
if (type == GSSocksAddressTypeDomain)
|
||||||
|
{
|
||||||
|
uint8_t length = (uint8_t)[addressData length];
|
||||||
|
[data appendBytes: &length length: 1];
|
||||||
|
}
|
||||||
|
[data appendData: addressData];
|
||||||
|
portWithNetworkEndianness = htons((uint16_t)port);
|
||||||
|
[data appendBytes: &portWithNetworkEndianness length: 2];
|
||||||
|
|
||||||
|
state = GSSocks5ParserStateResponse;
|
||||||
|
[delegate parser: self formedRequest: data];
|
||||||
|
[delegate parser: self needsMoreBytes: 4];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GSSocks5ParserStateResponse:
|
||||||
|
{
|
||||||
|
if (bytes[1] != GSSocks5ResponseStatusSuccess)
|
||||||
|
{
|
||||||
|
NSError *error = [self errorWithResponseStatus: bytes[1]];
|
||||||
|
[self reportError: error];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
addressType = bytes[3]; /* addess type */
|
||||||
|
if (addressType == GSSocksAddressTypeDomain)
|
||||||
|
{
|
||||||
|
state = GSSocks5ParserStateResponseAddressLength;
|
||||||
|
[delegate parser: self needsMoreBytes: 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = GSSocks5ParserStateResponseAddressAndPort;
|
||||||
|
addressSize = addressType == GSSocksAddressTypeIPv4 ? 4 : 16;
|
||||||
|
[delegate parser: self needsMoreBytes: addressSize + 2];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GSSocks5ParserStateResponseAddressLength:
|
||||||
|
{
|
||||||
|
addressSize = bytes[0];
|
||||||
|
state = GSSocks5ParserStateResponseAddressAndPort;
|
||||||
|
[delegate parser: self needsMoreBytes: addressSize + 2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GSSocks5ParserStateResponseAddressAndPort:
|
||||||
|
{
|
||||||
|
NSString *bndAddress;
|
||||||
|
NSUInteger bndPort;
|
||||||
|
NSData *data;
|
||||||
|
|
||||||
|
data = [NSData dataWithBytes: [aChunk bytes]
|
||||||
|
length: addressSize];
|
||||||
|
bndAddress = [self addressFromData: data
|
||||||
|
withType: addressType];
|
||||||
|
bndPort = ntohs(*(uint16_t *)(bytes + addressSize));
|
||||||
|
[delegate parser: self finishedWithAddress: bndAddress port: bndPort];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
73
Source/GSSocksParser/GSSocksParser.h
Normal file
73
Source/GSSocksParser/GSSocksParser.h
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Parsers of SOCKS protocol messages
|
||||||
|
* Copyright (C) 2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Written by Marat Ibadinov <ibadinov@me.com>
|
||||||
|
* Date: 2013
|
||||||
|
*
|
||||||
|
* This file is part of the GNUstep Base Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110 USA.
|
||||||
|
*
|
||||||
|
* $Date$ $Revision$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/NSData.h>
|
||||||
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSError.h>
|
||||||
|
#import <Foundation/NSStream.h>
|
||||||
|
#import <Foundation/NSString.h>
|
||||||
|
|
||||||
|
@class GSSocksParser;
|
||||||
|
|
||||||
|
@protocol GSSocksParserDelegate <NSObject>
|
||||||
|
|
||||||
|
- (void) parser: (GSSocksParser *)aParser
|
||||||
|
needsMoreBytes: (NSUInteger)aLength;
|
||||||
|
- (void) parser: (GSSocksParser *)aParser
|
||||||
|
formedRequest: (NSData *)aRequest;
|
||||||
|
- (void) parser: (GSSocksParser *)aParser
|
||||||
|
finishedWithAddress: (NSString *)anAddress
|
||||||
|
port: (NSUInteger)aPort;
|
||||||
|
|
||||||
|
- (void) parser: (GSSocksParser *)aParser
|
||||||
|
encounteredError: (NSError *)anError;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface GSSocksParser : NSObject
|
||||||
|
{
|
||||||
|
NSDictionary *configuration;
|
||||||
|
NSString *address;
|
||||||
|
id<GSSocksParserDelegate> delegate;
|
||||||
|
NSUInteger port;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithConfiguration: (NSDictionary *)aConfiguration
|
||||||
|
address: (NSString *)anAddress
|
||||||
|
port: (NSUInteger)aPort;
|
||||||
|
|
||||||
|
- (id<GSSocksParserDelegate>) delegate;
|
||||||
|
- (void) setDelegate: (id<GSSocksParserDelegate>)aDelegate;
|
||||||
|
|
||||||
|
- (NSString *) address;
|
||||||
|
- (NSUInteger) port;
|
||||||
|
|
||||||
|
- (void) start;
|
||||||
|
- (void) parseNextChunk: (NSData *)aChunk;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
121
Source/GSSocksParser/GSSocksParser.m
Normal file
121
Source/GSSocksParser/GSSocksParser.m
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* Parsers of SOCKS protocol messages
|
||||||
|
* Copyright (C) 2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Written by Marat Ibadinov <ibadinov@me.com>
|
||||||
|
* Date: 2013
|
||||||
|
*
|
||||||
|
* This file is part of the GNUstep Base Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110 USA.
|
||||||
|
*
|
||||||
|
* $Date$ $Revision$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "GSSocksParser.h"
|
||||||
|
#import "GSSocks4Parser.h"
|
||||||
|
#import "GSSocks5Parser.h"
|
||||||
|
#import "Foundation/NSException.h"
|
||||||
|
|
||||||
|
@interface NSObject (SubclassResponsibility)
|
||||||
|
- (id) subclassResponsibility: (SEL)aSelector;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GSSocksParser
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
if (nil != (self = [super init]))
|
||||||
|
{
|
||||||
|
configuration = nil;
|
||||||
|
address = nil;
|
||||||
|
delegate = nil;
|
||||||
|
port = 0;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithConfiguration: (NSDictionary *)aConfiguration
|
||||||
|
address: (NSString *)anAddress
|
||||||
|
port: (NSUInteger)aPort
|
||||||
|
{
|
||||||
|
NSString *version;
|
||||||
|
Class concreteClass;
|
||||||
|
|
||||||
|
version = [aConfiguration objectForKey: NSStreamSOCKSProxyVersionKey];
|
||||||
|
version = version ? version : NSStreamSOCKSProxyVersion5;
|
||||||
|
|
||||||
|
[self release];
|
||||||
|
|
||||||
|
if ([version isEqualToString: NSStreamSOCKSProxyVersion5])
|
||||||
|
{
|
||||||
|
concreteClass = [GSSocks5Parser class];
|
||||||
|
}
|
||||||
|
else if ([version isEqualToString: NSStreamSOCKSProxyVersion4])
|
||||||
|
{
|
||||||
|
concreteClass = [GSSocks4Parser class];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[NSException raise: NSInternalInconsistencyException
|
||||||
|
format: @"Unsupported socks verion: %@", version];
|
||||||
|
}
|
||||||
|
return [[concreteClass alloc] initWithConfiguration: aConfiguration
|
||||||
|
address: anAddress
|
||||||
|
port: aPort];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[delegate release];
|
||||||
|
[address release];
|
||||||
|
[configuration release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id<GSSocksParserDelegate>) delegate
|
||||||
|
{
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setDelegate: (id<GSSocksParserDelegate>)aDelegate
|
||||||
|
{
|
||||||
|
id previous = delegate;
|
||||||
|
delegate = [aDelegate retain];
|
||||||
|
[previous release];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) address
|
||||||
|
{
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger) port
|
||||||
|
{
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) start
|
||||||
|
{
|
||||||
|
[self subclassResponsibility:_cmd];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) parseNextChunk: (NSData *)aChunk
|
||||||
|
{
|
||||||
|
[self subclassResponsibility: _cmd];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
49
Source/GSSocksParser/GSSocksParserPrivate.h
Normal file
49
Source/GSSocksParser/GSSocksParserPrivate.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Parsers of SOCKS protocol messages
|
||||||
|
* Copyright (C) 2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Written by Marat Ibadinov <ibadinov@me.com>
|
||||||
|
* Date: 2013
|
||||||
|
*
|
||||||
|
* This file is part of the GNUstep Base Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110 USA.
|
||||||
|
*
|
||||||
|
* $Date$ $Revision$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "GSSocksParser.h"
|
||||||
|
|
||||||
|
typedef enum GSSocksAddressType {
|
||||||
|
GSSocksAddressTypeIPv4 = 0x1,
|
||||||
|
GSSocksAddressTypeIPv6 = 0x4,
|
||||||
|
GSSocksAddressTypeDomain = 0x3,
|
||||||
|
} GSSocksAddressType;
|
||||||
|
|
||||||
|
@interface GSSocksParser (Private)
|
||||||
|
|
||||||
|
- (NSError *) errorWithCode: (NSInteger)aCode
|
||||||
|
description: (NSString *)aDescription;
|
||||||
|
|
||||||
|
|
||||||
|
- (GSSocksAddressType) addressType;
|
||||||
|
|
||||||
|
- (NSData *) addressData;
|
||||||
|
- (NSString *) addressFromData: (NSData *)aData
|
||||||
|
withType: (GSSocksAddressType)anAddressType;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
219
Source/GSSocksParser/GSSocksParserPrivate.m
Normal file
219
Source/GSSocksParser/GSSocksParserPrivate.m
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
/*
|
||||||
|
* Parsers of SOCKS protocol messages
|
||||||
|
* Copyright (C) 2013 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* Written by Marat Ibadinov <ibadinov@me.com>
|
||||||
|
* Date: 2013
|
||||||
|
*
|
||||||
|
* This file is part of the GNUstep Base Library.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110 USA.
|
||||||
|
*
|
||||||
|
* $Date$ $Revision$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "GSSocksParserPrivate.h"
|
||||||
|
#import "Foundation/NSArray.h"
|
||||||
|
#import "Foundation/NSBundle.h"
|
||||||
|
#import "Foundation/NSCharacterSet.h"
|
||||||
|
#import "Foundation/NSException.h"
|
||||||
|
#import <stdio.h>
|
||||||
|
|
||||||
|
@interface NSString (GSSocksParser)
|
||||||
|
- (NSString *) stringByRepeatingCurrentString: (NSUInteger)times;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSString (GSSocksParser)
|
||||||
|
|
||||||
|
- (NSString *) stringByRepeatingCurrentString: (NSUInteger)times
|
||||||
|
{
|
||||||
|
return [@"" stringByPaddingToLength: times * [self length]
|
||||||
|
withString: self
|
||||||
|
startingAtIndex: 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GSSocksParser (Private)
|
||||||
|
|
||||||
|
- (NSError *) errorWithCode: (NSInteger)aCode
|
||||||
|
description: (NSString *)aDescription
|
||||||
|
{
|
||||||
|
NSDictionary *userInfo;
|
||||||
|
|
||||||
|
aDescription = NSLocalizedString(aDescription, @"");
|
||||||
|
userInfo = [NSDictionary dictionaryWithObject: aDescription
|
||||||
|
forKey: NSLocalizedDescriptionKey];
|
||||||
|
return [NSError errorWithDomain: NSStreamSOCKSErrorDomain
|
||||||
|
code: aCode
|
||||||
|
userInfo: userInfo];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (GSSocksAddressType) addressType
|
||||||
|
{
|
||||||
|
const char *cAddress;
|
||||||
|
NSUInteger index;
|
||||||
|
BOOL hasAlpha;
|
||||||
|
BOOL hasDot;
|
||||||
|
char character;
|
||||||
|
|
||||||
|
if ([address length] > 16)
|
||||||
|
{
|
||||||
|
return GSSocksAddressTypeDomain;
|
||||||
|
}
|
||||||
|
cAddress = [address UTF8String];
|
||||||
|
index = 0;
|
||||||
|
hasAlpha = NO;
|
||||||
|
hasDot = NO;
|
||||||
|
|
||||||
|
while (0 != (character = cAddress[index]))
|
||||||
|
{
|
||||||
|
BOOL isAlpha = character >= 'a' && character <= 'f';
|
||||||
|
|
||||||
|
if (!(character >= '0' && character <= '9')
|
||||||
|
&& !isAlpha && character != '.' && character != ':')
|
||||||
|
{
|
||||||
|
return GSSocksAddressTypeDomain;
|
||||||
|
}
|
||||||
|
hasAlpha = hasAlpha || isAlpha;
|
||||||
|
hasDot = hasDot || character == '.';
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
return hasAlpha && hasDot ? GSSocksAddressTypeDomain
|
||||||
|
: (hasDot ? GSSocksAddressTypeIPv4 : GSSocksAddressTypeIPv6);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSData *) addressData
|
||||||
|
{
|
||||||
|
switch ([self addressType])
|
||||||
|
{
|
||||||
|
case GSSocksAddressTypeIPv4:
|
||||||
|
{
|
||||||
|
NSMutableData *result = [NSMutableData dataWithLength: 4];
|
||||||
|
const char *cString = [address UTF8String];
|
||||||
|
uint8_t *bytes = [result mutableBytes];
|
||||||
|
|
||||||
|
sscanf(cString, "%hhu.%hhu.%hhu.%hhu",
|
||||||
|
&bytes[0], &bytes[1], &bytes[2], &bytes[3]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case GSSocksAddressTypeIPv6:
|
||||||
|
{
|
||||||
|
NSArray *components = [address componentsSeparatedByString: @"::"];
|
||||||
|
NSMutableData *result;
|
||||||
|
uint16_t *bytes;
|
||||||
|
|
||||||
|
if ([components count] == 2)
|
||||||
|
{
|
||||||
|
NSString *leading;
|
||||||
|
NSString *trailing;
|
||||||
|
NSCharacterSet *charset;
|
||||||
|
NSArray *separated;
|
||||||
|
NSUInteger leadingCount;
|
||||||
|
NSUInteger trailingCount;
|
||||||
|
|
||||||
|
leading = [components objectAtIndex: 0];
|
||||||
|
trailing = [components objectAtIndex: 1];
|
||||||
|
charset
|
||||||
|
= [NSCharacterSet characterSetWithCharactersInString: @":"];
|
||||||
|
separated
|
||||||
|
= [leading componentsSeparatedByCharactersInSet: charset];
|
||||||
|
leadingCount = [leading length] ? [separated count] : 0;
|
||||||
|
/* FIXME ... do we need to add this following statement?
|
||||||
|
separated
|
||||||
|
= [trailing componentsSeparatedByCharactersInSet: charset];
|
||||||
|
*/
|
||||||
|
trailingCount = [trailing length] ? [separated count] : 0;
|
||||||
|
|
||||||
|
if (leadingCount && trailingCount)
|
||||||
|
{
|
||||||
|
NSString *middle;
|
||||||
|
|
||||||
|
middle = [@"0:" stringByRepeatingCurrentString:
|
||||||
|
8 - leadingCount - trailingCount];
|
||||||
|
address = [[[leading stringByAppendingString: @":"]
|
||||||
|
stringByAppendingString: middle]
|
||||||
|
stringByAppendingString: trailing];
|
||||||
|
}
|
||||||
|
else if (!leadingCount)
|
||||||
|
{
|
||||||
|
NSString *start;
|
||||||
|
|
||||||
|
start = [@"0:" stringByRepeatingCurrentString:
|
||||||
|
8 - trailingCount];
|
||||||
|
address = [start stringByAppendingString: trailing];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSString *end;
|
||||||
|
|
||||||
|
end = [@":0" stringByRepeatingCurrentString:
|
||||||
|
8 - leadingCount];
|
||||||
|
address = [leading stringByAppendingString: end];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = [NSMutableData dataWithLength:16];
|
||||||
|
bytes = [result mutableBytes];
|
||||||
|
sscanf([address UTF8String], "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
|
||||||
|
&bytes[0], &bytes[1], &bytes[2], &bytes[3],
|
||||||
|
&bytes[4], &bytes[5], &bytes[6], &bytes[7]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case GSSocksAddressTypeDomain:
|
||||||
|
{
|
||||||
|
return [address dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
[NSException raise: NSInternalInconsistencyException
|
||||||
|
format: @"Unknown address type"];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) addressFromData: (NSData *)aData
|
||||||
|
withType: (GSSocksAddressType)anAddressType
|
||||||
|
{
|
||||||
|
switch (anAddressType)
|
||||||
|
{
|
||||||
|
case GSSocksAddressTypeIPv4:
|
||||||
|
{
|
||||||
|
const uint8_t *bytes = [aData bytes];
|
||||||
|
|
||||||
|
return [NSString stringWithFormat: @"%hhu.%hhu.%hhu.%hhu",
|
||||||
|
bytes[0], bytes[1], bytes[2], bytes[3]];
|
||||||
|
}
|
||||||
|
case GSSocksAddressTypeIPv6:
|
||||||
|
{
|
||||||
|
const uint16_t *bytes = [aData bytes];
|
||||||
|
|
||||||
|
return [NSString stringWithFormat: @"%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
|
||||||
|
bytes[0], bytes[1], bytes[2], bytes[3],
|
||||||
|
bytes[4], bytes[5], bytes[6], bytes[7]];
|
||||||
|
}
|
||||||
|
case GSSocksAddressTypeDomain:
|
||||||
|
{
|
||||||
|
return [[[NSString alloc] initWithData: aData
|
||||||
|
encoding: NSUTF8StringEncoding] autorelease];
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
[NSException raise: NSInternalInconsistencyException
|
||||||
|
format: @"Unknown address type"];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
Loading…
Add table
Add a link
Reference in a new issue