mirror of
https://github.com/esiur/esiur-dart.git
synced 2025-05-06 04:02:57 +00:00
1.4.5
This commit is contained in:
parent
614c6853e3
commit
eed16df29a
1
.pubignore
Normal file
1
.pubignore
Normal file
@ -0,0 +1 @@
|
||||
test/
|
@ -1,3 +1,9 @@
|
||||
## [1.4.3] - Hotfix
|
||||
Bugfix
|
||||
|
||||
## [1.4.2] - Release
|
||||
Added get-template command
|
||||
|
||||
## [1.2.3] - Release
|
||||
Improved property updating
|
||||
|
||||
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019-2021 Esiur Foundation, Ahmed Kh. Zamil
|
||||
Copyright (c) 2019-2022 Esiur Foundation, 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
|
||||
|
@ -1,47 +1,47 @@
|
||||
import 'package:source_gen/source_gen.dart';
|
||||
import 'package:build/build.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
// import 'package:source_gen/source_gen.dart';
|
||||
// import 'package:build/build.dart';
|
||||
// import 'package:yaml/yaml.dart';
|
||||
|
||||
//Builder iipService(BuilderOptions options) {
|
||||
//return LibraryBuilder(TemplateBuilder(), generatedExtension: '.info.dart');
|
||||
//}
|
||||
// //Builder iipService(BuilderOptions options) {
|
||||
// //return LibraryBuilder(TemplateBuilder(), generatedExtension: '.info.dart');
|
||||
// //}
|
||||
|
||||
class TemplateBuilder implements Builder {
|
||||
//BuilderOptions options;
|
||||
String _fileName;
|
||||
TemplateBuilder([BuilderOptions? options]) : _fileName = _get_dest(options);
|
||||
// class TemplateBuilder implements Builder {
|
||||
// //BuilderOptions options;
|
||||
// String _fileName;
|
||||
// TemplateBuilder([BuilderOptions? options]) : _fileName = _get_dest(options);
|
||||
|
||||
@override
|
||||
Future build(BuildStep buildStep) async {
|
||||
final id = AssetId(buildStep.inputId.package, _fileName);
|
||||
|
||||
// generate
|
||||
var content = "Testing";
|
||||
|
||||
await buildStep.writeAsString(id, content);
|
||||
}
|
||||
|
||||
static String _get_dest(BuilderOptions? options) {
|
||||
const defaultDestination = 'lib/src/iip_template.dart';
|
||||
if (options == null) return defaultDestination;
|
||||
if (options.config == null) return defaultDestination;
|
||||
return options.config['destination_file'] as String ?? defaultDestination;
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, List<String>> get buildExtensions {
|
||||
return {
|
||||
'.iip.yaml': [".iip.dart"]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// class TemplateBuilder extends Generator {
|
||||
// @override
|
||||
// String generate(LibraryReader library, BuildStep buildStep) {
|
||||
// return '''
|
||||
// // Source library: ${library.element.source.uri}
|
||||
// const Testinggggg = 3;
|
||||
// ''';
|
||||
// Future build(BuildStep buildStep) async {
|
||||
// final id = AssetId(buildStep.inputId.package, _fileName);
|
||||
|
||||
// // generate
|
||||
// var content = "Testing";
|
||||
|
||||
// await buildStep.writeAsString(id, content);
|
||||
// }
|
||||
|
||||
// static String _get_dest(BuilderOptions? options) {
|
||||
// const defaultDestination = 'lib/src/iip_template.dart';
|
||||
// if (options == null) return defaultDestination;
|
||||
// if (options.config == null) return defaultDestination;
|
||||
// return options.config['destination_file'] as String ?? defaultDestination;
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Map<String, List<String>> get buildExtensions {
|
||||
// return {
|
||||
// '.iip.yaml': [".iip.dart"]
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
// // class TemplateBuilder extends Generator {
|
||||
// // @override
|
||||
// // String generate(LibraryReader library, BuildStep buildStep) {
|
||||
// // return '''
|
||||
// // // Source library: ${library.element.source.uri}
|
||||
// // const Testinggggg = 3;
|
||||
// // ''';
|
||||
// // }
|
||||
// // }
|
||||
|
@ -23,7 +23,14 @@ class AsyncBag<T> extends AsyncReply<List<T>> {
|
||||
if (_sealedBag) return;
|
||||
_sealedBag = true;
|
||||
|
||||
if (_replies.length == 0) trigger(<T>[]);
|
||||
if (_replies.length == 0) {
|
||||
if (arrayType != null) {
|
||||
var ar = Warehouse.createArray(arrayType as Type);
|
||||
trigger(ar as List<T>);
|
||||
} else {
|
||||
trigger(<T>[]);
|
||||
}
|
||||
}
|
||||
|
||||
var results = List<T?>.filled(_replies.length, null);
|
||||
|
||||
@ -31,7 +38,8 @@ class AsyncBag<T> extends AsyncReply<List<T>> {
|
||||
var k = _replies[i];
|
||||
var index = i;
|
||||
|
||||
k..then((r) {
|
||||
k
|
||||
..then((r) {
|
||||
results[index] = r;
|
||||
_count++;
|
||||
if (_count == _replies.length) {
|
||||
@ -43,7 +51,8 @@ class AsyncBag<T> extends AsyncReply<List<T>> {
|
||||
trigger(results.cast<T>());
|
||||
}
|
||||
}
|
||||
})..error((ex) {
|
||||
})
|
||||
..error((ex) {
|
||||
triggerError(ex);
|
||||
});
|
||||
}
|
||||
|
@ -1,4 +1,8 @@
|
||||
import 'dart:async';
|
||||
|
||||
class IEventHandler {
|
||||
final _propertyModifiedController = StreamController<String>();
|
||||
|
||||
Map<String, List<Function>> _events = {};
|
||||
|
||||
register(String event) {
|
||||
@ -7,6 +11,12 @@ class IEventHandler {
|
||||
|
||||
IEventHandler() {}
|
||||
|
||||
Stream get properyModified => _propertyModifiedController.stream;
|
||||
|
||||
emitProperty(String name) {
|
||||
_propertyModifiedController.add(name);
|
||||
}
|
||||
|
||||
emitArgs(String event, List arguments) {
|
||||
//event = event.toLowerCase();
|
||||
|
||||
@ -21,13 +31,13 @@ class IEventHandler {
|
||||
|
||||
on(String event, Function callback) {
|
||||
event = event.toLowerCase();
|
||||
if (_events.containsKey(event)) register(event);
|
||||
if (!_events.containsKey(event)) register(event);
|
||||
_events[event]?.add(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
off(event, callback) {
|
||||
event = event.toString();
|
||||
off(String event, callback) {
|
||||
event = event.toLowerCase();
|
||||
if (_events.containsKey(event)) {
|
||||
if (callback != null)
|
||||
_events[event]?.remove(callback);
|
||||
|
@ -170,9 +170,12 @@ class Codec {
|
||||
|
||||
AsyncReply<IRecord?>? previous = null;
|
||||
|
||||
if (result == RecordComparisonResult.Null)
|
||||
if (result == RecordComparisonResult.Empty) {
|
||||
reply.seal();
|
||||
return reply;
|
||||
} else if (result == RecordComparisonResult.Null) {
|
||||
previous = AsyncReply<IRecord?>.ready(null);
|
||||
else if (result == RecordComparisonResult.Record ||
|
||||
} else if (result == RecordComparisonResult.Record ||
|
||||
result == RecordComparisonResult.RecordSameType) {
|
||||
var cs = data.getUint32(offset);
|
||||
var recordLength = cs;
|
||||
@ -203,8 +206,10 @@ class Codec {
|
||||
} else {
|
||||
AsyncReply<IRecord?>? previous = null;
|
||||
Guid? classId = null;
|
||||
|
||||
if (result == RecordComparisonResult.Null)
|
||||
if (result == RecordComparisonResult.Empty) {
|
||||
reply.seal();
|
||||
return reply;
|
||||
} else if (result == RecordComparisonResult.Null)
|
||||
previous = new AsyncReply<IRecord?>.ready(null);
|
||||
else if (result == RecordComparisonResult.Record) {
|
||||
var cs = data.getUint32(offset);
|
||||
@ -392,11 +397,13 @@ class Codec {
|
||||
static DC composeRecordArray<T extends IRecord>(
|
||||
List<T>? records, DistributedConnection connection,
|
||||
[bool prependLength = false]) {
|
||||
if (records == null || records.length == 0)
|
||||
if (records == null) // || records.length == 0)
|
||||
return prependLength ? new DC(4) : new DC(0);
|
||||
|
||||
var rt = new BinaryList();
|
||||
var comparsion = compareRecords(null, records[0]);
|
||||
var comparsion = records.length == 0
|
||||
? RecordComparisonResult.Empty
|
||||
: compareRecords(null, records[0]);
|
||||
|
||||
//var type = records.getType().GetElementType();
|
||||
var isTyped = T == IRecord; // != typeof(IRecord);
|
||||
@ -960,11 +967,14 @@ class Codec {
|
||||
static DC composeResourceArray<T extends IResource>(
|
||||
List<T>? resources, DistributedConnection connection,
|
||||
[bool prependLength = false]) {
|
||||
if (resources == null || resources.length == 0)
|
||||
if (resources == null) // || resources.length == 0)
|
||||
return prependLength ? new DC(4) : new DC(0);
|
||||
|
||||
var rt = new BinaryList();
|
||||
var comparsion = compareResources(null, resources[0], connection);
|
||||
//var comparsion = compareResources(null, resources[0], connection);
|
||||
var comparsion = resources.length == 0
|
||||
? ResourceComparisonResult.Empty
|
||||
: compareResources(null, resources[0], connection);
|
||||
|
||||
if (T != IResource) {
|
||||
// get template
|
||||
@ -1048,7 +1058,10 @@ class Codec {
|
||||
|
||||
AsyncReply<IResource?>? previous = null;
|
||||
|
||||
if (result == ResourceComparisonResult.Null)
|
||||
if (result == ResourceComparisonResult.Empty) {
|
||||
reply.seal();
|
||||
return reply;
|
||||
} else if (result == ResourceComparisonResult.Null)
|
||||
previous = new AsyncReply<IResource?>.ready(null);
|
||||
else if (result == ResourceComparisonResult.Local) {
|
||||
previous = Warehouse.getById(data.getUint32(offset));
|
||||
@ -1065,7 +1078,10 @@ class Codec {
|
||||
|
||||
AsyncReply<IResource?>? current = null;
|
||||
|
||||
if (result == ResourceComparisonResult.Null) {
|
||||
if (result == ResourceComparisonResult.Empty) {
|
||||
reply.seal();
|
||||
return reply;
|
||||
} else if (result == ResourceComparisonResult.Null) {
|
||||
current = new AsyncReply<IResource?>.ready(null);
|
||||
} else if (result == ResourceComparisonResult.Same) {
|
||||
current = previous;
|
||||
|
@ -3,4 +3,6 @@ class RecordComparisonResult {
|
||||
static const Record = 1;
|
||||
static const RecordSameType = 2;
|
||||
static const Same = 3;
|
||||
static const Empty = 4;
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
class ResourceComparisonResult
|
||||
{
|
||||
class ResourceComparisonResult {
|
||||
static const Null = 0;
|
||||
static const Distributed = 1;
|
||||
static const Local = 2;
|
||||
static const Same = 3;
|
||||
static const Empty = 4;
|
||||
}
|
@ -22,6 +22,8 @@ SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
import '../Sockets/WSocket.dart';
|
||||
|
||||
import '../../Resource/Template/TemplateDescriber.dart';
|
||||
import '../../Resource/Template/TemplateType.dart';
|
||||
import '../../Security/Authority/AuthenticationMethod.dart';
|
||||
@ -161,7 +163,7 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
/// Send data to the other end as parameters
|
||||
/// </summary>
|
||||
/// <param name="values">Values will be converted to bytes then sent.</param>
|
||||
SendList sendParams([AsyncReply<List<dynamic>>? reply = null]) {
|
||||
SendList sendParams([AsyncReply<List<dynamic>?>? reply = null]) {
|
||||
return new SendList(this, reply);
|
||||
}
|
||||
|
||||
@ -188,6 +190,11 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
|
||||
var domain = instance?.attributes["domain"] ?? address;
|
||||
|
||||
var ws = instance?.attributes.containsKey("ws") == true ||
|
||||
instance?.attributes.containsKey("wss") == true;
|
||||
var secure = instance?.attributes.containsKey("secure") == true ||
|
||||
instance?.attributes.containsKey("wss") == true;
|
||||
|
||||
if (instance?.attributes.containsKey("username") == true &&
|
||||
instance?.attributes.containsKey("password") == true) {
|
||||
var username = instance?.attributes["username"] as String;
|
||||
@ -200,7 +207,9 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
hostname: address,
|
||||
port: port,
|
||||
passwordOrToken: password,
|
||||
username: username);
|
||||
username: username,
|
||||
useWebsocket: ws,
|
||||
secureWebSocket: secure);
|
||||
} else if (instance?.attributes.containsKey("token") == true) {
|
||||
var token = DC.stringToBytes(instance?.attributes["token"] ?? "");
|
||||
var tokenIndex = instance?.attributes["tokenIndex"] ?? 0;
|
||||
@ -210,13 +219,17 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
hostname: address,
|
||||
port: port,
|
||||
passwordOrToken: token,
|
||||
tokenIndex: tokenIndex);
|
||||
tokenIndex: tokenIndex,
|
||||
useWebsocket: ws,
|
||||
secureWebSocket: secure);
|
||||
} else {
|
||||
return connect(
|
||||
method: AuthenticationMethod.None,
|
||||
hostname: address,
|
||||
port: port,
|
||||
domain: domain);
|
||||
domain: domain,
|
||||
useWebsocket: ws,
|
||||
secureWebSocket: secure);
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,7 +244,9 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
String? username,
|
||||
int? tokenIndex,
|
||||
DC? passwordOrToken,
|
||||
String? domain}) {
|
||||
String? domain,
|
||||
bool useWebsocket = false,
|
||||
bool secureWebSocket = false}) {
|
||||
if (_openReply != null)
|
||||
throw AsyncException(ErrorType.Exception, 0, "Connection in progress");
|
||||
|
||||
@ -251,19 +266,26 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
if (_session == null)
|
||||
throw AsyncException(ErrorType.Exception, 0, "Session not initialized");
|
||||
|
||||
if (socket == null) socket = new TCPSocket();
|
||||
if (socket == null) {
|
||||
if (useWebsocket) {
|
||||
socket = new WSocket()..secure = secureWebSocket;
|
||||
} else
|
||||
socket = new TCPSocket();
|
||||
}
|
||||
|
||||
_port = port ?? _port;
|
||||
_hostname = hostname ?? _hostname;
|
||||
|
||||
if (_hostname == null) throw Exception("Host not specified.");
|
||||
|
||||
if (socket != null) {
|
||||
socket.connect(_hostname as String, _port).then<dynamic>((x) {
|
||||
assign(socket as ISocket);
|
||||
}).error((x) {
|
||||
_openReply?.triggerError(x);
|
||||
_openReply = null;
|
||||
});
|
||||
}
|
||||
|
||||
return _openReply as AsyncReply<bool>;
|
||||
}
|
||||
@ -961,7 +983,7 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
/// <param name="args">Arguments to send.</param>
|
||||
/// <returns></returns>
|
||||
SendList sendRequest(int action) {
|
||||
var reply = new AsyncReply<List<dynamic>>();
|
||||
var reply = new AsyncReply<List<dynamic>?>();
|
||||
var c = _callbackCounter++; // avoid thread racing
|
||||
_requests.add(c, reply);
|
||||
|
||||
@ -2248,10 +2270,14 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
|
||||
(sendRequest(IIPPacketAction.TemplateFromClassId)..addGuid(classId)).done()
|
||||
..then((rt) {
|
||||
if (rt != null) {
|
||||
_templateRequests.remove(classId);
|
||||
_templates[(rt[0] as TypeTemplate).classId] = rt[0] as TypeTemplate;
|
||||
Warehouse.putTemplate(rt[0] as TypeTemplate);
|
||||
reply.trigger(rt[0]);
|
||||
} else {
|
||||
reply.triggerError(Exception("Null response"));
|
||||
}
|
||||
})
|
||||
..error((ex) {
|
||||
reply.triggerError(ex);
|
||||
@ -2305,6 +2331,7 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
List<TypeTemplate> templates = [];
|
||||
// parse templates
|
||||
|
||||
if (rt != null) {
|
||||
DC data = rt[0];
|
||||
//var offset = 0;
|
||||
for (int offset = 0; offset < data.length;) {
|
||||
@ -2313,6 +2340,9 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
templates.add(TypeTemplate.parse(data, offset, cs));
|
||||
offset += cs;
|
||||
}
|
||||
} else {
|
||||
reply.triggerError(Exception("Null response"));
|
||||
}
|
||||
|
||||
reply.trigger(templates);
|
||||
})
|
||||
@ -2347,6 +2377,7 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
|
||||
(sendRequest(IIPPacketAction.AttachResource)..addUint32(id)).done()
|
||||
..then((rt) {
|
||||
if (rt != null) {
|
||||
// @TODO: Generator code
|
||||
DistributedResource dr;
|
||||
|
||||
@ -2396,6 +2427,9 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
..error((ex) {
|
||||
reply.triggerError(ex);
|
||||
});
|
||||
} else {
|
||||
reply.triggerError(Exception("Null response"));
|
||||
}
|
||||
})
|
||||
..error((ex) {
|
||||
reply.triggerError(ex);
|
||||
@ -2410,10 +2444,14 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
sendRequest(IIPPacketAction.ResourceChildren)
|
||||
..addUint32(resource.instance?.id as int)
|
||||
..done().then<dynamic>((ar) {
|
||||
if (ar != null) {
|
||||
var d = ar[0] as DC;
|
||||
Codec.parseResourceArray(d, 0, d.length, this).then((resources) {
|
||||
rt.trigger(resources);
|
||||
}).error((ex) => rt.triggerError(ex));
|
||||
} else {
|
||||
rt.triggerError(Exception("Null response"));
|
||||
}
|
||||
});
|
||||
|
||||
return rt;
|
||||
@ -2425,11 +2463,15 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
sendRequest(IIPPacketAction.ResourceParents)
|
||||
..addUint32((resource.instance as Instance).id)
|
||||
..done().then<dynamic>((ar) {
|
||||
if (ar != null) {
|
||||
var d = ar[0] as DC;
|
||||
Codec.parseResourceArray(d, 0, d.length, this)
|
||||
.then<dynamic>((resources) {
|
||||
rt.trigger(resources);
|
||||
}).error((ex) => rt.triggerError(ex));
|
||||
} else {
|
||||
rt.triggerError(Exception("Null response"));
|
||||
}
|
||||
});
|
||||
|
||||
return rt;
|
||||
@ -2484,6 +2526,7 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
..addUint32(resource.instance?.id as int))
|
||||
.done()
|
||||
..then((ar) {
|
||||
if (ar != null) {
|
||||
var d = ar[0] as DC;
|
||||
Codec.parseStructure(d, 0, d.length, this)
|
||||
..then((st) {
|
||||
@ -2491,6 +2534,9 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
rt.trigger(st);
|
||||
})
|
||||
..error((ex) => rt.triggerError(ex));
|
||||
} else {
|
||||
rt.triggerError(Exception("Null response"));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var attrs = DC.stringArrayToBytes(attributes);
|
||||
@ -2500,6 +2546,7 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
..addDC(attrs))
|
||||
.done()
|
||||
..then((ar) {
|
||||
if (ar != null) {
|
||||
var d = ar[0] as DC;
|
||||
Codec.parseStructure(d, 0, d.length, this)
|
||||
..then((st) {
|
||||
@ -2508,6 +2555,9 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
rt.trigger(st);
|
||||
})
|
||||
..error((ex) => rt.triggerError(ex));
|
||||
} else {
|
||||
rt.triggerError(Exception("Null response"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -2538,10 +2588,14 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
..addDateTime(fromDate)
|
||||
..addDateTime(toDate)
|
||||
..done().then<dynamic>((rt) {
|
||||
if (rt != null) {
|
||||
var content = rt[0] as DC;
|
||||
|
||||
Codec.parseHistory(content, 0, content.length, resource, this)
|
||||
.then((history) => reply.trigger(history));
|
||||
} else {
|
||||
reply.triggerError(Exception("Null response"));
|
||||
}
|
||||
}).error((ex) => reply.triggerError(ex));
|
||||
|
||||
return reply;
|
||||
@ -2563,10 +2617,14 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
..addUint16(str.length)
|
||||
..addDC(str)
|
||||
..done().then<dynamic>((args) {
|
||||
if (args != null) {
|
||||
var content = args[0] as DC;
|
||||
|
||||
Codec.parseResourceArray(content, 0, content.length, this)
|
||||
.then((resources) => reply.trigger(resources));
|
||||
} else {
|
||||
reply.triggerError(Exception("Null response"));
|
||||
}
|
||||
}).error((ex) => reply.triggerError(ex));
|
||||
|
||||
return reply;
|
||||
@ -2602,11 +2660,15 @@ class DistributedConnection extends NetworkConnection with IStore {
|
||||
|
||||
(sendRequest(IIPPacketAction.CreateResource)..addDC(pkt.toDC())).done()
|
||||
..then((args) {
|
||||
if (args != null) {
|
||||
var rid = args[0];
|
||||
|
||||
fetch(rid).then((r) {
|
||||
reply.trigger(r);
|
||||
});
|
||||
} else {
|
||||
reply.triggerError(Exception("Null response"));
|
||||
}
|
||||
});
|
||||
|
||||
return reply;
|
||||
|
@ -22,6 +22,7 @@ SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import '../../Resource/Instance.dart';
|
||||
|
||||
|
@ -4,12 +4,12 @@ import 'NetworkConnection.dart';
|
||||
|
||||
class SendList extends BinaryList {
|
||||
NetworkConnection connection;
|
||||
AsyncReply<List<dynamic>>? reply;
|
||||
AsyncReply<List<dynamic>?>? reply;
|
||||
|
||||
SendList(this.connection, this.reply) {}
|
||||
|
||||
@override
|
||||
AsyncReply<List<dynamic>> done() {
|
||||
AsyncReply<List<dynamic>?> done() {
|
||||
connection.send(super.toDC());
|
||||
|
||||
return reply ?? AsyncReply.ready([]);
|
||||
|
164
lib/src/Net/Sockets/WSocket.dart
Normal file
164
lib/src/Net/Sockets/WSocket.dart
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
|
||||
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 WSocket 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<int> 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<bool> connect(String hostname, int port) {
|
||||
var rt = new AsyncReply<bool>();
|
||||
|
||||
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<ISocket> accept() {
|
||||
var reply = new AsyncReply<ISocket>();
|
||||
return reply;
|
||||
}
|
||||
}
|
@ -1,192 +0,0 @@
|
||||
/*
|
||||
|
||||
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 'ISocket.dart';
|
||||
import '../../Data/DC.dart';
|
||||
import '../NetworkBuffer.dart';
|
||||
import 'SocketState.dart';
|
||||
import 'IPEndPoint.dart';
|
||||
import '../../Core/AsyncReply.dart';
|
||||
|
||||
import 'package:web_socket_channel/io.dart';
|
||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
import 'package:web_socket_channel/status.dart' as status;
|
||||
|
||||
class WSSocket extends ISocket
|
||||
{
|
||||
WebSocketChannel sock;
|
||||
|
||||
NetworkBuffer receiveNetworkBuffer = new NetworkBuffer();
|
||||
|
||||
bool began = false;
|
||||
|
||||
SocketState _state = SocketState.Initial;
|
||||
|
||||
|
||||
IPEndPoint _localEP, _remoteEP;
|
||||
|
||||
bool begin()
|
||||
{
|
||||
if (began)
|
||||
return false;
|
||||
|
||||
began = true;
|
||||
|
||||
_localEP = IPEndPoint(sock. address.rawAddress, sock.port);
|
||||
_remoteEP = IPEndPoint(sock.remoteAddress.rawAddress, sock.remotePort);
|
||||
return true;
|
||||
}
|
||||
|
||||
void dataHandler(List<int> data){
|
||||
//print(new String.fromCharCodes(data).trim());
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
if (_state == SocketState.Closed || _state == SocketState.Terminated)
|
||||
return;
|
||||
|
||||
|
||||
var dc = new DC.fromList(data);
|
||||
receiveNetworkBuffer.write(dc, 0, dc.length);
|
||||
emitArgs("receive", [receiveNetworkBuffer]);
|
||||
|
||||
}
|
||||
catch (ex)
|
||||
{
|
||||
if (_state != SocketState.Closed)// && !sock.connected)
|
||||
{
|
||||
_state = SocketState.Terminated;
|
||||
close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void errorHandler(error, StackTrace trace){
|
||||
print(error);
|
||||
}
|
||||
|
||||
void doneHandler(){
|
||||
sock.destroy();
|
||||
}
|
||||
|
||||
|
||||
AsyncReply<bool> connect(String hostname, int port)
|
||||
{
|
||||
var rt = new AsyncReply<bool>();
|
||||
|
||||
try
|
||||
{
|
||||
_state = SocketState.Connecting;
|
||||
|
||||
WebSocket()
|
||||
prefix0.WebSocket(url)
|
||||
IOWebSocketChannel.
|
||||
Socket.connect(hostname, port).then((s){
|
||||
sock = s;
|
||||
s.listen(dataHandler,
|
||||
onError: errorHandler,
|
||||
onDone: doneHandler,
|
||||
cancelOnError: false);
|
||||
_state = SocketState.Established;
|
||||
emitArgs("connect", []);
|
||||
begin();
|
||||
rt.trigger(true);
|
||||
|
||||
}).catchError((ex){
|
||||
close();
|
||||
rt.triggerError(ex);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
rt.triggerError(ex);
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
IPEndPoint get localEndPoint => _localEP;
|
||||
IPEndPoint get remoteEndPoint => _remoteEP;
|
||||
|
||||
|
||||
SocketState get state => _state;
|
||||
|
||||
|
||||
TCPSocket.fromSocket(Socket socket)
|
||||
{
|
||||
sock = socket;
|
||||
//if (socket.)
|
||||
// _state = SocketState.Established;
|
||||
}
|
||||
|
||||
TCPSocket()
|
||||
{
|
||||
// default constructor
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (state != SocketState.Closed && state != SocketState.Terminated)
|
||||
_state = SocketState.Closed;
|
||||
|
||||
sock?.close();
|
||||
|
||||
emitArgs("close", []);
|
||||
}
|
||||
|
||||
|
||||
void send(DC message, [int offset, int size])
|
||||
{
|
||||
if (state == SocketState.Established)
|
||||
sock.add(message.toList());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void destroy()
|
||||
{
|
||||
close();
|
||||
emitArgs("destroy", [this]);
|
||||
}
|
||||
|
||||
AsyncReply<ISocket> accept()
|
||||
{
|
||||
|
||||
|
||||
var reply = new AsyncReply<ISocket>();
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
*/
|
@ -219,7 +219,7 @@ class TemplateGenerator {
|
||||
var con = await Warehouse.get<DistributedConnection>(
|
||||
(path[1] as String) + "://" + (path[2] as String),
|
||||
!isNullOrEmpty(username) && !isNullOrEmpty(password)
|
||||
? {username: username, password: password}
|
||||
? {"username": username, "password": password}
|
||||
: null);
|
||||
|
||||
if (con == null) throw Exception("Can't connect to server");
|
||||
|
@ -40,4 +40,5 @@ abstract class IResource extends IDestructible {
|
||||
getProperty(String name);
|
||||
|
||||
TemplateDescriber get template;
|
||||
|
||||
}
|
||||
|
@ -386,6 +386,8 @@ class Instance extends IEventHandler {
|
||||
emitArgs("resourceModified", [_resource, pt.name, value]);
|
||||
//_resource.emitArgs("modified", [pt.name, value]);
|
||||
_resource.emitArgs(":${pt.name}", [value]);
|
||||
|
||||
_resource.emitProperty(pt.name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,7 +65,8 @@ class Warehouse {
|
||||
|
||||
static KeyList<Type, FactoryEntry> _factory = _getBuiltInTypes();
|
||||
|
||||
static KeyList<String, AsyncReply<IStore> Function(String, dynamic)>
|
||||
static KeyList<String,
|
||||
AsyncReply<IStore> Function(String, Map<String, dynamic>?)>
|
||||
protocols = _getSupportedProtocols();
|
||||
|
||||
static bool _warehouseIsOpen = false;
|
||||
@ -222,7 +223,7 @@ class Warehouse {
|
||||
/// <param name="path"></param>
|
||||
/// <returns>Resource instance.</returns>
|
||||
static AsyncReply<T?> get<T extends IResource>(String path,
|
||||
[attributes = null,
|
||||
[Map<String, dynamic>? attributes = null,
|
||||
IResource? parent = null,
|
||||
IPermissionsManager? manager = null]) {
|
||||
var rt = AsyncReply<T?>();
|
||||
@ -232,8 +233,8 @@ class Warehouse {
|
||||
var url = _urlRegex.allMatches(path).first;
|
||||
|
||||
if (protocols.containsKey(url[1])) {
|
||||
var handler =
|
||||
protocols[url[1]] as AsyncReply<IStore> Function(String, dynamic);
|
||||
var handler = protocols[url[1]] as AsyncReply<IStore> Function(
|
||||
String, Map<String, dynamic>?);
|
||||
|
||||
var getFromStore = () {
|
||||
handler(url[2] as String, attributes)
|
||||
@ -360,7 +361,7 @@ class Warehouse {
|
||||
TypeTemplate? customTemplate = null,
|
||||
int age = 0,
|
||||
IPermissionsManager? manager = null,
|
||||
attributes = null]) {
|
||||
Map<String, dynamic>? attributes = null]) {
|
||||
var rt = AsyncReply<T?>();
|
||||
|
||||
if (resource.instance != null) {
|
||||
@ -493,7 +494,7 @@ class Warehouse {
|
||||
[IStore? store = null,
|
||||
IResource? parent = null,
|
||||
IPermissionsManager? manager = null,
|
||||
attributes = null,
|
||||
Map<String, dynamic>? attributes = null,
|
||||
properties = null]) {
|
||||
if (_factory[T] == null)
|
||||
throw Exception("No Instance Creator was found for type ${T}");
|
||||
@ -640,15 +641,30 @@ class Warehouse {
|
||||
return true;
|
||||
}
|
||||
|
||||
static KeyList<String, AsyncReply<IStore> Function(String, dynamic)>
|
||||
static KeyList<String,
|
||||
AsyncReply<IStore> Function(String, Map<String, dynamic>?)>
|
||||
_getSupportedProtocols() {
|
||||
var rt =
|
||||
new KeyList<String, AsyncReply<IStore> Function(String, dynamic)>();
|
||||
rt.add(
|
||||
var rt = new KeyList<String,
|
||||
AsyncReply<IStore> Function(String, Map<String, dynamic>?)>();
|
||||
rt
|
||||
..add(
|
||||
"iip",
|
||||
(String name, attributes) =>
|
||||
(String name, Map<String, dynamic>? attributes) =>
|
||||
Warehouse.newResource<DistributedConnection>(
|
||||
name, null, null, null, attributes));
|
||||
name, null, null, null, attributes))
|
||||
..add("iipws", (String name, Map<String, dynamic>? attributes) {
|
||||
if (attributes == null) attributes = {};
|
||||
attributes['ws'] = true;
|
||||
return Warehouse.newResource<DistributedConnection>(
|
||||
name, null, null, null, attributes);
|
||||
})
|
||||
..add("iipwss", (String name, Map<String, dynamic>? attributes) {
|
||||
if (attributes == null) attributes = {};
|
||||
attributes['wss'] = true;
|
||||
return Warehouse.newResource<DistributedConnection>(
|
||||
name, null, null, null, attributes);
|
||||
});
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
|
31
pubspec.lock
31
pubspec.lock
@ -21,7 +21,7 @@ packages:
|
||||
name: args
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
version: "2.3.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -36,13 +36,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
build:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -92,13 +85,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -154,7 +140,7 @@ packages:
|
||||
name: json_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
version: "4.4.0"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -231,7 +217,7 @@ packages:
|
||||
name: pubspec_parse
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.2.0"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -260,13 +246,6 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
source_gen:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: source_gen
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
source_map_stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -359,7 +338,7 @@ packages:
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: web_socket_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
@ -380,4 +359,4 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
sdks:
|
||||
dart: ">=2.12.0 <3.0.0"
|
||||
dart: ">=2.14.0 <3.0.0"
|
||||
|
11
pubspec.yaml
11
pubspec.yaml
@ -1,17 +1,18 @@
|
||||
name: esiur
|
||||
description: Distributed Object Framework.
|
||||
version: 1.4.1
|
||||
version: 1.4.5
|
||||
#author: Ahmed Zamil <ahmed@esiur.com>
|
||||
homepage: https://github.com/esiur/esiur-dart
|
||||
|
||||
|
||||
environment:
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
sdk: ">=2.14.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
source_gen:
|
||||
args: #
|
||||
pubspec_parse:
|
||||
# source_gen: ^1.0.5
|
||||
args: ^2.3.0
|
||||
pubspec_parse: ^1.2.0
|
||||
web_socket_channel: ^2.1.0
|
||||
|
||||
dev_dependencies:
|
||||
test:
|
||||
|
Loading…
x
Reference in New Issue
Block a user