Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle trickled candidates in WebRTC native #77

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 101 additions & 70 deletions net_drivers/webrtc_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,57 +316,6 @@ static void NBN_WebRTC_C_StringReplaceAll(char *res, const char *str, const char

#pragma region WebRTC common

static char *NBN_WebRTC_C_ParseSignalingMessage(const char *msg, size_t msg_len, const char *type)
{
char *sdp = NULL;
struct json_value_s* root = json_parse(msg, msg_len); // this has to be freed

struct json_object_s* object = (struct json_object_s*)root->payload;
struct json_object_element_s *curr = object->start;

if (root->type != json_type_object)
{
NBN_LogDebug("Received an invalid signaling message: %s", msg);
goto leave_free_root;
}

while (curr != NULL)
{
if (strncmp(curr->name->string, "type", 4) == 0)
{
struct json_string_s *str = json_value_as_string(curr->value);

if (strncmp(str->string, type, strlen(type)))
{
// unexpected type
NBN_LogDebug("Received a signaling message with an unexpected type: %s (expected: %s)", str->string, type);
sdp = NULL;
goto leave_free_root;
}
}
else if (strncmp(curr->name->string, "sdp", 3) == 0)
{
struct json_string_s *str = json_value_as_string(curr->value);

if (str)
{
// strdup equivalent using NBN_Allocator, make sure this get freed
size_t len = strlen(str->string);

sdp = (char*)NBN_Allocator(len + 1);
memcpy(sdp, str->string, len + 1);
}
}

curr = curr->next;
}

leave_free_root:
free(root);

return sdp;
}

static char *NBN_WebRTC_C_EscapeSDP(const char *sdp)
{
size_t len = strlen(sdp) * 2; // TODO: kinda lame way of making sure it's going to be big enough, find a better way
Expand Down Expand Up @@ -513,39 +462,121 @@ static void NBN_WebRTC_C_ProcessLocalDescription(NBN_WebRTC_C_Peer *peer, const
NBN_Deallocator(escaped_sdp);
}

static void NBN_WebRTC_C_ProcessSignalingMessage(NBN_WebRTC_C_Peer *peer, int ws, const char *msg, int size, const char *type)
{
// for some reason the size of the message is negative
// in libdatachannel documentation (https://github.com/paullouisageneau/libdatachannel/blob/master/DOC.md) there is mention of:
// size: if size >= 0, data is interpreted as a binary message of length size, otherwise it is interpreted as a null-terminated UTF-8 string.
// so I guess in this case msg is a null terminated string? I could not find more information about this so I decided to go with
// flipping the size to positive even though it feels weird, but it works so... ¯\_(ツ)_/¯

if (size < 0) size *= -1;
size -= 1;
static struct json_value_s* NBN_WebRTC_C_JsonGetValue(struct json_value_s *json, const char *name) {
struct json_object_s* object = (struct json_object_s*)json->payload;
struct json_object_element_s *curr = object->start;
while (curr != NULL)
{
if (strcmp(curr->name->string, name) == 0)
{
return curr->value;
}
curr = curr->next;
}
return NULL;
}

NBN_LogDebug("Received signaling message on WS %d (size: %d): %s", ws, size, msg);
static const char* NBN_WebRTC_C_JsonGetStringValue(struct json_value_s *json, const char *name) {
struct json_value_s *value = NBN_WebRTC_C_JsonGetValue(json, name);
if(value) {
struct json_string_s* str = json_value_as_string(value);
if(str) {
return str->string;
}
} else {
return NULL;
}
}

char *sdp = NBN_WebRTC_C_ParseSignalingMessage(msg, size, type);
static void NBN_WebRTC_C_SendSignalingReadyMessage(NBN_WebRTC_C_Peer *peer) {
const char* json = "{ \"signaling\": { \"ready_for_candidates\": true } }";
if (rtcSendMessage(peer->ws, json, -1) < 0)
{
NBN_WebRTC_C_DestroyPeer(peer);
}
}

static void NBN_WebRTC_C_ProcessSDPMessage(NBN_WebRTC_C_Peer *peer, int ws, struct json_value_s *root, const char *type) {
const char *sdp = NBN_WebRTC_C_JsonGetStringValue(root, "sdp");
if (!sdp)
{
NBN_LogWarning("Failed to parse signaling data for WS %d", ws);
NBN_LogWarning("Failed to parse sdp signaling data for WS %d", ws);
return;
}

NBN_LogDebug("Successfully parsed signaling payload (sdp: %s)", sdp);

// we don't need to worry about keeping sdp or type alive because rtcSetRemoteDescription copies them
int ret = rtcSetRemoteDescription(peer->id, sdp, type);

if (ret < 0)
{
NBN_LogError("Failed to set remote description for peer %d (WS: %d): %d", peer->id, ws, ret);
rtcClose(ws);
} else {
NBN_WebRTC_C_SendSignalingReadyMessage(peer);
}
}

static void NBN_WebRTC_C_ProcessCandidateMessage(NBN_WebRTC_C_Peer *peer, int ws, struct json_value_s *json) {
const char *candidate = NBN_WebRTC_C_JsonGetStringValue(json, "candidate");
if (!candidate)
{
NBN_LogWarning("Failed to parse candidate signaling data for WS %d", ws);
return;
}
NBN_LogDebug("Successfully parsed trickled candidate payload (candidate: %s)", candidate);

if(strlen(candidate) == 0) {
NBN_LogDebug("Ignoring empty candidate WS %d", ws);
return;
}

int ret = rtcAddRemoteCandidate(peer->id, candidate, NULL);

if (ret < 0)
{
NBN_LogError("Failed to add trickled candidate for peer %d (WS: %d): %d", peer->id, ws, ret);
rtcClose(ws);
}
}


static void NBN_WebRTC_C_ProcessSignalingMessage(NBN_WebRTC_C_Peer *peer, int ws, const char *msg, int size)
{
// for some reason the size of the message is negative
// in libdatachannel documentation (https://github.com/paullouisageneau/libdatachannel/blob/master/DOC.md) there is mention of:
// size: if size >= 0, data is interpreted as a binary message of length size, otherwise it is interpreted as a null-terminated UTF-8 string.
// so I guess in this case msg is a null terminated string? I could not find more information about this so I decided to go with
// flipping the size to positive even though it feels weird, but it works so... ¯\_(ツ)_/¯

if (size < 0) size *= -1;
size -= 1;

NBN_LogDebug("Received signaling message on WS %d (size: %d): %s", ws, size, msg);

struct json_value_s* root = json_parse(msg, size);

if (root->type != json_type_object)
{
NBN_LogDebug("Received an invalid signaling message: %s", msg);
}

// IMPORTANT: not sure I can free this because it's passed to rtcSetRemoteDescription
NBN_Deallocator(sdp);
const char *type = NBN_WebRTC_C_JsonGetStringValue(root, "type");
struct json_value_s *signaling = NBN_WebRTC_C_JsonGetValue(root, "signaling");
struct json_value_s *candidate = NBN_WebRTC_C_JsonGetValue(root, "candidate");

if(type) {
NBN_WebRTC_C_ProcessSDPMessage(peer, ws, root, type);
} else if(signaling) {
// TODO: handle sending trickled ice candidates
} else if(candidate) {
NBN_WebRTC_C_ProcessCandidateMessage(peer, ws, candidate);
}
else {
NBN_LogWarning("Failed to parse signaling message for WS %d", ws);
}
free(root);
}

#pragma endregion /* WebRTC common */
Expand All @@ -567,7 +598,7 @@ static void NBN_WebRTC_C_Serv_OnLocalDescription(int pc, const char *sdp, const
{
NBN_LogDebug("Processing local description of type '%s'", type);

if (strncmp(type, "answer", strlen("answer")) != 0)
if (strcmp(type, "answer") != 0)
{
NBN_LogWarning("Ignoring local description of type '%s' (expected 'answer')", type);
return;
Expand Down Expand Up @@ -626,7 +657,7 @@ static void NBN_WebRTC_C_Serv_OnWsClosed(int ws, void *user_ptr)

static void NBN_WebRTC_C_Serv_OnWsMessage(int ws, const char *msg, int size, void *user_ptr)
{
NBN_WebRTC_C_ProcessSignalingMessage((NBN_WebRTC_C_Peer *)user_ptr, ws, msg, size, "offer");
NBN_WebRTC_C_ProcessSignalingMessage((NBN_WebRTC_C_Peer *)user_ptr, ws, msg, size);
}

static void NBN_WebRTC_C_Serv_OnWsConnection(int wsserver, int ws, void *user_ptr)
Expand Down Expand Up @@ -750,7 +781,7 @@ static void NBN_WebRTC_C_Cli_OnLocalDescription(int pc, const char *sdp, const c
{
NBN_LogDebug("Processing local description of type '%s'", type);

if (strncmp(type, "offer", strlen("offer")) != 0)
if (strcmp(type, "offer") != 0)
{
NBN_LogWarning("Ignoring local description of type '%s' (expected 'offer')", type);
return;
Expand Down Expand Up @@ -805,7 +836,7 @@ static void NBN_WebRTC_C_Cli_OnWsClosed(int ws, void *user_ptr)

static void NBN_WebRTC_C_Cli_OnWsMessage(int ws, const char *msg, int size, void *user_ptr)
{
NBN_WebRTC_C_ProcessSignalingMessage((NBN_WebRTC_C_Peer *)user_ptr, ws, msg, size, "answer");
NBN_WebRTC_C_ProcessSignalingMessage((NBN_WebRTC_C_Peer *)user_ptr, ws, msg, size);
}

static int AttemptConnection(void)
Expand Down
Loading