Ejemplo n.º 1
0
  void BulkRound::HandleBulkData(QDataStream &stream, const Id &from)
  {
    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() <<
      ": received bulk data from " << GetGroup().GetIndex(from) << from.ToString();

    if(IsLeader() || !_app_broadcast) {
      if(_state != DataSharing) {
        throw QRunTimeError("Received a misordered BulkData message");
      }
    } else if(_app_broadcast && _state != ProcessingLeaderData) {
      throw QRunTimeError("Waiting for data from leader, received something else.");
    }

    int idx = GetGroup().GetIndex(from);
    if(!_messages[idx].isEmpty()) {
      throw QRunTimeError("Already have bulk data.");
    }

    QByteArray payload;
    stream >> payload;

    if(payload.size() != _expected_bulk_size) {
      throw QRunTimeError("Incorrect bulk message length");
    }

    _messages[idx] = payload;

    if(++_received_messages == GetGroup().Count()) {
      ProcessMessages();
      Finish();
    }
  }
Ejemplo n.º 2
0
  void RepeatingBulkRound::ProcessDataBase(const Id &from, const QByteArray &data)
  {
    QByteArray payload;
    if(!Verify(from, data, payload)) {
      throw QRunTimeError("Invalid signature or data");
    }

    if(_state == Offline) {
      throw QRunTimeError("Should never receive a message in the bulk"
          " round while offline.");
    }

    QDataStream stream(payload);

    int mtype;
    QByteArray round_id;
    uint phase;
    stream >> mtype >> round_id >> phase;

    MessageType msg_type = (MessageType) mtype;

    Id rid(round_id);
    if(rid != GetRoundId()) {
      throw QRunTimeError("Not this round: " + rid.ToString() + " " +
          GetRoundId().ToString());
    }

    if(_state == Shuffling) {
      _log.Pop();
      _offline_log.Append(data, from);
      return;
    }

    if(_phase != phase) {
      if(_phase == phase - 1 && _state == DataSharing) {
        _log.Pop();
        _offline_log.Append(data, from);
        return;
      } else {
        throw QRunTimeError("Received a message for phase: " + 
            QString::number(phase) + ", while in phase: " +
            QString::number(_phase));
      }
    } else if(_state == PhasePreparation) {
      _log.Pop();
      _offline_log.Append(data, from);
      return;
    }

    switch(msg_type) {
      case BulkData:
        HandleBulkData(stream, from);
        break;
      default:
        throw QRunTimeError("Unknown message type");
    }
  }
Ejemplo n.º 3
0
  void RepeatingBulkRound::HandleBulkData(QDataStream &stream, const Id &from)
  {
    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() <<
      ": received bulk data from " << GetGroup().GetIndex(from) << from.ToString()
      << "Have" << (_received_messages + 1) << "expecting" << _messages.count();

    if(_state != DataSharing) {
      throw QRunTimeError("Received a misordered BulkData message");
    }

    uint idx = GetGroup().GetIndex(from);
    if(!_messages[idx].isEmpty()) {
      throw QRunTimeError("Already have bulk data.");
    }

    QByteArray payload;
    stream >> payload;

    if(static_cast<uint>(payload.size()) != _expected_bulk_size) {
      throw QRunTimeError("Incorrect bulk message length, got " +
          QString::number(payload.size()) + " expected " +
          QString::number(_expected_bulk_size));
    }

    _messages[idx] = payload;

    if(++_received_messages == static_cast<uint>(GetGroup().Count())) {
      ProcessMessages();

      SetState(PhasePreparation);
      qDebug() << "In" << ToString() << "ending phase.";
      _phase++;
      if(!PrepForNextPhase()) {
        return;
      }

      SetState(DataSharing);

      uint count = static_cast<uint>(_offline_log.Count());
      for(uint idx = 0; idx < count; idx++) {
        QPair<QByteArray, Id> entry = _offline_log.At(idx);
        ProcessData(entry.second, entry.first);
      }

      _offline_log.Clear();

      NextPhase();
    }
  }
