FS-7587 Add ipv6 support to Verto / Websockets
This commit is contained in:
parent
55a955787c
commit
3b2d00f3e6
|
@ -5,9 +5,9 @@
|
|||
</settings>
|
||||
|
||||
<profiles>
|
||||
<profile name="mine">
|
||||
<param name="bind-local" value="0.0.0.0:8081"/>
|
||||
<param name="bind-local" value="0.0.0.0:8082" secure="true"/>
|
||||
<profile name="default-v4">
|
||||
<param name="bind-local" value="$${local_ip_v4}:8081"/>
|
||||
<param name="bind-local" value="$${local_ip_v4}: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"/>
|
||||
|
@ -21,7 +21,28 @@
|
|||
<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.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"/>
|
||||
|
||||
</profile>
|
||||
|
|
|
@ -125,6 +125,9 @@ typedef struct switch_core_media_params_s {
|
|||
|
||||
char *extrtpip;
|
||||
char *rtpip;
|
||||
char *rtpip4;
|
||||
char *rtpip6;
|
||||
|
||||
|
||||
char *remote_ip;
|
||||
int remote_port;
|
||||
|
|
|
@ -105,6 +105,7 @@ typedef struct ice_s {
|
|||
icand_t cands[MAX_CAND][2];
|
||||
int cand_idx;
|
||||
int chosen[2];
|
||||
int is_chosen[2];
|
||||
char *ufrag;
|
||||
char *pwd;
|
||||
char *options;
|
||||
|
|
|
@ -58,16 +58,29 @@
|
|||
int mcast_socket_create(const char *host, int16_t port, mcast_handle_t *handle, mcast_flag_t flags)
|
||||
{
|
||||
uint32_t one = 1;
|
||||
int family = AF_INET;
|
||||
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
|
||||
if ((!(flags & MCAST_SEND) && !(flags & MCAST_RECV)) || (handle->sock = socket(AF_INET, SOCK_DGRAM, 0)) <= 0 ) {
|
||||
return -1;
|
||||
if (strchr(host, ':')) {
|
||||
family = AF_INET6;
|
||||
}
|
||||
|
||||
handle->send_addr.sin_family = AF_INET;
|
||||
handle->send_addr.sin_addr.s_addr = inet_addr(host);
|
||||
handle->send_addr.sin_port = htons(port);
|
||||
if ((!(flags & MCAST_SEND) && !(flags & MCAST_RECV)) || (handle->sock = socket(family, SOCK_DGRAM, 0)) <= 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
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 ) {
|
||||
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)) {
|
||||
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;
|
||||
handle->recv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
handle->recv_addr.sin_port = htons(port);
|
||||
mreq.imr_multiaddr.s_addr = inet_addr(host);
|
||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
mreq.imr_multiaddr.s_addr = inet_addr(host);
|
||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
if (setsockopt(handle->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) < 0) {
|
||||
close(handle->sock);
|
||||
handle->sock = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(handle->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) < 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
} 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;
|
||||
|
@ -155,7 +201,11 @@ ssize_t mcast_socket_send(mcast_handle_t *handle, void *data, size_t datalen)
|
|||
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)
|
||||
|
@ -175,6 +225,9 @@ ssize_t mcast_socket_recv(mcast_handle_t *handle, void *data, size_t datalen, in
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return recvfrom(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->recv_addr, &addrlen);
|
||||
if (handle->family == AF_INET6) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,9 @@ typedef struct {
|
|||
unsigned char ttl;
|
||||
struct sockaddr_in send_addr;
|
||||
struct sockaddr_in recv_addr;
|
||||
struct sockaddr_in6 send_addr6;
|
||||
struct sockaddr_in6 recv_addr6;
|
||||
int family;
|
||||
unsigned char buffer[65536];
|
||||
int ready;
|
||||
} mcast_handle_t;
|
||||
|
|
|
@ -1803,12 +1803,6 @@ error:
|
|||
|
||||
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 (jsock->profile->vhosts) {
|
||||
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;
|
||||
|
||||
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) {
|
||||
profile->rtpip_cur = 0;
|
||||
if (!zstr(profile->rtpip6[profile->rtpip_cur6])) {
|
||||
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;
|
||||
|
@ -3376,7 +3390,7 @@ static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock
|
|||
switch_either(jsock->dialplan, jsock->profile->dialplan),
|
||||
caller_id_name,
|
||||
caller_id_number,
|
||||
inet_ntoa(jsock->remote_addr.sin_addr),
|
||||
jsock->remote_host,
|
||||
cJSON_GetObjectCstr(dialog, "ani"),
|
||||
cJSON_GetObjectCstr(dialog, "aniii"),
|
||||
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;
|
||||
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->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) {
|
||||
die("ACCEPT FAILED\n");
|
||||
if ((jsock->client_socket = accept(sock, (struct sockaddr *) &jsock->remote_addr, &len)) < 0) {
|
||||
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++) {
|
||||
|
@ -3818,7 +3841,15 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock)
|
|||
jsock->profile = profile;
|
||||
|
||||
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;
|
||||
|
@ -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);
|
||||
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(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);
|
||||
}
|
||||
|
||||
|
@ -3873,7 +3904,7 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock)
|
|||
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;
|
||||
#ifndef WIN32
|
||||
|
@ -3881,29 +3912,48 @@ static ws_socket_t prepare_socket(int ip, uint16_t port)
|
|||
#else
|
||||
char reuse_addr = 1;
|
||||
#endif
|
||||
int family;
|
||||
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");
|
||||
}
|
||||
|
||||
if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)) < 0 ) {
|
||||
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) {
|
||||
die("Listen error\n");
|
||||
}
|
||||
|
||||
ips->family = family;
|
||||
|
||||
return sock;
|
||||
|
||||
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) {
|
||||
handle_mcast_sub(profile);
|
||||
} 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
globals.running = 0;
|
||||
|
@ -4105,20 +4161,35 @@ static void do_shutdown(void)
|
|||
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;
|
||||
struct hostent *hent;
|
||||
//struct hostent *hent;
|
||||
|
||||
strncpy(host, input, 255);
|
||||
|
||||
host[255] = 0;
|
||||
|
||||
if ((p = strchr(host, ':')) != NULL) {
|
||||
*p++ = '\0';
|
||||
*port = (uint16_t)atoi(p);
|
||||
if ((p = strchr(input, '['))) {
|
||||
char *end = switch_find_end_paren(p, '[', ']');
|
||||
if (end) {
|
||||
p++;
|
||||
strncpy(host, p, end - p);
|
||||
if (*(end+1) == ':' && end + 2 < end_of_p(input)) {
|
||||
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' ) {
|
||||
// Non-numeric host (at least it doesn't start with one). Convert it to ip addr first
|
||||
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 {
|
||||
*addr = inet_addr(host);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static verto_profile_t *find_profile(const char *name)
|
||||
{
|
||||
verto_profile_t *p, *r = NULL;
|
||||
|
@ -4264,7 +4337,7 @@ static switch_status_t parse_config(const char *cf)
|
|||
if (!strcasecmp(var, "bind-local")) {
|
||||
const char *secure = switch_xml_attr_soft(param, "secure");
|
||||
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)) {
|
||||
profile->ip[profile->i].secure = 1;
|
||||
}
|
||||
|
@ -4316,10 +4389,18 @@ static switch_status_t parse_config(const char *cf)
|
|||
if (zstr(val)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid RTP IP.\n");
|
||||
} else {
|
||||
if (profile->rtpip_index < MAX_RTPIP -1) {
|
||||
profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, val);
|
||||
if (strchr(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 {
|
||||
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")) {
|
||||
|
|
|
@ -106,9 +106,8 @@ struct jsock_s {
|
|||
unsigned char buf[65535];
|
||||
char *name;
|
||||
jsock_type_t ptype;
|
||||
struct sockaddr_in local_addr;
|
||||
struct sockaddr_in remote_addr;
|
||||
struct sockaddr_in send_addr;
|
||||
struct sockaddr_in6 remote_addr6;
|
||||
#ifndef WIN32
|
||||
struct passwd pw;
|
||||
#endif
|
||||
|
@ -132,6 +131,11 @@ struct jsock_s {
|
|||
char *dialplan;
|
||||
char *context;
|
||||
|
||||
|
||||
char remote_host[256];
|
||||
int remote_port;
|
||||
int family;
|
||||
|
||||
struct verto_profile_s *profile;
|
||||
switch_thread_rwlock_t *rwlock;
|
||||
|
||||
|
@ -155,12 +159,12 @@ typedef struct jsock_s jsock_t;
|
|||
#define MAX_BIND 25
|
||||
#define MAX_RTPIP 25
|
||||
|
||||
struct ips {
|
||||
typedef struct ips {
|
||||
char local_ip[256];
|
||||
in_addr_t local_ip_addr;
|
||||
uint16_t local_port;
|
||||
int secure;
|
||||
};
|
||||
int family;
|
||||
} ips_t;
|
||||
|
||||
typedef enum {
|
||||
TFLAG_SENT_MEDIA = (1 << 0),
|
||||
|
@ -240,6 +244,10 @@ struct verto_profile_s {
|
|||
int rtpip_index;
|
||||
int rtpip_cur;
|
||||
|
||||
char *rtpip6[MAX_RTPIP];
|
||||
int rtpip_index6;
|
||||
int rtpip_cur6;
|
||||
|
||||
char *cand_acl[SWITCH_MAX_CAND_ACL];
|
||||
uint32_t cand_acl_count;
|
||||
|
||||
|
|
|
@ -691,6 +691,7 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
ssize_t need = 2;
|
||||
char *maskp;
|
||||
int ll = 0;
|
||||
int frag = 0;
|
||||
|
||||
again:
|
||||
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_PONG:
|
||||
{
|
||||
//int fin = (wsh->buffer[0] >> 7) & 1;
|
||||
int fin = (wsh->buffer[0] >> 7) & 1;
|
||||
int mask = (wsh->buffer[1] >> 7) & 1;
|
||||
|
||||
if (fin) {
|
||||
if (*oc == WSOC_CONTINUATION) {
|
||||
frag = 1;
|
||||
} else {
|
||||
frag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask) {
|
||||
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);
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (frag) {
|
||||
goto again;
|
||||
}
|
||||
|
||||
|
||||
*(wsh->payload+wsh->rplen) = '\0';
|
||||
|
|
|
@ -1331,7 +1331,12 @@ SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_
|
|||
free(list_name_dup);
|
||||
} else {
|
||||
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);
|
||||
|
@ -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_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";
|
||||
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);
|
||||
|
|
|
@ -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[1] = 0;
|
||||
engine->ice_in.is_chosen[0] = 0;
|
||||
engine->ice_in.is_chosen[1] = 0;
|
||||
engine->ice_in.cand_idx = 0;
|
||||
memset(&engine->ice_in, 0, sizeof(engine->ice_in));
|
||||
engine->remote_rtcp_port = 0;
|
||||
|
@ -3047,6 +3049,52 @@ SWITCH_DECLARE(switch_call_direction_t) switch_ice_direction(switch_core_session
|
|||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
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;
|
||||
}
|
||||
|
||||
engine->ice_in.chosen[0] = 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;
|
||||
|
||||
if (m) {
|
||||
|
@ -3074,6 +3124,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
|
|||
char *fields[15];
|
||||
int argc = 0, j = 0;
|
||||
int cid = 0;
|
||||
int pass_acl = 0;
|
||||
|
||||
if (zstr(attr->a_name)) {
|
||||
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,
|
||||
"Checking Candidate cid: %d proto: %s type: %s addr: %s:%s\n", cid+1, fields[2], fields[7], fields[4], fields[5]);
|
||||
|
||||
|
||||
engine->ice_in.cand_idx++;
|
||||
|
||||
pass_acl = 0;
|
||||
|
||||
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])) {
|
||||
engine->ice_in.chosen[cid] = engine->ice_in.cand_idx;
|
||||
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]);
|
||||
} 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]);
|
||||
if (switch_check_network_list_ip(fields[4], engine->cand_acl[i])) {
|
||||
pass_acl = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
/* look for candidates on the same network */
|
||||
if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) {
|
||||
for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.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 && switch_check_network_list_ip(engine->ice_in.cands[i][0].con_addr, "localnet.auto")) {
|
||||
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.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) {
|
||||
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) &&
|
||||
switch_check_network_list_ip(engine->ice_in.cands[i][0].con_addr, "localnet.auto")) {
|
||||
engine->ice_in.chosen[0] = i;
|
||||
engine->ice_in.is_chosen[0] = 1;
|
||||
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,
|
||||
"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 &&
|
||||
!engine->ice_in.cands[i][1].rport && switch_check_network_list_ip(engine->ice_in.cands[i][1].con_addr, "localnet.auto")) {
|
||||
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) &&
|
||||
switch_check_network_list_ip(engine->ice_in.cands[i][1].con_addr, "localnet.auto")) {
|
||||
engine->ice_in.chosen[1] = i;
|
||||
engine->ice_in.is_chosen[1] = 1;
|
||||
engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
|
||||
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));
|
||||
|
@ -3226,16 +3288,21 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
|
|||
}
|
||||
|
||||
/* look for candidates with srflx */
|
||||
if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) {
|
||||
for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.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.is_chosen[1]) {
|
||||
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.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[1] = 1;
|
||||
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,
|
||||
"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.is_chosen[1] = 1;
|
||||
engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
|
||||
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));
|
||||
|
@ -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 */
|
||||
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.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],
|
||||
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 */
|
||||
if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) {
|
||||
for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.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.is_chosen[1]) {
|
||||
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.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.is_chosen[0] = 1;
|
||||
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,
|
||||
"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.is_chosen[1] = 1;
|
||||
engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
|
||||
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));
|
||||
|
@ -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++) {
|
||||
if (engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready) {
|
||||
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_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 (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_channel_test_flag(session->channel, CF_PROXY_MEDIA) ? "PROXY " : "",
|
||||
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->cur_payload_map->remote_sdp_ip,
|
||||
v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->agreed_pt,
|
||||
|
|
|
@ -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) {
|
||||
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) {
|
||||
ok = SWITCH_TRUE;
|
||||
} 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) {
|
||||
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) {
|
||||
ok = SWITCH_TRUE;
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue