2021-05-15 07:19:35 +00:00
|
|
|
part of angel3_websocket.server;
|
2016-09-18 02:53:58 +00:00
|
|
|
|
2017-01-29 20:02:19 +00:00
|
|
|
/// Marks a method as available to WebSockets.
|
2016-09-18 02:53:58 +00:00
|
|
|
class ExposeWs {
|
|
|
|
final String eventName;
|
|
|
|
|
|
|
|
const ExposeWs(this.eventName);
|
|
|
|
}
|
|
|
|
|
2017-01-29 20:02:19 +00:00
|
|
|
/// A special controller that also supports WebSockets.
|
2016-09-18 02:53:58 +00:00
|
|
|
class WebSocketController extends Controller {
|
2019-05-01 22:53:30 +00:00
|
|
|
/// The plug-in instance powering this controller.
|
2017-10-19 22:26:59 +00:00
|
|
|
final AngelWebSocket ws;
|
|
|
|
|
2021-04-10 15:12:43 +00:00
|
|
|
final Map<String, MethodMirror> _handlers = {};
|
|
|
|
final Map<String, Symbol> _handlerSymbols = {};
|
2017-01-29 20:02:19 +00:00
|
|
|
|
2017-10-19 22:26:59 +00:00
|
|
|
WebSocketController(this.ws) : super();
|
2016-12-23 20:57:46 +00:00
|
|
|
|
2017-01-29 20:02:19 +00:00
|
|
|
/// Sends an event to all clients.
|
2021-04-10 15:12:43 +00:00
|
|
|
void broadcast(String eventName, data,
|
2021-04-26 00:47:32 +00:00
|
|
|
{Function(WebSocketContext socket)? filter}) {
|
2021-02-21 02:47:23 +00:00
|
|
|
ws.batchEvent(WebSocketEvent(eventName: eventName, data: data),
|
2017-01-29 20:02:19 +00:00
|
|
|
filter: filter);
|
2016-09-18 02:53:58 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 20:02:19 +00:00
|
|
|
/// Fired on new connections.
|
2021-04-10 15:12:43 +00:00
|
|
|
dynamic onConnect(WebSocketContext socket) {}
|
2016-12-23 20:57:46 +00:00
|
|
|
|
2017-01-29 20:02:19 +00:00
|
|
|
/// Fired on disconnections.
|
2021-04-10 15:12:43 +00:00
|
|
|
dynamic onDisconnect(WebSocketContext socket) {}
|
2016-12-23 20:57:46 +00:00
|
|
|
|
2017-01-29 20:02:19 +00:00
|
|
|
/// Fired on all incoming actions.
|
2021-04-10 15:12:43 +00:00
|
|
|
dynamic onAction(WebSocketAction action, WebSocketContext socket) async {}
|
2016-12-23 20:57:46 +00:00
|
|
|
|
2017-01-29 20:02:19 +00:00
|
|
|
/// Fired on arbitrary incoming data.
|
2021-04-10 15:12:43 +00:00
|
|
|
dynamic onData(data, WebSocketContext socket) {}
|
2016-12-23 20:57:46 +00:00
|
|
|
|
2016-09-18 02:53:58 +00:00
|
|
|
@override
|
2017-10-19 22:26:59 +00:00
|
|
|
Future configureServer(Angel app) async {
|
2021-04-26 00:47:32 +00:00
|
|
|
if (findExpose(app.container!.reflector) != null) {
|
2018-08-28 14:17:14 +00:00
|
|
|
await super.configureServer(app);
|
2021-04-10 15:12:43 +00:00
|
|
|
}
|
2016-09-18 02:53:58 +00:00
|
|
|
|
2021-04-10 15:12:43 +00:00
|
|
|
var instanceMirror = reflect(this);
|
|
|
|
var classMirror = reflectClass(runtimeType);
|
2016-09-18 02:53:58 +00:00
|
|
|
classMirror.instanceMembers.forEach((sym, mirror) {
|
|
|
|
if (mirror.isRegularMethod) {
|
2021-04-26 00:47:32 +00:00
|
|
|
var exposeMirror = mirror.metadata
|
|
|
|
.firstWhereOrNull((mirror) => mirror.reflectee is ExposeWs);
|
2016-09-18 02:53:58 +00:00
|
|
|
|
|
|
|
if (exposeMirror != null) {
|
2021-04-10 15:12:43 +00:00
|
|
|
var exposeWs = exposeMirror.reflectee as ExposeWs;
|
2016-09-18 02:53:58 +00:00
|
|
|
_handlers[exposeWs.eventName] = mirror;
|
|
|
|
_handlerSymbols[exposeWs.eventName] = sym;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
ws.onConnection.listen((socket) async {
|
2021-04-26 00:47:32 +00:00
|
|
|
if (!socket.request.container!.has<WebSocketContext>()) {
|
|
|
|
socket.request.container!.registerSingleton<WebSocketContext>(socket);
|
2018-08-28 14:17:14 +00:00
|
|
|
}
|
2016-12-23 20:57:46 +00:00
|
|
|
|
2016-09-18 02:53:58 +00:00
|
|
|
await onConnect(socket);
|
|
|
|
|
2016-12-23 20:57:46 +00:00
|
|
|
socket.onData.listen((data) => onData(data, socket));
|
2016-09-18 02:53:58 +00:00
|
|
|
|
2016-12-23 20:57:46 +00:00
|
|
|
socket.onAction.listen((WebSocketAction action) async {
|
2021-04-26 00:47:32 +00:00
|
|
|
var container = socket.request.container!.createChild();
|
2018-10-21 08:15:51 +00:00
|
|
|
container.registerSingleton<WebSocketAction>(action);
|
2016-09-18 02:53:58 +00:00
|
|
|
|
2017-04-23 18:40:30 +00:00
|
|
|
try {
|
|
|
|
await onAction(action, socket);
|
|
|
|
|
|
|
|
if (_handlers.containsKey(action.eventName)) {
|
2021-04-26 00:47:32 +00:00
|
|
|
var methodMirror = _handlers[action.eventName!]!;
|
2016-12-23 20:57:46 +00:00
|
|
|
var fn = instanceMirror.getField(methodMirror.simpleName).reflectee;
|
2018-08-28 14:17:14 +00:00
|
|
|
return app.runContained(
|
2018-10-21 08:15:51 +00:00
|
|
|
fn as Function, socket.request, socket.response, container);
|
2016-09-18 02:53:58 +00:00
|
|
|
}
|
2017-04-23 18:40:30 +00:00
|
|
|
} catch (e, st) {
|
2017-09-24 04:37:58 +00:00
|
|
|
ws.catchError(e, st, socket);
|
2016-09-18 02:53:58 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2016-09-18 03:16:51 +00:00
|
|
|
|
|
|
|
ws.onDisconnection.listen(onDisconnect);
|
2016-09-18 02:53:58 +00:00
|
|
|
}
|
|
|
|
}
|