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

Implement ICE-TCP #293

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ set(TESTS_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/test/conflict.c
${CMAKE_CURRENT_SOURCE_DIR}/test/bind.c
${CMAKE_CURRENT_SOURCE_DIR}/test/ufrag.c
${CMAKE_CURRENT_SOURCE_DIR}/test/tcp.c
)
source_group("Test Files" FILES "${TESTS_SOURCES}")

Expand Down
8 changes: 8 additions & 0 deletions include/juice/juice.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ typedef enum juice_concurrency_mode {
JUICE_CONCURRENCY_MODE_THREAD, // Each connection runs in its own thread
} juice_concurrency_mode_t;

typedef enum juice_ice_tcp_mode {
JUICE_ICE_TCP_MODE_NONE = 0, // ICE-TCP is disabled
JUICE_ICE_TCP_MODE_ACTIVE, // ICE-TCP will operate as a client
JUICE_ICE_TCP_MODE_PASSIVE, // ICE-TCP will operate as a server
} juice_ice_tcp_mode_t;

typedef struct juice_config {
juice_concurrency_mode_t concurrency_mode;

Expand All @@ -104,6 +110,8 @@ typedef struct juice_config {
uint16_t local_port_range_begin;
uint16_t local_port_range_end;

juice_ice_tcp_mode_t ice_tcp_mode;

juice_cb_state_changed_t cb_state_changed;
juice_cb_candidate_t cb_candidate;
juice_cb_gathering_done_t cb_gathering_done;
Expand Down
7 changes: 7 additions & 0 deletions test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ int test_turn(void);
int test_conflict(void);
int test_bind(void);
int test_ufrag(void);
int test_tcp(void);

#ifndef NO_SERVER
int test_server(void);
Expand All @@ -30,6 +31,12 @@ int test_server(void);
int main(int argc, char **argv) {
juice_set_log_level(JUICE_LOG_LEVEL_WARN);

printf("\nRunning TCP test...\n");
if (test_tcp()) {
fprintf(stderr, "TCP test failed\n");
return -2;
}

printf("\nRunning CRC32 implementation test...\n");
if (test_crc32()) {
fprintf(stderr, "CRC32 implementation test failed\n");
Expand Down
220 changes: 220 additions & 0 deletions test/tcp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/**
* Copyright (c) 2020 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

#include "juice/juice.h"

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#ifdef _WIN32
#include <windows.h>
static void sleep(unsigned int secs) { Sleep(secs * 1000); }
#else
#include <unistd.h> // for sleep
#endif

#define BUFFER_SIZE 4096

static juice_agent_t *agent1;
static juice_agent_t *agent2;

static void on_state_changed1(juice_agent_t *agent, juice_state_t state, void *user_ptr);
static void on_state_changed2(juice_agent_t *agent, juice_state_t state, void *user_ptr);

static void on_candidate1(juice_agent_t *agent, const char *sdp, void *user_ptr);
static void on_candidate2(juice_agent_t *agent, const char *sdp, void *user_ptr);

static void on_gathering_done1(juice_agent_t *agent, void *user_ptr);
static void on_gathering_done2(juice_agent_t *agent, void *user_ptr);

static void on_recv1(juice_agent_t *agent, const char *data, size_t size, void *user_ptr);
static void on_recv2(juice_agent_t *agent, const char *data, size_t size, void *user_ptr);

int test_tcp() {
juice_set_log_level(JUICE_LOG_LEVEL_DEBUG);

// Agent 1: Create agent
juice_config_t config1;
memset(&config1, 0, sizeof(config1));

config1.cb_state_changed = on_state_changed1;
config1.cb_candidate = on_candidate1;
config1.cb_gathering_done = on_gathering_done1;
config1.cb_recv = on_recv1;
config1.user_ptr = NULL;
config1.ice_tcp_mode = JUICE_ICE_TCP_MODE_PASSIVE;

agent1 = juice_create(&config1);

// Agent 2: Create agent
juice_config_t config2;
memset(&config2, 0, sizeof(config2));

config2.cb_state_changed = on_state_changed2;
config2.cb_candidate = on_candidate2;
config2.cb_gathering_done = on_gathering_done2;
config2.cb_recv = on_recv2;
config2.user_ptr = NULL;
config1.ice_tcp_mode = JUICE_ICE_TCP_MODE_ACTIVE;

// agent2 = juice_create(&config2);

// Agent 1: Generate local description
char sdp1[JUICE_MAX_SDP_STRING_LEN];
juice_get_local_description(agent1, sdp1, JUICE_MAX_SDP_STRING_LEN);
printf("Local description 1:\n%s\n", sdp1);

// // Agent 2: Receive description from agent 1
// juice_set_remote_description(agent2, sdp1);

// // Agent 2: Generate local description
// char sdp2[JUICE_MAX_SDP_STRING_LEN];
// juice_get_local_description(agent2, sdp2, JUICE_MAX_SDP_STRING_LEN);
// printf("Local description 2:\n%s\n", sdp2);

// // Agent 1: Receive description from agent 2
// juice_set_remote_description(agent1, sdp2);

// Agent 1: Gather candidates (and send them to agent 2)
juice_gather_candidates(agent1);
sleep(2);

// // Agent 2: Gather candidates (and send them to agent 1)
// juice_gather_candidates(agent2);
// sleep(2);

// -- Connection should be finished --

// // Check states
// juice_state_t state1 = juice_get_state(agent1);
// juice_state_t state2 = juice_get_state(agent2);
// bool success = (state1 == JUICE_STATE_COMPLETED && state2 == JUICE_STATE_COMPLETED);

// // Retrieve candidates
// char local[JUICE_MAX_CANDIDATE_SDP_STRING_LEN];
// char remote[JUICE_MAX_CANDIDATE_SDP_STRING_LEN];
// if (success &=
// (juice_get_selected_candidates(agent1, local, JUICE_MAX_CANDIDATE_SDP_STRING_LEN, remote,
// JUICE_MAX_CANDIDATE_SDP_STRING_LEN) == 0)) {
// printf("Local candidate 1: %s\n", local);
// printf("Remote candidate 1: %s\n", remote);
// if ((!strstr(local, "typ host") && !strstr(local, "typ prflx")) ||
// (!strstr(remote, "typ host") && !strstr(remote, "typ prflx")))
// success = false; // local connection should be possible
// }
// if (success &=
// (juice_get_selected_candidates(agent2, local, JUICE_MAX_CANDIDATE_SDP_STRING_LEN, remote,
// JUICE_MAX_CANDIDATE_SDP_STRING_LEN) == 0)) {
// printf("Local candidate 2: %s\n", local);
// printf("Remote candidate 2: %s\n", remote);
// if ((!strstr(local, "typ host") && !strstr(local, "typ prflx")) ||
// (!strstr(remote, "typ host") && !strstr(remote, "typ prflx")))
// success = false; // local connection should be possible
// }

// // Retrieve addresses
// char localAddr[JUICE_MAX_ADDRESS_STRING_LEN];
// char remoteAddr[JUICE_MAX_ADDRESS_STRING_LEN];
// if (success &= (juice_get_selected_addresses(agent1, localAddr, JUICE_MAX_ADDRESS_STRING_LEN,
// remoteAddr, JUICE_MAX_ADDRESS_STRING_LEN) == 0)) {
// printf("Local address 1: %s\n", localAddr);
// printf("Remote address 1: %s\n", remoteAddr);
// }
// if (success &= (juice_get_selected_addresses(agent2, localAddr, JUICE_MAX_ADDRESS_STRING_LEN,
// remoteAddr, JUICE_MAX_ADDRESS_STRING_LEN) == 0)) {
// printf("Local address 2: %s\n", localAddr);
// printf("Remote address 2: %s\n", remoteAddr);
// }

// // Agent 1: destroy
// juice_destroy(agent1);

// // Agent 2: destroy
// juice_destroy(agent2);

// if (success) {
// printf("Success\n");
// return 0;
// } else {
// printf("Failure\n");
// return -1;
// }
//
return -1;
}

// Agent 1: on state changed
static void on_state_changed1(juice_agent_t *agent, juice_state_t state, void *user_ptr) {
// printf("State 1: %s\n", juice_state_to_string(state));
//
// if (state == JUICE_STATE_CONNECTED) {
// // Agent 1: on connected, send a message
// const char *message = "Hello from 1";
// juice_send(agent, message, strlen(message));
// }
}
//
// Agent 2: on state changed
static void on_state_changed2(juice_agent_t *agent, juice_state_t state, void *user_ptr) {
// printf("State 2: %s\n", juice_state_to_string(state));
// if (state == JUICE_STATE_CONNECTED) {
// // Agent 2: on connected, send a message
// const char *message = "Hello from 2";
// juice_send(agent, message, strlen(message));
// }
}

// Agent 1: on local candidate gathered
static void on_candidate1(juice_agent_t *agent, const char *sdp, void *user_ptr) {
// printf("Candidate 1: %s\n", sdp);
//
// // Agent 2: Receive it from agent 1
// juice_add_remote_candidate(agent2, sdp);
}
//
// Agent 2: on local candidate gathered
static void on_candidate2(juice_agent_t *agent, const char *sdp, void *user_ptr) {
// printf("Candidate 2: %s\n", sdp);
//
// // Agent 1: Receive it from agent 2
// juice_add_remote_candidate(agent1, sdp);
}

// Agent 1: on local candidates gathering done
static void on_gathering_done1(juice_agent_t *agent, void *user_ptr) {
// printf("Gathering done 1\n");
// juice_set_remote_gathering_done(agent2); // optional
}

// Agent 2: on local candidates gathering done
static void on_gathering_done2(juice_agent_t *agent, void *user_ptr) {
// printf("Gathering done 2\n");
// juice_set_remote_gathering_done(agent1); // optional
}

// Agent 1: on message received
static void on_recv1(juice_agent_t *agent, const char *data, size_t size, void *user_ptr) {
// char buffer[BUFFER_SIZE];
// if (size > BUFFER_SIZE - 1)
// size = BUFFER_SIZE - 1;
// memcpy(buffer, data, size);
// buffer[size] = '\0';
// printf("Received 1: %s\n", buffer);
}
//
// Agent 2: on message received
static void on_recv2(juice_agent_t *agent, const char *data, size_t size, void *user_ptr) {
// char buffer[BUFFER_SIZE];
// if (size > BUFFER_SIZE - 1)
// size = BUFFER_SIZE - 1;
// memcpy(buffer, data, size);
// buffer[size] = '\0';
// printf("Received 2: %s\n", buffer);
}
Loading