Skip to content

Commit

Permalink
Check if IPv6 is disabled to avoid failure when creating forwarder so…
Browse files Browse the repository at this point in the history
…cket (see #2915 and #2916)
  • Loading branch information
lminiero committed Apr 1, 2022
1 parent e111be2 commit d7e593b
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 33 deletions.
50 changes: 38 additions & 12 deletions plugins/janus_audiobridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -1251,6 +1251,7 @@ static janus_mutex config_mutex = JANUS_MUTEX_INITIALIZER;
static volatile gint initialized = 0, stopping = 0;
static gboolean notify_events = TRUE;
static gboolean string_ids = FALSE;
static gboolean ipv6_disabled = FALSE;
static janus_callbacks *gateway = NULL;
static GThread *handler_thread;
static void *janus_audiobridge_handler(void *data);
Expand Down Expand Up @@ -2075,15 +2076,19 @@ static int janus_audiobridge_create_udp_socket_if_needed(janus_audiobridge_room
return 0;
}

audiobridge->rtp_udp_sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
audiobridge->rtp_udp_sock = socket(!ipv6_disabled ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(audiobridge->rtp_udp_sock <= 0) {
JANUS_LOG(LOG_ERR, "Could not open UDP socket for RTP forwarder (room %s)\n", audiobridge->room_id_str);
JANUS_LOG(LOG_ERR, "Could not open UDP socket for RTP forwarder (room %s), %d (%s)\n",
audiobridge->room_id_str, errno, g_strerror(errno));
return -1;
}
int v6only = 0;
if(setsockopt(audiobridge->rtp_udp_sock, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) != 0) {
JANUS_LOG(LOG_ERR, "Could not open UDP socket for RTP forwarder (room %s)\n", audiobridge->room_id_str);
return -1;
if(!ipv6_disabled) {
int v6only = 0;
if(setsockopt(audiobridge->rtp_udp_sock, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) != 0) {
JANUS_LOG(LOG_ERR, "Could not configure UDP socket for RTP forwarder (room %s), %d (%s))\n",
audiobridge->room_id_str, errno, g_strerror(errno));
return -1;
}
}

return 0;
Expand Down Expand Up @@ -2352,7 +2357,7 @@ int janus_audiobridge_init(janus_callbacks *callback, const char *config_path) {
janus_network_address_string_buffer ibuf;
if(getifaddrs(&ifas) == -1) {
JANUS_LOG(LOG_ERR, "Unable to acquire list of network devices/interfaces; some configurations may not work as expected... %d (%s)\n",
errno, strerror(errno));
errno, g_strerror(errno));
} else {
if(janus_network_lookup_interface(ifas, lip->value, &iface) != 0) {
JANUS_LOG(LOG_WARN, "Error setting local IP address to %s, falling back to detecting IP address...\n", lip->value);
Expand Down Expand Up @@ -2678,6 +2683,21 @@ int janus_audiobridge_init(janus_callbacks *callback, const char *config_path) {
}
janus_mutex_unlock(&rooms_mutex);

/* Finally, let's check if IPv6 is disabled, as we may need to know for forwarders */
int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if(fd <= 0) {
ipv6_disabled = TRUE;
} else {
int v6only = 0;
if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) != 0)
ipv6_disabled = TRUE;
}
if(fd > 0)
close(fd);
if(ipv6_disabled) {
JANUS_LOG(LOG_WARN, "IPv6 disabled, will only create VideoRoom forwarders to IPv4 addresses\n");
}

g_atomic_int_set(&initialized, 1);

/* Launch the thread that will handle incoming messages */
Expand Down Expand Up @@ -4579,6 +4599,12 @@ static json_t *janus_audiobridge_process_synchronous_request(janus_audiobridge_s
goto prepare_response;
}
host = resolved_host;
if(ipv6_disabled && strstr(host, ":") != NULL) {
JANUS_LOG(LOG_ERR, "Attempt to create an IPv6 forwarder, but IPv6 networking is not available\n");
error_code = JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT;
g_snprintf(error_cause, 512, "Attempt to create an IPv6 forwarder, but IPv6 networking is not available");
goto prepare_response;
}
json_t *always = json_object_get(root, "always_on");
gboolean always_on = always ? json_is_true(always) : FALSE;
/* Besides, we may need to SRTP-encrypt this stream */
Expand Down Expand Up @@ -6423,7 +6449,7 @@ static void *janus_audiobridge_handler(void *data) {
if(connect(participant->plainrtp_media.audio_rtp_fd, (struct sockaddr *)&audio_server_addr, sizeof(struct sockaddr)) == -1) {
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] Couldn't connect audio RTP? (%s:%d)\n", session,
participant->plainrtp_media.remote_audio_ip, participant->plainrtp_media.remote_audio_rtp_port);
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] -- %d (%s)\n", session, errno, strerror(errno));
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] -- %d (%s)\n", session, errno, g_strerror(errno));
} else {
participant->plainrtp_media.audio_send = TRUE;
}
Expand Down Expand Up @@ -8497,7 +8523,7 @@ static void janus_audiobridge_relay_rtp_packet(gpointer data, gpointer user_data
if(participant->plainrtp_media.audio_send) {
int ret = send(participant->plainrtp_media.audio_rtp_fd, (char *)packet->data, packet->length, 0);
if(ret < 0) {
JANUS_LOG(LOG_WARN, "Error sending plain RTP packet: %d (%s)\n", errno, strerror(errno));
JANUS_LOG(LOG_WARN, "Error sending plain RTP packet: %d (%s)\n", errno, g_strerror(errno));
}
}
} else if(gateway != NULL) {
Expand Down Expand Up @@ -8626,11 +8652,11 @@ static void *janus_audiobridge_plainrtp_relay_thread(void *data) {
resfd = poll(fds, num, 1000);
if(resfd < 0) {
if(errno == EINTR) {
JANUS_LOG(LOG_HUGE, "[AudioBridge-%p] Got an EINTR (%s), ignoring...\n", session, strerror(errno));
JANUS_LOG(LOG_HUGE, "[AudioBridge-%p] Got an EINTR (%s), ignoring...\n", session, g_strerror(errno));
continue;
}
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] Error polling...\n", session);
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] -- %d (%s)\n", session, errno, strerror(errno));
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] -- %d (%s)\n", session, errno, g_strerror(errno));
break;
} else if(resfd == 0) {
/* No data, keep going */
Expand All @@ -8655,7 +8681,7 @@ static void *janus_audiobridge_plainrtp_relay_thread(void *data) {
continue;
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] Too many errors polling %d (socket #%d): %s...\n", session,
fds[i].fd, i, fds[i].revents & POLLERR ? "POLLERR" : "POLLHUP");
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] -- %d (%s)\n", session, error, strerror(error));
JANUS_LOG(LOG_ERR, "[AudioBridge-%p] -- %d (%s)\n", session, error, g_strerror(error));
/* Can we assume it's pretty much over, after a POLLERR? */
goon = FALSE;
/* Close the channel */
Expand Down
77 changes: 56 additions & 21 deletions plugins/janus_videoroom.c
Original file line number Diff line number Diff line change
Expand Up @@ -1473,6 +1473,7 @@ static janus_mutex config_mutex = JANUS_MUTEX_INITIALIZER;
static volatile gint initialized = 0, stopping = 0;
static gboolean notify_events = TRUE;
static gboolean string_ids = FALSE;
static gboolean ipv6_disabled = FALSE;
static janus_callbacks *gateway = NULL;
static GThread *handler_thread;
static void *janus_videoroom_handler(void *data);
Expand Down Expand Up @@ -1981,45 +1982,62 @@ static guint32 janus_videoroom_rtp_forwarder_add_helper(janus_videoroom_publishe
if(!p || !host) {
return 0;
}
if(ipv6_disabled && strstr(host, ":") != NULL) {
JANUS_LOG(LOG_ERR, "Attempt to create an IPv6 forwarder, but IPv6 networking is not available\n");
return 0;
}
janus_refcount_increase(&p->ref);
janus_mutex_lock(&p->rtp_forwarders_mutex);
/* Do we need to bind to a port for RTCP? */
int fd = -1;
uint16_t local_rtcp_port = 0;
if(!is_data && rtcp_port > 0) {
fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
fd = socket(!ipv6_disabled ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(fd < 0) {
janus_mutex_unlock(&p->rtp_forwarders_mutex);
janus_refcount_decrease(&p->ref);
JANUS_LOG(LOG_ERR, "Error creating RTCP socket for new RTP forwarder... %d (%s)\n",
errno, g_strerror(errno));
return 0;
}
int v6only = 0;
if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) != 0) {
janus_mutex_unlock(&p->rtp_forwarders_mutex);
janus_refcount_decrease(&p->ref);
JANUS_LOG(LOG_ERR, "Error creating RTCP socket for new RTP forwarder... %d (%s)\n",
errno, g_strerror(errno));
close(fd);
return 0;
struct sockaddr *address = NULL;
struct sockaddr_in addr4 = { 0 };
struct sockaddr_in6 addr6 = { 0 };
socklen_t len = 0;
if(!ipv6_disabled) {
/* Configure the socket so that it can be used both on IPv4 and IPv6 */
int v6only = 0;
if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) != 0) {
janus_mutex_unlock(&p->rtp_forwarders_mutex);
janus_refcount_decrease(&p->ref);
JANUS_LOG(LOG_ERR, "Error configuring RTCP socket for new RTP forwarder... %d (%s)\n",
errno, g_strerror(errno));
close(fd);
return 0;
}
len = sizeof(addr6);
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(0); /* The RTCP port we received is the remote one */
addr6.sin6_addr = in6addr_any;
address = (struct sockaddr *)&addr6;
} else {
/* IPv6 is disabled, only do IPv4 */
len = sizeof(addr4);
addr4.sin_family = AF_INET;
addr4.sin_port = htons(0); /* The RTCP port we received is the remote one */
addr4.sin_addr.s_addr = INADDR_ANY;
address = (struct sockaddr *)&addr4;
}
struct sockaddr_in6 address = { 0 };
socklen_t len = sizeof(address);
memset(&address, 0, sizeof(address));
address.sin6_family = AF_INET6;
address.sin6_port = htons(0); /* The RTCP port we received is the remote one */
address.sin6_addr = in6addr_any;
if(bind(fd, (struct sockaddr *)&address, len) < 0 ||
getsockname(fd, (struct sockaddr *)&address, &len) < 0) {
if(bind(fd, (struct sockaddr *)address, len) < 0 ||
getsockname(fd, (struct sockaddr *)address, &len) < 0) {
janus_mutex_unlock(&p->rtp_forwarders_mutex);
janus_refcount_decrease(&p->ref);
JANUS_LOG(LOG_ERR, "Error binding RTCP socket for new RTP forwarder... %d (%s)\n",
errno, g_strerror(errno));
close(fd);
return 0;
}
local_rtcp_port = ntohs(address.sin6_port);
local_rtcp_port = ntohs(!ipv6_disabled ? addr6.sin6_port : addr4.sin_port);
JANUS_LOG(LOG_VERB, "Bound local %s RTCP port: %"SCNu16"\n",
is_video ? "video" : "audio", local_rtcp_port);
}
Expand Down Expand Up @@ -2578,6 +2596,22 @@ int janus_videoroom_init(janus_callbacks *callback, const char *config_path) {
g_error_free(error);
}

