std::streamsize CryptoStreamBuf::xsputn()

in sdk/src/encryption/CryptoStreamBuf.cc [164:230]


std::streamsize CryptoStreamBuf::xsputn(const char *_Ptr, std::streamsize _Count)
{
    const std::streamsize startCount = _Count;
    unsigned char block[BLK_SIZE * 2];
    std::streamsize writeCnt;
    //update iv
    if (!initDecrypt) {
        cipher_->DecryptInit(key_, iv_);
        decBufferCnt_ = 0;
        decBufferOff_ = 0;
        initDecrypt = true;
    }

    //append to decBuffer first
    if (decBufferCnt_ > 0) {
        writeCnt = std::min(_Count, (BLK_SIZE - decBufferCnt_));
        memcpy(decBuffer_ + decBufferOff_, _Ptr, static_cast<int>(writeCnt));
        decBufferOff_ += writeCnt;
        decBufferCnt_ += writeCnt;
        _Ptr += writeCnt;
        _Count -= writeCnt;
    }

    //flush decBuffer when its size is BLK_SIZE
    if (decBufferCnt_ == BLK_SIZE) {
        auto ret = cipher_->Decrypt(block, static_cast<int>(BLK_SIZE), decBuffer_, static_cast<int>(BLK_SIZE));
        if (ret < 0) {
            return -1;
        }
        decBufferCnt_ = 0;
        decBufferOff_ = 0;
        writeCnt = xsputn_with_skip(reinterpret_cast<char *>(block), BLK_SIZE);
        if (writeCnt != BLK_SIZE) {
            //Todo Save decrypted data
            return startCount - _Count;
        }
    }

    auto blkOff = _Count / BLK_SIZE;
    auto blkIdx = _Count % BLK_SIZE;

    //decrypt by BLK_SIZE
    for (auto i = std::streamsize(0); i < blkOff; i++) {
        auto ret = cipher_->Decrypt(block, static_cast<int>(BLK_SIZE), reinterpret_cast<const unsigned char *>(_Ptr), static_cast<int>(BLK_SIZE));
        if (ret < 0) {
            return -1;
        }
        _Ptr += BLK_SIZE;
        _Count -= BLK_SIZE;
        writeCnt = xsputn_with_skip(reinterpret_cast<char *>(block), BLK_SIZE);
        if (writeCnt != BLK_SIZE) {
            //Todo Save decrypted data
            return startCount - _Count;
        }
    }

    //save to decBuffer and decrypt next time
    if (blkIdx > 0) {
        memcpy(decBuffer_, _Ptr, static_cast<int>(blkIdx));
        _Ptr += blkIdx;
        _Count -= blkIdx;
        decBufferCnt_ = blkIdx;
        decBufferOff_ = blkIdx;
    }

    return startCount - _Count;
}