1
#include "source/common/quic/envoy_quic_packet_writer.h"
2

            
3
#include <memory>
4

            
5
#include "source/common/buffer/buffer_impl.h"
6
#include "source/common/quic/envoy_quic_utils.h"
7

            
8
namespace Envoy {
9
namespace Quic {
10

            
11
namespace {
12

            
13
596655
quic::WriteResult convertToQuicWriteResult(Api::IoCallUint64Result& result) {
14
596659
  if (result.ok()) {
15
596631
    return {quic::WRITE_STATUS_OK, static_cast<int>(result.return_value_)};
16
596631
  }
17
28
  quic::WriteStatus status = result.err_->getErrorCode() == Api::IoError::IoErrorCode::Again
18
28
                                 ? quic::WRITE_STATUS_BLOCKED
19
28
                                 : quic::WRITE_STATUS_ERROR;
20
28
  return {status, static_cast<int>(result.err_->getSystemErrorCode())};
21
596655
}
22

            
23
} // namespace
24

            
25
EnvoyQuicPacketWriter::EnvoyQuicPacketWriter(Network::UdpPacketWriterPtr envoy_udp_packet_writer)
26
4037
    : envoy_udp_packet_writer_(std::move(envoy_udp_packet_writer)) {}
27

            
28
quic::WriteResult EnvoyQuicPacketWriter::WritePacket(
29
    const char* buffer, size_t buffer_len, const quic::QuicIpAddress& self_ip,
30
    const quic::QuicSocketAddress& peer_address, quic::PerPacketOptions* options,
31
596657
    [[maybe_unused]] const quic::QuicPacketWriterParams& params) {
32
596657
  ASSERT(options == nullptr, "Per packet option is not supported yet.");
33

            
34
596657
  Buffer::BufferFragmentImpl fragment(buffer, buffer_len, nullptr);
35
596657
  Buffer::OwnedImpl buf;
36
596657
  buf.addBufferFragment(fragment);
37

            
38
596657
  quic::QuicSocketAddress self_address(self_ip, /*port=*/0);
39
596657
  Network::Address::InstanceConstSharedPtr local_addr =
40
596657
      quicAddressToEnvoyAddressInstance(self_address);
41
596657
  Network::Address::InstanceConstSharedPtr remote_addr =
42
596657
      quicAddressToEnvoyAddressInstance(peer_address);
43

            
44
596657
  Api::IoCallUint64Result result = envoy_udp_packet_writer_->writePacket(
45
596657
      buf, local_addr == nullptr ? nullptr : local_addr->ip(), *remote_addr);
46

            
47
596657
  return convertToQuicWriteResult(result);
48
596657
}
49

            
50
601835
absl::optional<int> EnvoyQuicPacketWriter::MessageTooBigErrorCode() const { return EMSGSIZE; }
51

            
52
quic::QuicByteCount
53
9739
EnvoyQuicPacketWriter::GetMaxPacketSize(const quic::QuicSocketAddress& peer_address) const {
54
9739
  Network::Address::InstanceConstSharedPtr remote_addr =
55
9739
      quicAddressToEnvoyAddressInstance(peer_address);
56
9739
  return static_cast<quic::QuicByteCount>(envoy_udp_packet_writer_->getMaxPacketSize(*remote_addr));
57
9739
}
58

            
59
quic::QuicPacketBuffer
60
EnvoyQuicPacketWriter::GetNextWriteLocation(const quic::QuicIpAddress& self_ip,
61
575502
                                            const quic::QuicSocketAddress& peer_address) {
62
575502
  quic::QuicSocketAddress self_address(self_ip, /*port=*/0);
63
575502
  Network::Address::InstanceConstSharedPtr local_addr =
64
575502
      quicAddressToEnvoyAddressInstance(self_address);
65
575502
  Network::Address::InstanceConstSharedPtr remote_addr =
66
575502
      quicAddressToEnvoyAddressInstance(peer_address);
67
575502
  Network::UdpPacketWriterBuffer write_location = envoy_udp_packet_writer_->getNextWriteLocation(
68
575502
      local_addr == nullptr ? nullptr : local_addr->ip(), *remote_addr);
69
575502
  return {reinterpret_cast<char*>(write_location.buffer_), write_location.release_buffer_};
70
575502
}
71

            
72
quic::WriteResult EnvoyQuicPacketWriter::Flush() {
73
  Api::IoCallUint64Result result = envoy_udp_packet_writer_->flush();
74
  return convertToQuicWriteResult(result);
75
}
76

            
77
} // namespace Quic
78
} // namespace Envoy