Support for async connecting

This commit is contained in:
Jonathan Schleifer 2018-10-07 23:07:13 +02:00
parent 9c45593f47
commit 2fdbf231bb
No known key found for this signature in database
GPG key ID: D83A76BFE376345E
2 changed files with 141 additions and 24 deletions

View file

@ -35,10 +35,10 @@ OF_ASSUME_NONNULL_BEGIN
@property (readonly, nonatomic) unsigned long SSLError; @property (readonly, nonatomic) unsigned long SSLError;
@property (readonly, nonatomic) long verifyResult; @property (readonly, nonatomic) long verifyResult;
+ (instancetype)exceptionWithHost: (OFString *)host + (instancetype)exceptionWithHost: (nullable OFString *)host
port: (uint16_t)port port: (uint16_t)port
socket: (id)socket OF_UNAVAILABLE; socket: (id)socket OF_UNAVAILABLE;
+ (instancetype)exceptionWithHost: (OFString *)host + (instancetype)exceptionWithHost: (nullable OFString *)host
port: (uint16_t)port port: (uint16_t)port
socket: (id)socket socket: (id)socket
errNo: (int)errNo OF_UNAVAILABLE; errNo: (int)errNo OF_UNAVAILABLE;
@ -51,22 +51,22 @@ OF_ASSUME_NONNULL_BEGIN
socket: (SSLSocket *)socket socket: (SSLSocket *)socket
SSLError: (unsigned long)SSLError SSLError: (unsigned long)SSLError
verifyResult: (long)verifyResult; verifyResult: (long)verifyResult;
- initWithHost: (OFString *)host - (instancetype)initWithHost: (nullable OFString *)host
port: (uint16_t)port port: (uint16_t)port
socket: (id)socket OF_UNAVAILABLE; socket: (id)socket OF_UNAVAILABLE;
- initWithHost: (OFString *)host - (instancetype)initWithHost: (nullable OFString *)host
port: (uint16_t)port port: (uint16_t)port
socket: (id)socket socket: (id)socket
errNo: (int)errNo OF_UNAVAILABLE; errNo: (int)errNo OF_UNAVAILABLE;
- initWithHost: (OFString *)host - (instancetype)initWithHost: (OFString *)host
port: (uint16_t)port port: (uint16_t)port
socket: (SSLSocket *)socket socket: (SSLSocket *)socket
SSLError: (unsigned long)SSLError; SSLError: (unsigned long)SSLError;
- initWithHost: (OFString *)host - (instancetype)initWithHost: (OFString *)host
port: (uint16_t)port port: (uint16_t)port
socket: (SSLSocket *)socket socket: (SSLSocket *)socket
SSLError: (unsigned long)SSLError SSLError: (unsigned long)SSLError
verifyResult: (long)verifyResult OF_DESIGNATED_INITIALIZER; verifyResult: (long)verifyResult OF_DESIGNATED_INITIALIZER;
@end @end
OF_ASSUME_NONNULL_END OF_ASSUME_NONNULL_END

View file

@ -91,9 +91,84 @@ locking_callback(int mode, int n, const char *file, int line)
} }
@interface SSLSocket () @interface SSLSocket ()
- (void)SSL_startTLSWithExpectedHost: (OFString *)host
port: (uint16_t)port;
- (void)SSL_super_close; - (void)SSL_super_close;
@end @end
@interface SSLSocket_ConnectContext: OFObject
{
OFString *_host;
uint16_t _port;
id _target;
SEL _selector;
id _context;
}
- (instancetype)initWithHost: (OFString *)host
port: (uint16_t)port
target: (id)target
selector: (SEL)selector
context: (id)context;
- (void)socketDidConnect: (SSLSocket *)sock
context: (id)context
exception: (id)exception;
@end
@implementation SSLSocket_ConnectContext
- (instancetype)initWithHost: (OFString *)host
port: (uint16_t)port
target: (id)target
selector: (SEL)selector
context: (id)context
{
self = [super init];
@try {
_host = [host copy];
_port = port;
_target = [target retain];
_selector = selector;
_context = [context retain];
} @catch (id e) {
[self release];
@throw e;
}
return self;
}
- (void)dealloc
{
[_host release];
[_target release];
[_context release];
[super dealloc];
}
- (void)socketDidConnect: (SSLSocket *)sock
context: (id)context
exception: (id)exception
{
void (*func)(id, SEL, OFTCPSocket *, id, id) =
(void (*)(id, SEL, OFTCPSocket *, id, id))
[_target methodForSelector: _selector];
if (exception == nil) {
@try {
[sock SSL_startTLSWithExpectedHost: _host
port: _port];
} @catch (id e) {
func(_target, _selector, sock, _context, e);
return;
}
}
func(_target, _selector, sock, _context, exception);
}
@end
@implementation SSLSocket @implementation SSLSocket
@synthesize delegate = _delegate, certificateFile = _certificateFile; @synthesize delegate = _delegate, certificateFile = _certificateFile;
@synthesize privateKeyFile = _privateKeyFile; @synthesize privateKeyFile = _privateKeyFile;
@ -281,16 +356,58 @@ locking_callback(int mode, int n, const char *file, int line)
port: 0]; port: 0];
} }
- (void)connectToHost: (OFString *)host - (void)asyncConnectToHost: (OFString *)host
port: (uint16_t)port port: (uint16_t)port
runLoopMode: (of_run_loop_mode_t)runLoopMode
target: (id)target
selector: (SEL)selector
context: (id)userContext
{ {
[super connectToHost: host void *pool = objc_autoreleasePoolPush();
port: port]; SSLSocket_ConnectContext *context;
[self SSL_startTLSWithExpectedHost: host context = [[[SSLSocket_ConnectContext alloc]
port: port]; initWithHost: host
port: port
target: target
selector: selector
context: userContext] autorelease];
[super asyncConnectToHost: host
port: port
runLoopMode: runLoopMode
target: context
selector: @selector(socketDidConnect:context:
exception:)
context: nil];
objc_autoreleasePoolPop(pool);
} }
#ifdef OF_HAVE_BLOCKS
- (void)asyncConnectToHost: (OFString *)host
port: (uint16_t)port
runLoopMode: (of_run_loop_mode_t)runLoopMode
block: (of_tcp_socket_async_connect_block_t)block
{
[super asyncConnectToHost: host
port: port
runLoopMode: runLoopMode
block: ^ (SSLSocket *sock, id exception) {
if (exception == nil) {
@try {
[sock SSL_startTLSWithExpectedHost: host
port: port];
} @catch (id e) {
block(sock, e);
return;
}
}
block(sock, exception);
}];
}
#endif
- (instancetype)accept - (instancetype)accept
{ {
SSLSocket *client = (SSLSocket *)[super accept]; SSLSocket *client = (SSLSocket *)[super accept];