Implementation
Future<void> receivedMessage(Message msg, {bool skipAuth = false}) async {
GeigerApi.logger.info('## got message in plugin $id => $msg');
if (!isMaster && msg.sourceId != GeigerApi.masterId) return;
final pluginInfo = plugins[StorableString(msg.sourceId)];
// TODO: match behavior of Java version for increased security
// only when excluding all these events from authentication, will starting the master app from the client app work
if (!ignoreMessageSignature &&
!skipAuth &&
msg.type != MessageType.authError &&
msg.type != MessageType.registerPlugin &&
((isMaster &&
(pluginInfo == null ||
msg.hash != msg.integrityHash(pluginInfo.secret))) ||
(!isMaster &&
pluginInfo != null &&
msg.hash != msg.integrityHash(pluginInfo.secret)))) {
await sendMessage(Message(
id, msg.sourceId, MessageType.authError, null, null, msg.requestId));
return;
}
switch (msg.type) {
case MessageType.enableMenu:
final item = menuItems[StorableString(msg.payloadString)];
if (item != null) {
item.enabled = true;
}
await sendMessage(Message(id, msg.sourceId, MessageType.comapiSuccess,
GeigerUrl(null, msg.sourceId, 'enableMenu'), null, msg.requestId));
break;
case MessageType.disableMenu:
final item = menuItems[StorableString(msg.payloadString)];
if (item != null) {
item.enabled = false;
}
await sendMessage(Message(id, msg.sourceId, MessageType.comapiSuccess,
GeigerUrl(null, msg.sourceId, 'disableMenu'), null, msg.requestId));
break;
case MessageType.registerMenu:
final item =
await MenuItem.fromByteArrayStream(ByteStream(null, msg.payload));
menuItems[StorableString(item.menu.path)] = item;
await sendMessage(Message(
id,
msg.sourceId,
MessageType.comapiSuccess,
GeigerUrl(null, msg.sourceId, 'registerMenu'),
null,
msg.requestId));
break;
case MessageType.deregisterMenu:
final menuString = utf8.fuse(base64).decode(msg.payloadString!);
menuItems.remove(StorableString(menuString));
await sendMessage(Message(
id,
msg.sourceId,
MessageType.comapiSuccess,
GeigerUrl(null, msg.sourceId, 'deregisterMenu'),
null,
msg.requestId));
break;
case MessageType.registerPlugin:
PluginInformation info =
await PluginInformation.fromByteArray(msg.payload);
final keyPair = await _keyExchangeAlgorithm.newKeyPair();
final secret = await _keyExchangeAlgorithm.sharedSecretKey(
keyPair: keyPair,
remotePublicKey: SimplePublicKey(info.secret.secret,
type: _keyExchangeAlgorithm.keyPairType));
info.secret = CommunicationSecret(await secret.extractBytes());
ByteSink sink = ByteSink();
info.toByteArrayStream(sink);
sink.close();
msg.payload = await sink.bytes;
await sendMessageDirect(
Message(
id,
msg.sourceId,
MessageType.comapiSuccess,
GeigerUrl(null, msg.sourceId, 'registerPlugin'),
(await keyPair.extractPublicKey()).bytes,
msg.requestId),
null,
info);
if (autoAcceptRegistration) {
await _registerPlugin(info);
await sendMessageDirect(Message(id, info.id, MessageType.authSuccess,
GeigerUrl(null, info.id, 'registerPlugin')));
}
break;
case MessageType.authorizePlugin:
if (autoAcceptRegistration) break;
final stream = ByteStream(null, msg.payload);
final isAccepted = await SerializerHelper.readInt(stream) == 1;
final info = await PluginInformation.fromByteArrayStream(stream);
MessageType type = MessageType.authError;
if (isAccepted) {
await _registerPlugin(info);
type = MessageType.authSuccess;
}
await sendMessage(Message(
id, info.id, type, GeigerUrl(null, info.id, 'registerPlugin')));
break;
case MessageType.deregisterPlugin:
await sendMessageDirect(Message(
id,
msg.sourceId,
MessageType.comapiSuccess,
GeigerUrl(null, msg.sourceId, 'deregisterPlugin'),
null,
msg.requestId));
await deregisterPlugin(msg.sourceId);
break;
case MessageType.activatePlugin:
{
final PluginInformation pluginInfo =
plugins[StorableString(msg.sourceId)]!;
final port = SerializerHelper.byteArrayToInt(msg.payload);
plugins[StorableString(msg.sourceId)] = PluginInformation(
msg.sourceId,
pluginInfo.getExecutable(),
port,
pluginInfo.declaration,
pluginInfo.secret);
await sendMessage(Message(
id,
msg.sourceId,
MessageType.comapiSuccess,
GeigerUrl(null, msg.sourceId, 'activatePlugin'),
null,
msg.requestId));
break;
}
case MessageType.deactivatePlugin:
{
var pluginInfo = plugins[StorableString(msg.sourceId)]!;
await sendMessage(Message(
id,
msg.sourceId,
MessageType.comapiSuccess,
GeigerUrl(null, msg.sourceId, 'deactivatePlugin'),
null,
msg.requestId));
plugins[StorableString(msg.sourceId)] = PluginInformation(
msg.sourceId,
pluginInfo.getExecutable(),
0,
pluginInfo.declaration,
pluginInfo.secret);
break;
}
case MessageType.scanPressed:
if (isMaster) {
await scanButtonPressed();
}
// if its not the Master there should be a listener registered for this event
break;
case MessageType.ping:
{
await sendMessage(
Message(id, msg.sourceId, MessageType.pong,
GeigerUrl(null, msg.sourceId, ''), msg.payload, msg.requestId),
);
break;
}
default:
break;
}
_notifyListeners(msg.type, msg);
if (msg.type.id < MessageType.allEvents.id) {
_notifyListeners(MessageType.allEvents, msg);
}
}