blob: 15da7c0556f98bc139dbdb589aa7e0514f8c94a0 [file] [log] [blame]
Austin Schuhe84c3ed2019-12-14 15:29:48 -08001#include "aos/network/sctp_server.h"
2
3#include <arpa/inet.h>
4#include <net/if.h>
5#include <netdb.h>
6#include <netinet/in.h>
7#include <netinet/sctp.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
16#include "aos/network/sctp_lib.h"
17#include "aos/unique_malloc_ptr.h"
18#include "glog/logging.h"
19
20namespace aos {
21namespace message_bridge {
22
Austin Schuh0a0a8272021-12-08 13:19:32 -080023SctpServer::SctpServer(int streams, std::string_view local_host,
24 int local_port) {
25 bool use_ipv6 = Ipv6Enabled();
26 sockaddr_local_ = ResolveSocket(local_host, local_port, use_ipv6);
Austin Schuh387b7de2020-03-15 14:28:07 -070027 while (true) {
Austin Schuh507f7582021-07-31 20:39:55 -070028 sctp_.OpenSocket(sockaddr_local_);
Austin Schuhe84c3ed2019-12-14 15:29:48 -080029
Austin Schuh387b7de2020-03-15 14:28:07 -070030 {
Brian Silverman833dfb62021-11-03 10:47:55 -070031 struct sctp_initmsg initmsg;
32 memset(&initmsg, 0, sizeof(struct sctp_initmsg));
33 initmsg.sinit_num_ostreams = streams;
34 initmsg.sinit_max_instreams = streams;
35 PCHECK(setsockopt(fd(), IPPROTO_SCTP, SCTP_INITMSG, &initmsg,
36 sizeof(struct sctp_initmsg)) == 0);
37 }
38
39 {
Austin Schuh387b7de2020-03-15 14:28:07 -070040 // Turn off the NAGLE algorithm.
41 int on = 1;
Austin Schuh507f7582021-07-31 20:39:55 -070042 PCHECK(setsockopt(fd(), IPPROTO_SCTP, SCTP_NODELAY, &on, sizeof(int)) ==
Austin Schuh387b7de2020-03-15 14:28:07 -070043 0);
44 }
45
Austin Schuhf6ed4522020-12-13 16:40:38 -080046 {
47 int on = 1;
Austin Schuh507f7582021-07-31 20:39:55 -070048 LOG(INFO) << "setsockopt(" << fd()
49 << ", SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)";
50 PCHECK(setsockopt(fd(), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) == 0);
Austin Schuhf6ed4522020-12-13 16:40:38 -080051 }
52
Austin Schuh387b7de2020-03-15 14:28:07 -070053 // And go!
Austin Schuh507f7582021-07-31 20:39:55 -070054 if (bind(fd(), (struct sockaddr *)&sockaddr_local_,
Austin Schuh387b7de2020-03-15 14:28:07 -070055 sockaddr_local_.ss_family == AF_INET6
56 ? sizeof(struct sockaddr_in6)
57 : sizeof(struct sockaddr_in)) != 0) {
58 PLOG(ERROR) << "Failed to bind, retrying";
Austin Schuh507f7582021-07-31 20:39:55 -070059 close(fd());
Austin Schuh387b7de2020-03-15 14:28:07 -070060 std::this_thread::sleep_for(std::chrono::seconds(5));
61 continue;
62 }
Austin Schuh507f7582021-07-31 20:39:55 -070063 LOG(INFO) << "bind(" << fd() << ", " << Address(sockaddr_local_) << ")";
Austin Schuh387b7de2020-03-15 14:28:07 -070064
Austin Schuh507f7582021-07-31 20:39:55 -070065 PCHECK(listen(fd(), 100) == 0);
Austin Schuh387b7de2020-03-15 14:28:07 -070066
67 SetMaxSize(1000);
68 break;
Austin Schuhe84c3ed2019-12-14 15:29:48 -080069 }
Austin Schuhe84c3ed2019-12-14 15:29:48 -080070}
71
Austin Schuhe84c3ed2019-12-14 15:29:48 -080072void SctpServer::SetPriorityScheduler(sctp_assoc_t assoc_id) {
73 struct sctp_assoc_value scheduler;
74 memset(&scheduler, 0, sizeof(scheduler));
75 scheduler.assoc_id = assoc_id;
76 scheduler.assoc_value = SCTP_SS_PRIO;
77 if (setsockopt(fd(), IPPROTO_SCTP, SCTP_STREAM_SCHEDULER, &scheduler,
78 sizeof(scheduler)) != 0) {
79 PLOG(WARNING) << "Failed to set scheduler";
80 }
81}
82
83void SctpServer::SetStreamPriority(sctp_assoc_t assoc_id, int stream_id,
84 uint16_t priority) {
85 struct sctp_stream_value sctp_priority;
86 memset(&sctp_priority, 0, sizeof(sctp_priority));
87 sctp_priority.assoc_id = assoc_id;
88 sctp_priority.stream_id = stream_id;
89 sctp_priority.stream_value = priority;
90 if (setsockopt(fd(), IPPROTO_SCTP, SCTP_STREAM_SCHEDULER_VALUE,
91 &sctp_priority, sizeof(sctp_priority)) != 0) {
92 PLOG(WARNING) << "Failed to set scheduler";
93 }
94}
95
96} // namespace message_bridge
97} // namespace aos