From f26a960c17d9c88a222dcbb3f55716f0c89938f2 Mon Sep 17 00:00:00 2001 From: Rich LeGrand Date: Tue, 18 Jun 2024 15:58:23 -0500 Subject: [PATCH 1/6] changed peer_connection_datachannel_send --- CMakeLists.txt | 5 ++++- src/config.h | 2 +- src/peer_connection.c | 9 ++++----- src/sctp.c | 9 +++++---- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 502588d..836383e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,11 +6,14 @@ option(ENABLE_TESTS "Enable tests" OFF) include(third_party/coreHTTP/httpFilePaths.cmake) include(third_party/coreMQTT/mqttFilePaths.cmake) -include_directories(dist/include) +include_directories(dist/include dist/include/cjson) link_directories(dist/lib) set(DEP_LIBS "srtp2" "usrsctp" "mbedtls" "mbedcrypto" "mbedx509" "cjson") +# Extended debug information (symbols, source code, and macro definitions) +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g3") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g3") add_definitions("-Wunused-variable -Werror=sequence-point -Werror=pointer-sign -Werror=return-type -Werror=sizeof-pointer-memaccess -Wincompatible-pointer-types -DHTTP_DO_NOT_USE_CUSTOM_CONFIG -DMQTT_DO_NOT_USE_CUSTOM_CONFIG") diff --git a/src/config.h b/src/config.h index c9d6ceb..e0d7096 100644 --- a/src/config.h +++ b/src/config.h @@ -35,7 +35,7 @@ #define WHIP_PORT 443 #define KEEPALIVE_CONNCHECK 0 -#define CONFIG_IPV6 0 +#define CONFIG_IPV6 1 // default use wifi interface #define IFR_NAME "w" diff --git a/src/peer_connection.c b/src/peer_connection.c index a9e05ef..24d4ab4 100644 --- a/src/peer_connection.c +++ b/src/peer_connection.c @@ -256,11 +256,10 @@ int peer_connection_datachannel_send(PeerConnection *pc, char *message, size_t l return -1; } - if (buffer_push_tail(pc->data_rb, (const uint8_t*)message, len) < 0) { - buffer_clear(pc->data_rb); - } - - return 0; + if (pc->config.datachannel == DATA_CHANNEL_STRING) + return sctp_outgoing_data(&pc->sctp, message, len, PPID_STRING); + else + return sctp_outgoing_data(&pc->sctp, message, len, PPID_BINARY); } static void peer_connection_state_new(PeerConnection *pc) { diff --git a/src/sctp.c b/src/sctp.c index 8b6b5ec..c6cfafd 100644 --- a/src/sctp.c +++ b/src/sctp.c @@ -111,6 +111,7 @@ static int sctp_outgoing_data_cb(void *userdata, void *buf, size_t len, uint8_t int sctp_outgoing_data(Sctp *sctp, char *buf, size_t len, SctpDataPpid ppid) { #ifdef HAVE_USRSCTP + int res; struct sctp_sendv_spa spa = {0}; spa.sendv_flags = SCTP_SEND_SNDINFO_VALID; @@ -119,10 +120,10 @@ int sctp_outgoing_data(Sctp *sctp, char *buf, size_t len, SctpDataPpid ppid) { spa.sendv_sndinfo.snd_flags = SCTP_EOR; spa.sendv_sndinfo.snd_ppid = htonl(ppid); - if(usrsctp_sendv(sctp->sock, buf, len, NULL, 0, &spa, sizeof(spa), SCTP_SENDV_SPA, 0) < 0) { - LOGE("sctp sendv error"); - return -1; - } + res = usrsctp_sendv(sctp->sock, buf, len, NULL, 0, &spa, sizeof(spa), SCTP_SENDV_SPA, 0); + if(res < 0) + LOGE("sctp sendv error %d %s", errno, strerror(errno)); + return res; #else size_t padding_len = 0; size_t payload_max = SCTP_MTU - sizeof(SctpPacket) - sizeof(SctpDataChunk); From 7013024f9da98fc09c856a621ddf34ac85429875 Mon Sep 17 00:00:00 2001 From: Rich LeGrand Date: Wed, 19 Jun 2024 12:25:56 -0500 Subject: [PATCH 2/6] add binary message reception, tweak other pieces of code --- src/sctp.c | 29 ++++++++++++----------------- src/sctp.h | 4 ++-- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/sctp.c b/src/sctp.c index c6cfafd..f5b7820 100644 --- a/src/sctp.c +++ b/src/sctp.c @@ -221,6 +221,7 @@ void sctp_incoming_data(Sctp *sctp, char *buf, size_t len) { switch (chunk_common->type) { case SCTP_DATA: + data_chunk = (SctpDataChunk*)(buf + pos); LOGD("SCTP_DATA. ppid = %ld", ntohl(data_chunk->ppid)); @@ -232,8 +233,8 @@ void sctp_incoming_data(Sctp *sctp, char *buf, size_t len) { #endif if (ntohl(data_chunk->ppid) == DATA_CHANNEL_PPID_DOMSTRING) { - if (sctp->onmessasge) { - sctp->onmessasge((char*)data_chunk->data, ntohs(data_chunk->length) - sizeof(SctpDataChunk), sctp->userdata); + if (sctp->onmessage) { + sctp->onmessage((char*)data_chunk->data, ntohs(data_chunk->length) - sizeof(SctpDataChunk), sctp->userdata); } } @@ -347,26 +348,19 @@ void sctp_incoming_data(Sctp *sctp, char *buf, size_t len) { static int sctp_handle_incoming_data(Sctp *sctp, char *data, size_t len, uint32_t ppid, uint16_t stream, int flags) { #ifdef HAVE_USRSCTP - char *msg = NULL; - switch(ppid) { case DATA_CHANNEL_PPID_CONTROL: break; case DATA_CHANNEL_PPID_DOMSTRING: - - msg = strndup(data, len); - LOGD("Got message %s (size = %ld)", msg, len); - if(msg && sctp->onmessasge) { - sctp->onmessasge(msg, len, sctp->userdata); - free(msg); - } - break; case DATA_CHANNEL_PPID_BINARY: - break; case DATA_CHANNEL_PPID_DOMSTRING_PARTIAL: - break; case DATA_CHANNEL_PPID_BINARY_PARTIAL: + + LOGD("Got message (size = %ld)", len); + if(sctp->onmessage) { + sctp->onmessage(data, len, sctp->userdata); + } break; default: break; @@ -401,7 +395,8 @@ static void sctp_process_notification(Sctp *sctp, union sctp_notification *notif break; case SCTP_COMM_LOST: - sctp->connected = 1; + case SCTP_SHUTDOWN_COMP: + sctp->connected = 0; if(sctp->onclose) { sctp->onclose(sctp->userdata); } @@ -568,9 +563,9 @@ void sctp_destroy(Sctp *sctp) { #endif } -void sctp_onmessage(Sctp *sctp, void (*onmessasge)(char *msg, size_t len, void *userdata)) { +void sctp_onmessage(Sctp *sctp, void (*onmessage)(char *msg, size_t len, void *userdata)) { - sctp->onmessasge = onmessasge; + sctp->onmessage = onmessage; } void sctp_onopen(Sctp *sctp, void (*onopen)(void *userdata)) { diff --git a/src/sctp.h b/src/sctp.h index 70f29cb..ae2c276 100644 --- a/src/sctp.h +++ b/src/sctp.h @@ -150,7 +150,7 @@ typedef struct Sctp { DtlsSrtp *dtls_srtp; Buffer **data_rb; /* datachannel */ - void (*onmessasge)(char *msg, size_t len, void *userdata); + void (*onmessage)(char *msg, size_t len, void *userdata); void (*onopen)(void *userdata); void (*onclose)(void *userdata); @@ -171,7 +171,7 @@ void sctp_incoming_data(Sctp *sctp, char *buf, size_t len); int sctp_outgoing_data(Sctp *sctp, char *buf, size_t len, SctpDataPpid ppid); -void sctp_onmessage(Sctp *sctp, void (*onmessasge)(char *msg, size_t len, void *userdata)); +void sctp_onmessage(Sctp *sctp, void (*onmessage)(char *msg, size_t len, void *userdata)); void sctp_onopen(Sctp *sctp, void (*onopen)(void *userdata)); From 28f0de186e6bd9b0f5adc56b0371025952de5e7d Mon Sep 17 00:00:00 2001 From: Rich LeGrand Date: Thu, 27 Jun 2024 13:51:53 -0500 Subject: [PATCH 3/6] move PeerConnection into peer_connection.h --- src/mediacodec.h | 20 +++++++++++++++ src/peer_connection.c | 42 ------------------------------- src/peer_connection.h | 58 ++++++++++++++++++++++++++++++------------- src/rtp.h | 2 +- src/sctp.c | 7 +++--- 5 files changed, 65 insertions(+), 64 deletions(-) create mode 100644 src/mediacodec.h diff --git a/src/mediacodec.h b/src/mediacodec.h new file mode 100644 index 0000000..eba95d1 --- /dev/null +++ b/src/mediacodec.h @@ -0,0 +1,20 @@ +#ifndef MEDIA_CODEC +#define MEDIA_CODEC + +typedef enum MediaCodec { + + CODEC_NONE = 0, + + /* Video */ + CODEC_H264, + CODEC_VP8, // not implemented yet + CODEC_MJPEG, // not implemented yet + + /* Audio */ + CODEC_OPUS, // not implemented yet + CODEC_PCMA, + CODEC_PCMU, + +} MediaCodec; + +#endif \ No newline at end of file diff --git a/src/peer_connection.c b/src/peer_connection.c index 24d4ab4..07f6060 100644 --- a/src/peer_connection.c +++ b/src/peer_connection.c @@ -3,54 +3,13 @@ #include #include -#include "sctp.h" -#include "agent.h" -#include "dtls_srtp.h" -#include "sdp.h" #include "config.h" -#include "rtp.h" #include "rtcp.h" -#include "buffer.h" #include "ports.h" #include "peer_connection.h" #define STATE_CHANGED(pc, curr_state) if(pc->oniceconnectionstatechange && pc->state != curr_state) { pc->oniceconnectionstatechange(curr_state, pc->config.user_data); pc->state = curr_state; } -struct PeerConnection { - - PeerConfiguration config; - PeerConnectionState state; - Agent agent; - DtlsSrtp dtls_srtp; - Sctp sctp; - - Sdp local_sdp; - Sdp remote_sdp; - - void (*onicecandidate)(char *sdp, void *user_data); - void (*oniceconnectionstatechange)(PeerConnectionState state, void *user_data); - void (*on_connected)(void *userdata); - void (*on_receiver_packet_loss)(float fraction_loss, uint32_t total_loss, void *user_data); - - uint8_t temp_buf[CONFIG_MTU]; - uint8_t agent_buf[CONFIG_MTU]; - int agent_ret; - int b_offer_created; - - Buffer *audio_rb; - Buffer *video_rb; - Buffer *data_rb; - - RtpEncoder artp_encoder; - RtpEncoder vrtp_encoder; - RtpDecoder vrtp_decoder; - RtpDecoder artp_decoder; - - uint32_t remote_assrc; - uint32_t remote_vssrc; - -}; - static void peer_connection_outgoing_rtp_packet(uint8_t *data, size_t size, void *user_data) { PeerConnection *pc = (PeerConnection *) user_data; @@ -344,7 +303,6 @@ static void peer_connection_state_new(PeerConnection *pc) { } int peer_connection_loop(PeerConnection *pc) { - int bytes; uint8_t *data = NULL; uint32_t ssrc = 0; diff --git a/src/peer_connection.h b/src/peer_connection.h index 5454999..e3e4039 100644 --- a/src/peer_connection.h +++ b/src/peer_connection.h @@ -7,6 +7,13 @@ #include #include +#include "sctp.h" +#include "agent.h" +#include "dtls_srtp.h" +#include "sdp.h" +#include "mediacodec.h" +#include "rtp.h" +#include "buffer.h" #ifdef __cplusplus extern "C" { @@ -32,22 +39,6 @@ typedef enum DataChannelType { } DataChannelType; -typedef enum MediaCodec { - - CODEC_NONE = 0, - - /* Video */ - CODEC_H264, - CODEC_VP8, // not implemented yet - CODEC_MJPEG, // not implemented yet - - /* Audio */ - CODEC_OPUS, // not implemented yet - CODEC_PCMA, - CODEC_PCMU, - -} MediaCodec; - typedef struct IceServer { const char *urls; @@ -71,7 +62,40 @@ typedef struct PeerConfiguration { } PeerConfiguration; -typedef struct PeerConnection PeerConnection; +typedef struct PeerConnection { + + PeerConfiguration config; + PeerConnectionState state; + Agent agent; + DtlsSrtp dtls_srtp; + Sctp sctp; + + Sdp local_sdp; + Sdp remote_sdp; + + void (*onicecandidate)(char *sdp, void *user_data); + void (*oniceconnectionstatechange)(PeerConnectionState state, void *user_data); + void (*on_connected)(void *userdata); + void (*on_receiver_packet_loss)(float fraction_loss, uint32_t total_loss, void *user_data); + + uint8_t temp_buf[CONFIG_MTU]; + uint8_t agent_buf[CONFIG_MTU]; + int agent_ret; + int b_offer_created; + + Buffer *audio_rb; + Buffer *video_rb; + Buffer *data_rb; + + RtpEncoder artp_encoder; + RtpEncoder vrtp_encoder; + RtpDecoder vrtp_decoder; + RtpDecoder artp_decoder; + + uint32_t remote_assrc; + uint32_t remote_vssrc; + +} PeerConnection; const char* peer_connection_state_to_string(PeerConnectionState state); diff --git a/src/rtp.h b/src/rtp.h index acdf6da..d74cba4 100644 --- a/src/rtp.h +++ b/src/rtp.h @@ -4,7 +4,7 @@ #include #include -#include "peer_connection.h" +#include "mediacodec.h" #include "config.h" #ifdef ESP32 diff --git a/src/sctp.c b/src/sctp.c index f5b7820..70b2e01 100644 --- a/src/sctp.c +++ b/src/sctp.c @@ -185,7 +185,6 @@ void sctp_incoming_data(Sctp *sctp, char *buf, size_t len) { #ifdef HAVE_USRSCTP usrsctp_conninput(sctp, buf, len, 0); #else - size_t length = 0; size_t pos = sizeof(SctpHeader); SctpChunkCommon *chunk_common; @@ -350,8 +349,8 @@ static int sctp_handle_incoming_data(Sctp *sctp, char *data, size_t len, uint32_ #ifdef HAVE_USRSCTP switch(ppid) { case DATA_CHANNEL_PPID_CONTROL: - break; + case DATA_CHANNEL_PPID_DOMSTRING: case DATA_CHANNEL_PPID_BINARY: case DATA_CHANNEL_PPID_DOMSTRING_PARTIAL: @@ -362,6 +361,7 @@ static int sctp_handle_incoming_data(Sctp *sctp, char *data, size_t len, uint32_ sctp->onmessage(data, len, sctp->userdata); } break; + default: break; } @@ -421,8 +421,7 @@ static int sctp_incoming_data_cb(struct socket *sock, union sctp_sockstore addr, ntohl(recv_info.rcv_ppid)); if(flags & MSG_NOTIFICATION) { sctp_process_notification(sctp, (union sctp_notification *)data, len); - } - else { + } else { sctp_handle_incoming_data(sctp, data, len, ntohl(recv_info.rcv_ppid), recv_info.rcv_sid, flags); } return 0; From a51caadc3964f1f3b693ad6304604241dcbbea9f Mon Sep 17 00:00:00 2001 From: Rich LeGrand Date: Sat, 29 Jun 2024 13:48:06 -0500 Subject: [PATCH 4/6] added stream id to messages --- examples/sample/main.c | 6 ++-- src/peer_connection.c | 35 ++++++++++++++++---- src/peer_connection.h | 8 ++++- src/sctp.c | 75 ++++++++++++++++++++++++++++++++++++++---- src/sctp.h | 18 +++++++--- 5 files changed, 120 insertions(+), 22 deletions(-) diff --git a/examples/sample/main.c b/examples/sample/main.c index 443b3e3..4d420e6 100644 --- a/examples/sample/main.c +++ b/examples/sample/main.c @@ -26,9 +26,9 @@ static void onclose(void *user_data) { } -static void onmessasge(char *msg, size_t len, void *user_data) { +static void onmessage(char *msg, size_t len, void *user_data, uint16_t sid) { - printf("on message: %s", msg); + printf("on message: %d %s", sid, msg); if (strncmp(msg, "ping", 4) == 0) { printf(", send pong\n"); @@ -96,7 +96,7 @@ int main(int argc, char *argv[]) { peer_init(); g_pc = peer_connection_create(&config); peer_connection_oniceconnectionstatechange(g_pc, onconnectionstatechange); - peer_connection_ondatachannel(g_pc, onmessasge, onopen, onclose); + peer_connection_ondatachannel(g_pc, onmessage, onopen, onclose); peer_signaling_join_channel((const char*)buf, g_pc); diff --git a/src/peer_connection.c b/src/peer_connection.c index 07f6060..5b3b75d 100644 --- a/src/peer_connection.c +++ b/src/peer_connection.c @@ -209,6 +209,10 @@ int peer_connection_send_video(PeerConnection *pc, const uint8_t *buf, size_t le } int peer_connection_datachannel_send(PeerConnection *pc, char *message, size_t len) { + return peer_connection_datachannel_send_sid(pc, message, len, 0); +} + +int peer_connection_datachannel_send_sid(PeerConnection *pc, char *message, size_t len, uint16_t sid) { if(!sctp_is_connected(&pc->sctp)) { LOGE("sctp not connected"); @@ -216,9 +220,9 @@ int peer_connection_datachannel_send(PeerConnection *pc, char *message, size_t l } if (pc->config.datachannel == DATA_CHANNEL_STRING) - return sctp_outgoing_data(&pc->sctp, message, len, PPID_STRING); + return sctp_outgoing_data(&pc->sctp, message, len, PPID_STRING, sid); else - return sctp_outgoing_data(&pc->sctp, message, len, PPID_BINARY); + return sctp_outgoing_data(&pc->sctp, message, len, PPID_BINARY, sid); } static void peer_connection_state_new(PeerConnection *pc) { @@ -359,9 +363,9 @@ int peer_connection_loop(PeerConnection *pc) { if (data) { if (pc->config.datachannel == DATA_CHANNEL_STRING) - sctp_outgoing_data(&pc->sctp, (char*)data, bytes, PPID_STRING); + sctp_outgoing_data(&pc->sctp, (char*)data, bytes, PPID_STRING, 0); else - sctp_outgoing_data(&pc->sctp, (char*)data, bytes, PPID_BINARY); + sctp_outgoing_data(&pc->sctp, (char*)data, bytes, PPID_BINARY, 0); buffer_pop_head(pc->data_rb); } @@ -496,7 +500,7 @@ void peer_connection_oniceconnectionstatechange(PeerConnection *pc, } void peer_connection_ondatachannel(PeerConnection *pc, - void (*onmessasge)(char *msg, size_t len, void *userdata), + void (*onmessage)(char *msg, size_t len, void *userdata, uint16_t sid), void (*onopen)(void *userdata), void (*onclose)(void *userdata)) { @@ -504,7 +508,26 @@ void peer_connection_ondatachannel(PeerConnection *pc, sctp_onopen(&pc->sctp, onopen); sctp_onclose(&pc->sctp, onclose); - sctp_onmessage(&pc->sctp, onmessasge); + sctp_onmessage(&pc->sctp, onmessage); } } +int peer_connection_lookup_sid(PeerConnection *pc, const char *label, uint16_t *sid) { + for (int i = 0; i < pc->sctp.stream_count; i++) { + if (strncmp(pc->sctp.stream_table[i].label, label, sizeof(pc->sctp.stream_table[i].label)) == 0) { + *sid = pc->sctp.stream_table[i].sid; + return 0; + } + } + return -1; // Not found +} + +char *peer_connection_lookup_sid_label(PeerConnection *pc, uint16_t sid) { + for (int i = 0; i < pc->sctp.stream_count; i++) { + if (pc->sctp.stream_table[i].sid == sid) { + return pc->sctp.stream_table[i].label; + } + } + return NULL; // Not found +} + diff --git a/src/peer_connection.h b/src/peer_connection.h index e3e4039..9c202d7 100644 --- a/src/peer_connection.h +++ b/src/peer_connection.h @@ -116,6 +116,8 @@ int peer_connection_loop(PeerConnection *pc); */ int peer_connection_datachannel_send(PeerConnection *pc, char *message, size_t len); +int peer_connection_datachannel_send_sid(PeerConnection *pc, char *message, size_t len, uint16_t sid); + int peer_connection_send_audio(PeerConnection *pc, const uint8_t *packet, size_t bytes); int peer_connection_send_video(PeerConnection *pc, const uint8_t *packet, size_t bytes); @@ -158,10 +160,14 @@ void peer_connection_oniceconnectionstatechange(PeerConnection *pc, * @param[in] callback function when connection is closed */ void peer_connection_ondatachannel(PeerConnection *pc, - void (*onmessasge)(char *msg, size_t len, void *userdata), + void (*onmessage)(char *msg, size_t len, void *userdata, uint16_t sid), void (*onopen)(void *userdata), void (*onclose)(void *userdata)); +int peer_connection_lookup_sid(PeerConnection *pc, const char *label, uint16_t *sid); + +char *peer_connection_lookup_sid_label(PeerConnection *pc, uint16_t sid); + #ifdef __cplusplus } #endif diff --git a/src/sctp.c b/src/sctp.c index 70b2e01..d35d0c2 100644 --- a/src/sctp.c +++ b/src/sctp.c @@ -15,6 +15,8 @@ #define DATA_CHANNEL_PPID_BINARY_PARTIAL 52 #define DATA_CHANNEL_PPID_BINARY 53 #define DATA_CHANNEL_PPID_DOMSTRING_PARTIAL 54 +#define DCEP_PPID 0x32 +#define DATA_CHANNEL_OPEN 0x03 static const uint32_t crc32c_table[256] = { 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, @@ -108,7 +110,7 @@ static int sctp_outgoing_data_cb(void *userdata, void *buf, size_t len, uint8_t return 0; } -int sctp_outgoing_data(Sctp *sctp, char *buf, size_t len, SctpDataPpid ppid) { +int sctp_outgoing_data(Sctp *sctp, char *buf, size_t len, SctpDataPpid ppid, uint16_t sid) { #ifdef HAVE_USRSCTP int res; @@ -116,7 +118,7 @@ int sctp_outgoing_data(Sctp *sctp, char *buf, size_t len, SctpDataPpid ppid) { spa.sendv_flags = SCTP_SEND_SNDINFO_VALID; - spa.sendv_sndinfo.snd_sid = 0; + spa.sendv_sndinfo.snd_sid = sid; spa.sendv_sndinfo.snd_flags = SCTP_EOR; spa.sendv_sndinfo.snd_ppid = htonl(ppid); @@ -177,12 +179,72 @@ int sctp_outgoing_data(Sctp *sctp, char *buf, size_t len, SctpDataPpid ppid) { return len; } +void add_stream_mapping(Sctp *sctp, const char *label, uint16_t sid) { + if (sctp->stream_countstream_table[sctp->stream_count].label, label, sizeof(sctp->stream_table[sctp->stream_count].label)); + sctp->stream_table[sctp->stream_count].sid = sid; + sctp->stream_count++; + } else + LOGE("Stream table full. Cannot add more streams."); +} + +void parse_data_channel_open(Sctp *sctp, uint16_t sid, char *data, size_t length) { + if (length < 12) + return; // Not enough data for a DATA_CHANNEL_OPEN message + + if (data[0]==DATA_CHANNEL_OPEN) { + uint16_t label_length = ntohs(*(uint16_t *)(data + 8)); + uint16_t protocol_length = ntohs(*(uint16_t *)(data + 10)); + + // Ensure we have enough data for the label and protocol + if (length < 12 + label_length + protocol_length) + return; + + char *label = (char *)(data + 12); + + // copy and null-terminate + char label_str[label_length + 1]; + memcpy(label_str, label, label_length); + label_str[label_length] = '\0'; + + // Log or process the DATA_CHANNEL_OPEN message + printf("DATA_CHANNEL_OPEN: Label=%s, sid=%d\n", label_str, sid); + + // Add stream mapping + add_stream_mapping(sctp, label_str, sid); + } +} + +void handle_sctp_packet(Sctp *sctp, char *buf, size_t len) { + if (len<=29) + return; + + if (buf[12]!=0) // if chunk_type is no zero, it's not data + return; + + uint16_t sid = ntohs(*(uint16_t *)(buf + 20)); + uint32_t ppid = ntohl(*(uint32_t *)(buf + 24)); + + if (ppid==DCEP_PPID) + parse_data_channel_open(sctp, sid, buf + 28, len - 28); +} + +void print_hex_buffer(uint8_t *buf, int len) { + printf("data (%d): ", len); + for (int i = 0; i < len; i++) { + printf("%02X ", buf[i]); + } + printf("\n"); +} + void sctp_incoming_data(Sctp *sctp, char *buf, size_t len) { if(!sctp) return; #ifdef HAVE_USRSCTP + //print_hex_buffer((uint8_t *)buf, len); + handle_sctp_packet(sctp, buf, len); usrsctp_conninput(sctp, buf, len, 0); #else size_t length = 0; @@ -233,7 +295,7 @@ void sctp_incoming_data(Sctp *sctp, char *buf, size_t len) { if (ntohl(data_chunk->ppid) == DATA_CHANNEL_PPID_DOMSTRING) { if (sctp->onmessage) { - sctp->onmessage((char*)data_chunk->data, ntohs(data_chunk->length) - sizeof(SctpDataChunk), sctp->userdata); + sctp->onmessage((char*)data_chunk->data, ntohs(data_chunk->length) - sizeof(SctpDataChunk), sctp->userdata, ntohs(data_chunk->sid)); } } @@ -344,8 +406,7 @@ void sctp_incoming_data(Sctp *sctp, char *buf, size_t len) { } -static int sctp_handle_incoming_data(Sctp *sctp, char *data, size_t len, uint32_t ppid, uint16_t stream, int flags) { - +static int sctp_handle_incoming_data(Sctp *sctp, char *data, size_t len, uint32_t ppid, uint16_t sid, int flags) { #ifdef HAVE_USRSCTP switch(ppid) { case DATA_CHANNEL_PPID_CONTROL: @@ -358,7 +419,7 @@ static int sctp_handle_incoming_data(Sctp *sctp, char *data, size_t len, uint32_ LOGD("Got message (size = %ld)", len); if(sctp->onmessage) { - sctp->onmessage(data, len, sctp->userdata); + sctp->onmessage(data, len, sctp->userdata, sid); } break; @@ -562,7 +623,7 @@ void sctp_destroy(Sctp *sctp) { #endif } -void sctp_onmessage(Sctp *sctp, void (*onmessage)(char *msg, size_t len, void *userdata)) { +void sctp_onmessage(Sctp *sctp, void (*onmessage)(char *msg, size_t len, void *userdata, uint16_t sid)) { sctp->onmessage = onmessage; } diff --git a/src/sctp.h b/src/sctp.h index ae2c276..979da09 100644 --- a/src/sctp.h +++ b/src/sctp.h @@ -105,7 +105,7 @@ typedef struct SctpDataChunk { uint8_t iube; uint16_t length; uint32_t tsn; - uint16_t si; + uint16_t sid; uint16_t sqn; uint32_t ppid; uint8_t data[0]; @@ -136,7 +136,12 @@ typedef enum SctpDataPpid { } SctpDataPpid; -typedef struct Sctp Sctp; +#define SCTP_MAX_STREAMS 5 + +typedef struct { + char label[32]; // Stream label + uint16_t sid; // Stream ID +} Stream_entry; typedef struct Sctp { @@ -149,8 +154,11 @@ typedef struct Sctp { uint32_t tsn; DtlsSrtp *dtls_srtp; Buffer **data_rb; + int stream_count; + Stream_entry stream_table[SCTP_MAX_STREAMS]; + /* datachannel */ - void (*onmessage)(char *msg, size_t len, void *userdata); + void (*onmessage)(char *msg, size_t len, void *userdata, uint16_t sid); void (*onopen)(void *userdata); void (*onclose)(void *userdata); @@ -169,9 +177,9 @@ int sctp_is_connected(Sctp *sctp); void sctp_incoming_data(Sctp *sctp, char *buf, size_t len); -int sctp_outgoing_data(Sctp *sctp, char *buf, size_t len, SctpDataPpid ppid); +int sctp_outgoing_data(Sctp *sctp, char *buf, size_t len, SctpDataPpid ppid, uint16_t sid); -void sctp_onmessage(Sctp *sctp, void (*onmessage)(char *msg, size_t len, void *userdata)); +void sctp_onmessage(Sctp *sctp, void (*onmessage)(char *msg, size_t len, void *userdata, uint16_t sid)); void sctp_onopen(Sctp *sctp, void (*onopen)(void *userdata)); From 90fda92975a30312d2fdf167f5d7a2a5188870c0 Mon Sep 17 00:00:00 2001 From: Rich LeGrand Date: Sat, 29 Jun 2024 18:54:33 -0500 Subject: [PATCH 5/6] fix memory leak --- src/sctp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sctp.c b/src/sctp.c index d35d0c2..323c35d 100644 --- a/src/sctp.c +++ b/src/sctp.c @@ -468,7 +468,7 @@ static void sctp_process_notification(Sctp *sctp, union sctp_notification *notif default: break; } - + free(notification); // we need to free the memory that usrsctp allocates } static int sctp_incoming_data_cb(struct socket *sock, union sctp_sockstore addr, From f6f84340b637b1d0a230fd3b03e9d93846b00a02 Mon Sep 17 00:00:00 2001 From: Rich LeGrand Date: Fri, 19 Jul 2024 16:16:14 -0500 Subject: [PATCH 6/6] clean up a bit --- src/mediacodec.h | 20 --------------- src/peer_connection.c | 47 ++++++++++++++++++++++++++++++++++ src/peer_connection.h | 59 ++++++++++++++----------------------------- src/rtp.h | 2 +- src/sctp.c | 24 +++++------------- src/sctp.h | 4 +-- 6 files changed, 76 insertions(+), 80 deletions(-) delete mode 100644 src/mediacodec.h diff --git a/src/mediacodec.h b/src/mediacodec.h deleted file mode 100644 index eba95d1..0000000 --- a/src/mediacodec.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef MEDIA_CODEC -#define MEDIA_CODEC - -typedef enum MediaCodec { - - CODEC_NONE = 0, - - /* Video */ - CODEC_H264, - CODEC_VP8, // not implemented yet - CODEC_MJPEG, // not implemented yet - - /* Audio */ - CODEC_OPUS, // not implemented yet - CODEC_PCMA, - CODEC_PCMU, - -} MediaCodec; - -#endif \ No newline at end of file diff --git a/src/peer_connection.c b/src/peer_connection.c index 5b3b75d..91b7066 100644 --- a/src/peer_connection.c +++ b/src/peer_connection.c @@ -3,13 +3,54 @@ #include #include +#include "sctp.h" +#include "agent.h" +#include "dtls_srtp.h" +#include "sdp.h" #include "config.h" +#include "rtp.h" #include "rtcp.h" +#include "buffer.h" #include "ports.h" #include "peer_connection.h" #define STATE_CHANGED(pc, curr_state) if(pc->oniceconnectionstatechange && pc->state != curr_state) { pc->oniceconnectionstatechange(curr_state, pc->config.user_data); pc->state = curr_state; } +struct PeerConnection { + + PeerConfiguration config; + PeerConnectionState state; + Agent agent; + DtlsSrtp dtls_srtp; + Sctp sctp; + + Sdp local_sdp; + Sdp remote_sdp; + + void (*onicecandidate)(char *sdp, void *user_data); + void (*oniceconnectionstatechange)(PeerConnectionState state, void *user_data); + void (*on_connected)(void *userdata); + void (*on_receiver_packet_loss)(float fraction_loss, uint32_t total_loss, void *user_data); + + uint8_t temp_buf[CONFIG_MTU]; + uint8_t agent_buf[CONFIG_MTU]; + int agent_ret; + int b_offer_created; + + Buffer *audio_rb; + Buffer *video_rb; + Buffer *data_rb; + + RtpEncoder artp_encoder; + RtpEncoder vrtp_encoder; + RtpDecoder vrtp_decoder; + RtpDecoder artp_decoder; + + uint32_t remote_assrc; + uint32_t remote_vssrc; + +}; + static void peer_connection_outgoing_rtp_packet(uint8_t *data, size_t size, void *user_data) { PeerConnection *pc = (PeerConnection *) user_data; @@ -123,6 +164,11 @@ PeerConnectionState peer_connection_get_state(PeerConnection *pc) { return pc->state; } +Sctp *peer_connection_get_sctp(PeerConnection *pc) { + + return &pc->sctp; +} + PeerConnection* peer_connection_create(PeerConfiguration *config) { PeerConnection *pc = calloc(1, sizeof(PeerConnection)); @@ -307,6 +353,7 @@ static void peer_connection_state_new(PeerConnection *pc) { } int peer_connection_loop(PeerConnection *pc) { + int bytes; uint8_t *data = NULL; uint32_t ssrc = 0; diff --git a/src/peer_connection.h b/src/peer_connection.h index 9c202d7..1b620e1 100644 --- a/src/peer_connection.h +++ b/src/peer_connection.h @@ -8,12 +8,6 @@ #include #include #include "sctp.h" -#include "agent.h" -#include "dtls_srtp.h" -#include "sdp.h" -#include "mediacodec.h" -#include "rtp.h" -#include "buffer.h" #ifdef __cplusplus extern "C" { @@ -39,6 +33,22 @@ typedef enum DataChannelType { } DataChannelType; +typedef enum MediaCodec { + + CODEC_NONE = 0, + + /* Video */ + CODEC_H264, + CODEC_VP8, // not implemented yet + CODEC_MJPEG, // not implemented yet + + /* Audio */ + CODEC_OPUS, // not implemented yet + CODEC_PCMA, + CODEC_PCMU, + +} MediaCodec; + typedef struct IceServer { const char *urls; @@ -62,45 +72,14 @@ typedef struct PeerConfiguration { } PeerConfiguration; -typedef struct PeerConnection { - - PeerConfiguration config; - PeerConnectionState state; - Agent agent; - DtlsSrtp dtls_srtp; - Sctp sctp; - - Sdp local_sdp; - Sdp remote_sdp; - - void (*onicecandidate)(char *sdp, void *user_data); - void (*oniceconnectionstatechange)(PeerConnectionState state, void *user_data); - void (*on_connected)(void *userdata); - void (*on_receiver_packet_loss)(float fraction_loss, uint32_t total_loss, void *user_data); - - uint8_t temp_buf[CONFIG_MTU]; - uint8_t agent_buf[CONFIG_MTU]; - int agent_ret; - int b_offer_created; - - Buffer *audio_rb; - Buffer *video_rb; - Buffer *data_rb; - - RtpEncoder artp_encoder; - RtpEncoder vrtp_encoder; - RtpDecoder vrtp_decoder; - RtpDecoder artp_decoder; - - uint32_t remote_assrc; - uint32_t remote_vssrc; - -} PeerConnection; +typedef struct PeerConnection PeerConnection; const char* peer_connection_state_to_string(PeerConnectionState state); PeerConnectionState peer_connection_get_state(PeerConnection *pc); +Sctp *peer_connection_get_sctp(PeerConnection *pc); + PeerConnection* peer_connection_create(PeerConfiguration *config); void peer_connection_destroy(PeerConnection *pc); diff --git a/src/rtp.h b/src/rtp.h index d74cba4..acdf6da 100644 --- a/src/rtp.h +++ b/src/rtp.h @@ -4,7 +4,7 @@ #include #include -#include "mediacodec.h" +#include "peer_connection.h" #include "config.h" #ifdef ESP32 diff --git a/src/sctp.c b/src/sctp.c index 323c35d..1a8a472 100644 --- a/src/sctp.c +++ b/src/sctp.c @@ -15,7 +15,6 @@ #define DATA_CHANNEL_PPID_BINARY_PARTIAL 52 #define DATA_CHANNEL_PPID_BINARY 53 #define DATA_CHANNEL_PPID_DOMSTRING_PARTIAL 54 -#define DCEP_PPID 0x32 #define DATA_CHANNEL_OPEN 0x03 static const uint32_t crc32c_table[256] = { @@ -179,7 +178,7 @@ int sctp_outgoing_data(Sctp *sctp, char *buf, size_t len, SctpDataPpid ppid, uin return len; } -void add_stream_mapping(Sctp *sctp, const char *label, uint16_t sid) { +void sctp_add_stream_mapping(Sctp *sctp, const char *label, uint16_t sid) { if (sctp->stream_countstream_table[sctp->stream_count].label, label, sizeof(sctp->stream_table[sctp->stream_count].label)); sctp->stream_table[sctp->stream_count].sid = sid; @@ -188,7 +187,7 @@ void add_stream_mapping(Sctp *sctp, const char *label, uint16_t sid) { LOGE("Stream table full. Cannot add more streams."); } -void parse_data_channel_open(Sctp *sctp, uint16_t sid, char *data, size_t length) { +void sctp_parse_data_channel_open(Sctp *sctp, uint16_t sid, char *data, size_t length) { if (length < 12) return; // Not enough data for a DATA_CHANNEL_OPEN message @@ -211,11 +210,11 @@ void parse_data_channel_open(Sctp *sctp, uint16_t sid, char *data, size_t length printf("DATA_CHANNEL_OPEN: Label=%s, sid=%d\n", label_str, sid); // Add stream mapping - add_stream_mapping(sctp, label_str, sid); + sctp_add_stream_mapping(sctp, label_str, sid); } } -void handle_sctp_packet(Sctp *sctp, char *buf, size_t len) { +void sctp_handle_sctp_packet(Sctp *sctp, char *buf, size_t len) { if (len<=29) return; @@ -225,16 +224,8 @@ void handle_sctp_packet(Sctp *sctp, char *buf, size_t len) { uint16_t sid = ntohs(*(uint16_t *)(buf + 20)); uint32_t ppid = ntohl(*(uint32_t *)(buf + 24)); - if (ppid==DCEP_PPID) - parse_data_channel_open(sctp, sid, buf + 28, len - 28); -} - -void print_hex_buffer(uint8_t *buf, int len) { - printf("data (%d): ", len); - for (int i = 0; i < len; i++) { - printf("%02X ", buf[i]); - } - printf("\n"); + if (ppid==DATA_CHANNEL_PPID_CONTROL) + sctp_parse_data_channel_open(sctp, sid, buf + 28, len - 28); } void sctp_incoming_data(Sctp *sctp, char *buf, size_t len) { @@ -243,8 +234,7 @@ void sctp_incoming_data(Sctp *sctp, char *buf, size_t len) { return; #ifdef HAVE_USRSCTP - //print_hex_buffer((uint8_t *)buf, len); - handle_sctp_packet(sctp, buf, len); + sctp_handle_sctp_packet(sctp, buf, len); usrsctp_conninput(sctp, buf, len, 0); #else size_t length = 0; diff --git a/src/sctp.h b/src/sctp.h index 979da09..ddcabca 100644 --- a/src/sctp.h +++ b/src/sctp.h @@ -141,7 +141,7 @@ typedef enum SctpDataPpid { typedef struct { char label[32]; // Stream label uint16_t sid; // Stream ID -} Stream_entry; +} SctpStreamEntry; typedef struct Sctp { @@ -155,7 +155,7 @@ typedef struct Sctp { DtlsSrtp *dtls_srtp; Buffer **data_rb; int stream_count; - Stream_entry stream_table[SCTP_MAX_STREAMS]; + SctpStreamEntry stream_table[SCTP_MAX_STREAMS]; /* datachannel */ void (*onmessage)(char *msg, size_t len, void *userdata, uint16_t sid);