blob: 8eb57d387aaa2161ebf1c06203a1022fa4be80ba [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>
Adam Snaiderbe263512023-05-18 20:40:23 -07005#include <linux/sctp.h>
Austin Schuhe84c3ed2019-12-14 15:29:48 -08006
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?
Austin Schuh89f23e32023-05-15 17:06:43 -070056 enum MessageType {
57 // Block of data?
58 kMessage,
59 // struct sctp_notification?
60 kNotification,
61 // Client sent too large a message and was disconnected.
62 kOverflow,
63 } message_type;
Austin Schuhe84c3ed2019-12-14 15:29:48 -080064
65 size_t size = 0u;
66 uint8_t *mutable_data() {
67 return reinterpret_cast<uint8_t *>(&actual_data[0].data);
68 }
69 const uint8_t *data() const {
70 return reinterpret_cast<const uint8_t *>(&actual_data[0].data);
71 }
72
Austin Schuhc4202572021-03-31 21:06:55 -070073 uint32_t partial_deliveries = 0;
74
Austin Schuhe84c3ed2019-12-14 15:29:48 -080075 // Returns a human readable peer IP address.
76 std::string PeerAddress() const;
77
78 // Prints out the RcvInfo structure.
79 void LogRcvInfo() const;
80
81 // The start of the data.
82 OveralignedChar actual_data[];
83};
84
85void PrintNotification(const Message *msg);
86
87std::string GetHostname();
88
89// Gets and logs the contents of the sctp_status message.
90void LogSctpStatus(int fd, sctp_assoc_t assoc_id);
91
Austin Schuh507f7582021-07-31 20:39:55 -070092// Manages reading and writing SCTP messages.
93class SctpReadWrite {
94 public:
95 SctpReadWrite() = default;
96 ~SctpReadWrite() { CloseSocket(); }
97
98 // Opens a new socket.
99 void OpenSocket(const struct sockaddr_storage &sockaddr_local);
100
101 // Sends a message to the kernel.
102 // Returns true for success. Will not send a partial message on failure.
103 bool SendMessage(int stream, std::string_view data, int time_to_live,
104 std::optional<struct sockaddr_storage> sockaddr_remote,
105 sctp_assoc_t snd_assoc_id);
106
107 // Reads from the kernel until a complete message is received or it blocks.
108 // Returns nullptr if the kernel blocks before returning a complete message.
109 aos::unique_c_ptr<Message> ReadMessage();
110
Sarah Newman80e955e2022-04-13 11:19:36 -0700111 // Send an abort message for the given association.
112 bool Abort(sctp_assoc_t snd_assoc_id);
113
Austin Schuh507f7582021-07-31 20:39:55 -0700114 int fd() const { return fd_; }
115
Austin Schuh89e1e9c2023-05-15 14:38:44 -0700116 void SetMaxReadSize(size_t max_size) {
Austin Schuha705d782021-07-31 20:40:00 -0700117 CHECK(partial_messages_.empty())
118 << ": May not update size with queued fragments because we do not "
119 "track individual message sizes";
Austin Schuh89e1e9c2023-05-15 14:38:44 -0700120 max_read_size_ = max_size;
121 if (fd_ != -1) {
122 DoSetMaxSize();
123 }
124 }
125
126 void SetMaxWriteSize(size_t max_size) {
127 CHECK(partial_messages_.empty())
128 << ": May not update size with queued fragments because we do not "
129 "track individual message sizes";
130 max_write_size_ = max_size;
Austin Schuh507f7582021-07-31 20:39:55 -0700131 if (fd_ != -1) {
132 DoSetMaxSize();
133 }
134 }
135
Austin Schuhf95a6ab2023-05-15 14:34:57 -0700136 // Returns a message returned from ReadMessage back to the pool.
137 void FreeMessage(aos::unique_c_ptr<Message> &&message);
138
139 // Allocates messages for the pool. SetMaxSize must be set first.
140 void SetPoolSize(size_t pool_size);
141
Austin Schuh507f7582021-07-31 20:39:55 -0700142 private:
Austin Schuhf95a6ab2023-05-15 14:34:57 -0700143 aos::unique_c_ptr<Message> AcquireMessage();
144
Austin Schuh507f7582021-07-31 20:39:55 -0700145 void CloseSocket();
146 void DoSetMaxSize();
147
Austin Schuha705d782021-07-31 20:40:00 -0700148 // Examines a notification message for ones we handle here.
149 // Returns true if the notification was handled by this class.
150 bool ProcessNotification(const Message *message);
151
Austin Schuh507f7582021-07-31 20:39:55 -0700152 int fd_ = -1;
153
154 // We use this as a unique identifier that just increments for each message.
155 uint32_t send_ppid_ = 0;
156
Austin Schuh89e1e9c2023-05-15 14:38:44 -0700157 size_t max_read_size_ = 1000;
158 size_t max_write_size_ = 1000;
Austin Schuha705d782021-07-31 20:40:00 -0700159
160 std::vector<aos::unique_c_ptr<Message>> partial_messages_;
Austin Schuhf95a6ab2023-05-15 14:34:57 -0700161
162 bool use_pool_ = false;
163 std::vector<aos::unique_c_ptr<Message>> free_messages_;
Austin Schuh507f7582021-07-31 20:39:55 -0700164};
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800165
Austin Schuh2fe4b712020-03-15 14:21:45 -0700166// Returns the max network buffer available for reading for a socket.
167size_t ReadRMemMax();
168// Returns the max network buffer available for writing for a socket.
169size_t ReadWMemMax();
170
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800171} // namespace message_bridge
172} // namespace aos
173
174#endif // AOS_NETWORK_SCTP_LIB_H_