1

I have the following class holding an std::vector as a resizable "buffer" for data.

class packet
{
public:
    struct PacketHeader
    {
        size_t dataSize = 0;
        size_t paddedDataSize = 0;
    } header_;

    const unsigned char* data() const
    {
        return &data_[0];
    }

    unsigned char* data()
    {
        return &data_[0];
    }

    /// changes the size of the data vector
    void resize(size_t sz)
    {
       header_.dataSize = sz;

        // check if padding is needed
        if (sz % AES_BLOCK_SIZE != 0){
            auto padding = AES_BLOCK_SIZE - (sz % AES_BLOCK_SIZE);      
            data_.resize(sz + padding);
            for (int i = 1; i <= padding; i++)
            {               
                data_[(sz + padding) - i] = '\0';
            }
            header_.paddedDataSize = sz + padding;
        } else{         
            data_.resize(sz);
        }
    }

private:    
    std::vector<unsigned char> data_;   
};

Then I'm performing some AES encryption on the data before transfering them over the network, which requires another temporary buffer of the same size to generate the ciphertext, which then has to be copied back into the vector.

void TcpConnection::send_packet(packet& pkg)
{
    // I cut out all the unrelevant lines of code

    // We need a temporary buffer for the encryption
    unsigned char* enc_out = (unsigned char*)malloc(pkg.header_.paddedDataSize);

    // AES-128 bit CBC encryption
    aes_cbc_encrypt(pkg.data(), enc_out, pkg.header_.paddedDataSize);

    // now I need to copy all the data back from the temporary buffer into the objects vector

    memcpy(pkg.data(), enc_out, pkg.header_.paddedDataSize);    

    free(enc_out);

    io_service_.post([this, pkg]() { transmit(pkg); });
}

This seems like a rather expensive task. Isn't there a better way, to kind of let the vector take ownership of the temporary buffer (did I understand it correctly that these new std::move and rvalue move semantics are used for this kind of stuff?)

netik
  • 1,736
  • 4
  • 22
  • 45

1 Answers1

1

Move semantics can help avoid the copy.

However instead of malloc'ing the buffer for the encrypted data, use a vector. You can then use std::move to replace the contents of the packet's data_ member.

  • Thank you, should I better do it this way or use the suggested std::swap? – netik Apr 21 '16 at 21:15
  • std::swap will use a move so won't cost any more. The difference is that it will preserve the previous contents of the packet by moving it into the encrypted data vector.Just performing the move will leave the encrypted data vector empty and immediately – Graham Rushton Apr 21 '16 at 21:18
  • release the previous contents of the packet. – Graham Rushton Apr 21 '16 at 21:19