ErrorCode LTSendBuffer::Frame::PrepareForSending(LTSendBuffer & sendBuffer) { Invariant(!preparedForSending_); preparedForSending_ = true; ErrorCode error = EncryptIfNeeded(sendBuffer); if (!error.IsSuccess()) { return error; } if (!encrypted_.empty()) { Invariant(shouldEncrypt_); sendBuffer.preparedBuffers_.emplace_back(ConstBuffer(encrypted_.data(), encrypted_.size())); sendBuffer.sendingLength_ += encrypted_.size(); return error; } // add frame header if (message_->Actor != Actor::SecurityContext) { sendBuffer.preparedBuffers_.emplace_back(ConstBuffer(&header_, sizeof(header_))); sendBuffer.sendingLength_ += sizeof(header_); } // add message body for (BufferIterator chunk = message_->BeginBodyChunks(); chunk != message_->EndBodyChunks(); ++chunk) { if (chunk->size() == 0) continue; sendBuffer.preparedBuffers_.emplace_back(ConstBuffer(chunk->cbegin(), chunk->size())); sendBuffer.sendingLength_ += chunk->size(); } return error; }
ErrorCode LTSendBuffer::Frame::EncryptIfNeeded(LTSendBuffer & sendBuffer) { if (!shouldEncrypt_) { return ErrorCode(); } #ifdef PLATFORM_UNIX auto securityContext = sendBuffer.connection_->securityContext_.get(); Invariant(securityContext->TransportSecurity().SecurityProvider == SecurityProvider::Ssl); auto securityContextSsl = (SecurityContextSsl*)securityContext; //LINUXTODO avoid data copying during encryption auto reserveSize = sizeof(header_) + message_->SerializedBodySize(); ByteBuffer2 buffer(reserveSize); TcpConnection::WriteNoise( TraceType, sendBuffer.connection_->TraceId(), "Encrypt: {0}, plaintext length (including frame header) = {1}", message_->TraceId(), buffer.size()); buffer.append(&header_, sizeof(header_)); for (BufferIterator chunk = message_->BeginBodyChunks(); chunk != message_->EndBodyChunks(); ++chunk) { buffer.append(chunk->cbegin(), chunk->size()); } Invariant(buffer.size() == reserveSize); auto error = securityContextSsl->Encrypt(buffer.data(), buffer.size()); if (!error.IsSuccess()) return error; encrypted_ = securityContextSsl->EncryptFinal(); // adjust for size change due to encryption auto bufferedBefore = sendBuffer.totalBufferedBytes_; sendBuffer.totalBufferedBytes_ -= buffer.size(); sendBuffer.totalBufferedBytes_ += encrypted_.size(); TcpConnection::WriteNoise( TraceType, sendBuffer.connection_->TraceId(), "Encrypt: plain = {0}, encrypted = {1}, totalBufferedBytes_: before = {2}, after = {3}", buffer.size(), encrypted_.size(), bufferedBefore, sendBuffer.totalBufferedBytes_); return error; #else sendBuffer; Assert::CodingError("not implemented"); #endif }