receivedMessage method

Future<void> receivedMessage(
  1. Message msg, {
  2. bool skipAuth = false,
})

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);
  }
}