Ejemplo n.º 4
0
  void BulkRound::ProcessDataBase(const Id &from, const QByteArray &data)
  {
    QByteArray payload;
    if(!Verify(from, data, payload)) {
      throw QRunTimeError("Invalid signature or data");
    }

    if(_state == Offline) {
      throw QRunTimeError("Should never receive a message in the bulk"
          " round while offline.");
    }

    QDataStream stream(payload);

    int mtype;
    QByteArray round_id;
    stream >> mtype >> round_id;

    MessageType msg_type = (MessageType) mtype;

    Id rid(round_id);
    if(rid != GetRoundId()) {
      throw QRunTimeError("Not this round: " + rid.ToString() + " " +
          GetRoundId().ToString());
    }

    if(_state == Shuffling) {
      _log.Pop();
      _offline_log.Append(data, from);
      return;
    }

    switch(msg_type) {
      case BulkData:
        HandleBulkData(stream, from);
        break;
      case LoggedBulkData:
        HandleLoggedBulkData(stream, from);
        break;
      case AggregatedBulkData:
        HandleAggregatedBulkData(stream, from);
        break;
      default:
        throw QRunTimeError("Unknown message type");
    }
  }
Ejemplo n.º 5
0
  void BulkRound::HandleAggregatedBulkData(QDataStream &stream, const Id &from)
  {
    if(from == GetLocalId()) {
      return;
    }

    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() <<
      ": received aggregated bulk data from " << GetGroup().GetIndex(from) <<
      from.ToString();

    if(GetGroup().GetLeader() != from) {
      throw QRunTimeError("Received aggregated bulk data from non-leader.");
    }

    if(_state != ReceivingLeaderData) {
      throw QRunTimeError("Not expected at this time.");
    }

    QVector<QByteArray> cleartexts;
    stream >> cleartexts;

    const QVector<Descriptor> &des = GetDescriptors();

    if(cleartexts.count() != des.count()) {
      throw QRunTimeError("Cleartext count does not match descriptor count: " +
          QString::number(cleartexts.count()) + " " +
          QString::number(des.count()));
    }

    Hash hashalgo;

    for(int idx = 0; idx < cleartexts.count(); idx++) {
      QByteArray cleartext = cleartexts[idx];
      QByteArray hash = hashalgo.ComputeHash(cleartext);
      if(hash != des[idx].CleartextHash()) {
        throw QRunTimeError("Cleartext hash does not match descriptor hash.");
      }
      if(!cleartext.isEmpty()) {
        PushData(GetSharedPointer(), cleartext);
      }
    }

    Finish();
  }
Ejemplo n.º 6
0
  void BulkRound::HandleLoggedBulkData(QDataStream &stream, const Id &from)
  {
    if(from == GetLocalId()) {
      return;
    }

    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() <<
      ": received logged bulk data from " << GetGroup().GetIndex(from) <<
      from.ToString();

    if(GetGroup().GetLeader() != from) {
      throw QRunTimeError("Received logged bulk data from non-leader.");
    }

    if(_state != ReceivingLeaderData) {
      throw QRunTimeError("Not expected at this time.");
    }

    QByteArray binary_log;
    stream >> binary_log;
    Log log(binary_log);
    
    if(log.Count() != GetGroup().Count()) {
      throw QRunTimeError("Incorrect number of log messages.");
    }

    _state = ProcessingLeaderData;
    for(int idx = 0; idx < log.Count(); idx++) {
      const QPair<QByteArray, Id> &res = log.At(idx);
      try {
        ProcessDataBase(res.second, res.first);
      } catch (QRunTimeError &err) {
        const Id &from = res.second;
        qWarning() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() <<
          "leader equivocated in message from" << GetGroup().GetIndex(from) <<
          from.ToString() << "in session / round" << GetRoundId().ToString() <<
          "in state" << StateToString(_state) <<
          "causing the following exception: " << err.What();
        // Should end round.
        break;
      }
    }
  }