mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-20 18:36:46 +00:00
ice ice baby
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@1040 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
0fe4db12d0
commit
fb796a0180
@ -64,6 +64,7 @@ SWITCH_DECLARE(switch_rtp *)switch_rtp_new(char *rx_ip,
|
|||||||
const char **err,
|
const char **err,
|
||||||
switch_memory_pool *pool);
|
switch_memory_pool *pool);
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status) switch_rtp_activate_ice(switch_rtp *rtp_session, char *login, char *rlogin);
|
||||||
SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp **rtp_session);
|
SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp **rtp_session);
|
||||||
SWITCH_DECLARE(switch_socket_t *)switch_rtp_get_rtp_socket(switch_rtp *rtp_session);
|
SWITCH_DECLARE(switch_socket_t *)switch_rtp_get_rtp_socket(switch_rtp *rtp_session);
|
||||||
SWITCH_DECLARE(void) switch_rtp_set_invald_handler(switch_rtp *rtp_session, switch_rtp_invalid_handler on_invalid);
|
SWITCH_DECLARE(void) switch_rtp_set_invald_handler(switch_rtp *rtp_session, switch_rtp_invalid_handler on_invalid);
|
||||||
|
@ -113,11 +113,9 @@ struct private_object {
|
|||||||
char *remote_user;
|
char *remote_user;
|
||||||
unsigned int cand_id;
|
unsigned int cand_id;
|
||||||
unsigned int desc_id;
|
unsigned int desc_id;
|
||||||
switch_socket_t *rtp_sock;
|
|
||||||
char last_digit;
|
char last_digit;
|
||||||
unsigned int dc;
|
unsigned int dc;
|
||||||
time_t last_digit_time;
|
time_t last_digit_time;
|
||||||
switch_mutex_t *rtp_lock;
|
|
||||||
switch_queue_t *dtmf_queue;
|
switch_queue_t *dtmf_queue;
|
||||||
char out_digit;
|
char out_digit;
|
||||||
unsigned char out_digit_packet[4];
|
unsigned char out_digit_packet[4];
|
||||||
@ -127,17 +125,11 @@ struct private_object {
|
|||||||
int32_t timestamp_send;
|
int32_t timestamp_send;
|
||||||
int32_t timestamp_recv;
|
int32_t timestamp_recv;
|
||||||
int32_t timestamp_dtmf;
|
int32_t timestamp_dtmf;
|
||||||
int8_t stuncount;
|
|
||||||
char *codec_name;
|
char *codec_name;
|
||||||
int codec_num;
|
int codec_num;
|
||||||
switch_time_t cng_next;
|
switch_time_t cng_next;
|
||||||
switch_time_t last_stun;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct rfc2833_digit {
|
struct rfc2833_digit {
|
||||||
char digit;
|
char digit;
|
||||||
int duration;
|
int duration;
|
||||||
@ -169,7 +161,6 @@ static switch_status channel_write_frame(switch_core_session *session, switch_fr
|
|||||||
static switch_status channel_kill_channel(switch_core_session *session, int sig);
|
static switch_status channel_kill_channel(switch_core_session *session, int sig);
|
||||||
static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsession, ldl_signal_t signal, char *msg);
|
static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsession, ldl_signal_t signal, char *msg);
|
||||||
static ldl_status handle_response(ldl_handle_t *handle, char *id);
|
static ldl_status handle_response(ldl_handle_t *handle, char *id);
|
||||||
static void switch_stun_callback(struct switch_rtp *switch_rtp, switch_socket_t *sock, void *data, switch_size_t len, switch_sockaddr_t *from_addr);
|
|
||||||
static switch_status load_config(void);
|
static switch_status load_config(void);
|
||||||
|
|
||||||
|
|
||||||
@ -692,37 +683,6 @@ static switch_status channel_write_frame(switch_core_session *session, switch_fr
|
|||||||
assert(tech_pvt->rtp_session != NULL);
|
assert(tech_pvt->rtp_session != NULL);
|
||||||
|
|
||||||
|
|
||||||
if (tech_pvt->stuncount == 0) {
|
|
||||||
uint8_t buf[256] = {0};
|
|
||||||
char login[80];
|
|
||||||
switch_stun_packet_t *packet;
|
|
||||||
//struct sockaddr_in servaddr;
|
|
||||||
unsigned int elapsed;
|
|
||||||
switch_size_t bytes;
|
|
||||||
|
|
||||||
if (tech_pvt->last_stun) {
|
|
||||||
elapsed = (unsigned int)((switch_time_now() - tech_pvt->last_stun) / 1000);
|
|
||||||
|
|
||||||
if (elapsed > 10000) {
|
|
||||||
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No stun for a long time (PUNT!)\n");
|
|
||||||
return SWITCH_STATUS_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(login, sizeof(login), "%s%s", tech_pvt->remote_user, tech_pvt->local_user);
|
|
||||||
packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, buf);
|
|
||||||
switch_stun_packet_attribute_add_username(packet, login, 32);
|
|
||||||
bytes = switch_stun_packet_length(packet);
|
|
||||||
switch_socket_sendto(tech_pvt->rtp_sock, tech_pvt->switch_stun_addr, 0, (void *)packet, &bytes);
|
|
||||||
|
|
||||||
//sendto(tech_pvt->rtp_sock, (char *)packet, switch_stun_packet_length(packet), 0 ,(struct sockaddr *)&servaddr, sizeof(servaddr));
|
|
||||||
//xstun
|
|
||||||
//printf("XXXX SEND STUN REQ %s U=%s to %s:%d\n", packet->header.id, login, tech_pvt->remote_ip, tech_pvt->remote_port);
|
|
||||||
tech_pvt->stuncount = 25;
|
|
||||||
} else {
|
|
||||||
tech_pvt->stuncount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!switch_test_flag(tech_pvt, TFLAG_RTP_READY)) {
|
if (!switch_test_flag(tech_pvt, TFLAG_RTP_READY)) {
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1353,10 +1313,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
|
|||||||
switch_channel_hangup(channel);
|
switch_channel_hangup(channel);
|
||||||
return LDL_STATUS_FALSE;
|
return LDL_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
tech_pvt->rtp_sock = switch_rtp_get_rtp_socket(tech_pvt->rtp_session);
|
|
||||||
switch_rtp_set_invald_handler(tech_pvt->rtp_session, switch_stun_callback);
|
|
||||||
switch_rtp_set_private(tech_pvt->rtp_session, tech_pvt);
|
|
||||||
switch_set_flag(tech_pvt, TFLAG_RTP_READY);
|
switch_set_flag(tech_pvt, TFLAG_RTP_READY);
|
||||||
|
switch_rtp_activate_ice(tech_pvt->rtp_session, tech_pvt->remote_user, tech_pvt->local_user);
|
||||||
switch_rtp_start(tech_pvt->rtp_session);
|
switch_rtp_start(tech_pvt->rtp_session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1394,75 +1352,3 @@ static ldl_status handle_response(ldl_handle_t *handle, char *id)
|
|||||||
return LDL_STATUS_SUCCESS;
|
return LDL_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void switch_stun_callback(struct switch_rtp *switch_rtp, switch_socket_t *sock, void *data, switch_size_t len, switch_sockaddr_t *from_addr)
|
|
||||||
{
|
|
||||||
switch_stun_packet_t *packet;
|
|
||||||
switch_stun_packet_attribute_t *attr;
|
|
||||||
char username[33] = {0};
|
|
||||||
struct private_object *tech_pvt;
|
|
||||||
unsigned char buf[512] = {0};
|
|
||||||
|
|
||||||
tech_pvt = switch_rtp_get_private(switch_rtp);
|
|
||||||
assert(tech_pvt != NULL);
|
|
||||||
|
|
||||||
memcpy(buf, data, len);
|
|
||||||
packet = switch_stun_packet_parse(buf, sizeof(buf));
|
|
||||||
tech_pvt->last_stun = switch_time_now();
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "read %d\ntype: [%s] (0x%04x)\nlength 0x%04x\nid %s\n",
|
|
||||||
len,
|
|
||||||
switch_stun_value_to_name(SWITCH_STUN_TYPE_PACKET_TYPE, packet->header.type),
|
|
||||||
packet->header.type,
|
|
||||||
packet->header.length,
|
|
||||||
packet->header.id);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch_stun_packet_first_attribute(packet, attr);
|
|
||||||
|
|
||||||
do {
|
|
||||||
//switch_console_printf(SWITCH_CHANNEL_CONSOLE, "ATTRIBUTE [%s] (0x%04x) [%04x bytes]\n", switch_stun_value_to_name(SWITCH_STUN_TYPE_ATTRIBUTE, attr->type), attr->type, attr->length);
|
|
||||||
|
|
||||||
switch(attr->type) {
|
|
||||||
case SWITCH_STUN_ATTR_MAPPED_ADDRESS:
|
|
||||||
if (attr->type) {
|
|
||||||
char ip[16];
|
|
||||||
uint16_t port;
|
|
||||||
switch_stun_packet_attribute_get_mapped_address(attr, ip, &port);
|
|
||||||
//switch_console_printf(SWITCH_CHANNEL_CONSOLE, "IP/PORT: %s:%d\n", ip, port);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SWITCH_STUN_ATTR_USERNAME:
|
|
||||||
if(attr->type) {
|
|
||||||
|
|
||||||
if (switch_stun_packet_attribute_get_username(attr, username, 32)) {
|
|
||||||
//switch_console_printf(SWITCH_CHANNEL_CONSOLE, "USERNAME: %s\n", username);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (switch_stun_packet_next_attribute(attr));
|
|
||||||
|
|
||||||
|
|
||||||
if (packet->header.type == SWITCH_STUN_BINDING_REQUEST && strstr(username,tech_pvt->remote_user)) {
|
|
||||||
uint8_t buf[512];
|
|
||||||
switch_stun_packet_t *rpacket;
|
|
||||||
char *remote_ip;
|
|
||||||
switch_size_t bytes;
|
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
rpacket = switch_stun_packet_build_header(SWITCH_STUN_BINDING_RESPONSE, packet->header.id, buf);
|
|
||||||
switch_stun_packet_attribute_add_username(rpacket, username, 32);
|
|
||||||
switch_sockaddr_ip_get(&remote_ip, from_addr);
|
|
||||||
switch_stun_packet_attribute_add_binded_address(rpacket, remote_ip, from_addr->port);
|
|
||||||
//xstun
|
|
||||||
//switch_console_printf(SWITCH_CHANNEL_CONSOLE, "RESPONSE TO BIND %s:%d [%s]\n", remote_ip, port, username);
|
|
||||||
//sendto(sock, (char *)rpacket, switch_stun_packet_length(rpacket), 0 ,(struct sockaddr *)&servaddr, sizeof(servaddr));
|
|
||||||
bytes = switch_stun_packet_length(rpacket);
|
|
||||||
switch_socket_sendto(tech_pvt->rtp_sock, from_addr, 0, (void*)rpacket, &bytes);
|
|
||||||
//switch_set_flag(tech_pvt, TFLAG_IO);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
114
src/switch_rtp.c
114
src/switch_rtp.c
@ -71,10 +71,95 @@ struct switch_rtp {
|
|||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
switch_memory_pool *pool;
|
switch_memory_pool *pool;
|
||||||
switch_sockaddr_t *from_addr;
|
switch_sockaddr_t *from_addr;
|
||||||
|
|
||||||
|
char *ice_user;
|
||||||
|
char *user_ice;
|
||||||
|
switch_time_t last_stun;
|
||||||
|
uint8_t stuncount;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int global_init = 0;
|
static int global_init = 0;
|
||||||
|
|
||||||
|
static switch_status ice_out(switch_rtp *rtp_session)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert(rtp_session != NULL);
|
||||||
|
assert(rtp_session->ice_user != NULL);
|
||||||
|
|
||||||
|
if (rtp_session->stuncount == 0) {
|
||||||
|
uint8_t buf[256] = {0};
|
||||||
|
switch_stun_packet_t *packet;
|
||||||
|
unsigned int elapsed;
|
||||||
|
switch_size_t bytes;
|
||||||
|
|
||||||
|
if (rtp_session->last_stun) {
|
||||||
|
elapsed = (unsigned int)((switch_time_now() - rtp_session->last_stun) / 1000);
|
||||||
|
|
||||||
|
if (elapsed > 10000) {
|
||||||
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No stun for a long time (PUNT!)\n");
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, buf);
|
||||||
|
switch_stun_packet_attribute_add_username(packet, rtp_session->ice_user, 32);
|
||||||
|
bytes = switch_stun_packet_length(packet);
|
||||||
|
switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void *)packet, &bytes);
|
||||||
|
rtp_session->stuncount = 25;
|
||||||
|
} else {
|
||||||
|
rtp_session->stuncount--;
|
||||||
|
}
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_ice(switch_rtp *rtp_session, void *data, switch_size_t len)
|
||||||
|
{
|
||||||
|
switch_stun_packet_t *packet;
|
||||||
|
switch_stun_packet_attribute_t *attr;
|
||||||
|
char username[33] = {0};
|
||||||
|
unsigned char buf[512] = {0};
|
||||||
|
|
||||||
|
memcpy(buf, data, len);
|
||||||
|
packet = switch_stun_packet_parse(buf, sizeof(buf));
|
||||||
|
rtp_session->last_stun = switch_time_now();
|
||||||
|
|
||||||
|
switch_stun_packet_first_attribute(packet, attr);
|
||||||
|
|
||||||
|
do {
|
||||||
|
switch(attr->type) {
|
||||||
|
case SWITCH_STUN_ATTR_MAPPED_ADDRESS:
|
||||||
|
if (attr->type) {
|
||||||
|
char ip[16];
|
||||||
|
uint16_t port;
|
||||||
|
switch_stun_packet_attribute_get_mapped_address(attr, ip, &port);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SWITCH_STUN_ATTR_USERNAME:
|
||||||
|
if(attr->type) {
|
||||||
|
switch_stun_packet_attribute_get_username(attr, username, 32);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (switch_stun_packet_next_attribute(attr));
|
||||||
|
|
||||||
|
|
||||||
|
if (packet->header.type == SWITCH_STUN_BINDING_REQUEST && !strcmp(rtp_session->user_ice, username)) {
|
||||||
|
uint8_t buf[512];
|
||||||
|
switch_stun_packet_t *rpacket;
|
||||||
|
char *remote_ip;
|
||||||
|
switch_size_t bytes;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
rpacket = switch_stun_packet_build_header(SWITCH_STUN_BINDING_RESPONSE, packet->header.id, buf);
|
||||||
|
switch_stun_packet_attribute_add_username(rpacket, username, 32);
|
||||||
|
switch_sockaddr_ip_get(&remote_ip, rtp_session->from_addr);
|
||||||
|
switch_stun_packet_attribute_add_binded_address(rpacket, remote_ip, rtp_session->from_addr->port);
|
||||||
|
bytes = switch_stun_packet_length(rpacket);
|
||||||
|
switch_socket_sendto(rtp_session->sock, rtp_session->from_addr, 0, (void*)rpacket, &bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void init_rtp(void)
|
static void init_rtp(void)
|
||||||
{
|
{
|
||||||
if (global_init) {
|
if (global_init) {
|
||||||
@ -186,6 +271,19 @@ SWITCH_DECLARE(switch_rtp *)switch_rtp_new(char *rx_ip,
|
|||||||
return rtp_session;
|
return rtp_session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status) switch_rtp_activate_ice(switch_rtp *rtp_session, char *login, char *rlogin)
|
||||||
|
{
|
||||||
|
char ice_user[80];
|
||||||
|
char user_ice[80];
|
||||||
|
|
||||||
|
snprintf(ice_user, sizeof(ice_user), "%s%s", login, rlogin);
|
||||||
|
snprintf(user_ice, sizeof(user_ice), "%s%s", rlogin, login);
|
||||||
|
rtp_session->ice_user = switch_core_strdup(rtp_session->pool, ice_user);
|
||||||
|
rtp_session->user_ice = switch_core_strdup(rtp_session->pool, user_ice);
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_rtp_killread(switch_rtp *rtp_session)
|
SWITCH_DECLARE(void) switch_rtp_killread(switch_rtp *rtp_session)
|
||||||
{
|
{
|
||||||
apr_socket_shutdown(rtp_session->sock, APR_SHUTDOWN_READWRITE);
|
apr_socket_shutdown(rtp_session->sock, APR_SHUTDOWN_READWRITE);
|
||||||
@ -227,6 +325,10 @@ SWITCH_DECLARE(int) switch_rtp_read(switch_rtp *rtp_session, void *data, uint32_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rtp_session->recv_msg.header.version != 2) {
|
if (rtp_session->recv_msg.header.version != 2) {
|
||||||
|
if (rtp_session->recv_msg.header.version == 0 && rtp_session->ice_user) {
|
||||||
|
handle_ice(rtp_session, (void *) &rtp_session->recv_msg, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
if (rtp_session->invalid_handler) {
|
if (rtp_session->invalid_handler) {
|
||||||
rtp_session->invalid_handler(rtp_session, rtp_session->sock, (void *) &rtp_session->recv_msg, bytes, rtp_session->from_addr);
|
rtp_session->invalid_handler(rtp_session, rtp_session->sock, (void *) &rtp_session->recv_msg, bytes, rtp_session->from_addr);
|
||||||
}
|
}
|
||||||
@ -254,6 +356,10 @@ SWITCH_DECLARE(int) switch_rtp_zerocopy_read(switch_rtp *rtp_session, void **dat
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rtp_session->recv_msg.header.version != 2) {
|
if (rtp_session->recv_msg.header.version != 2) {
|
||||||
|
if (rtp_session->recv_msg.header.version == 0 && rtp_session->ice_user) {
|
||||||
|
handle_ice(rtp_session, (void *) &rtp_session->recv_msg, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
if (rtp_session->invalid_handler) {
|
if (rtp_session->invalid_handler) {
|
||||||
rtp_session->invalid_handler(rtp_session, rtp_session->sock, (void *) &rtp_session->recv_msg, bytes, rtp_session->from_addr);
|
rtp_session->invalid_handler(rtp_session, rtp_session->sock, (void *) &rtp_session->recv_msg, bytes, rtp_session->from_addr);
|
||||||
}
|
}
|
||||||
@ -272,6 +378,7 @@ SWITCH_DECLARE(int) switch_rtp_write(switch_rtp *rtp_session, void *data, int da
|
|||||||
if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_IO)) {
|
if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_IO)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtp_session->ts += ts;
|
rtp_session->ts += ts;
|
||||||
rtp_session->seq = ntohs(rtp_session->seq) + 1;
|
rtp_session->seq = ntohs(rtp_session->seq) + 1;
|
||||||
rtp_session->seq = htons(rtp_session->seq);
|
rtp_session->seq = htons(rtp_session->seq);
|
||||||
@ -283,6 +390,9 @@ SWITCH_DECLARE(int) switch_rtp_write(switch_rtp *rtp_session, void *data, int da
|
|||||||
|
|
||||||
bytes = datalen + rtp_header_len;
|
bytes = datalen + rtp_header_len;
|
||||||
switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void*)&rtp_session->send_msg, &bytes);
|
switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void*)&rtp_session->send_msg, &bytes);
|
||||||
|
if (rtp_session->ice_user) {
|
||||||
|
ice_out(rtp_session);
|
||||||
|
}
|
||||||
|
|
||||||
return (int)bytes;
|
return (int)bytes;
|
||||||
}
|
}
|
||||||
@ -303,6 +413,10 @@ SWITCH_DECLARE(int) switch_rtp_write_payload(switch_rtp *rtp_session, void *data
|
|||||||
bytes = datalen + rtp_header_len;
|
bytes = datalen + rtp_header_len;
|
||||||
switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void*)&rtp_session->send_msg, &bytes);
|
switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void*)&rtp_session->send_msg, &bytes);
|
||||||
|
|
||||||
|
if (rtp_session->ice_user) {
|
||||||
|
ice_out(rtp_session);
|
||||||
|
}
|
||||||
|
|
||||||
return (int)bytes;
|
return (int)bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user