diff --git a/lib/src/Data/DC.dart b/lib/src/Data/DC.dart index b2633e6..86c944d 100644 --- a/lib/src/Data/DC.dart +++ b/lib/src/Data/DC.dart @@ -20,12 +20,15 @@ * SOFTWARE. */ + import 'dart:typed_data'; import 'dart:convert'; import 'BinaryList.dart'; import 'dart:collection'; import 'Guid.dart'; +const bool kIsWeb = identical(0, 0.0); + /** * Created by Ahmed Zamil on 6/10/2019. */ @@ -245,8 +248,9 @@ class DC with IterableMixin { var list = new BinaryList(); for (var i = 0; i < value.length; i++) { var s = DC.stringToBytes(value[i]); - list..addUint32(s.length) - ..addUint8Array(s.toArray()); + list + ..addUint32(s.length) + ..addUint8Array(s.toArray()); } return list.toDC(); @@ -386,12 +390,26 @@ class DC with IterableMixin { return _data.buffer.asFloat64List(offset, length); } - Int64List getInt64Array(int offset, int length) { - return _data.buffer.asInt64List(offset, length); + //Int64List + getInt64Array(int offset, int length) { + if (kIsWeb) { + var rt = []; + for (var i = offset; i < length; i += 4) rt.add(this.getInt64(offset)); + return rt; + } else { + return _data.buffer.asInt64List(offset, length); + } } - Uint64List getUint64Array(int offset, int length) { - return _data.buffer.asUint64List(offset, length); + //Uint64List + getUint64Array(int offset, int length) { + if (kIsWeb) { + var rt = []; + for (var i = offset; i < length; i += 4) rt.add(this.getUint64(offset)); + return rt; + } else { + return _data.buffer.asUint64List(offset, length); + } } bool getBoolean(int offset) { @@ -464,11 +482,23 @@ class DC with IterableMixin { } int getInt64(offset) { - return _dv.getUint64(offset); + if (kIsWeb) { + var h = this.getUint32(offset); + var l = this.getUint32(offset + 4); + return h * TWO_PWR_32 + ((l >= 0) ? l : TWO_PWR_32 + l); + } else { + return _dv.getUint64(offset); + } } int getUint64(offset) { - return _dv.getInt64(offset); + if (kIsWeb) { + var h = this.getUint32(offset); + var l = this.getUint32(offset + 4); + return h * TWO_PWR_32 + ((l >= 0) ? l : TWO_PWR_32 + l); + } else { + return _dv.getInt64(offset); + } } void setInt64(offset, value) { @@ -476,7 +506,14 @@ class DC with IterableMixin { } void setUint64(offset, value) { - _dv.setUint64(offset, value); + if (kIsWeb) { + var l = (value % TWO_PWR_32) | 0; + var h = (value / TWO_PWR_32) | 0; + _dv.setInt32(offset, h); + _dv.setInt32(offset + 4, l); + } else { + _dv.setUint64(offset, value); + } } void setDateTime(offset, DateTime value) { diff --git a/lib/src/Net/IIP/DistributedConnection.dart b/lib/src/Net/IIP/DistributedConnection.dart index b15005f..ed9fd69 100644 --- a/lib/src/Net/IIP/DistributedConnection.dart +++ b/lib/src/Net/IIP/DistributedConnection.dart @@ -267,7 +267,7 @@ class DistributedConnection extends NetworkConnection with IStore { throw AsyncException(ErrorType.Exception, 0, "Session not initialized"); if (socket == null) { - if (useWebsocket) { + if (useWebsocket || kIsWeb) { socket = new WSocket()..secure = secureWebSocket; } else socket = new TCPSocket(); @@ -2381,7 +2381,7 @@ class DistributedConnection extends NetworkConnection with IStore { // @TODO: Generator code DistributedResource dr; - if (resource == null) { + if (resource == null) { var template = Warehouse.getTemplateByClassId(rt[0], TemplateType.Wrapper); if (template?.definedType != null) { diff --git a/lib/src/Net/Sockets/WSocket.dart b/lib/src/Net/Sockets/WSocket.dart index 509abc8..e7c5f8b 100644 --- a/lib/src/Net/Sockets/WSocket.dart +++ b/lib/src/Net/Sockets/WSocket.dart @@ -22,10 +22,8 @@ SOFTWARE. */ -import 'dart:io'; - -//import 'package:web_socket_channel/io.dart' as WS; -import 'package:web_socket_channel/io.dart'; +//import 'package:web_socket_channel/html.dart'; +import 'package:web_socket_channel/web_socket_channel.dart'; import '../../Core/ErrorType.dart'; import '../../Core/ExceptionCode.dart'; @@ -40,8 +38,7 @@ import 'IPEndPoint.dart'; import '../../Core/AsyncReply.dart'; class WSocket extends ISocket { - WebSocket? _sock; - IOWebSocketChannel? _channel; + WebSocketChannel? _channel; NetworkBuffer receiveNetworkBuffer = new NetworkBuffer(); @@ -58,16 +55,19 @@ class WSocket extends ISocket { began = true; - if (_sock != null) { - var s = _sock as Socket; - _localEP = IPEndPoint(s.address.rawAddress, s.port); - _remoteEP = IPEndPoint(s.remoteAddress.rawAddress, s.remotePort); + if (_channel != null) { + _localEP = IPEndPoint([0, 0, 0, 0], 0); + _remoteEP = IPEndPoint([0, 0, 0, 0], 0); + _channel?.stream + .listen(_dataHandler, onError: errorHandler, onDone: doneHandler); } + return true; } - void dataHandler(List data) { + void _dataHandler(data) { try { + //List data if (_state == SocketState.Closed || _state == SocketState.Terminated) return; @@ -85,6 +85,7 @@ class WSocket extends ISocket { void errorHandler(error, StackTrace trace) { print(error); + close(); } void doneHandler() { @@ -98,19 +99,15 @@ class WSocket extends ISocket { try { _state = SocketState.Connecting; - WebSocket.connect("${secure ? 'wss' : 'ws'}://${hostname}:${port}'") - .then((s) { - _sock = s; - _state = SocketState.Established; - _channel = IOWebSocketChannel(s); - begin(); - receiver?.networkConnect(this); - rt.trigger(true); - }).catchError((ex) { - close(); - rt.triggerError(AsyncException(ErrorType.Management, - ExceptionCode.HostNotReachable.index, ex.toString())); - }); + _channel = WebSocketChannel.connect( + Uri.parse("${secure ? 'wss' : 'ws'}://${hostname}:${port}"), + ); //binaryType: BinaryType.list); + + _state = SocketState.Established; + + begin(); + receiver?.networkConnect(this); + rt.trigger(true); } catch (ex) { rt.triggerError(AsyncException(ErrorType.Management, ExceptionCode.HostNotReachable.index, ex.toString())); @@ -132,22 +129,19 @@ class WSocket extends ISocket { if (state != SocketState.Closed && state != SocketState.Terminated) _state = SocketState.Closed; - _sock?.close(); - + _channel?.sink.close(); receiver?.networkClose(this); - - //emitArgs("close", []); } void send(DC message, [int? offset, int? size]) { if (state == SocketState.Established) { if (offset != null && size == null) { _channel?.sink - .add(message.clip(offset, message.length - offset).toList()); + .add(message.clip(offset, message.length - offset).toArray()); } else if (offset != null && size != null) { - _channel?.sink.add(message.clip(offset, size).toList()); + _channel?.sink.add(message.clip(offset, size).toArray()); } else { - _channel?.sink.add(message.toList()); + _channel?.sink.add(message.toArray()); } } } diff --git a/lib/src/Net/Sockets/WSocketIO.dart b/lib/src/Net/Sockets/WSocketIO.dart new file mode 100644 index 0000000..856aee5 --- /dev/null +++ b/lib/src/Net/Sockets/WSocketIO.dart @@ -0,0 +1,165 @@ +/* + +Copyright (c) 2019 Ahmed Kh. Zamil + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +import 'dart:io'; + +//import 'package:web_socket_channel/io.dart' as WS; + +import 'package:web_socket_channel/io.dart'; + +import '../../Core/ErrorType.dart'; +import '../../Core/ExceptionCode.dart'; + +import '../../Core/AsyncException.dart'; + +import 'ISocket.dart'; +import '../../Data/DC.dart'; +import '../NetworkBuffer.dart'; +import 'SocketState.dart'; +import 'IPEndPoint.dart'; +import '../../Core/AsyncReply.dart'; + +class WSocketIO extends ISocket { + WebSocket? _sock; + IOWebSocketChannel? _channel; + + NetworkBuffer receiveNetworkBuffer = new NetworkBuffer(); + + bool began = false; + + bool secure = false; + + SocketState _state = SocketState.Initial; + + IPEndPoint? _localEP, _remoteEP; + + bool begin() { + if (began) return false; + + began = true; + + if (_sock != null) { + var s = _sock as Socket; + _localEP = IPEndPoint(s.address.rawAddress, s.port); + _remoteEP = IPEndPoint(s.remoteAddress.rawAddress, s.remotePort); + } + return true; + } + + void dataHandler(List data) { + try { + if (_state == SocketState.Closed || _state == SocketState.Terminated) + return; + + var dc = new DC.fromList(data); + receiveNetworkBuffer.write(dc, 0, dc.length); + receiver?.networkReceive(this, receiveNetworkBuffer); + } catch (ex) { + if (_state != SocketState.Closed) // && !sock.connected) + { + _state = SocketState.Terminated; + close(); + } + } + } + + void errorHandler(error, StackTrace trace) { + print(error); + } + + void doneHandler() { + close(); + //_sock?.destroy(); + } + + AsyncReply connect(String hostname, int port) { + var rt = new AsyncReply(); + + try { + _state = SocketState.Connecting; + + WebSocket.connect("${secure ? 'wss' : 'ws'}://${hostname}:${port}'") + .then((s) { + _sock = s; + _state = SocketState.Established; + _channel = IOWebSocketChannel(s); + begin(); + receiver?.networkConnect(this); + rt.trigger(true); + }).catchError((ex) { + close(); + rt.triggerError(AsyncException(ErrorType.Management, + ExceptionCode.HostNotReachable.index, ex.toString())); + }); + } catch (ex) { + rt.triggerError(AsyncException(ErrorType.Management, + ExceptionCode.HostNotReachable.index, ex.toString())); + } + + return rt; + } + + IPEndPoint? get localEndPoint => _localEP; + IPEndPoint? get remoteEndPoint => _remoteEP; + + SocketState get state => _state; + + TCPSocket() { + // default constructor + } + + void close() { + if (state != SocketState.Closed && state != SocketState.Terminated) + _state = SocketState.Closed; + + _sock?.close(); + + receiver?.networkClose(this); + + //emitArgs("close", []); + } + + void send(DC message, [int? offset, int? size]) { + if (state == SocketState.Established) { + if (offset != null && size == null) { + _channel?.sink + .add(message.clip(offset, message.length - offset).toList()); + } else if (offset != null && size != null) { + _channel?.sink.add(message.clip(offset, size).toList()); + } else { + _channel?.sink.add(message.toList()); + } + } + } + + void destroy() { + close(); + emitArgs("destroy", [this]); + } + + AsyncReply accept() { + var reply = new AsyncReply(); + return reply; + } +} diff --git a/lib/src/Resource/Instance.dart b/lib/src/Resource/Instance.dart index b48fb95..3769258 100644 --- a/lib/src/Resource/Instance.dart +++ b/lib/src/Resource/Instance.dart @@ -1,4 +1,5 @@ import 'dart:core'; + import '../Data/DC.dart'; import '../Data/Structure.dart'; import '../Data/AutoList.dart'; @@ -21,6 +22,9 @@ import './Template/MemberTemplate.dart'; import '../Data/PropertyValue.dart'; import 'Warehouse.dart'; +import '../Core/PropertyModificationInfo.dart'; + + class Instance extends IEventHandler { String _name; @@ -387,7 +391,8 @@ class Instance extends IEventHandler { //_resource.emitArgs("modified", [pt.name, value]); _resource.emitArgs(":${pt.name}", [value]); - _resource.emitProperty(pt.name); + _resource.emitProperty( + PropertyModificationInfo(_resource, pt, value, _instanceAge)); } /// @@ -542,7 +547,7 @@ class Instance extends IEventHandler { if (customTemplate != null) _template = customTemplate; else - _template = Warehouse.getTemplateByType(resource.runtimeType); + _template = Warehouse.getTemplateByType(resource.runtimeType)!; // set ages for (int i = 0; i < _template.properties.length; i++) { diff --git a/lib/src/Resource/Template/TemplateDataType.dart b/lib/src/Resource/Template/TemplateDataType.dart index 5054657..443b02c 100644 --- a/lib/src/Resource/Template/TemplateDataType.dart +++ b/lib/src/Resource/Template/TemplateDataType.dart @@ -1,4 +1,4 @@ -import 'dart:ffi'; +//import 'dart:ffi'; import '../../Data/IRecord.dart'; import '../../Resource/IResource.dart'; @@ -27,31 +27,32 @@ class TemplateDataType { TemplateDataType.fromType(type, bool isArray) { int dt; - if (type == null || type == dynamic) + if (type == null || type == dynamic) { dt = DataType.Void; - else if (type is int) { - dt = type; - } else if (type == bool) + } + // else if (type is int) { + // dt = type; + else if (type == bool) dt = DataType.Bool; - else if (type == Uint8) - dt = DataType.UInt8; - else if (type == Int8) - dt = DataType.Int8; - else if (type == Uint16) - dt = DataType.UInt16; - else if (type == Int16) - dt = DataType.Int16; - else if (type == Uint32) - dt = DataType.UInt32; - else if (type == Int32) - dt = DataType.Int32; - else if (type == Uint64) - dt = DataType.UInt64; - else if (type == Int64 || type == int) + // else if (type == Uint8) + // dt = DataType.UInt8; + // else if (type == Int8) + // dt = DataType.Int8; + // else if (type == Uint16) + // dt = DataType.UInt16; + // else if (type == Int16) + // dt = DataType.Int16; + // else if (type == Uint32) + // dt = DataType.UInt32; + // else if (type == Int32) + // dt = DataType.Int32; + // else if (type == Uint64) + // dt = DataType.UInt64; + else if (/* type == Int64 || */ type == int) dt = DataType.Int64; - else if (type == Float) - dt = DataType.Float32; - else if (type == Double || type == double) + // else if (type == Float) + // dt = DataType.Float32; + else if (/* type == Double || */ type == double) dt = DataType.Float64; else if (type == String) dt = DataType.String; diff --git a/lib/src/Resource/Template/TypeTemplate.dart b/lib/src/Resource/Template/TypeTemplate.dart index b6e49d5..8c80db7 100644 --- a/lib/src/Resource/Template/TypeTemplate.dart +++ b/lib/src/Resource/Template/TypeTemplate.dart @@ -1,4 +1,4 @@ -import 'dart:ffi'; +//import 'dart:ffi'; import '../../Net/IIP/DistributedResource.dart'; diff --git a/lib/src/Resource/Warehouse.dart b/lib/src/Resource/Warehouse.dart index 2af6529..7081f7e 100644 --- a/lib/src/Resource/Warehouse.dart +++ b/lib/src/Resource/Warehouse.dart @@ -482,12 +482,12 @@ class Warehouse { return rt; } - static T createInstance(Type T) { - return _factory[T]?.instanceCreator.call(); + static T createInstance(Type type) { + return _factory[type]?.instanceCreator.call(); } - static List createArray(Type T) { - return _factory[T]?.arrayCreator.call(); + static List createArray(Type type) { + return _factory[type]?.arrayCreator.call(); } static AsyncReply newResource(String name, @@ -546,16 +546,17 @@ class Warehouse { /// /// .Net type. /// Resource template. - static TypeTemplate getTemplateByType(Type type) { + static TypeTemplate? getTemplateByType(Type type) { // loaded ? for (var tmps in _templates.values) for (var tmp in tmps.values) if (tmp.definedType == type) return tmp; - //if (tmp.className == type.toString()) return tmp; - + //try { var template = new TypeTemplate.fromType(type, true); - return template; + //} catch (ex) { + // return null; + //} } /// diff --git a/lib/src/Security/Integrity/SHA256.dart b/lib/src/Security/Integrity/SHA256.dart index 6abbe13..f042ccd 100644 --- a/lib/src/Security/Integrity/SHA256.dart +++ b/lib/src/Security/Integrity/SHA256.dart @@ -137,7 +137,7 @@ class SHA256 { // (The initial values in w[0..63] don't matter, so many implementations zero them here) // copy chunk into first 16 words w[0..15] of the message schedule array - var w = new Uint64List(64); // uint[64]; + var w = new Uint32List(64); // new Uint64List(64); // uint[64]; for (var i = 0; i < 16; i++) w[i] = data.getUint32(chunk + (i * 4)); //for(var i = 16; i < 64; i++)