int WdtSocket::readAndDecryptWithTag()

in util/WdtSocket.cpp [253:308]


int WdtSocket::readAndDecryptWithTag(char *buf, int nbyte, int timeoutMs,
                                     bool tryFull) {
  WDT_CHECK_GT(readTagInterval_, 0);
  WDT_CHECK_LE(nbyte, readTagInterval_);
  // first try to figure out whether this read will contain a tag
  const int nextTagOffset = computeNextTagOffset(totalRead_, readTagInterval_);

  int numRead = 0;
  if (nextTagOffset < nbyte) {
    // tag is contained in this read
    if (nextTagOffset > 0) {
      // try to read till the tag
      const int ret = readAndDecrypt(buf, nextTagOffset, timeoutMs, tryFull);
      if (ret <= 0) {
        // read error
        return ret;
      }
      totalRead_ += ret;
      if (ret < nextTagOffset) {
        // couldn't read till the tag. Tag will get read during next read
        return ret;
      }
      WDT_CHECK_EQ(nextTagOffset, ret);
      numRead = ret;
    }
    WDT_CHECK_EQ(0, totalRead_ % readTagInterval_);
    // now read and verify tag
    const std::string tag = readEncryptionTag();
    if (tag.empty()) {
      // readEncryptionTag already logs error
      return -1;
    }
    if (!decryptor_->verifyTag(tag)) {
      // verifyTag logs
      readErrorCode_ = ENCRYPTION_ERROR;
      return -1;
    }
    // tag verification successful, inform higher layer
    if (tagVerificationSuccessCallback_ != nullptr) {
      tagVerificationSuccessCallback_();
    }
    if (!checkAndChangeDecryptionIv(tag)) {
      readErrorCode_ = ENCRYPTION_ERROR;
      return -1;
    }
  }
  // now try to read rest of the data
  const int ret =
      readAndDecrypt(buf + numRead, nbyte - numRead, timeoutMs, tryFull);
  if (ret <= 0) {
    // read error
    return (numRead > 0 ? numRead : ret);
  }
  totalRead_ += ret;
  return numRead + ret;
}