Move ReadSctpMessage to a class

In preparation for reassembling partial messages in userspace.

Change-Id: Ifa530698058ea775362eee4ec1bf9e6e0d3dd5de
Signed-off-by: Austin Schuh <austin.schuh@bluerivertech.com>
diff --git a/aos/network/sctp_server.cc b/aos/network/sctp_server.cc
index 47a5719..327f5a0 100644
--- a/aos/network/sctp_server.cc
+++ b/aos/network/sctp_server.cc
@@ -23,10 +23,7 @@
 SctpServer::SctpServer(std::string_view local_host, int local_port)
     : sockaddr_local_(ResolveSocket(local_host, local_port)) {
   while (true) {
-    fd_ = socket(sockaddr_local_.ss_family, SOCK_SEQPACKET, IPPROTO_SCTP);
-    LOG(INFO) << "socket(" << Family(sockaddr_local_)
-              << ", SOCK_SEQPACKET, IPPROTOSCTP) = " << fd_;
-    PCHECK(fd_ != -1);
+    sctp_.OpenSocket(sockaddr_local_);
 
     {
       struct sctp_event_subscribe subscribe;
@@ -35,60 +32,42 @@
       subscribe.sctp_send_failure_event = 1;
       subscribe.sctp_partial_delivery_event = 1;
 
-      PCHECK(setsockopt(fd_, SOL_SCTP, SCTP_EVENTS, (char *)&subscribe,
+      PCHECK(setsockopt(fd(), SOL_SCTP, SCTP_EVENTS, (char *)&subscribe,
                         sizeof(subscribe)) == 0);
     }
     {
-      // Enable recvinfo when a packet arrives.
-      int on = 1;
-      PCHECK(setsockopt(fd_, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on,
-                        sizeof(int)) == 0);
-    }
-    {
-      // Per https://tools.ietf.org/html/rfc6458
-      // Setting this to !0 allows event notifications to be interleaved
-      // with data if enabled, and would have to be handled in the code.
-      // Enabling interleaving would only matter during congestion, which
-      // typically only happens during application startup.
-      int interleaving = 0;
-      PCHECK(setsockopt(fd_, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE,
-                        &interleaving, sizeof(interleaving)) == 0);
-    }
-    {
       // Turn off the NAGLE algorithm.
       int on = 1;
-      PCHECK(setsockopt(fd_, IPPROTO_SCTP, SCTP_NODELAY, &on, sizeof(int)) ==
+      PCHECK(setsockopt(fd(), IPPROTO_SCTP, SCTP_NODELAY, &on, sizeof(int)) ==
              0);
     }
 
     {
       int on = 1;
-      PCHECK(setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) == 0);
+      LOG(INFO) << "setsockopt(" << fd()
+                << ", SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)";
+      PCHECK(setsockopt(fd(), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) == 0);
     }
 
     // And go!
-    if (bind(fd_, (struct sockaddr *)&sockaddr_local_,
+    if (bind(fd(), (struct sockaddr *)&sockaddr_local_,
              sockaddr_local_.ss_family == AF_INET6
                  ? sizeof(struct sockaddr_in6)
                  : sizeof(struct sockaddr_in)) != 0) {
       PLOG(ERROR) << "Failed to bind, retrying";
-      close(fd_);
+      close(fd());
       std::this_thread::sleep_for(std::chrono::seconds(5));
       continue;
     }
-    LOG(INFO) << "bind(" << fd_ << ", " << Address(sockaddr_local_) << ")";
+    LOG(INFO) << "bind(" << fd() << ", " << Address(sockaddr_local_) << ")";
 
-    PCHECK(listen(fd_, 100) == 0);
+    PCHECK(listen(fd(), 100) == 0);
 
     SetMaxSize(1000);
     break;
   }
 }
 
-aos::unique_c_ptr<Message> SctpServer::Read() {
-  return ReadSctpMessage(fd_, max_size_);
-}
-
 bool SctpServer::Abort(sctp_assoc_t snd_assoc_id) {
   // Use the assoc_id for the destination instead of the msg_name.
   struct msghdr outmsg;
@@ -109,13 +88,12 @@
 
   struct sctp_sndrcvinfo *sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
   memset(sinfo, 0, sizeof(struct sctp_sndrcvinfo));
-  sinfo->sinfo_ppid = ++ppid_;
   sinfo->sinfo_stream = 0;
   sinfo->sinfo_flags = SCTP_ABORT;
   sinfo->sinfo_assoc_id = snd_assoc_id;
 
   // And send.
-  const ssize_t size = sendmsg(fd_, &outmsg, MSG_NOSIGNAL | MSG_DONTWAIT);
+  const ssize_t size = sendmsg(fd(), &outmsg, MSG_NOSIGNAL | MSG_DONTWAIT);
   if (size == -1) {
     if (errno == EPIPE || errno == EAGAIN || errno == ESHUTDOWN) {
       return false;
@@ -127,53 +105,6 @@
   }
 }
 
-bool SctpServer::Send(std::string_view data, sctp_assoc_t snd_assoc_id,
-                      int stream, int timetolive) {
-  struct iovec iov;
-  iov.iov_base = const_cast<char *>(data.data());
-  iov.iov_len = data.size();
-
-  // Use the assoc_id for the destination instead of the msg_name.
-  struct msghdr outmsg;
-  outmsg.msg_namelen = 0;
-
-  // Data to send.
-  outmsg.msg_iov = &iov;
-  outmsg.msg_iovlen = 1;
-
-  // Build up the sndinfo message.
-  char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
-  outmsg.msg_control = outcmsg;
-  outmsg.msg_controllen = CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
-  outmsg.msg_flags = 0;
-
-  struct cmsghdr *cmsg = CMSG_FIRSTHDR(&outmsg);
-  cmsg->cmsg_level = IPPROTO_SCTP;
-  cmsg->cmsg_type = SCTP_SNDRCV;
-  cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
-
-  struct sctp_sndrcvinfo *sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
-  memset(sinfo, 0, sizeof(struct sctp_sndrcvinfo));
-  sinfo->sinfo_ppid = ++ppid_;
-  sinfo->sinfo_stream = stream;
-  sinfo->sinfo_flags = 0;
-  sinfo->sinfo_assoc_id = snd_assoc_id;
-  sinfo->sinfo_timetolive = timetolive;
-
-  // And send.
-  const ssize_t size = sendmsg(fd_, &outmsg, MSG_NOSIGNAL | MSG_DONTWAIT);
-  if (size == -1) {
-    if (errno == EPIPE || errno == EAGAIN || errno == ESHUTDOWN) {
-      return false;
-    }
-    PCHECK(size == static_cast<ssize_t>(data.size()));
-    return false;
-  } else {
-    CHECK_EQ(static_cast<ssize_t>(data.size()), size);
-    return true;
-  }
-}
-
 void SctpServer::SetPriorityScheduler(sctp_assoc_t assoc_id) {
   struct sctp_assoc_value scheduler;
   memset(&scheduler, 0, sizeof(scheduler));