FS-7587 Add ipv6 support to Verto / Websockets

This commit is contained in:
Anthony Minessale 2015-05-28 18:02:21 -05:00
parent 55a955787c
commit 3b2d00f3e6
11 changed files with 489 additions and 188 deletions

View File

@ -5,9 +5,9 @@
</settings> </settings>
<profiles> <profiles>
<profile name="mine"> <profile name="default-v4">
<param name="bind-local" value="0.0.0.0:8081"/> <param name="bind-local" value="$${local_ip_v4}:8081"/>
<param name="bind-local" value="0.0.0.0:8082" secure="true"/> <param name="bind-local" value="$${local_ip_v4}:8082" secure="true"/>
<param name="force-register-domain" value="$${domain}"/> <param name="force-register-domain" value="$${domain}"/>
<param name="secure-combined" value="$${certs_dir}/wss.pem"/> <param name="secure-combined" value="$${certs_dir}/wss.pem"/>
<param name="secure-chain" value="$${certs_dir}/wss.pem"/> <param name="secure-chain" value="$${certs_dir}/wss.pem"/>
@ -21,7 +21,28 @@
<param name="local-network" value="localnet.auto"/> <param name="local-network" value="localnet.auto"/>
<param name="outbound-codec-string" value="opus,vp8"/> <param name="outbound-codec-string" value="opus,vp8"/>
<param name="inbound-codec-string" value="opus,vp8"/> <param name="inbound-codec-string" value="opus,vp8"/>
<param name="apply-candidate-acl" value="wan.auto"/> <param name="apply-candidate-acl" value="wan_v4.auto"/>
<param name="timer-name" value="soft"/>
</profile>
<profile name="default-v6">
<param name="bind-local" value="[$${local_ip_v6}]:8081"/>
<param name="bind-local" value="[$${local_ip_v6}]:8082" secure="true"/>
<param name="force-register-domain" value="$${domain}"/>
<param name="secure-combined" value="$${certs_dir}/wss.pem"/>
<param name="secure-chain" value="$${certs_dir}/wss.pem"/>
<param name="userauth" value="true"/>
<!-- setting this to true will allow anyone to register even with no account so use with care -->
<param name="blind-reg" value="false"/>
<param name="mcast-ip" value="ff02::1"/>
<param name="mcast-port" value="1337"/>
<param name="rtp-ip" value="$${local_ip_v6}"/>
<!-- <param name="ext-rtp-ip" value=""/> -->
<param name="local-network" value="localnet.auto"/>
<param name="outbound-codec-string" value="opus,vp8"/>
<param name="inbound-codec-string" value="opus,vp8"/>
<param name="apply-candidate-acl" value="wan_v6.auto"/>
<param name="timer-name" value="soft"/> <param name="timer-name" value="soft"/>
</profile> </profile>

View File

