Mon 21 Jul 22:43:21 CEST 2025
This commit is contained in:
parent
6f55d53b70
commit
f864e27e47
|
@ -0,0 +1,735 @@
|
|||
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import "ChromeSocketsTcp.h"
|
||||
#import "GCDAsyncSocket.h"
|
||||
|
||||
#ifndef CHROME_SOCKETS_TCP_VERBOSE_LOGGING
|
||||
#define CHROME_SOCKETS_TCP_VERBOSE_LOGGING 0
|
||||
#endif
|
||||
|
||||
#if CHROME_SOCKETS_TCP_VERBOSE_LOGGING
|
||||
#define VERBOSE_LOG NSLog
|
||||
#else
|
||||
#define VERBOSE_LOG(args...) do {} while (false)
|
||||
#endif
|
||||
|
||||
#if CHROME_SOCKETS_TCP_VERBOSE_LOGGING
|
||||
static NSString* stringFromData(NSData* data) {
|
||||
NSUInteger len = [data length];
|
||||
if (len > 200) {
|
||||
len = 200;
|
||||
}
|
||||
char* buf = (char*)malloc(len + 1);
|
||||
memcpy(buf, [data bytes], len);
|
||||
buf[len] = 0;
|
||||
NSString* ret = [NSString stringWithUTF8String:buf];
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
#endif // CHROME_SOCKETS_TCP_VERBOSE_LOGGING
|
||||
|
||||
#pragma mark ChromeSocketsTcpSocket interface
|
||||
|
||||
@interface ChromeSocketsTcpSocket : NSObject {
|
||||
@public
|
||||
__weak ChromeSocketsTcp* _plugin;
|
||||
|
||||
NSUInteger _socketId;
|
||||
NSNumber* _persistent;
|
||||
NSString* _name;
|
||||
NSNumber* _bufferSize;
|
||||
|
||||
// pipeToFile options
|
||||
NSNumber* _append;
|
||||
NSString* _uri;
|
||||
NSFileHandle* _uriFileHandle;
|
||||
NSInteger _numBytes;
|
||||
id _pipeToFileCompleteCallback;
|
||||
long _bytesReadNotSend;
|
||||
NSTimeInterval _lastProgressTimestamp;
|
||||
|
||||
NSUInteger _readTag;
|
||||
NSUInteger _receivedTag;
|
||||
|
||||
NSNumber* _paused;
|
||||
NSMutableArray* _pausedBuffers;
|
||||
|
||||
GCDAsyncSocket* _socket;
|
||||
|
||||
NSMutableArray* _sendCallbacks;
|
||||
|
||||
id _connectCallback;
|
||||
id _disconnectCallback;
|
||||
id _secureCallback;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark ChromeSocketsTcp interface
|
||||
|
||||
@interface ChromeSocketsTcp() {
|
||||
NSMutableDictionary* _sockets;
|
||||
NSUInteger _nextSocketId;
|
||||
NSString* _receiveEventsCallbackId;
|
||||
|
||||
@public
|
||||
NSInteger _pendingReceive;
|
||||
}
|
||||
|
||||
- (void)create:(CDVInvokedUrlCommand*)command;
|
||||
- (void)update:(CDVInvokedUrlCommand*)command;
|
||||
- (void)setPaused:(CDVInvokedUrlCommand*)command;
|
||||
// - (void)setKeepAlive:(CDVInvokedUrlCommand*)command;
|
||||
// - (void)setNoDelay:(CDVInvokedUrlCommand*)command;
|
||||
- (void)connect:(CDVInvokedUrlCommand*)command;
|
||||
- (void)disconnect:(CDVInvokedUrlCommand*)command;
|
||||
- (void)secure:(CDVInvokedUrlCommand*)command;
|
||||
- (void)send:(CDVInvokedUrlCommand*)command;
|
||||
- (void)close:(CDVInvokedUrlCommand*)command;
|
||||
- (void)getInfo:(CDVInvokedUrlCommand*)command;
|
||||
- (void)getSockets:(CDVInvokedUrlCommand*)command;
|
||||
- (void)pipeToFile:(CDVInvokedUrlCommand*)command;
|
||||
- (void)registerReceiveEvents:(CDVInvokedUrlCommand*)command;
|
||||
- (void)readyToRead:(CDVInvokedUrlCommand*)command;
|
||||
- (void)fireReceiveEventsWithSocketId:(NSUInteger)theSocketId data:(NSData*)theData;
|
||||
- (void)fireReceiveEventsWithInfo:(NSDictionary*)theInfo waitReadyToRead:(BOOL)waitReadyToRead;
|
||||
- (void)fireReceiveErrorEventsWithSocketId:(NSUInteger)theSocketId errorCode:(NSUInteger)theErrorCode message:(NSString*)theMessage;
|
||||
@end
|
||||
|
||||
@implementation ChromeSocketsTcpSocket
|
||||
|
||||
NSTimeInterval const PIPE_TO_FILE_PROGRESS_INTERVAL = 0.1;
|
||||
|
||||
- (ChromeSocketsTcpSocket*)initWithId:(NSUInteger)theSocketId plugin:(ChromeSocketsTcp*)thePlugin properties:(NSDictionary*)theProperties
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_socketId = theSocketId;
|
||||
_plugin = thePlugin;
|
||||
_paused = [NSNumber numberWithBool:NO];
|
||||
_socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
|
||||
[self resetSocket];
|
||||
[self setProperties:theProperties];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (ChromeSocketsTcpSocket*)initAcceptedSocketWithId:(NSUInteger)theSocketId plugin:(ChromeSocketsTcp*)thePlugin socket:(GCDAsyncSocket*)theSocket
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_socketId = theSocketId;
|
||||
_plugin = thePlugin;
|
||||
_socket = theSocket;
|
||||
[_socket setDelegate:self];
|
||||
_paused = [NSNumber numberWithBool:YES];
|
||||
[self resetSocket];
|
||||
[self setProperties:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)resetSocket
|
||||
{
|
||||
_readTag = 0;
|
||||
_receivedTag = 0;
|
||||
_pausedBuffers = [NSMutableArray array];
|
||||
_sendCallbacks = [NSMutableArray array];
|
||||
_connectCallback = nil;
|
||||
_disconnectCallback = nil;
|
||||
_secureCallback = nil;
|
||||
[self resetPipeToFileProperties];
|
||||
}
|
||||
|
||||
- (void)resetPipeToFileProperties
|
||||
{
|
||||
if (_uriFileHandle) {
|
||||
[_uriFileHandle closeFile];
|
||||
_uriFileHandle = nil;
|
||||
_uri = nil;
|
||||
}
|
||||
_append = nil;
|
||||
_pipeToFileCompleteCallback = nil;
|
||||
_numBytes = 0;
|
||||
_bytesReadNotSend = 0;
|
||||
}
|
||||
|
||||
- (NSDictionary*)getInfo
|
||||
{
|
||||
NSString* localAddress = [_socket localHost];
|
||||
NSNumber* localPort = [NSNumber numberWithUnsignedInt:[_socket localPort]];
|
||||
NSString* peerAddress = [_socket connectedHost];
|
||||
NSNumber* peerPort = [NSNumber numberWithUnsignedInt:[_socket connectedPort]];
|
||||
|
||||
NSMutableDictionary* socketInfo = [@{
|
||||
@"socketId": [NSNumber numberWithUnsignedInteger:_socketId],
|
||||
@"persistent": _persistent,
|
||||
@"name": _name,
|
||||
@"bufferSize": _bufferSize,
|
||||
@"connected": [NSNumber numberWithBool:[_socket isConnected]],
|
||||
@"paused": _paused,
|
||||
} mutableCopy];
|
||||
|
||||
if (localAddress) {
|
||||
socketInfo[@"localAddress"] = localAddress;
|
||||
socketInfo[@"localPort"] = localPort;
|
||||
}
|
||||
|
||||
if (peerAddress) {
|
||||
socketInfo[@"peerAddress"] = peerAddress;
|
||||
socketInfo[@"peerPort"] = peerPort;
|
||||
}
|
||||
|
||||
|
||||
return [socketInfo copy];
|
||||
}
|
||||
|
||||
- (void)setProperties:(NSDictionary*)theProperties
|
||||
{
|
||||
NSNumber* persistent = theProperties[@"persistent"];
|
||||
NSString* name = theProperties[@"name"];
|
||||
NSNumber* bufferSize = theProperties[@"bufferSize"];
|
||||
|
||||
if (persistent)
|
||||
_persistent = persistent;
|
||||
|
||||
if (name)
|
||||
_name = name;
|
||||
|
||||
if (bufferSize && _bufferSize == 0 && ![_paused boolValue]) // read delegate method won't be called when _bufferSize == 0
|
||||
[_socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:[bufferSize unsignedIntegerValue] tag:++_readTag];
|
||||
|
||||
if (bufferSize)
|
||||
_bufferSize = bufferSize;
|
||||
|
||||
// Set undefined properties to default value
|
||||
if (_persistent == nil)
|
||||
_persistent = [NSNumber numberWithBool:NO];
|
||||
|
||||
if (_name == nil)
|
||||
_name = @"";
|
||||
|
||||
if (_bufferSize == nil)
|
||||
_bufferSize = [NSNumber numberWithUnsignedInteger:4096];
|
||||
}
|
||||
|
||||
- (BOOL)setPipeToFileProperties:(NSDictionary*)theProperties
|
||||
{
|
||||
NSNumber* append = theProperties[@"append"];
|
||||
NSNumber* numBytes = theProperties[@"numBytes"];
|
||||
NSString* uri = theProperties[@"uri"];
|
||||
|
||||
[self resetPipeToFileProperties];
|
||||
|
||||
if (append) {
|
||||
_append = append;
|
||||
} else {
|
||||
_append = [NSNumber numberWithBool:NO];
|
||||
}
|
||||
|
||||
if (numBytes && [numBytes integerValue] > 0) {
|
||||
_numBytes = [numBytes integerValue];
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (uri && uri.length > 0) {
|
||||
NSString* filePath = [[NSURL URLWithString:uri] path];
|
||||
|
||||
if(![NSFileManager.defaultManager fileExistsAtPath:filePath]) {
|
||||
[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
|
||||
}
|
||||
|
||||
_uriFileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
|
||||
|
||||
if (append.boolValue) {
|
||||
[_uriFileHandle seekToEndOfFile];
|
||||
}
|
||||
|
||||
if (_uriFileHandle) {
|
||||
_uri = uri;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
|
||||
_lastProgressTimestamp = [[NSDate date] timeIntervalSince1970];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)resumeReadIfNotReading
|
||||
{
|
||||
if (_readTag == _receivedTag && _plugin->_pendingReceive == 0 && [_socket isConnected] && ![_paused boolValue]) {
|
||||
[_socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:[_bufferSize unsignedIntegerValue] tag:++_readTag];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setPaused:(NSNumber*)paused
|
||||
{
|
||||
if (![_paused isEqualToNumber:paused]) {
|
||||
_paused = paused;
|
||||
if (![_paused boolValue]) {
|
||||
for (NSData* data in _pausedBuffers) {
|
||||
[self sendReceivedData:data];
|
||||
}
|
||||
[_pausedBuffers removeAllObjects];
|
||||
[self resumeReadIfNotReading];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sendReceivedData:(NSData*)data
|
||||
{
|
||||
if (_uriFileHandle) {
|
||||
|
||||
NSUInteger bytesRead = 0;
|
||||
|
||||
// extra data that need to send to the webveiw
|
||||
NSData* extraData = nil;
|
||||
|
||||
if (_numBytes >= [data length]) {
|
||||
[_uriFileHandle writeData:data];
|
||||
bytesRead = data.length;
|
||||
} else {
|
||||
NSData* writeData = [data subdataWithRange:NSMakeRange(0, _numBytes)];
|
||||
extraData = [data subdataWithRange:NSMakeRange(_numBytes, data.length - _numBytes)];
|
||||
[_uriFileHandle writeData:writeData];
|
||||
bytesRead = writeData.length;
|
||||
}
|
||||
|
||||
_numBytes -= bytesRead;
|
||||
|
||||
NSTimeInterval timestamp = [[NSDate date] timeIntervalSince1970];
|
||||
|
||||
_bytesReadNotSend += bytesRead;
|
||||
if (_numBytes == 0 || timestamp - _lastProgressTimestamp > PIPE_TO_FILE_PROGRESS_INTERVAL) {
|
||||
NSDictionary *info = @{
|
||||
@"socketId": [NSNumber numberWithUnsignedInteger:_socketId],
|
||||
@"uri": _uri,
|
||||
@"bytesRead": [NSNumber numberWithUnsignedInteger:_bytesReadNotSend],
|
||||
};
|
||||
|
||||
[_plugin fireReceiveEventsWithInfo:info waitReadyToRead:NO];
|
||||
_bytesReadNotSend = 0;
|
||||
_lastProgressTimestamp = timestamp;
|
||||
}
|
||||
|
||||
if (_numBytes == 0) {
|
||||
void (^callback)() = _pipeToFileCompleteCallback;
|
||||
[self resetPipeToFileProperties];
|
||||
assert(callback != nil);
|
||||
callback();
|
||||
}
|
||||
|
||||
if (extraData) {
|
||||
[_plugin fireReceiveEventsWithSocketId:_socketId data:extraData];
|
||||
} else {
|
||||
[self resumeReadIfNotReading];
|
||||
}
|
||||
|
||||
} else {
|
||||
[_plugin fireReceiveEventsWithSocketId:_socketId data:data];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
|
||||
{
|
||||
VERBOSE_LOG(@"socket:didConnectToHost socketId: %u", _socketId);
|
||||
|
||||
void (^callback)(BOOL, NSError*) = _connectCallback;
|
||||
assert(callback != nil);
|
||||
_connectCallback = nil;
|
||||
|
||||
callback(YES, nil);
|
||||
|
||||
if (![_paused boolValue])
|
||||
[_socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:[_bufferSize unsignedIntegerValue] tag:++_readTag];
|
||||
}
|
||||
|
||||
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
|
||||
{
|
||||
VERBOSE_LOG(@"socket:didReadDataWithTag socketId: %u", _socketId);
|
||||
|
||||
_receivedTag = tag;
|
||||
|
||||
if ([_paused boolValue]) {
|
||||
[_pausedBuffers addObject:data];
|
||||
} else {
|
||||
[self sendReceivedData:data];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
|
||||
{
|
||||
assert([_sendCallbacks count] != 0);
|
||||
void (^callback)() = _sendCallbacks[0];
|
||||
assert(callback != nil);
|
||||
[_sendCallbacks removeObjectAtIndex:0];
|
||||
|
||||
callback();
|
||||
|
||||
[_socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:[_bufferSize unsignedIntegerValue] tag:-1];
|
||||
}
|
||||
|
||||
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
|
||||
{
|
||||
if (_disconnectCallback) {
|
||||
void (^callback)() = _disconnectCallback;
|
||||
assert(_disconnectCallback != nil);
|
||||
_disconnectCallback = nil;
|
||||
callback();
|
||||
} else if (_connectCallback) {
|
||||
void(^callback)(BOOL, NSError*) = _connectCallback;
|
||||
callback(NO, err);
|
||||
_connectCallback = nil;
|
||||
} else if (err) {
|
||||
[_plugin fireReceiveErrorEventsWithSocketId:_socketId errorCode:[err code] message:[err localizedDescription]];
|
||||
}
|
||||
|
||||
[self resetSocket];
|
||||
}
|
||||
|
||||
- (void)socketDidSecure:(GCDAsyncSocket *)sock
|
||||
{
|
||||
VERBOSE_LOG(@"socketDidSecure socketId: %u", _socketId);
|
||||
|
||||
assert(_secureCallback != nil);
|
||||
void (^callback)() = _secureCallback;
|
||||
_secureCallback = nil;
|
||||
callback();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ChromeSocketsTcp
|
||||
|
||||
- (void)pluginInitialize
|
||||
{
|
||||
_sockets = [NSMutableDictionary dictionary];
|
||||
_nextSocketId = 1;
|
||||
_receiveEventsCallbackId = nil;
|
||||
_pendingReceive = 0;
|
||||
}
|
||||
|
||||
- (void)onReset
|
||||
{
|
||||
for (NSNumber* socketId in _sockets) {
|
||||
[self closeSocketWithId:socketId callbackId:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary*)buildErrorInfoWithErrorCode:(NSInteger)theErrorCode message:(NSString*)message
|
||||
{
|
||||
return @{
|
||||
@"resultCode": [NSNumber numberWithInteger:theErrorCode],
|
||||
@"message": message,
|
||||
};
|
||||
}
|
||||
|
||||
- (void)create:(CDVInvokedUrlCommand*)command
|
||||
{
|
||||
NSDictionary* properties = [command argumentAtIndex:0];
|
||||
|
||||
ChromeSocketsTcpSocket* socket = [[ChromeSocketsTcpSocket alloc] initWithId:_nextSocketId++ plugin:self properties:properties];
|
||||
|
||||
_sockets[[NSNumber numberWithUnsignedInteger:socket->_socketId]] = socket;
|
||||
|
||||
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(int)socket->_socketId] callbackId:command.callbackId];
|
||||
}
|
||||
|
||||
- (void)update:(CDVInvokedUrlCommand*)command
|
||||
{
|
||||
NSNumber* socketId = [command argumentAtIndex:0];
|
||||
NSDictionary* properties = [command argumentAtIndex:1];
|
||||
|
||||
ChromeSocketsTcpSocket *socket = _sockets[socketId];
|
||||
|
||||
if (socket == nil)
|
||||
return;
|
||||
|
||||
[socket setProperties:properties];
|
||||
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] callbackId:command.callbackId];
|
||||
}
|
||||
|
||||
- (void)setPaused:(CDVInvokedUrlCommand*)command
|
||||
{
|
||||
NSNumber* socketId = [command argumentAtIndex:0];
|
||||
NSNumber* paused = [command argumentAtIndex:1];
|
||||
|
||||
ChromeSocketsTcpSocket* socket = _sockets[socketId];
|
||||
|
||||
if (socket == nil)
|
||||
return;
|
||||
|
||||
[socket setPaused:paused];
|
||||
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] callbackId:command.callbackId];
|
||||
}
|
||||
|
||||
- (void)connect:(CDVInvokedUrlCommand*)command
|
||||
{
|
||||
NSNumber* socketId = [command argumentAtIndex:0];
|
||||
NSString* peerAddress = [command argumentAtIndex:1];
|
||||
|
||||
NSUInteger peerPort = [[command argumentAtIndex:2] unsignedIntegerValue];
|
||||
|
||||
ChromeSocketsTcpSocket* socket = _sockets[socketId];
|
||||
|
||||
if (socket == nil) {
|
||||
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self buildErrorInfoWithErrorCode:ENOTSOCK message:@"Invalid Argument"]] callbackId:command.callbackId];
|
||||
return;
|
||||
}
|
||||
|
||||
id<CDVCommandDelegate> commandDelegate = self.commandDelegate;
|
||||
socket->_connectCallback = [^(BOOL success, NSError* error) {
|
||||
if (success) {
|
||||
[commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] callbackId:command.callbackId];
|
||||
} else {
|
||||
[commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self buildErrorInfoWithErrorCode:[error code] message:[error localizedDescription]]] callbackId:command.callbackId];
|
||||
}
|
||||
} copy];
|
||||
|
||||
NSError* err = nil;
|
||||
BOOL success = [socket->_socket connectToHost:peerAddress onPort:peerPort withTimeout:2 error:&err];
|
||||
|
||||
if (!success) {
|
||||
void(^callback)(BOOL, NSError*) = socket->_connectCallback;
|
||||
callback(NO, err);
|
||||
socket->_connectCallback = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)disconnectSocketWithId:(NSNumber*)socketId callbackId:(NSString*)theCallbackId close:(BOOL)close
|
||||
{
|
||||
ChromeSocketsTcpSocket* socket = _sockets[socketId];
|
||||
|
||||
if (socket == nil)
|
||||
return;
|
||||
|
||||
id<CDVCommandDelegate> commandDelegate = self.commandDelegate;
|
||||
socket->_disconnectCallback = [^(){
|
||||
if (theCallbackId)
|
||||
[commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] callbackId:theCallbackId];
|
||||
if (close)
|
||||
[_sockets removeObjectForKey:socketId];
|
||||
} copy];
|
||||
|
||||
if ([socket->_socket isDisconnected]) {
|
||||
void (^callback)() = socket->_disconnectCallback;
|
||||
socket->_disconnectCallback = nil;
|
||||
callback();
|
||||
} else {
|
||||
[socket->_socket disconnect];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)disconnect:(CDVInvokedUrlCommand*)command
|
||||
{
|
||||
NSNumber* socketId = [command argumentAtIndex:0];
|
||||
[self disconnectSocketWithId:socketId callbackId:command.callbackId close:NO];
|
||||
}
|
||||
|
||||
- (NSNumber*)getSecureVersion:(NSString*)versionString
|
||||
{
|
||||
if ([versionString isEqualToString:@"ssl3"]) {
|
||||
return [NSNumber numberWithInt:kSSLProtocol3];
|
||||
} else if ([versionString isEqualToString:@"tls1"]) {
|
||||
return [NSNumber numberWithInt:kTLSProtocol1];
|
||||
} else if ([versionString isEqualToString:@"tls1.1"]) {
|
||||
return [NSNumber numberWithInt:kTLSProtocol11];
|
||||
} else if ([versionString isEqualToString:@"tls1.2"]) {
|
||||
return [NSNumber numberWithInt:kTLSProtocol12];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)secure:(CDVInvokedUrlCommand *)command
|
||||
{
|
||||
NSNumber* socketId = [command argumentAtIndex:0];
|
||||
NSDictionary* options = [command argumentAtIndex:1];
|
||||
|
||||
ChromeSocketsTcpSocket* socket = _sockets[socketId];
|
||||
|
||||
if (socket == nil) {
|
||||
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self buildErrorInfoWithErrorCode:ENOTSOCK message:@"Invalid Argument"]] callbackId:command.callbackId];
|
||||
return;
|
||||
}
|
||||
|
||||
id<CDVCommandDelegate> commandDelegate = self.commandDelegate;
|
||||
socket->_secureCallback = [^() {
|
||||
[commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] callbackId:command.callbackId];
|
||||
} copy];
|
||||
|
||||
NSMutableDictionary* settings = [NSMutableDictionary dictionaryWithCapacity:2];
|
||||
|
||||
NSDictionary* tlsVersion = options[@"tlsVersion"];
|
||||
if (tlsVersion) {
|
||||
NSNumber* minVersion = [self getSecureVersion:tlsVersion[@"min"]];
|
||||
NSNumber* maxVersion = [self getSecureVersion:tlsVersion[@"max"]];
|
||||
|
||||
if (minVersion) {
|
||||
settings[GCDAsyncSocketSSLProtocolVersionMin] = minVersion;
|
||||
}
|
||||
|
||||
if (maxVersion) {
|
||||
settings[GCDAsyncSocketSSLProtocolVersionMax] = maxVersion;
|
||||
}
|
||||
}
|
||||
|
||||
[socket->_socket startTLS:settings];
|
||||
}
|
||||
|
||||
- (void)send:(CDVInvokedUrlCommand*)command
|
||||
{
|
||||
NSNumber* socketId = [command argumentAtIndex:0];
|
||||
NSData* data = [command argumentAtIndex:1];
|
||||
|
||||
ChromeSocketsTcpSocket* socket = _sockets[socketId];
|
||||
|
||||
if (socket == nil) {
|
||||
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self buildErrorInfoWithErrorCode:ENOTSOCK message:@"Invalid Argument"]] callbackId:command.callbackId];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([socket->_socket isConnected]) {
|
||||
id<CDVCommandDelegate> commandDelegate = self.commandDelegate;
|
||||
[socket->_sendCallbacks addObject:[^() {
|
||||
VERBOSE_LOG(@"ACK %@.%@ Write", socketId, command.callbackId);
|
||||
[commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(int)[data length]] callbackId:command.callbackId];
|
||||
} copy]];
|
||||
|
||||
[socket->_socket writeData:data withTimeout:-1 tag:-1];
|
||||
|
||||
} else {
|
||||
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self buildErrorInfoWithErrorCode:ENOTCONN message:@"Socket Not Connected"]] callbackId:command.callbackId];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)closeSocketWithId:(NSNumber*)socketId callbackId:(NSString*)theCallbackId
|
||||
{
|
||||
[self disconnectSocketWithId:socketId callbackId:theCallbackId close:YES];
|
||||
}
|
||||
|
||||
- (void)close:(CDVInvokedUrlCommand*)command
|
||||
{
|
||||
NSNumber* socketId = [command argumentAtIndex:0];
|
||||
[self closeSocketWithId:socketId callbackId:command.callbackId];
|
||||
}
|
||||
|
||||
- (void)getInfo:(CDVInvokedUrlCommand*)command
|
||||
{
|
||||
NSNumber* socketId = [command argumentAtIndex:0];
|
||||
|
||||
ChromeSocketsTcpSocket* socket = _sockets[socketId];
|
||||
|
||||
if (socket == nil)
|
||||
return;
|
||||
|
||||
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[socket getInfo]] callbackId:command.callbackId];
|
||||
}
|
||||
|
||||
- (void)getSockets:(CDVInvokedUrlCommand*)command
|
||||
{
|
||||
NSArray* sockets = [_sockets allValues];
|
||||
NSMutableArray* socketsInfo = [NSMutableArray arrayWithCapacity:[sockets count]];
|
||||
|
||||
for (ChromeSocketsTcpSocket* socket in sockets) {
|
||||
[socketsInfo addObject:[socket getInfo]];
|
||||
}
|
||||
|
||||
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:socketsInfo] callbackId:command.callbackId];
|
||||
}
|
||||
|
||||
- (void)pipeToFile:(CDVInvokedUrlCommand *)command
|
||||
{
|
||||
NSNumber* socketId = [command argumentAtIndex:0];
|
||||
NSDictionary* options = [command argumentAtIndex:1];
|
||||
|
||||
ChromeSocketsTcpSocket* socket = _sockets[socketId];
|
||||
|
||||
if (socket == nil)
|
||||
return;
|
||||
|
||||
if ([socket setPipeToFileProperties:options]) {
|
||||
id<CDVCommandDelegate> commandDelegate = self.commandDelegate;
|
||||
socket->_pipeToFileCompleteCallback = [^() {
|
||||
[commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] callbackId:command.callbackId];
|
||||
} copy];
|
||||
} else {
|
||||
[self fireReceiveErrorEventsWithSocketId:socket->_socketId errorCode:-1000 message:@"Failed to start pipeToFile"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)registerReceiveEvents:(CDVInvokedUrlCommand*)command
|
||||
{
|
||||
VERBOSE_LOG(@"registerReceiveEvents: ");
|
||||
_receiveEventsCallbackId = command.callbackId;
|
||||
}
|
||||
|
||||
- (void)fireReceiveEventsWithSocketId:(NSUInteger)theSocketId data:(NSData*)theData
|
||||
{
|
||||
NSArray* multipart = @[
|
||||
@{@"socketId":[NSNumber numberWithUnsignedInteger:theSocketId]},
|
||||
theData,
|
||||
];
|
||||
[self fireReceiveEventsWithMultiPart:multipart waitReadyToRead:YES];
|
||||
}
|
||||
|
||||
- (void)fireReceiveEventsWithInfo:(NSDictionary*)theInfo waitReadyToRead:(BOOL)waitReadyToRead
|
||||
{
|
||||
[self fireReceiveEventsWithMultiPart:@[theInfo] waitReadyToRead:waitReadyToRead];
|
||||
}
|
||||
|
||||
- (void)fireReceiveEventsWithMultiPart:(NSArray*)theMultiPart waitReadyToRead:(BOOL)waitReadyToRead
|
||||
{
|
||||
assert(_receiveEventsCallbackId != nil);
|
||||
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsMultipart:theMultiPart];
|
||||
[result setKeepCallbackAsBool:YES];
|
||||
if (waitReadyToRead) {
|
||||
_pendingReceive++;
|
||||
}
|
||||
[self.commandDelegate sendPluginResult:result callbackId:_receiveEventsCallbackId];
|
||||
}
|
||||
|
||||
- (void)fireReceiveErrorEventsWithSocketId:(NSUInteger)theSocketId errorCode:(NSUInteger)theErrorCode message:(NSString*)theMessage
|
||||
{
|
||||
assert(_receiveEventsCallbackId != nil);
|
||||
|
||||
NSDictionary* info = @{
|
||||
@"socketId": [NSNumber numberWithUnsignedInteger:theSocketId],
|
||||
@"resultCode": [NSNumber numberWithUnsignedInteger:theErrorCode],
|
||||
@"message": theMessage,
|
||||
};
|
||||
|
||||
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:info];
|
||||
[result setKeepCallbackAsBool:YES];
|
||||
|
||||
[self.commandDelegate sendPluginResult:result callbackId:_receiveEventsCallbackId];
|
||||
}
|
||||
|
||||
- (NSUInteger)registerAcceptedSocket:(GCDAsyncSocket*)theSocket
|
||||
{
|
||||
ChromeSocketsTcpSocket* socket = [[ChromeSocketsTcpSocket alloc] initAcceptedSocketWithId:_nextSocketId++ plugin:self socket:theSocket];
|
||||
_sockets[[NSNumber numberWithUnsignedInteger:socket->_socketId]] = socket;
|
||||
|
||||
[socket setPaused:[NSNumber numberWithBool:YES]];
|
||||
|
||||
return socket->_socketId;
|
||||
}
|
||||
|
||||
- (void)readyToRead:(CDVInvokedUrlCommand*)command
|
||||
{
|
||||
_pendingReceive--;
|
||||
if (_pendingReceive == 0) {
|
||||
for (ChromeSocketsTcpSocket* socket in [_sockets allValues]) {
|
||||
[socket resumeReadIfNotReading];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue
Block a user