blob: 42cecea240b80c75c76db1c9f1ffa067777c783f [file] [log] [blame]
Austin Schuhe84c3ed2019-12-14 15:29:48 -08001#ifndef AOS_NETWORK_SCTP_LIB_H_
2#define AOS_NETWORK_SCTP_LIB_H_
3
4#include <arpa/inet.h>
5#include <netinet/sctp.h>
6
7#include <memory>
Austin Schuh507f7582021-07-31 20:39:55 -07008#include <optional>
Austin Schuhe84c3ed2019-12-14 15:29:48 -08009#include <string>
10#include <string_view>
Austin Schuha705d782021-07-31 20:40:00 -070011#include <vector>
Austin Schuhe84c3ed2019-12-14 15:29:48 -080012
Austin Schuhe84c3ed2019-12-14 15:29:48 -080013#include "gflags/gflags.h"
14#include "glog/logging.h"
15
Philipp Schrader790cb542023-07-05 21:06:52 -070016#include "aos/unique_malloc_ptr.h"
17
Austin Schuhe84c3ed2019-12-14 15:29:48 -080018namespace aos {
19namespace message_bridge {
20
Austin Schuh0a0a8272021-12-08 13:19:32 -080021// Check if ipv6 is enabled.
22// If we don't try IPv6, and omit AI_ADDRCONFIG when resolving addresses, the
23// library will happily resolve nodes to IPv6 IPs that can't be used. If we add
24// AI_ADDRCONFIG, the unit tests no longer work because they only have loopback
25// addresses available.
26bool Ipv6Enabled();
27
Austin Schuhe84c3ed2019-12-14 15:29:48 -080028// Resolves a socket and returns the address. This can be either an ipv4 or
29// ipv6 address.
Austin Schuh0a0a8272021-12-08 13:19:32 -080030struct sockaddr_storage ResolveSocket(std::string_view host, int port,
31 bool use_ipv6);
Austin Schuhe84c3ed2019-12-14 15:29:48 -080032
33// Returns a formatted version of the address.
34std::string Address(const struct sockaddr_storage &sockaddr);
35// Returns a formatted version of the address family.
36std::string_view Family(const struct sockaddr_storage &sockaddr);
37
38// Message received.
39// This message is malloced bigger than needed and the extra space after it is
40// the data.
41struct Message {
42 // Struct to let us force data to be well aligned.
43 struct OveralignedChar {
44 uint8_t data alignas(32);
45 };
46
47 // Headers.
48 struct {
49 struct sctp_rcvinfo rcvinfo;
50 } header;
51
52 // Address of the sender.
53 struct sockaddr_storage sin;
54
55 // Data type. Is it a block of data, or is it a struct sctp_notification?
56 enum MessageType { kMessage, kNotification } message_type;
57
58 size_t size = 0u;
59 uint8_t *mutable_data() {
60 return reinterpret_cast<uint8_t *>(&actual_data[0].data);
61 }
62 const uint8_t *data() const {
63 return reinterpret_cast<const uint8_t *>(&actual_data[0].data);
64 }
65
Austin Schuhc4202572021-03-31 21:06:55 -070066 uint32_t partial_deliveries = 0;
67
Austin Schuhe84c3ed2019-12-14 15:29:48 -080068 // Returns a human readable peer IP address.
69 std::string PeerAddress() const;
70
71 // Prints out the RcvInfo structure.
72 void LogRcvInfo() const;
73
74 // The start of the data.
75 OveralignedChar actual_data[];
76};
77
78void PrintNotification(const Message *msg);
79
80std::string GetHostname();
81
82// Gets and logs the contents of the sctp_status message.
83void LogSctpStatus(int fd, sctp_assoc_t assoc_id);
84
Austin Schuh507f7582021-07-31 20:39:55 -070085// Manages reading and writing SCTP messages.
86class SctpReadWrite {
87 public:
88 SctpReadWrite() = default;
89 ~SctpReadWrite() { CloseSocket(); }
90
91 // Opens a new socket.
92 void OpenSocket(const struct sockaddr_storage &sockaddr_local);
93
94 // Sends a message to the kernel.
95 // Returns true for success. Will not send a partial message on failure.
96 bool SendMessage(int stream, std::string_view data, int time_to_live,
97 std::optional<struct sockaddr_storage> sockaddr_remote,
98 sctp_assoc_t snd_assoc_id);
99
100 // Reads from the kernel until a complete message is received or it blocks.
101 // Returns nullptr if the kernel blocks before returning a complete message.
102 aos::unique_c_ptr<Message> ReadMessage();
103
Sarah Newman80e955e2022-04-13 11:19:36 -0700104 // Send an abort message for the given association.
105 bool Abort(sctp_assoc_t snd_assoc_id);
106
Austin Schuh507f7582021-07-31 20:39:55 -0700107 int fd() const { return fd_; }
108
Austin Schuh89e1e9c2023-05-15 14:38:44 -0700109 void SetMaxReadSize(size_t max_size) {
Austin Schuha705d782021-07-31 20:40:00 -0700110 CHECK(partial_messages_.empty())
111 << ": May not update size with queued fragments because we do not "
112 "track individual message sizes";
Austin Schuh89e1e9c2023-05-15 14:38:44 -0700113 max_read_size_ = max_size;
114 if (fd_ != -1) {
115 DoSetMaxSize();
116 }
117 }
118
119 void SetMaxWriteSize(size_t max_size) {
120 CHECK(partial_messages_.empty())
121 << ": May not update size with queued fragments because we do not "
122 "track individual message sizes";
123 max_write_size_ = max_size;
Austin Schuh507f7582021-07-31 20:39:55 -0700124 if (fd_ != -1) {
125 DoSetMaxSize();
126 }
127 }
128
Austin Schuhf95a6ab2023-05-15 14:34:57 -0700129 // Returns a message returned from ReadMessage back to the pool.
130 void FreeMessage(aos::unique_c_ptr<Message> &&message);
131
132 // Allocates messages for the pool. SetMaxSize must be set first.
133 void SetPoolSize(size_t pool_size);
134
Austin Schuh507f7582021-07-31 20:39:55 -0700135 private:
Austin Schuhf95a6ab2023-05-15 14:34:57 -0700136 aos::unique_c_ptr<Message> AcquireMessage();
137
Austin Schuh507f7582021-07-31 20:39:55 -0700138 void CloseSocket();
139 void DoSetMaxSize();
140
Austin Schuha705d782021-07-31 20:40:00 -0700141 // Examines a notification message for ones we handle here.
142 // Returns true if the notification was handled by this class.
143 bool ProcessNotification(const Message *message);
144
Austin Schuh507f7582021-07-31 20:39:55 -0700145 int fd_ = -1;
146
147 // We use this as a unique identifier that just increments for each message.
148 uint32_t send_ppid_ = 0;
149
Austin Schuh89e1e9c2023-05-15 14:38:44 -0700150 size_t max_read_size_ = 1000;
151 size_t max_write_size_ = 1000;
Austin Schuha705d782021-07-31 20:40:00 -0700152
153 std::vector<aos::unique_c_ptr<Message>> partial_messages_;
Austin Schuhf95a6ab2023-05-15 14:34:57 -0700154
155 bool use_pool_ = false;
156 std::vector<aos::unique_c_ptr<Message>> free_messages_;
Austin Schuh507f7582021-07-31 20:39:55 -0700157};
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800158
Austin Schuh2fe4b712020-03-15 14:21:45 -0700159// Returns the max network buffer available for reading for a socket.
160size_t ReadRMemMax();
161// Returns the max network buffer available for writing for a socket.
162size_t ReadWMemMax();
163
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800164} // namespace message_bridge
165} // namespace aos
166
167#endif // AOS_NETWORK_SCTP_LIB_H_