FS-7587 Add ipv6 support to Verto / Websockets

This commit is contained in:
Anthony Minessale committed 2015-06-01 13:39:47 -05:00
1 parent 55a955787c
commit 3b2d00f3e6
11 files changed
+489 -188

No files matched your search

+79 -26
View File
@@ -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;
+168 -87
View File
@@ -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")) {
+13 -5
View File
@@ -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;
+14 -1
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;
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';