platform/packages/wings/lib/src/wings_socket.dart

131 lines
3.5 KiB
Dart
Raw Normal View History

import 'dart:async';
2019-04-26 23:11:58 +00:00
import 'dart:io';
import 'dart:isolate';
import 'dart:typed_data';
import 'dart-ext:angel_wings';
2019-04-27 19:12:09 +00:00
int bindWingsIPv4ServerSocket(
String address,
int port,
bool shared,
int backlog,
bool v6Only,
SendPort sendPort) native 'Dart_WingsSocket_bindIPv4';
2019-04-26 23:11:58 +00:00
2019-04-27 19:12:09 +00:00
int bindWingsIPv6ServerSocket(
String address,
int port,
bool shared,
int backlog,
bool v6Only,
2019-05-01 04:29:21 +00:00
SendPort sendPort) native 'Dart_WingsSocket_bindIPv6';
2019-04-26 23:11:58 +00:00
2019-05-01 01:33:46 +00:00
String getWingsServerSocketAddress(int pointer)
native 'Dart_WingsSocket_getAddress';
2019-04-26 23:11:58 +00:00
int getWingsServerSocketPort(int pointer) native 'Dart_WingsSocket_getPort';
2021-06-20 12:37:20 +00:00
void writeToNativeSocket(int? fd, Uint8List data)
2019-04-26 23:11:58 +00:00
native 'Dart_WingsSocket_write';
2021-06-20 12:37:20 +00:00
void closeNativeSocketDescriptor(int? fd)
2019-04-26 23:11:58 +00:00
native 'Dart_WingsSocket_closeDescriptor';
2019-04-29 05:55:02 +00:00
SendPort wingsSocketListen(int pointer) native 'Dart_WingsSocket_listen';
2019-05-01 04:29:21 +00:00
void closeWingsSocket(int pointer, SendPort sendPort)
native 'Dart_WingsSocket_close';
2019-04-29 08:22:36 +00:00
SendPort wingsParseHttp() native 'Dart_WingsSocket_parseHttp';
class WingsClientSocket {
2021-06-20 12:37:20 +00:00
final int? fileDescriptor;
2019-04-29 08:22:36 +00:00
final InternetAddress remoteAddress;
WingsClientSocket(this.fileDescriptor, this.remoteAddress);
}
class WingsSocket extends Stream<WingsClientSocket> {
final StreamController<WingsClientSocket> _ctrl = StreamController();
2021-06-20 12:37:20 +00:00
late SendPort _acceptor;
InternetAddress? _address;
final int _pointer;
2019-04-26 23:11:58 +00:00
final RawReceivePort _recv;
bool _open = true;
2021-06-20 12:37:20 +00:00
int? _port;
2019-04-26 23:11:58 +00:00
WingsSocket._(this._pointer, this._recv) {
2019-04-29 05:55:02 +00:00
_acceptor = wingsSocketListen(_pointer);
2019-04-26 23:11:58 +00:00
_recv.handler = (h) {
if (!_ctrl.isClosed) {
2019-04-29 08:22:36 +00:00
_ctrl.add(
2021-06-20 12:37:20 +00:00
WingsClientSocket(h[0] as int?, InternetAddress(h[1] as String)));
2019-04-29 05:55:02 +00:00
_acceptor.send([_recv.sendPort, _pointer]);
2019-04-26 23:11:58 +00:00
}
};
2019-04-29 05:55:02 +00:00
_acceptor.send([_recv.sendPort, _pointer]);
2019-04-26 23:11:58 +00:00
}
2019-04-26 23:22:30 +00:00
static Future<WingsSocket> bind(address, int port,
{bool shared = false, int backlog = 0, bool v6Only = false}) async {
2019-04-26 23:11:58 +00:00
var recv = RawReceivePort();
int ptr;
2019-04-26 23:22:30 +00:00
InternetAddress addr;
if (address is InternetAddress) {
addr = address;
} else if (address is String) {
var addrs = await InternetAddress.lookup(address);
if (addrs.isNotEmpty) {
addr = addrs[0];
} else {
throw StateError('Internet address lookup failed: $address');
}
} else {
throw ArgumentError.value(
address, 'address', 'must be an InternetAddress or String');
}
2019-04-26 23:11:58 +00:00
try {
2019-04-26 23:22:30 +00:00
if (addr.type == InternetAddressType.IPv6) {
2019-04-27 19:12:09 +00:00
ptr = bindWingsIPv6ServerSocket(
addr.address, port, shared, backlog, v6Only, recv.sendPort);
2019-04-26 23:11:58 +00:00
} else {
2019-04-27 19:12:09 +00:00
ptr = bindWingsIPv4ServerSocket(
addr.address, port, shared, backlog, v6Only, recv.sendPort);
2019-04-26 23:11:58 +00:00
}
2019-05-01 01:33:46 +00:00
return WingsSocket._(ptr, recv); //.._address = addr;
2019-04-26 23:11:58 +00:00
} catch (e) {
recv.close();
rethrow;
}
}
2019-05-01 01:33:46 +00:00
InternetAddress get address =>
_address ??= InternetAddress(getWingsServerSocketAddress(_pointer));
2019-04-30 17:40:11 +00:00
2019-04-26 23:11:58 +00:00
int get port => _port ??= getWingsServerSocketPort(_pointer);
@override
2019-04-29 08:22:36 +00:00
StreamSubscription<WingsClientSocket> listen(
2021-06-20 12:37:20 +00:00
void Function(WingsClientSocket event)? onData,
{Function? onError,
void Function()? onDone,
bool? cancelOnError}) {
return _ctrl.stream
.listen(onData, onError: onError, cancelOnError: cancelOnError);
}
2019-04-26 23:11:58 +00:00
2019-09-29 05:26:27 +00:00
Future<void> close(){
2019-04-26 23:11:58 +00:00
if (_open) {
_open = false;
2019-05-01 04:29:21 +00:00
closeWingsSocket(_pointer, _recv.sendPort);
2019-04-26 23:11:58 +00:00
_recv.close();
2019-09-29 05:26:27 +00:00
_ctrl.close();
2019-04-26 23:11:58 +00:00
}
2019-09-29 05:26:27 +00:00
return Future.value();
2019-04-26 23:11:58 +00:00
}
}