#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>
#endif
#define BUFFER_SIZE 4096
#define BIND_ADDRESS "127.0.0.1"
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_bind() {
juice_set_log_level(JUICE_LOG_LEVEL_DEBUG);
juice_config_t config1;
memset(&config1, 0, sizeof(config1));
config1.bind_address = BIND_ADDRESS;
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;
agent1 = juice_create(&config1);
juice_config_t config2;
memset(&config2, 0, sizeof(config2));
config2.bind_address = BIND_ADDRESS;
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;
agent2 = juice_create(&config2);
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);
juice_set_remote_description(agent2, sdp1);
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);
juice_set_remote_description(agent1, sdp2);
juice_gather_candidates(agent1);
sleep(2);
juice_gather_candidates(agent2);
sleep(2);
bool success = true;
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 (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);
}
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);
}
juice_destroy(agent1);
juice_destroy(agent2);
sleep(2);
if (success) {
printf("Success\n");
return 0;
} else {
printf("Failure\n");
return -1;
}
}
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) {
const char *message = "Hello from 1";
juice_send(agent, message, strlen(message));
}
}
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) {
const char *message = "Hello from 2";
juice_send(agent, message, strlen(message));
}
}
static void on_candidate1(juice_agent_t *agent, const char *sdp, void *user_ptr) {
printf("Candidate 1: %s\n", sdp);
if(!strstr(sdp, "host") || !strstr(sdp, BIND_ADDRESS))
return;
juice_add_remote_candidate(agent2, sdp);
}
static void on_candidate2(juice_agent_t *agent, const char *sdp, void *user_ptr) {
printf("Candidate 2: %s\n", sdp);
if(!strstr(sdp, "host") || !strstr(sdp, BIND_ADDRESS))
return;
juice_add_remote_candidate(agent1, sdp);
}
static void on_gathering_done1(juice_agent_t *agent, void *user_ptr) {
printf("Gathering done 1\n");
juice_set_remote_gathering_done(agent2); }
static void on_gathering_done2(juice_agent_t *agent, void *user_ptr) {
printf("Gathering done 2\n");
juice_set_remote_gathering_done(agent1); }
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);
}
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);
}