@ -125,6 +125,9 @@ typedef struct switch_core_media_params_s {
char *extrtpip; char *extrtpip;
char *rtpip; char *rtpip;
char *rtpip4;
char *rtpip6;
char *remote_ip; char *remote_ip;
int remote_port; int remote_port;

View File

@ -105,6 +105,7 @@ typedef struct ice_s {
icand_t cands[MAX_CAND][2]; icand_t cands[MAX_CAND][2];
int cand_idx; int cand_idx;
int chosen[2]; int chosen[2];
int is_chosen[2];
char *ufrag; char *ufrag;
char *pwd; char *pwd;
char *options; char *options;

View File

@ -58,16 +58,29 @@
int mcast_socket_create(const char *host, int16_t port, mcast_handle_t *handle, mcast_flag_t flags) int mcast_socket_create(const char *host, int16_t port, mcast_handle_t *handle, mcast_flag_t flags)
{ {
uint32_t one = 1; uint32_t one = 1;
int family = AF_INET;
memset(handle, 0, sizeof(*handle)); memset(handle, 0, sizeof(*handle));
if ((!(flags & MCAST_SEND) && !(flags & MCAST_RECV)) || (handle->sock = socket(AF_INET, SOCK_DGRAM, 0)) <= 0 ) { if (strchr(host, ':')) {
return -1; family = AF_INET6;
} }
handle->send_addr.sin_family = AF_INET; if ((!(flags & MCAST_SEND) && !(flags & MCAST_RECV)) || (handle->sock = socket(family, SOCK_DGRAM, 0)) <= 0 ) {
handle->send_addr.sin_addr.s_addr = inet_addr(host); return -1;
handle->send_addr.sin_port = htons(port); }
if (family == AF_INET6) {
handle->send_addr6.sin6_family = AF_INET6;
handle->send_addr6.sin6_port = htons(port);
inet_pton(AF_INET6, host, &(handle->send_addr6.sin6_addr));
handle->family = AF_INET6;
} else {
handle->send_addr.sin_family = AF_INET;
handle->send_addr.sin_addr.s_addr = inet_addr(host);
handle->send_addr.sin_port = htons(port);
handle->family = AF_INET;
}
if ( setsockopt(handle->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)) != 0 ) { if ( setsockopt(handle->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)) != 0 ) {
close(handle->sock); close(handle->sock);
@ -76,28 +89,61 @@ int mcast_socket_create(const char *host, int16_t port, mcast_handle_t *handle,
if ((flags & MCAST_RECV)) { if ((flags & MCAST_RECV)) {
struct ip_mreq mreq; if (handle->family == AF_INET) {
struct ip_mreq mreq;
handle->recv_addr.sin_family = AF_INET;
handle->recv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
handle->recv_addr.sin_port = htons(port);
handle->recv_addr.sin_family = AF_INET; mreq.imr_multiaddr.s_addr = inet_addr(host);
handle->recv_addr.sin_addr.s_addr = htonl(INADDR_ANY); mreq.imr_interface.s_addr = htonl(INADDR_ANY);
handle->recv_addr.sin_port = htons(port);
mreq.imr_multiaddr.s_addr = inet_addr(host); if (setsockopt(handle->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) < 0) {
mreq.imr_interface.s_addr = htonl(INADDR_ANY); close(handle->sock);
handle->sock = -1;
return -1;
}
if (setsockopt(handle->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) < 0) { if (bind(handle->sock, (struct sockaddr *) &handle->recv_addr, sizeof(handle->recv_addr)) < 0) {
close(handle->sock); close(handle->sock);
handle->sock = -1; handle->sock = -1;
return -1; return -1;
}
} else {
struct ipv6_mreq mreq;
struct addrinfo addr_criteria;
struct addrinfo *mcast_addr;
char service[80] = "";
memset(&addr_criteria, 0, sizeof(addr_criteria));
addr_criteria.ai_family = AF_UNSPEC;
addr_criteria.ai_socktype = SOCK_DGRAM;
addr_criteria.ai_protocol = IPPROTO_UDP;
addr_criteria.ai_flags |= AI_NUMERICHOST;
snprintf(service, sizeof(service), "%d", port);
getaddrinfo(host, service, &addr_criteria, &mcast_addr);
memset(&handle->recv_addr6, 0, sizeof(handle->recv_addr6));
handle->recv_addr6.sin6_family = AF_INET6;
handle->recv_addr6.sin6_port = htons(port);
inet_pton(AF_INET6, "::0", &(handle->recv_addr6.sin6_addr));
memcpy(&mreq.ipv6mr_multiaddr, &((struct sockaddr_in6 *)mcast_addr->ai_addr)->sin6_addr, sizeof(struct in6_addr));
mreq.ipv6mr_interface = 0;
setsockopt(handle->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq));
if (bind(handle->sock, (struct sockaddr *) &handle->recv_addr6, sizeof(handle->recv_addr6)) < 0) {
printf("FUCK (%s) %s\n", host, strerror(errno));
close(handle->sock);
handle->sock = -1;
return -1;
}
} }
if (bind(handle->sock, (struct sockaddr *) &handle->recv_addr, sizeof(handle->recv_addr)) < 0) {
close(handle->sock);
handle->sock = -1;
return -1;
}
} }
handle->ttl = 1; handle->ttl = 1;
@ -155,7 +201,11 @@ ssize_t mcast_socket_send(mcast_handle_t *handle, void *data, size_t datalen)
datalen = sizeof(handle->buffer); datalen = sizeof(handle->buffer);
} }
return sendto(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->send_addr, sizeof(handle->send_addr)); if (handle->family == AF_INET6) {
return sendto(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->send_addr6, sizeof(handle->send_addr6));
} else {
return sendto(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->send_addr, sizeof(handle->send_addr));
}
} }
ssize_t mcast_socket_recv(mcast_handle_t *handle, void *data, size_t datalen, int ms) ssize_t mcast_socket_recv(mcast_handle_t *handle, void *data, size_t datalen, int ms)
@ -175,6 +225,9 @@ ssize_t mcast_socket_recv(mcast_handle_t *handle, void *data, size_t datalen, in
} }
} }
if (handle->family == AF_INET6) {
return recvfrom(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->recv_addr, &addrlen); return recvfrom(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->recv_addr6, &addrlen);
} else {
return recvfrom(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->recv_addr, &addrlen);
}
} }

View File

@ -71,6 +71,9 @@ typedef struct {
unsigned char ttl; unsigned char ttl;
struct sockaddr_in send_addr; struct sockaddr_in send_addr;
struct sockaddr_in recv_addr; struct sockaddr_in recv_addr;
struct sockaddr_in6 send_addr6;
struct sockaddr_in6 recv_addr6;
int family;
unsigned char buffer[65536]; unsigned char buffer[65536];
int ready; int ready;
} mcast_handle_t; } mcast_handle_t;

View File