/* Finally, let's check if IPv6 is disabled, as we may need to know for forwarders */
int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if(fd <= 0) {
ipv6_disabled = TRUE;
} else {
int v6only = 0;
if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) != 0)
ipv6_disabled = TRUE;
}
if(fd > 0)
close(fd);
ipv6_disabled = TRUE;
if(ipv6_disabled) {
JANUS_LOG(LOG_WARN, "IPv6 disabled, will only create VideoRoom forwarders to IPv4 addresses\n");
}

g_atomic_int_set(&initialized, 1);

/* Launch the thread that will handle incoming messages */
Expand Down Expand Up @@ -4126,14 +4160,15 @@ static json_t *janus_videoroom_process_synchronous_request(janus_videoroom_sessi
}
janus_refcount_increase(&publisher->ref); /* This is just to handle the request for now */
if(publisher->udp_sock <= 0) {
publisher->udp_sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
publisher->udp_sock = socket(!ipv6_disabled ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP);
int v6only = 0;
if(publisher->udp_sock <= 0 ||
setsockopt(publisher->udp_sock, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) != 0) {
(!ipv6_disabled && setsockopt(publisher->udp_sock, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) != 0)) {
janus_refcount_decrease(&publisher->ref);
janus_mutex_unlock(&videoroom->mutex);
janus_refcount_decrease(&videoroom->ref);
JANUS_LOG(LOG_ERR, "Could not open UDP socket for RTP stream for publisher (%s)\n", publisher_id_str);
JANUS_LOG(LOG_ERR, "Could not open UDP socket for RTP stream for publisher (%s), %d (%s)\n",
publisher_id_str, errno, g_strerror(errno));
error_code = JANUS_VIDEOROOM_ERROR_UNKNOWN_ERROR;
g_snprintf(error_cause, 512, "Could not open UDP socket for RTP stream");
goto prepare_response;
Expand Down

0 comments on commit d7e593b

Please sign in to comment.