1
#pragma once
2

            
3
#include <cstdint>
4
#include <memory>
5

            
6
#include "envoy/api/io_error.h"
7
#include "envoy/buffer/buffer.h"
8
#include "envoy/common/optref.h"
9
#include "envoy/config/core/v3/extension.pb.h"
10
#include "envoy/config/typed_config.h"
11
#include "envoy/config/typed_metadata.h"
12
#include "envoy/network/address.h"
13
#include "envoy/network/socket.h"
14
#include "envoy/stats/scope.h"
15
#include "envoy/stats/stats_macros.h"
16

            
17
namespace Envoy {
18
namespace Network {
19

            
20
/**
21
 * Max v6 packet size, excluding IP and UDP headers.
22
 */
23
constexpr uint64_t UdpMaxOutgoingPacketSize = 1452;
24

            
25
/**
26
 * UdpPacketWriterBuffer bundles a buffer and a function that
27
 * releases it.
28
 */
29
struct UdpPacketWriterBuffer {
30
  UdpPacketWriterBuffer() = default;
31
  UdpPacketWriterBuffer(uint8_t* buffer, size_t length,
32
                        std::function<void(const char*)> release_buffer)
33
575484
      : buffer_(buffer), length_(length), release_buffer_(std::move(release_buffer)) {}
34

            
35
  uint8_t* buffer_ = nullptr;
36
  size_t length_ = 0;
37
  std::function<void(const char*)> release_buffer_;
38
};
39

            
40
class UdpPacketWriter {
41
public:
42
5491
  virtual ~UdpPacketWriter() = default;
43

            
44
  /**
45
   * @brief Sends a packet via given UDP socket with specific source address.
46
   *
47
   * @param buffer points to the buffer containing the packet
48
   * @param local_ip is the source address to be used to send. If it is null,
49
   * picks up the default network interface ip address.
50
   * @param peer_address is the destination address to send to.
51
   * @return result with number of bytes written, and write status
52
   */
53
  virtual Api::IoCallUint64Result writePacket(const Buffer::Instance& buffer,
54
                                              const Address::Ip* local_ip,
55
                                              const Address::Instance& peer_address) PURE;
56

            
57
  /**
58
   * @returns true if the network socket is not writable.
59
   */
60
  virtual bool isWriteBlocked() const PURE;
61

            
62
  /**
63
   * @brief mark the socket as writable when the socket is unblocked.
64
   */
65
  virtual void setWritable() PURE;
66

            
67
  /**
68
   * @brief Get the maximum size of the packet which can be written using this
69
   * writer for the supplied peer address.
70
   *
71
   * @param peer_address  is the destination address to send to.
72
   * @return the max packet size
73
   */
74
  virtual uint64_t getMaxPacketSize(const Address::Instance& peer_address) const PURE;
75

            
76
  /**
77
   * @return true if Batch Mode
78
   * @return false if PassThroughMode
79
   */
80
  virtual bool isBatchMode() const PURE;
81

            
82
  /**
83
   * @brief Get pointer to the next write location in internal buffer,
84
   * it should be called iff the caller does not call writePacket
85
   * for the returned buffer. The caller is expected to call writePacket
86
   * with the buffer returned from this function to save a memcpy.
87
   *
88
   * @param local_ip is the source address to be used to send.
89
   * @param peer_address is the destination address to send to.
90
   * @return { char* to the next write location,
91
   *           func to release buffer }
92
   */
93
  virtual UdpPacketWriterBuffer getNextWriteLocation(const Address::Ip* local_ip,
94
                                                     const Address::Instance& peer_address) PURE;
95

            
96
  /**
97
   * @brief Batch Mode: Try to send all buffered packets
98
   *        PassThrough Mode: NULL operation
99
   *
100
   * @return Api::IoCallUint64Result
101
   */
102
  virtual Api::IoCallUint64Result flush() PURE;
103
};
104

            
105
using UdpPacketWriterPtr = std::unique_ptr<UdpPacketWriter>;
106

            
107
class UdpPacketWriterFactory {
108
public:
109
18465
  virtual ~UdpPacketWriterFactory() = default;
110

            
111
  /**
112
   * Creates an UdpPacketWriter object for the given Udp Socket
113
   * @param io_handle The udp socket used for network I/O operations.
114
   * @param scope Recording statistics associated with the writer.
115
   * @param dispatcher Envoy dispatcher to schedule write block events.
116
   * @param on_can_write_cb Callback to signal when the underlying socket
117
   * becomes writable.
118
   * @return the UdpPacketWriter created.
119
   */
120
  virtual UdpPacketWriterPtr
121
  createUdpPacketWriter(Network::IoHandle& io_handle, Stats::Scope& scope,
122
                        Envoy::Event::Dispatcher& dispatcher,
123
                        absl::AnyInvocable<void() &&> on_can_write_cb) PURE;
124
};
125

            
126
using UdpPacketWriterFactoryPtr = std::unique_ptr<UdpPacketWriterFactory>;
127

            
128
/**
129
 * UdpPacketWriterFactoryFactory adds an extra layer of indirection In order to
130
 * support a UdpPacketWriterFactory whose behavior depends on the
131
 * TypedConfig for that factory. The UdpPacketWriterFactoryFactory is created
132
 * with a no-arg constructor based on the type of the config. Then this
133
 * `createUdpPacketWriterFactory1 can be called with the config to
134
 * create an actual UdpPacketWriterFactory.
135
 */
136
class UdpPacketWriterFactoryFactory : public Envoy::Config::TypedFactory {
137
public:
138
3
  ~UdpPacketWriterFactoryFactory() override = default;
139

            
140
  /**
141
   * Creates an UdpPacketWriterFactory based on the specified config.
142
   * @return the UdpPacketWriterFactory created.
143
   */
144
  virtual UdpPacketWriterFactoryPtr
145
  createUdpPacketWriterFactory(const envoy::config::core::v3::TypedExtensionConfig& config) PURE;
146

            
147
1534
  std::string category() const override { return "envoy.udp_packet_writer"; }
148
};
149

            
150
} // namespace Network
151
} // namespace Envoy