@ -1803,12 +1803,6 @@ error:
static void client_run(jsock_t *jsock) static void client_run(jsock_t *jsock)
{ {
jsock->local_addr.sin_family = AF_INET;
jsock->local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
jsock->local_addr.sin_port = 0;
if (ws_init(&jsock->ws, jsock->client_socket, (jsock->ptype & PTYPE_CLIENT_SSL) ? jsock->profile->ssl_ctx : NULL, 0, 1, !!jsock->profile->vhosts) < 0) { if (ws_init(&jsock->ws, jsock->client_socket, (jsock->ptype & PTYPE_CLIENT_SSL) ? jsock->profile->ssl_ctx : NULL, 0, 1, !!jsock->profile->vhosts) < 0) {
if (jsock->profile->vhosts) { if (jsock->profile->vhosts) {
http_run(jsock); http_run(jsock);
@ -2259,10 +2253,30 @@ static void verto_set_media_options(verto_pvt_t *tech_pvt, verto_profile_t *prof
{ {
uint32_t i; uint32_t i;
tech_pvt->mparams->rtpip = switch_core_session_strdup(tech_pvt->session, profile->rtpip[profile->rtpip_cur++]); if (!zstr(profile->rtpip[profile->rtpip_cur])) {
tech_pvt->mparams->rtpip4 = switch_core_session_strdup(tech_pvt->session, profile->rtpip[profile->rtpip_cur++]);
tech_pvt->mparams->rtpip = tech_pvt->mparams->rtpip4;
if (profile->rtpip_cur == profile->rtpip_index) {
profile->rtpip_cur = 0;
}
}
if (profile->rtpip_cur == profile->rtpip_index) { if (!zstr(profile->rtpip6[profile->rtpip_cur6])) {
profile->rtpip_cur = 0; tech_pvt->mparams->rtpip6 = switch_core_session_strdup(tech_pvt->session, profile->rtpip6[profile->rtpip_cur6++]);
if (zstr(tech_pvt->mparams->rtpip)) {
tech_pvt->mparams->rtpip = tech_pvt->mparams->rtpip6;
}
if (profile->rtpip_cur6 == profile->rtpip_index6) {
profile->rtpip_cur6 = 0;
}
}
if (zstr(tech_pvt->mparams->rtpip)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "%s has no media ip, check your configuration\n",
switch_channel_get_name(tech_pvt->channel));
switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL);
} }
tech_pvt->mparams->extrtpip = tech_pvt->mparams->extsipip = profile->extrtpip; tech_pvt->mparams->extrtpip = tech_pvt->mparams->extsipip = profile->extrtpip;
@ -3376,7 +3390,7 @@ static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock
switch_either(jsock->dialplan, jsock->profile->dialplan), switch_either(jsock->dialplan, jsock->profile->dialplan),
caller_id_name, caller_id_name,
caller_id_number, caller_id_number,
inet_ntoa(jsock->remote_addr.sin_addr), jsock->remote_host,
cJSON_GetObjectCstr(dialog, "ani"), cJSON_GetObjectCstr(dialog, "ani"),
cJSON_GetObjectCstr(dialog, "aniii"), cJSON_GetObjectCstr(dialog, "aniii"),
cJSON_GetObjectCstr(dialog, "rdnis"), cJSON_GetObjectCstr(dialog, "rdnis"),
@ -3778,7 +3792,7 @@ static void jrpc_init(void)
static int start_jsock(verto_profile_t *profile, ws_socket_t sock) static int start_jsock(verto_profile_t *profile, ws_socket_t sock, int family)
{ {
jsock_t *jsock = NULL; jsock_t *jsock = NULL;
int flag = 1; int flag = 1;
@ -3798,11 +3812,20 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock)
jsock = (jsock_t *) switch_core_alloc(pool, sizeof(*jsock)); jsock = (jsock_t *) switch_core_alloc(pool, sizeof(*jsock));
jsock->pool = pool; jsock->pool = pool;
jsock->family = family;
len = sizeof(jsock->remote_addr); if (family == PF_INET) {
len = sizeof(jsock->remote_addr);
if ((jsock->client_socket = accept(sock, (struct sockaddr *) &jsock->remote_addr, &len)) < 0) { if ((jsock->client_socket = accept(sock, (struct sockaddr *) &jsock->remote_addr, &len)) < 0) {
die("ACCEPT FAILED\n"); die("ACCEPT FAILED\n");
}
} else {
len = sizeof(jsock->remote_addr6);
if ((jsock->client_socket = accept(sock, (struct sockaddr *) &jsock->remote_addr6, &len)) < 0) {
die("ACCEPT FAILED\n");
}
} }
for (i = 0; i < profile->i; i++) { for (i = 0; i < profile->i; i++) {
@ -3818,7 +3841,15 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock)
jsock->profile = profile; jsock->profile = profile;
if (zstr(jsock->name)) { if (zstr(jsock->name)) {
jsock->name = switch_core_sprintf(pool, "%s:%d", inet_ntoa(jsock->remote_addr.sin_addr), ntohs(jsock->remote_addr.sin_port)); if (family == PF_INET) {
jsock->remote_port = ntohs(jsock->remote_addr.sin_port);
inet_ntop(AF_INET, &jsock->remote_addr.sin_addr, jsock->remote_host, sizeof(jsock->remote_host));
jsock->name = switch_core_sprintf(pool, "%s:%d", jsock->remote_host, jsock->remote_port);
} else {
jsock->remote_port = ntohs(jsock->remote_addr6.sin6_port);
inet_ntop(AF_INET6, &jsock->remote_addr6.sin6_addr, jsock->remote_host, sizeof(jsock->remote_host));
jsock->name = switch_core_sprintf(pool, "%s:%d", jsock->remote_host, jsock->remote_port);
}
} }
jsock->ptype = ptype; jsock->ptype = ptype;
@ -3826,7 +3857,7 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Client Connect.\n", jsock->name); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Client Connect.\n", jsock->name);
if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_CLIENT_CONNECT) == SWITCH_STATUS_SUCCESS) { if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_CLIENT_CONNECT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "verto_profile_name", profile->name); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "verto_profile_name", profile->name);
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "verto_client_address", "%s:%d", inet_ntoa(jsock->remote_addr.sin_addr), ntohs(jsock->remote_addr.sin_port)); switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "verto_client_address", "%s:%d", jsock->remote_host, jsock->remote_port);
switch_event_fire(&s_event); switch_event_fire(&s_event);
} }
@ -3873,7 +3904,7 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock)
return -1; return -1;
} }
static ws_socket_t prepare_socket(int ip, uint16_t port) static ws_socket_t prepare_socket(ips_t *ips)
{ {
ws_socket_t sock = ws_sock_invalid; ws_socket_t sock = ws_sock_invalid;
#ifndef WIN32 #ifndef WIN32
@ -3881,29 +3912,48 @@ static ws_socket_t prepare_socket(int ip, uint16_t port)
#else #else
char reuse_addr = 1; char reuse_addr = 1;
#endif #endif
int family;
struct sockaddr_in addr; struct sockaddr_in addr;
struct sockaddr_in6 addr6;
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { if (strchr(ips->local_ip, ':')) {
family = PF_INET6;
} else {
family = PF_INET;
}
if ((sock = socket(family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
die("Socket Error!\n"); die("Socket Error!\n");
} }
if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)) < 0 ) { if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)) < 0 ) {
die("Socket setsockopt Error!\n"); die("Socket setsockopt Error!\n");
} }
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = ip;
addr.sin_port = htons(port);
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
die("Bind Error!\n");
}
if (family == PF_INET) {
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ips->local_ip);
addr.sin_port = htons(ips->local_port);
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
die("Bind Error!\n");
}
} else {
memset(&addr6, 0, sizeof(addr6));
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(ips->local_port);
inet_pton(AF_INET6, ips->local_ip, &(addr6.sin6_addr));
if (bind(sock, (struct sockaddr *) &addr6, sizeof(addr6)) < 0) {
die("Bind Error!\n");
}
}
if (listen(sock, MAXPENDING) < 0) { if (listen(sock, MAXPENDING) < 0) {
die("Listen error\n"); die("Listen error\n");
} }
ips->family = family;
return sock; return sock;
error: error:
@ -3979,7 +4029,7 @@ static int profile_one_loop(verto_profile_t *profile)
if (profile->mcast_ip && pfds[x].sock == (switch_os_socket_t)profile->mcast_sub.sock) { if (profile->mcast_ip && pfds[x].sock == (switch_os_socket_t)profile->mcast_sub.sock) {
handle_mcast_sub(profile); handle_mcast_sub(profile);
} else { } else {
start_jsock(profile, pfds[x].sock); start_jsock(profile, pfds[x].sock, profile->ip[x].family);
} }
} }
} }
@ -3991,52 +4041,6 @@ static int profile_one_loop(verto_profile_t *profile)
} }
static int runtime(verto_profile_t *profile)
{
int i;
for (i = 0; i < profile->i; i++) {
if ((profile->server_socket[i] = prepare_socket(profile->ip[i].local_ip_addr, profile->ip[i].local_port)) < 0) {
die("Client Socket Error!\n");
}
}
if (profile->mcast_ip) {
if (mcast_socket_create(profile->mcast_ip, profile->mcast_port, &profile->mcast_sub, MCAST_RECV | MCAST_TTL_HOST) < 0) {
die("mcast recv socket create");
}
if (mcast_socket_create(profile->mcast_ip, profile->mcast_port + 1, &profile->mcast_pub, MCAST_SEND | MCAST_TTL_HOST) > 0) {
mcast_socket_close(&profile->mcast_sub);
die("mcast send socket create");
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MCAST Bound to %s:%d/%d\n", profile->mcast_ip, profile->mcast_port, profile->mcast_port + 1);
}
while(profile->running) {
if (profile_one_loop(profile) < 0) {
goto error;
}
}
if (profile->mcast_sub.sock > -1) {
mcast_socket_close(&profile->mcast_sub);
}
if (profile->mcast_pub.sock > -1) {
mcast_socket_close(&profile->mcast_pub);
}
return 0;
error:
return -1;
}
static void kill_profile(verto_profile_t *profile) static void kill_profile(verto_profile_t *profile)
{ {
jsock_t *p; jsock_t *p;
@ -4092,6 +4096,58 @@ static void kill_profiles(void)
} }
static int runtime(verto_profile_t *profile)
{
int i;
int r = 0;
for (i = 0; i < profile->i; i++) {
//if ((profile->server_socket[i] = prepare_socket(profile->ip[i].local_ip_addr, profile->ip[i].local_port)) < 0) {
if ((profile->server_socket[i] = prepare_socket(&profile->ip[i])) < 0) {
die("Client Socket Error!\n");
}
}
if (profile->mcast_ip) {
if (mcast_socket_create(profile->mcast_ip, profile->mcast_port, &profile->mcast_sub, MCAST_RECV | MCAST_TTL_HOST) < 0) {
r = -1;
die("mcast recv socket create\n");
}
if (mcast_socket_create(profile->mcast_ip, profile->mcast_port + 1, &profile->mcast_pub, MCAST_SEND | MCAST_TTL_HOST) > 0) {
mcast_socket_close(&profile->mcast_sub);
r = -1;
die("mcast send socket create\n");
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MCAST Bound to %s:%d/%d\n", profile->mcast_ip, profile->mcast_port, profile->mcast_port + 1);
}
while(profile->running) {
if (profile_one_loop(profile) < 0) {
goto error;
}
}
error:
if (profile->mcast_sub.sock > -1) {
mcast_socket_close(&profile->mcast_sub);
}
if (profile->mcast_pub.sock > -1) {
mcast_socket_close(&profile->mcast_pub);
}
if (r) {
kill_profile(profile);
}
return r;
}
static void do_shutdown(void) static void do_shutdown(void)
{ {
globals.running = 0; globals.running = 0;
@ -4105,20 +4161,35 @@ static void do_shutdown(void)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Done\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Done\n");
} }
static void parse_ip(char *host, uint16_t *port, in_addr_t *addr, char *input)
static void parse_ip(char *host, switch_size_t host_len, uint16_t *port, char *input)
{ {
char *p; char *p;
struct hostent *hent; //struct hostent *hent;
strncpy(host, input, 255); if ((p = strchr(input, '['))) {
char *end = switch_find_end_paren(p, '[', ']');
host[255] = 0; if (end) {
p++;
if ((p = strchr(host, ':')) != NULL) { strncpy(host, p, end - p);
*p++ = '\0'; if (*(end+1) == ':' && end + 2 < end_of_p(input)) {
*port = (uint16_t)atoi(p); end += 2;
if (end) {
*port = (uint16_t)atoi(end);
}
}
} else {
strncpy(host, "::", host_len);
}
} else {
strncpy(host, input, host_len);
if ((p = strrchr(host, ':')) != NULL) {
*p++ = '\0';
*port = (uint16_t)atoi(p);
}
} }
#if 0
if ( host[0] < '0' || host[0] > '9' ) { if ( host[0] < '0' || host[0] > '9' ) {
// Non-numeric host (at least it doesn't start with one). Convert it to ip addr first // Non-numeric host (at least it doesn't start with one). Convert it to ip addr first
if ((hent = gethostbyname(host)) != NULL) { if ((hent = gethostbyname(host)) != NULL) {
@ -4130,8 +4201,10 @@ static void parse_ip(char *host, uint16_t *port, in_addr_t *addr, char *input)
} else { } else {
*addr = inet_addr(host); *addr = inet_addr(host);
} }
#endif
} }
static verto_profile_t *find_profile(const char *name) static verto_profile_t *find_profile(const char *name)
{ {
verto_profile_t *p, *r = NULL; verto_profile_t *p, *r = NULL;
@ -4264,7 +4337,7 @@ static switch_status_t parse_config(const char *cf)
if (!strcasecmp(var, "bind-local")) { if (!strcasecmp(var, "bind-local")) {
const char *secure = switch_xml_attr_soft(param, "secure"); const char *secure = switch_xml_attr_soft(param, "secure");
if (i < MAX_BIND) { if (i < MAX_BIND) {
parse_ip(profile->ip[profile->i].local_ip, &profile->ip[profile->i].local_port, &profile->ip[profile->i].local_ip_addr, val); parse_ip(profile->ip[profile->i].local_ip, sizeof(profile->ip[profile->i].local_ip), &profile->ip[profile->i].local_port, val);
if (switch_true(secure)) { if (switch_true(secure)) {
profile->ip[profile->i].secure = 1; profile->ip[profile->i].secure = 1;
} }
@ -4316,10 +4389,18 @@ static switch_status_t parse_config(const char *cf)
if (zstr(val)) { if (zstr(val)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid RTP IP.\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid RTP IP.\n");
} else { } else {
if (profile->rtpip_index < MAX_RTPIP -1) { if (strchr(val, ':')) {
profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, val); if (profile->rtpip_index6 < MAX_RTPIP -1) {
profile->rtpip6[profile->rtpip_index6++] = switch_core_strdup(profile->pool, val);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many RTP IP.\n");
}
} else { } else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many RTP IP.\n"); if (profile->rtpip_index < MAX_RTPIP -1) {
profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, val);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many RTP IP.\n");
}
} }
} }
} else if (!strcasecmp(var, "ext-rtp-ip")) { } else if (!strcasecmp(var, "ext-rtp-ip")) {

View File

@ -106,9 +106,8 @@ struct jsock_s {
unsigned char buf[65535]; unsigned char buf[65535];
char *name; char *name;
jsock_type_t ptype; jsock_type_t ptype;
struct sockaddr_in local_addr;
struct sockaddr_in remote_addr; struct sockaddr_in remote_addr;
struct sockaddr_in send_addr; struct sockaddr_in6 remote_addr6;
#ifndef WIN32 #ifndef WIN32
struct passwd pw; struct passwd pw;
#endif #endif
@ -132,6 +131,11 @@ struct jsock_s {
char *dialplan; char *dialplan;
char *context; char *context;
char remote_host[256];
int remote_port;
int family;
struct verto_profile_s *profile; struct verto_profile_s *profile;
switch_thread_rwlock_t *rwlock; switch_thread_rwlock_t *rwlock;
@ -155,12 +159,12 @@ typedef struct jsock_s jsock_t;
#define MAX_BIND 25 #define MAX_BIND 25
#define MAX_RTPIP 25 #define MAX_RTPIP 25
struct ips { typedef struct ips {
char local_ip[256]; char local_ip[256];
in_addr_t local_ip_addr;
uint16_t local_port; uint16_t local_port;
int secure; int secure;
}; int family;
} ips_t;
typedef enum { typedef enum {
TFLAG_SENT_MEDIA = (1 << 0), TFLAG_SENT_MEDIA = (1 << 0),
@ -240,6 +244,10 @@ struct verto_profile_s {
int rtpip_index; int rtpip_index;
int rtpip_cur; int rtpip_cur;
char *rtpip6[MAX_RTPIP];
int rtpip_index6;
int rtpip_cur6;
char *cand_acl[SWITCH_MAX_CAND_ACL]; char *cand_acl[SWITCH_MAX_CAND_ACL];
uint32_t cand_acl_count; uint32_t cand_acl_count;

View File

@ -691,6 +691,7 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
ssize_t need = 2; ssize_t need = 2;
char *maskp; char *maskp;
int ll = 0; int ll = 0;
int frag = 0;
again: again:
need = 2; need = 2;
@ -741,8 +742,16 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
case WSOC_PING: case WSOC_PING:
case WSOC_PONG: case WSOC_PONG:
{ {
//int fin = (wsh->buffer[0] >> 7) & 1; int fin = (wsh->buffer[0] >> 7) & 1;
int mask = (wsh->buffer[1] >> 7) & 1; int mask = (wsh->buffer[1] >> 7) & 1;
if (fin) {
if (*oc == WSOC_CONTINUATION) {
frag = 1;
} else {
frag = 0;
}
}
if (mask) { if (mask) {
need += 4; need += 4;
@ -837,6 +846,10 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
ws_write_frame(wsh, WSOC_PONG, wsh->payload, wsh->rplen); ws_write_frame(wsh, WSOC_PONG, wsh->payload, wsh->rplen);
goto again; goto again;
} }
if (frag) {
goto again;
}
*(wsh->payload+wsh->rplen) = '\0'; *(wsh->payload+wsh->rplen) = '\0';

View File

@ -1331,7 +1331,12 @@ SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_
free(list_name_dup); free(list_name_dup);
} else { } else {
switch_parse_cidr(list_name, &net, &mask, &bits); switch_parse_cidr(list_name, &net, &mask, &bits);
ok = switch_test_subnet(ip.v4, net.v4, mask.v4);
if (ipv6) {
ok = switch_testv6_subnet(ip, net, mask);
} else {
ok = switch_test_subnet(ip.v4, net.v4, mask.v4);
}
} }
} }
switch_mutex_unlock(runtime.global_mutex); switch_mutex_unlock(runtime.global_mutex);
@ -1395,6 +1400,26 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_FALSE); switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_FALSE);
switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
tmp_name = "wan_v6.auto";
switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
switch_network_list_add_cidr(rfc_list, "0.0.0.0/0", SWITCH_FALSE);
switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_FALSE);
switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
tmp_name = "wan_v4.auto";
switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
switch_network_list_add_cidr(rfc_list, "0.0.0.0/8", SWITCH_FALSE);
switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_FALSE);
switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_FALSE);
switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_FALSE);
switch_network_list_add_cidr(rfc_list, "169.254.0.0/16", SWITCH_FALSE);
switch_network_list_add_cidr(rfc_list, "::/0", SWITCH_FALSE);
switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
tmp_name = "nat.auto"; tmp_name = "nat.auto";
switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);

View File

@ -2885,6 +2885,8 @@ static void clear_ice(switch_core_session_t *session, switch_media_type_t type)
engine->ice_in.chosen[0] = 0; engine->ice_in.chosen[0] = 0;
engine->ice_in.chosen[1] = 0; engine->ice_in.chosen[1] = 0;
engine->ice_in.is_chosen[0] = 0;
engine->ice_in.is_chosen[1] = 0;
engine->ice_in.cand_idx = 0; engine->ice_in.cand_idx = 0;
memset(&engine->ice_in, 0, sizeof(engine->ice_in)); memset(&engine->ice_in, 0, sizeof(engine->ice_in));
engine->remote_rtcp_port = 0; engine->remote_rtcp_port = 0;
@ -3047,6 +3049,52 @@ SWITCH_DECLARE(switch_call_direction_t) switch_ice_direction(switch_core_session
return r; return r;
} }
//?
static switch_status_t ip_choose_family(switch_media_handle_t *smh, const char *ip)
{
switch_status_t status = SWITCH_STATUS_FALSE;
if (zstr(ip)) {
return status;
}
if (strchr(ip, ':')) {
if (!zstr(smh->mparams->rtpip6)) {
smh->mparams->rtpip = smh->mparams->rtpip6;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s choosing family v6\n",
switch_channel_get_name(smh->session->channel));
status = SWITCH_STATUS_SUCCESS;
}
} else {
if (!zstr(smh->mparams->rtpip4)) {
smh->mparams->rtpip = smh->mparams->rtpip4;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s choosing family v4\n",
switch_channel_get_name(smh->session->channel));
status = SWITCH_STATUS_SUCCESS;
}
}
return status;
}
//?
static switch_bool_t ip_possible(switch_media_handle_t *smh, const char *ip)
{
switch_bool_t r = SWITCH_FALSE;
if (zstr(ip)) {
return r;
}
if (strchr(ip, ':')) {
r = (switch_bool_t) !zstr(smh->mparams->rtpip6);
} else {
r = (switch_bool_t) !zstr(smh->mparams->rtpip4);
}
return r;
}
//? //?
static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_session_t *sdp, sdp_media_t *m) static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_session_t *sdp, sdp_media_t *m)
{ {
@ -3055,12 +3103,14 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
int i = 0, got_rtcp_mux = 0; int i = 0, got_rtcp_mux = 0;
const char *val; const char *val;
if (engine->ice_in.chosen[0] && engine->ice_in.chosen[1] && !switch_channel_test_flag(smh->session->channel, CF_REINVITE)) { if (engine->ice_in.is_chosen[0] && engine->ice_in.is_chosen[1] && !switch_channel_test_flag(smh->session->channel, CF_REINVITE)) {
return; return;
} }
engine->ice_in.chosen[0] = 0; engine->ice_in.chosen[0] = 0;
engine->ice_in.chosen[1] = 0; engine->ice_in.chosen[1] = 0;
engine->ice_in.is_chosen[0] = 0;
engine->ice_in.is_chosen[1] = 0;
engine->ice_in.cand_idx = 0; engine->ice_in.cand_idx = 0;
if (m) { if (m) {
@ -3074,6 +3124,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
char *fields[15]; char *fields[15];
int argc = 0, j = 0; int argc = 0, j = 0;
int cid = 0; int cid = 0;
int pass_acl = 0;
if (zstr(attr->a_name)) { if (zstr(attr->a_name)) {
continue; continue;
@ -3150,55 +3201,61 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG,
"Checking Candidate cid: %d proto: %s type: %s addr: %s:%s\n", cid+1, fields[2], fields[7], fields[4], fields[5]); "Checking Candidate cid: %d proto: %s type: %s addr: %s:%s\n", cid+1, fields[2], fields[7], fields[4], fields[5]);
pass_acl = 0;
engine->ice_in.cand_idx++;
for (i = 0; i < engine->cand_acl_count; i++) { for (i = 0; i < engine->cand_acl_count; i++) {
if (!engine->ice_in.chosen[cid] && !strchr(fields[4], ':') && switch_check_network_list_ip(fields[4], engine->cand_acl[i])) { if (switch_check_network_list_ip(fields[4], engine->cand_acl[i])) {
engine->ice_in.chosen[cid] = engine->ice_in.cand_idx; pass_acl = 1;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, break;
"Choose %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n",
type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
cid+1, fields[2], fields[7], fields[4], fields[5]);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
"Save %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n",
type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
cid+1, fields[2], fields[7], fields[4], fields[5]);
} }
engine->ice_in.cands[engine->ice_in.cand_idx][cid].foundation = switch_core_session_strdup(smh->session, fields[0]);
engine->ice_in.cands[engine->ice_in.cand_idx][cid].component_id = atoi(fields[1]);
engine->ice_in.cands[engine->ice_in.cand_idx][cid].transport = switch_core_session_strdup(smh->session, fields[2]);
engine->ice_in.cands[engine->ice_in.cand_idx][cid].priority = atol(fields[3]);
engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_addr = switch_core_session_strdup(smh->session, fields[4]);
engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_port = (switch_port_t)atoi(fields[5]);
j = 6;
while(j < argc && fields[j+1]) {
if (!strcasecmp(fields[j], "typ")) {
engine->ice_in.cands[engine->ice_in.cand_idx][cid].cand_type = switch_core_session_strdup(smh->session, fields[j+1]);
} else if (!strcasecmp(fields[j], "raddr")) {
engine->ice_in.cands[engine->ice_in.cand_idx][cid].raddr = switch_core_session_strdup(smh->session, fields[j+1]);
} else if (!strcasecmp(fields[j], "rport")) {
engine->ice_in.cands[engine->ice_in.cand_idx][cid].rport = (switch_port_t)atoi(fields[j+1]);
} else if (!strcasecmp(fields[j], "generation")) {
engine->ice_in.cands[engine->ice_in.cand_idx][cid].generation = switch_core_session_strdup(smh->session, fields[j+1]);
}
j += 2;
}
if (engine->ice_in.chosen[cid]) {
engine->ice_in.cands[engine->ice_in.chosen[cid]][cid].ready++;
}
break;
} }
if (!engine->ice_in.is_chosen[cid] && ip_possible(smh, fields[4]) && pass_acl) {
engine->ice_in.chosen[cid] = engine->ice_in.cand_idx;
engine->ice_in.is_chosen[cid] = 1;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
"Choose %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n",
type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
cid+1, fields[2], fields[7], fields[4], fields[5]);
ip_choose_family(smh, fields[4]);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
"Save %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n",
type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
cid+1, fields[2], fields[7], fields[4], fields[5]);
}
engine->ice_in.cands[engine->ice_in.cand_idx][cid].foundation = switch_core_session_strdup(smh->session, fields[0]);
engine->ice_in.cands[engine->ice_in.cand_idx][cid].component_id = atoi(fields[1]);
engine->ice_in.cands[engine->ice_in.cand_idx][cid].transport = switch_core_session_strdup(smh->session, fields[2]);
engine->ice_in.cands[engine->ice_in.cand_idx][cid].priority = atol(fields[3]);
engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_addr = switch_core_session_strdup(smh->session, fields[4]);
engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_port = (switch_port_t)atoi(fields[5]);
j = 6;
while(j < argc && fields[j+1]) {
if (!strcasecmp(fields[j], "typ")) {
engine->ice_in.cands[engine->ice_in.cand_idx][cid].cand_type = switch_core_session_strdup(smh->session, fields[j+1]);
} else if (!strcasecmp(fields[j], "raddr")) {
engine->ice_in.cands[engine->ice_in.cand_idx][cid].raddr = switch_core_session_strdup(smh->session, fields[j+1]);
} else if (!strcasecmp(fields[j], "rport")) {
engine->ice_in.cands[engine->ice_in.cand_idx][cid].rport = (switch_port_t)atoi(fields[j+1]);
} else if (!strcasecmp(fields[j], "generation")) {
engine->ice_in.cands[engine->ice_in.cand_idx][cid].generation = switch_core_session_strdup(smh->session, fields[j+1]);
}
j += 2;
}
if (engine->ice_in.is_chosen[cid]) {
engine->ice_in.cands[engine->ice_in.chosen[cid]][cid].ready++;
}
engine->ice_in.cand_idx++;
} }
} }
@ -3206,18 +3263,23 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
/* still no candidates, so start searching for some based on sane deduction */ /* still no candidates, so start searching for some based on sane deduction */
/* look for candidates on the same network */ /* look for candidates on the same network */
if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) { if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) {
for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) { for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) {
if (!engine->ice_in.chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && if (!engine->ice_in.is_chosen[0] && engine->ice_in.cands[i][0].component_id == 1 &&
!engine->ice_in.cands[i][0].rport && switch_check_network_list_ip(engine->ice_in.cands[i][0].con_addr, "localnet.auto")) { !engine->ice_in.cands[i][0].rport && ip_possible(smh, engine->ice_in.cands[i][0].con_addr) &&
switch_check_network_list_ip(engine->ice_in.cands[i][0].con_addr, "localnet.auto")) {
engine->ice_in.chosen[0] = i; engine->ice_in.chosen[0] = i;
engine->ice_in.is_chosen[0] = 1;
engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++; engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
ip_choose_family(smh, engine->ice_in.cands[i][0].con_addr);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
"No %s RTP candidate found; defaulting to the first local one.\n", type2str(type)); "No %s RTP candidate found; defaulting to the first local one.\n", type2str(type));
} }
if (!engine->ice_in.chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && if (!engine->ice_in.is_chosen[1] && engine->ice_in.cands[i][1].component_id == 2 &&
!engine->ice_in.cands[i][1].rport && switch_check_network_list_ip(engine->ice_in.cands[i][1].con_addr, "localnet.auto")) { !engine->ice_in.cands[i][1].rport && ip_possible(smh, engine->ice_in.cands[i][1].con_addr) &&
switch_check_network_list_ip(engine->ice_in.cands[i][1].con_addr, "localnet.auto")) {
engine->ice_in.chosen[1] = i; engine->ice_in.chosen[1] = i;
engine->ice_in.is_chosen[1] = 1;
engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++; engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session),SWITCH_LOG_NOTICE, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session),SWITCH_LOG_NOTICE,
"No %s RTCP candidate found; defaulting to the first local one.\n", type2str(type)); "No %s RTCP candidate found; defaulting to the first local one.\n", type2str(type));
@ -3226,16 +3288,21 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
} }
/* look for candidates with srflx */ /* look for candidates with srflx */
if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) { if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) {
for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) { for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) {
if (!engine->ice_in.chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && engine->ice_in.cands[i][0].rport) { if (!engine->ice_in.is_chosen[0] &&
engine->ice_in.cands[i][0].component_id == 1 && engine->ice_in.cands[i][0].rport && ip_possible(smh, engine->ice_in.cands[i][0].con_addr)) {
engine->ice_in.chosen[0] = i; engine->ice_in.chosen[0] = i;
engine->ice_in.chosen[1] = 1;
engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++; engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
ip_choose_family(smh, engine->ice_in.cands[i][0].con_addr);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
"No %s RTP candidate found; defaulting to the first srflx one.\n", type2str(type)); "No %s RTP candidate found; defaulting to the first srflx one.\n", type2str(type));
} }
if (!engine->ice_in.chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && engine->ice_in.cands[i][1].rport) { if (!engine->ice_in.is_chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && engine->ice_in.cands[i][1].rport &&
ip_possible(smh, engine->ice_in.cands[i][1].con_addr)) {
engine->ice_in.chosen[1] = i; engine->ice_in.chosen[1] = i;
engine->ice_in.is_chosen[1] = 1;
engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++; engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session),SWITCH_LOG_NOTICE, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session),SWITCH_LOG_NOTICE,
"No %s RTCP candidate found; defaulting to the first srflx one.\n", type2str(type)); "No %s RTCP candidate found; defaulting to the first srflx one.\n", type2str(type));
@ -3244,8 +3311,9 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
} }
/* Got RTP but not RTCP, probably mux */ /* Got RTP but not RTCP, probably mux */
if (engine->ice_in.chosen[0] && !engine->ice_in.chosen[1] && got_rtcp_mux) { if (engine->ice_in.is_chosen[0] && !engine->ice_in.is_chosen[1] && got_rtcp_mux) {
engine->ice_in.chosen[1] = engine->ice_in.chosen[0]; engine->ice_in.chosen[1] = engine->ice_in.chosen[0];
engine->ice_in.is_chosen[1] = 1;
memcpy(&engine->ice_in.cands[engine->ice_in.chosen[1]][1], &engine->ice_in.cands[engine->ice_in.chosen[0]][0], memcpy(&engine->ice_in.cands[engine->ice_in.chosen[1]][1], &engine->ice_in.cands[engine->ice_in.chosen[0]][0],
sizeof(engine->ice_in.cands[engine->ice_in.chosen[0]][0])); sizeof(engine->ice_in.cands[engine->ice_in.chosen[0]][0]));
@ -3257,16 +3325,19 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
} }
/* look for any candidates and hope for auto-adjust */ /* look for any candidates and hope for auto-adjust */
if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) { if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) {
for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) { for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) {
if (!engine->ice_in.chosen[0] && engine->ice_in.cands[i][0].component_id == 1) { if (!engine->ice_in.is_chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && ip_possible(smh, engine->ice_in.cands[i][0].con_addr)) {
engine->ice_in.chosen[0] = i; engine->ice_in.chosen[0] = i;
engine->ice_in.is_chosen[0] = 1;
engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++; engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
ip_choose_family(smh, engine->ice_in.cands[i][0].con_addr);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
"No %s RTP candidate found; defaulting to the first one.\n", type2str(type)); "No %s RTP candidate found; defaulting to the first one.\n", type2str(type));
} }
if (!engine->ice_in.chosen[1] && engine->ice_in.cands[i][1].component_id == 2) { if (!engine->ice_in.is_chosen[1] && engine->ice_in.cands[i][1].component_id == 2) {
engine->ice_in.chosen[1] = i; engine->ice_in.chosen[1] = i;
engine->ice_in.is_chosen[1] = 1;
engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++; engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
"No %s RTCP candidate found; defaulting to the first one.\n", type2str(type)); "No %s RTCP candidate found; defaulting to the first one.\n", type2str(type));
@ -3274,6 +3345,13 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
} }
} }
if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) {
/* PUNT */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s no suitable candidates found.\n",
switch_channel_get_name(smh->session->channel));
return;
}
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
if (engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready) { if (engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready) {
if (zstr(engine->ice_in.ufrag) || zstr(engine->ice_in.pwd)) { if (zstr(engine->ice_in.ufrag) || zstr(engine->ice_in.pwd)) {
@ -5476,6 +5554,20 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_choose_port(switch_core_sessio
SWITCH_DECLARE(switch_status_t) switch_core_media_choose_ports(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video) SWITCH_DECLARE(switch_status_t) switch_core_media_choose_ports(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video)
{ {
switch_status_t status = SWITCH_STATUS_SUCCESS; switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_media_handle_t *smh;
if (!(smh = session->media_handle)) {
return SWITCH_STATUS_FALSE;
}
if (zstr(smh->mparams->rtpip)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no media ip\n",
switch_channel_get_name(smh->session->channel));
switch_channel_hangup(smh->session->channel, SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL);
return SWITCH_STATUS_FALSE;
}
if (audio && (status = switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_AUDIO, 0)) == SWITCH_STATUS_SUCCESS) { if (audio && (status = switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_AUDIO, 0)) == SWITCH_STATUS_SUCCESS) {
if (video) { if (video) {
@ -6316,7 +6408,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%sVIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n", switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%sVIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n",
switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ? "PROXY " : "", switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ? "PROXY " : "",
switch_channel_get_name(session->channel), switch_channel_get_name(session->channel),
a_engine->cur_payload_map->remote_sdp_ip, a_engine->local_sdp_ip,
v_engine->local_sdp_port, v_engine->local_sdp_port,
v_engine->cur_payload_map->remote_sdp_ip, v_engine->cur_payload_map->remote_sdp_ip,
v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->agreed_pt, v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->agreed_pt,

View File

@ -431,7 +431,8 @@ SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_token(switch_netw
for (node = list->node_head; node; node = node->next) { for (node = list->node_head; node; node = node->next) {
if (node->family == AF_INET) continue; if (node->family == AF_INET) continue;
if (node->bits > bits && switch_testv6_subnet(ip, node->ip, node->mask)) {
if (node->bits >= bits && switch_testv6_subnet(ip, node->ip, node->mask)) {
if (node->ok) { if (node->ok) {
ok = SWITCH_TRUE; ok = SWITCH_TRUE;
} else { } else {
@ -457,7 +458,7 @@ SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_netwo
for (node = list->node_head; node; node = node->next) { for (node = list->node_head; node; node = node->next) {
if (node->family == AF_INET6) continue; /* want AF_INET */ if (node->family == AF_INET6) continue; /* want AF_INET */
if (node->bits > bits && switch_test_subnet(ip, node->ip.v4, node->mask.v4)) { if (node->bits >= bits && switch_test_subnet(ip, node->ip.v4, node->mask.v4)) {
if (node->ok) { if (node->ok) {
ok = SWITCH_TRUE; ok = SWITCH_TRUE;
} else { } else {