react-native-tcp/ios/TcpSocketClient.m

170 lines
4.5 KiB
Mathematica
Raw Normal View History

//
// TcpSocketClient.m
// react-native-tcp
//
// Created by Andy Prock on 12/14/15.
// Copyright (c) 2015 peel, Inc. All rights reserved.
//
#import <netinet/in.h>
#import <arpa/inet.h>
#import "TcpSocketClient.h"
#import "RCTBridgeModule.h"
#import "GCDAsyncSocket.h"
2015-12-07 19:45:33 +00:00
NSString *const RCTTCPErrorDomain = @"RCTTCPErrorDomain";
@interface TcpSocketClient()
{
@private
GCDAsyncSocket *_tcpSocket;
id<SocketClientDelegate> _clientDelegate;
2015-12-16 23:05:08 +00:00
NSMutableDictionary<NSNumber *, RCTResponseSenderBlock> *_pendingSends;
2015-12-15 00:16:45 +00:00
long _sendTag;
}
- (id)initWithConfig:(id<SocketClientDelegate>) aDelegate;
@end
@implementation TcpSocketClient
+ (id)socketClientWithConfig:(id<SocketClientDelegate>)delegate
{
return [[[self class] alloc] initWithConfig:delegate];
}
- (id)initWithConfig:(id<SocketClientDelegate>) aDelegate
{
self = [super init];
if (self) {
_clientDelegate = aDelegate;
_pendingSends = [NSMutableDictionary dictionary];
}
return self;
}
2015-12-15 00:16:45 +00:00
- (BOOL)connect:(NSString *)host port:(int)port withOptions:(NSDictionary *)options error:(NSError **)error
{
2015-12-15 00:16:45 +00:00
if (_tcpSocket) {
if (error) {
*error = [self badInvocationError:@"this client's socket is already connected"];
}
return false;
}
_tcpSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:[self methodQueue]];
2015-12-15 00:16:45 +00:00
BOOL result = false;
NSString *localAddress = (options?options[@"localAddress"]:nil);
NSNumber *localPort = (options?options[@"localPort"]:nil);
if (!localAddress && !localPort) {
result = [_tcpSocket connectToHost:host onPort:port error:error];
} else {
NSMutableArray *interface = [NSMutableArray arrayWithCapacity:2];
[interface addObject: localAddress?localAddress:@""];
if (localPort) {
[interface addObject:[localPort stringValue]];
}
result = [_tcpSocket connectToHost:host
onPort:port
viaInterface:[interface componentsJoinedByString:@":"]
withTimeout:-1
error:error];
}
return result;
}
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)msgTag
{
NSNumber* tagNum = [NSNumber numberWithLong:msgTag];
RCTResponseSenderBlock callback = [_pendingSends objectForKey:tagNum];
if (callback) {
callback(@[]);
[_pendingSends removeObjectForKey:tagNum];
}
}
- (void) writeData:(NSData *)data
callback:(RCTResponseSenderBlock)callback
{
2015-12-15 00:16:45 +00:00
[_tcpSocket writeData:data withTimeout:-1 tag:_sendTag];
if (callback) {
2015-12-15 00:16:45 +00:00
[_pendingSends setObject:callback forKey:[NSNumber numberWithLong:_sendTag]];
}
2015-12-15 00:16:45 +00:00
_sendTag++;
[_tcpSocket readDataWithTimeout:-1 tag:-1];
}
2015-12-15 00:16:45 +00:00
- (void)end
{
[_tcpSocket disconnectAfterReadingAndWriting];
}
2015-12-15 00:16:45 +00:00
- (void)destroy
{
[_tcpSocket disconnect];
}
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
if (!_clientDelegate) return;
[_clientDelegate onData:self data:data];
2015-12-15 00:16:45 +00:00
[sock readDataWithTimeout:-1 tag:-1];
}
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
[sock readDataWithTimeout:-1 tag:-1];
}
2015-12-15 00:16:45 +00:00
- (void)socketDidCloseReadStream:(GCDAsyncSocket *)sock
{
}
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
if (!_clientDelegate) return;
[_clientDelegate onClose:self withError:err];
}
- (NSError *)badParamError:(NSString *)errMsg
{
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
2015-12-07 19:45:33 +00:00
return [NSError errorWithDomain:RCTTCPErrorDomain
code:RCTTCPBadParamError
userInfo:userInfo];
}
- (NSError *)badInvocationError:(NSString *)errMsg
{
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
2015-12-07 19:45:33 +00:00
return [NSError errorWithDomain:RCTTCPErrorDomain
code:RCTTCPInvalidInvocationError
userInfo:userInfo];
}
- (NSError *)sendFailedError:(NSString *)errMsg
{
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
2015-12-07 19:45:33 +00:00
return [NSError errorWithDomain:RCTTCPErrorDomain
code:RCTTCPSendFailedError
userInfo:userInfo];
}
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
@end