Differences From Artifact [8b7939a5bd]:
- File
src/OFTCPSocket+SOCKS5.m
— part of check-in
[2a27cf3000]
at
2016-01-03 00:41:26
on branch trunk
— Update copyright
While at it, also update the mail address. (user: js, size: 2338) [annotate] [blame] [check-ins using] [more...]
To Artifact [f0cdd75885]:
- File
src/OFTCPSocket+SOCKS5.m
— part of check-in
[f8422ce7e9]
at
2016-03-12 11:55:00
on branch trunk
— OFTCPSocket+SOCKS5.m: Use send/recv directly
This is necessary to make SOCKS5 support work with subclasses of
OFTCPSocket that override read and write, for example SSL sockets. (user: js, size: 3339) [annotate] [blame] [check-ins using]
| ︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
* LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
* file.
*/
#include "config.h"
#import "OFTCPSocket+SOCKS5.h"
#import "OFConnectionFailedException.h"
/* Reference for static linking */
int _OFTCPSocket_SOCKS5_reference;
@implementation OFTCPSocket (SOCKS5)
- (void)OF_SOCKS5ConnectToHost: (OFString*)host
port: (uint16_t)port
{
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | > > | < < | | | > < | | > | > | > | | > > > | > | > < | < | | | < | | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
* LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
* file.
*/
#include "config.h"
#import "OFTCPSocket+SOCKS5.h"
#import "OFDataArray.h"
#import "OFConnectionFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"
#import "socket_helpers.h"
/* Reference for static linking */
int _OFTCPSocket_SOCKS5_reference;
static void
send_or_exception(OFTCPSocket *self, int socket, char *buffer, size_t length)
{
if (send(socket, buffer, length, 0) != length)
@throw [OFWriteFailedException
exceptionWithObject: self
requestedLength: length
errNo: of_socket_errno()];
}
static void
recv_exact(OFTCPSocket *self, int socket, char *buffer, size_t length)
{
while (length > 0) {
ssize_t ret = recv(socket, buffer, length, 0);
if (ret < 0)
@throw [OFReadFailedException
exceptionWithObject: self
requestedLength: length
errNo: of_socket_errno()];
buffer += ret;
length -= ret;
}
}
@implementation OFTCPSocket (SOCKS5)
- (void)OF_SOCKS5ConnectToHost: (OFString*)host
port: (uint16_t)port
{
char request[] = { 5, 1, 0, 3 };
char reply[256];
void *pool;
OFDataArray *connectRequest;
if ([host UTF8StringLength] > 255)
@throw [OFOutOfRangeException exception];
/* 5 1 0 -> no authentication */
send_or_exception(self, _socket, request, 3);
recv_exact(self, _socket, reply, 2);
if (reply[0] != 5 || reply[1] != 0) {
[self close];
@throw [OFConnectionFailedException exceptionWithHost: host
port: port
socket: self];
}
/* CONNECT request */
pool = objc_autoreleasePoolPush();
connectRequest = [OFDataArray dataArray];
[connectRequest addItems: request
count: 4];
request[0] = [host UTF8StringLength];
[connectRequest addItem: request];
[connectRequest addItems: [host UTF8String]
count: request[0]];
request[0] = port >> 8;
request[1] = port & 0xFF;
[connectRequest addItems: request
count: 2];
send_or_exception(self, _socket,
[connectRequest items], [connectRequest count]);
objc_autoreleasePoolPop(pool);
recv_exact(self, _socket, reply, 4);
if (reply[0] != 5 || reply[1] != 0 || reply[2] != 0) {
[self close];
@throw [OFConnectionFailedException exceptionWithHost: host
port: port
socket: self];
}
/* Skip the rest of the reply */
switch (reply[3]) {
case 1: /* IPv4 */
recv_exact(self, _socket, reply, 4);
break;
case 3: /* Domainname */
recv_exact(self, _socket, reply, 1);
recv_exact(self, _socket, reply, reply[0]);
break;
case 4: /* IPv6 */
recv_exact(self, _socket, reply, 16);
break;
default:
[self close];
@throw [OFConnectionFailedException exceptionWithHost: host
port: port
socket: self];
}
recv_exact(self, _socket, reply, 2);
}
@end
|