blob: c4951805e23ea66018a3ed9be28a85717ed8a7c5 [file] [log] [blame]
Austin Schuhe84c3ed2019-12-14 15:29:48 -08001#include "aos/network/sctp_server.h"
2
3#include <arpa/inet.h>
Adam Snaiderbe263512023-05-18 20:40:23 -07004#include <linux/sctp.h>
Austin Schuhe84c3ed2019-12-14 15:29:48 -08005#include <net/if.h>
6#include <netdb.h>
7#include <netinet/in.h>
Austin Schuhe84c3ed2019-12-14 15:29:48 -08008#include <sys/socket.h>
Tyler Chatowbf0609c2021-07-31 16:13:27 -07009
10#include <cstdio>
11#include <cstdlib>
12#include <cstring>
Austin Schuhe84c3ed2019-12-14 15:29:48 -080013#include <memory>
Austin Schuh387b7de2020-03-15 14:28:07 -070014#include <thread>
Austin Schuhe84c3ed2019-12-14 15:29:48 -080015
Austin Schuh99f7c6a2024-06-25 22:07:44 -070016#include "absl/log/check.h"
17#include "absl/log/log.h"
Philipp Schrader790cb542023-07-05 21:06:52 -070018
Austin Schuhe84c3ed2019-12-14 15:29:48 -080019#include "aos/network/sctp_lib.h"
20#include "aos/unique_malloc_ptr.h"
Austin Schuhe84c3ed2019-12-14 15:29:48 -080021
Stephan Pleinesf63bde82024-01-13 15:59:33 -080022namespace aos::message_bridge {
Austin Schuhe84c3ed2019-12-14 15:29:48 -080023
Adam Snaider96a0f4b2023-05-18 20:41:19 -070024SctpServer::SctpServer(int streams, std::string_view local_host, int local_port,
Adam Snaider9bb33442023-06-26 16:31:37 -070025 SctpAuthMethod requested_authentication)
26 : sctp_(requested_authentication) {
Austin Schuh0a0a8272021-12-08 13:19:32 -080027 bool use_ipv6 = Ipv6Enabled();
28 sockaddr_local_ = ResolveSocket(local_host, local_port, use_ipv6);
Austin Schuh387b7de2020-03-15 14:28:07 -070029 while (true) {
Austin Schuh507f7582021-07-31 20:39:55 -070030 sctp_.OpenSocket(sockaddr_local_);
Austin Schuhe84c3ed2019-12-14 15:29:48 -080031
Austin Schuh387b7de2020-03-15 14:28:07 -070032 {
Brian Silverman833dfb62021-11-03 10:47:55 -070033 struct sctp_initmsg initmsg;
34 memset(&initmsg, 0, sizeof(struct sctp_initmsg));
35 initmsg.sinit_num_ostreams = streams;
36 initmsg.sinit_max_instreams = streams;
37 PCHECK(setsockopt(fd(), IPPROTO_SCTP, SCTP_INITMSG, &initmsg,
38 sizeof(struct sctp_initmsg)) == 0);
39 }
40
41 {
Austin Schuh387b7de2020-03-15 14:28:07 -070042 // Turn off the NAGLE algorithm.
43 int on = 1;
Austin Schuh507f7582021-07-31 20:39:55 -070044 PCHECK(setsockopt(fd(), IPPROTO_SCTP, SCTP_NODELAY, &on, sizeof(int)) ==
Austin Schuh387b7de2020-03-15 14:28:07 -070045 0);
46 }
47
Austin Schuhf6ed4522020-12-13 16:40:38 -080048 {
49 int on = 1;
Austin Schuh507f7582021-07-31 20:39:55 -070050 LOG(INFO) << "setsockopt(" << fd()
51 << ", SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)";
52 PCHECK(setsockopt(fd(), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) == 0);
Austin Schuhf6ed4522020-12-13 16:40:38 -080053 }
54
Austin Schuh387b7de2020-03-15 14:28:07 -070055 // And go!
Austin Schuh507f7582021-07-31 20:39:55 -070056 if (bind(fd(), (struct sockaddr *)&sockaddr_local_,
Austin Schuh387b7de2020-03-15 14:28:07 -070057 sockaddr_local_.ss_family == AF_INET6
58 ? sizeof(struct sockaddr_in6)
59 : sizeof(struct sockaddr_in)) != 0) {
60 PLOG(ERROR) << "Failed to bind, retrying";
Austin Schuh507f7582021-07-31 20:39:55 -070061 close(fd());
Austin Schuh387b7de2020-03-15 14:28:07 -070062 std::this_thread::sleep_for(std::chrono::seconds(5));
63 continue;
64 }
Austin Schuh507f7582021-07-31 20:39:55 -070065 LOG(INFO) << "bind(" << fd() << ", " << Address(sockaddr_local_) << ")";
Austin Schuh387b7de2020-03-15 14:28:07 -070066
Austin Schuh507f7582021-07-31 20:39:55 -070067 PCHECK(listen(fd(), 100) == 0);
Austin Schuh387b7de2020-03-15 14:28:07 -070068
Austin Schuh89e1e9c2023-05-15 14:38:44 -070069 SetMaxReadSize(1000);
70 SetMaxWriteSize(1000);
Austin Schuh387b7de2020-03-15 14:28:07 -070071 break;
Austin Schuhe84c3ed2019-12-14 15:29:48 -080072 }
Austin Schuhe84c3ed2019-12-14 15:29:48 -080073}
74
Sarah Newman1e1b0492023-01-12 14:57:31 -080075void SctpServer::SetPriorityScheduler([[maybe_unused]] sctp_assoc_t assoc_id) {
76// Kernel 4.9 does not have SCTP_SS_PRIO
77#ifdef SCTP_SS_PRIO
Austin Schuhe84c3ed2019-12-14 15:29:48 -080078 struct sctp_assoc_value scheduler;
79 memset(&scheduler, 0, sizeof(scheduler));
80 scheduler.assoc_id = assoc_id;
81 scheduler.assoc_value = SCTP_SS_PRIO;
82 if (setsockopt(fd(), IPPROTO_SCTP, SCTP_STREAM_SCHEDULER, &scheduler,
83 sizeof(scheduler)) != 0) {
James Kuszmaul18e71182023-09-04 15:32:49 -070084 PLOG(FATAL) << "Failed to set scheduler.";
Austin Schuhe84c3ed2019-12-14 15:29:48 -080085 }
Sarah Newman1e1b0492023-01-12 14:57:31 -080086#endif
Austin Schuhe84c3ed2019-12-14 15:29:48 -080087}
88
Sarah Newman1e1b0492023-01-12 14:57:31 -080089void SctpServer::SetStreamPriority([[maybe_unused]] sctp_assoc_t assoc_id,
90 [[maybe_unused]] int stream_id,
91 [[maybe_unused]] uint16_t priority) {
92// Kernel 4.9 does not have SCTP_STREAM_SCHEDULER_VALUE
93#ifdef SCTP_STREAM_SCHEDULER_VALUE
Austin Schuhe84c3ed2019-12-14 15:29:48 -080094 struct sctp_stream_value sctp_priority;
95 memset(&sctp_priority, 0, sizeof(sctp_priority));
96 sctp_priority.assoc_id = assoc_id;
97 sctp_priority.stream_id = stream_id;
98 sctp_priority.stream_value = priority;
99 if (setsockopt(fd(), IPPROTO_SCTP, SCTP_STREAM_SCHEDULER_VALUE,
100 &sctp_priority, sizeof(sctp_priority)) != 0) {
James Kuszmaul18e71182023-09-04 15:32:49 -0700101 // Treat "Protocol not available" as equivalent to the
102 // SCTP_STREAM_SCHEDULER_VALUE not being defined--silently ignore it.
103 if (errno == ENOPROTOOPT) {
104 VLOG(1) << "Stream scheduler not supported on this kernel.";
105 return;
106 }
107 PLOG(FATAL) << "Failed to set scheduler.";
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800108 }
Sarah Newman1e1b0492023-01-12 14:57:31 -0800109#endif
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800110}
111
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800112} // namespace aos::message_bridge