blob: a852365eb4ddb3f557c3c9b06907eb8ab98ffb4c [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
13#include "aos/unique_malloc_ptr.h"
14#include "gflags/gflags.h"
15#include "glog/logging.h"
16
17namespace aos {
18namespace message_bridge {
19
Austin Schuh0a0a8272021-12-08 13:19:32 -080020// Check if ipv6 is enabled.
21// If we don't try IPv6, and omit AI_ADDRCONFIG when resolving addresses, the
22// library will happily resolve nodes to IPv6 IPs that can't be used. If we add
23// AI_ADDRCONFIG, the unit tests no longer work because they only have loopback
24// addresses available.
25bool Ipv6Enabled();
26
Austin Schuhe84c3ed2019-12-14 15:29:48 -080027// Resolves a socket and returns the address. This can be either an ipv4 or
28// ipv6 address.
Austin Schuh0a0a8272021-12-08 13:19:32 -080029struct sockaddr_storage ResolveSocket(std::string_view host, int port,
30 bool use_ipv6);
Austin Schuhe84c3ed2019-12-14 15:29:48 -080031
32// Returns a formatted version of the address.
33std::string Address(const struct sockaddr_storage &sockaddr);
34// Returns a formatted version of the address family.
35std::string_view Family(const struct sockaddr_storage &sockaddr);
36
37// Message received.
38// This message is malloced bigger than needed and the extra space after it is
39// the data.
40struct Message {
41 // Struct to let us force data to be well aligned.
42 struct OveralignedChar {
43 uint8_t data alignas(32);
44 };
45
46 // Headers.
47 struct {
48 struct sctp_rcvinfo rcvinfo;
49 } header;
50
51 // Address of the sender.
52 struct sockaddr_storage sin;
53
54 // Data type. Is it a block of data, or is it a struct sctp_notification?
55 enum MessageType { kMessage, kNotification } message_type;
56
57 size_t size = 0u;
58 uint8_t *mutable_data() {
59 return reinterpret_cast<uint8_t *>(&actual_data[0].data);
60 }
61 const uint8_t *data() const {
62 return reinterpret_cast<const uint8_t *>(&actual_data[0].data);
63 }
64
Austin Schuhc4202572021-03-31 21:06:55 -070065 uint32_t partial_deliveries = 0;
66
Austin Schuhe84c3ed2019-12-14 15:29:48 -080067 // Returns a human readable peer IP address.
68 std::string PeerAddress() const;
69
70 // Prints out the RcvInfo structure.
71 void LogRcvInfo() const;
72
73 // The start of the data.
74 OveralignedChar actual_data[];
75};
76
77void PrintNotification(const Message *msg);
78
79std::string GetHostname();
80
81// Gets and logs the contents of the sctp_status message.
82void LogSctpStatus(int fd, sctp_assoc_t assoc_id);
83
Austin Schuh507f7582021-07-31 20:39:55 -070084// Manages reading and writing SCTP messages.
85class SctpReadWrite {
86 public:
87 SctpReadWrite() = default;
88 ~SctpReadWrite() { CloseSocket(); }
89
90 // Opens a new socket.
91 void OpenSocket(const struct sockaddr_storage &sockaddr_local);
92
93 // Sends a message to the kernel.
94 // Returns true for success. Will not send a partial message on failure.
95 bool SendMessage(int stream, std::string_view data, int time_to_live,
96 std::optional<struct sockaddr_storage> sockaddr_remote,
97 sctp_assoc_t snd_assoc_id);
98
99 // Reads from the kernel until a complete message is received or it blocks.
100 // Returns nullptr if the kernel blocks before returning a complete message.
101 aos::unique_c_ptr<Message> ReadMessage();
102
Sarah Newman80e955e2022-04-13 11:19:36 -0700103 // Send an abort message for the given association.
104 bool Abort(sctp_assoc_t snd_assoc_id);
105
Austin Schuh507f7582021-07-31 20:39:55 -0700106 int fd() const { return fd_; }
107
Austin Schuh89e1e9c2023-05-15 14:38:44 -0700108 void SetMaxReadSize(size_t max_size) {
Austin Schuha705d782021-07-31 20:40:00 -0700109 CHECK(partial_messages_.empty())
110 << ": May not update size with queued fragments because we do not "
111 "track individual message sizes";
Austin Schuh89e1e9c2023-05-15 14:38:44 -0700112 max_read_size_ = max_size;
113 if (fd_ != -1) {
114 DoSetMaxSize();
115 }
116 }
117
118 void SetMaxWriteSize(size_t max_size) {
119 CHECK(partial_messages_.empty())
120 << ": May not update size with queued fragments because we do not "
121 "track individual message sizes";
122 max_write_size_ = max_size;
Austin Schuh507f7582021-07-31 20:39:55 -0700123 if (fd_ != -1) {
124 DoSetMaxSize();
125 }
126 }
127
Austin Schuhf95a6ab2023-05-15 14:34:57 -0700128 // Returns a message returned from ReadMessage back to the pool.
129 void FreeMessage(aos::unique_c_ptr<Message> &&message);
130
131 // Allocates messages for the pool. SetMaxSize must be set first.
132 void SetPoolSize(size_t pool_size);
133
Austin Schuh507f7582021-07-31 20:39:55 -0700134 private:
Austin Schuhf95a6ab2023-05-15 14:34:57 -0700135 aos::unique_c_ptr<Message> AcquireMessage();
136
Austin Schuh507f7582021-07-31 20:39:55 -0700137 void CloseSocket();
138 void DoSetMaxSize();
139
Austin Schuha705d782021-07-31 20:40:00 -0700140 // Examines a notification message for ones we handle here.
141 // Returns true if the notification was handled by this class.
142 bool ProcessNotification(const Message *message);
143
Austin Schuh507f7582021-07-31 20:39:55 -0700144 int fd_ = -1;
145
146 // We use this as a unique identifier that just increments for each message.
147 uint32_t send_ppid_ = 0;
148
Austin Schuh89e1e9c2023-05-15 14:38:44 -0700149 size_t max_read_size_ = 1000;
150 size_t max_write_size_ = 1000;
Austin Schuha705d782021-07-31 20:40:00 -0700151
152 std::vector<aos::unique_c_ptr<Message>> partial_messages_;
Austin Schuhf95a6ab2023-05-15 14:34:57 -0700153
154 bool use_pool_ = false;
155 std::vector<aos::unique_c_ptr<Message>> free_messages_;
Austin Schuh507f7582021-07-31 20:39:55 -0700156};
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800157
Austin Schuh2fe4b712020-03-15 14:21:45 -0700158// Returns the max network buffer available for reading for a socket.
159size_t ReadRMemMax();
160// Returns the max network buffer available for writing for a socket.
161size_t ReadWMemMax();
162
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800163} // namespace message_bridge
164} // namespace aos
165
166#endif // AOS_NETWORK_SCTP_LIB_H_