Overview

This article provides a step-by-step approach to configure SCTP messaging over UDP in a Mediasoup environment. If you encounter issues with message retransmissions, this guide will help troubleshoot and optimize your setup.

Steps to Configure SCTP over UDP

  1. Create a UDP Socket: Initialize a new UDP socket using the socket() function.
  2. Bind the Socket: Use the bind() function to associate the socket with a local port.
  3. Connect the Socket: Establish a connection to a remote port using the connect() function.
  4. Initialize SCTP: Call usrsctp_init() with the local port and a callback function for sending data.
    • In the callback, utilize sendto() to transmit data through the UDP socket to the specified remote address.
  5. Register Remote Address: Use usrsctp_register_address() to register the remote port address.
  6. Create SCTP Socket: Instantiate a new SCTP socket with usrsctp_socket() using the parameters: AF_CONN, SOCK_STREAM, IPPROTO_SCTP, and the remote port.
  7. Set Non-blocking Option: Configure the socket to be non-blocking.
  8. Bind SCTP Socket: Bind the SCTP socket to port 5000, which is required by Mediasoup, using usrsctp_bind().
  9. Connect SCTP Socket: Connect the SCTP socket to the same port using usrsctp_connect().
  10. Receive Data Loop: Continuously call recvfrom() on the UDP socket and pass the received data to usrsctp_conninput() with the remote port address.

Handling Message Transmission

While the connection should establish successfully (evidenced by the handshake sequence: INIT -> INIT_ACK -> COOKIE_ECHO -> COOKIE_ACK), you may encounter issues with message retransmission. When sending messages using usrsctp_sendv(), you might receive SACK responses, yet the messages may still be retransmitted.

Troubleshooting Retransmissions

  • Ensure that the SCTP retransmission policy is correctly set. You can attempt to disable retransmissions by setting the SCTP_PR_SCTP_RTX policy to 0, although this may not always resolve the issue.
  • Review your implementation for any discrepancies that could lead to unexpected behavior in message handling.

Example Code

Here’s a simplified version of the code to illustrate the setup:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <usrsctp.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>

int sock;
struct socket *sctp_socket;

void *keypress_listener(void *arg) {
    getchar();
    struct sctp_sendv_spa spa;
    memset(&spa, 0, sizeof(spa));
    spa.sendv_flags = SCTP_SEND_SNDINFO_VALID;
    spa.sendv_sndinfo.snd_sid = 1;
    spa.sendv_sndinfo.snd_ppid = htonl(51);
    spa.sendv_sndinfo.snd_flags = SCTP_EOR; // End of message
    spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_RTX;
    spa.sendv_prinfo.pr_value = 0;

    const char *msg = "Hello World";
    if (usrsctp_sendv(sctp_socket, (void *)msg, strlen(msg), NULL, 0, &spa, (socklen_t)sizeof(spa), SCTP_SENDV_SPA, 0) < 0) {
        printf("Failed to send message\n");
    }
}

int main(int argc, char *argv[]) {
    // Setup UDP transport
    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    int local_port = 40001;
    int remote_port = 44444;

    struct sockaddr_in local_addr;
    memset(&local_addr, 0, sizeof(local_addr));
    local_addr.sin_family = AF_INET;
    local_addr.sin_port = htons(local_port);
    local_addr.sin_addr.s_addr = INADDR_ANY;

    bind(sock, (struct sockaddr *)&local_addr, sizeof(local_addr));

    struct sockaddr_in remote_addr;
    memset(&remote_addr, 0, sizeof(remote_addr));
    remote_addr.sin_family = AF_INET;
    remote_addr.sin_port = htons(remote_port);
    remote_addr.sin_addr.s_addr = INADDR_ANY; // Replace with actual IP address

    connect(sock, (struct sockaddr *)&remote_addr, sizeof(remote_addr));
    // Additional setup...
}

Conclusion

By following these steps and troubleshooting tips, you should be able to effectively configure SCTP messaging over UDP with Mediasoup. If issues persist, consider reviewing your network configuration and SCTP settings for further optimization.