diff --git a/README.md b/README.md index bdd8747be..0ee1a0f43 100644 --- a/README.md +++ b/README.md @@ -919,6 +919,9 @@ Optionally included keys are: This flag operates independently of the `replace` flags. + Note that if config parameter `save-interface-ports = true`, ICE will be broken, because + rtpengine will bind ports only on the first local interface of desired family of logical interface. + * `ICE-lite` Contains a string which must be one of the following values: diff --git a/daemon/call.c b/daemon/call.c index 5825393bc..9bfd2976a 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -870,7 +870,7 @@ static struct endpoint_map *__get_endpoint_map(struct call_media *media, unsigne alloc: if (num_ports > 16) return NULL; - if (get_consecutive_ports(&intf_sockets, num_ports, media->logical_intf, &media->call->callid)) + if (get_consecutive_ports(&intf_sockets, num_ports, media)) return NULL; __C_DBG("allocating stream_fds for %u ports", num_ports); diff --git a/daemon/log.c b/daemon/log.c index 57ad53bc5..b2bf4d802 100644 --- a/daemon/log.c +++ b/daemon/log.c @@ -47,6 +47,10 @@ static void ilog_prefix_default(char *prefix, size_t prefix_len) { snprintf(prefix, prefix_len, "[" STR_FORMAT_M " port %5u]: ", STR_FMT_M(&log_info.u.stream_fd->call->callid), log_info.u.stream_fd->socket.local.port); + else + snprintf(prefix, prefix_len, "[no call, port %5u]: ", + log_info.u.stream_fd->socket.local.port); + break; case LOG_INFO_STR: snprintf(prefix, prefix_len, "[" STR_FORMAT_M "]: ", diff --git a/daemon/main.c b/daemon/main.c index 7e96816e9..db3ba905f 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -395,6 +395,7 @@ static void options(int *argc, char ***argv) { { "table", 't', 0, G_OPTION_ARG_INT, &rtpe_config.kernel_table, "Kernel table to use", "INT" }, { "no-fallback",'F', 0, G_OPTION_ARG_NONE, &rtpe_config.no_fallback, "Only start when kernel module is available", NULL }, { "interface", 'i', 0, G_OPTION_ARG_STRING_ARRAY,&if_a, "Local interface for RTP", "[NAME/]IP[!IP]"}, + { "save-interface-ports",'S', 0, G_OPTION_ARG_NONE, &rtpe_config.save_interface_ports, "Bind ports only on first available interface of desired family", NULL }, { "subscribe-keyspace", 'k', 0, G_OPTION_ARG_STRING_ARRAY,&ks_a, "Subscription keyspace list", "INT INT ..."}, { "listen-tcp", 'l', 0, G_OPTION_ARG_STRING, &listenps, "TCP port to listen on", "[IP:]PORT" }, { "listen-udp", 'u', 0, G_OPTION_ARG_STRING, &listenudps, "UDP port to listen on", "[IP46|HOSTNAME:]PORT" }, diff --git a/daemon/media_socket.c b/daemon/media_socket.c index d60300ffb..9ea26974a 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -911,40 +911,84 @@ fail: } /* puts a list of "struct intf_list" into "out", containing socket_t list */ -int get_consecutive_ports(GQueue *out, unsigned int num_ports, const struct logical_intf *log, - const str *label) +int get_consecutive_ports(GQueue *out, unsigned int num_ports, struct call_media *media) { GList *l; struct intf_list *il; const struct local_intf *loc; + const struct logical_intf *log = media->logical_intf; + const sockfamily_t *desired_family = media->desired_family; + const str *label = &media->call->callid; + /* + // debug locals of logical incerface + char ip[100]; for (l = log->list.head; l; l = l->next) { loc = l->data; + inet_ntop(loc->spec->local_address.addr.family->af, &loc->spec->local_address.addr.u, ip, sizeof(ip)); + ilog(LOG_DEBUG, "XXXXXXXXXX IP: %s", ip); + } + ilog(LOG_DEBUG, ""); + */ - il = g_slice_alloc0(sizeof(*il)); - il->local_intf = loc; - g_queue_push_tail(out, il); - if (G_LIKELY(!__get_consecutive_ports(&il->list, num_ports, 0, loc->spec, label))) { - // success - found available ports on local interfaces, so far - continue; - } + if (!rtpe_config.save_interface_ports) { + for (l = log->list.head; l; l = l->next) { + loc = l->data; - // error - found at least one local interface with no ports available - goto error_ports; - } + il = g_slice_alloc0(sizeof(*il)); + il->local_intf = loc; + g_queue_push_tail(out, il); + if (G_LIKELY(!__get_consecutive_ports(&il->list, num_ports, 0, loc->spec, label))) { + // success - found available ports on local interfaces, so far + continue; + } else { + // fail - did not found available ports on at least one local interface + goto error_ports; + } + } - return 0; + return 0; error_ports: - ilog(LOG_ERR, "Failed to get %d consecutive ports on all locals of logical '"STR_FORMAT"'", - num_ports, STR_FMT(&log->name)); + ilog(LOG_ERR, "Failed to get %d consecutive ports on all locals of logical '"STR_FORMAT"'", + num_ports, STR_FMT(&log->name)); - // free all ports alloc'ed so far for the previous local interfaces - while ((il = g_queue_pop_head(out))) { - free_socket_intf_list(il); - } + // free all ports alloc'ed so far for the previous local interfaces + while ((il = g_queue_pop_head(out))) { + free_socket_intf_list(il); + } - return -1; + return -1; + + } else { + for (l = log->list.head; l; l = l->next) { + loc = l->data; + + // check desired family of local interface + if (desired_family != loc->spec->local_address.addr.family) { + ilog(LOG_DEBUG, "Did not find yet one local interface for family %s; continue...", desired_family->rfc_name); + continue; + } + + ilog(LOG_DEBUG, "Found one local interface for family %s", desired_family->rfc_name); + + il = g_slice_alloc0(sizeof(*il)); + il->local_intf = loc; + if (G_LIKELY(!__get_consecutive_ports(&il->list, num_ports, 0, loc->spec, label))) { + // success - found available ports on one local interface + g_queue_push_tail(out, il); + return 0; + } else { + // fail - no available ports on one local interface... continue + free_socket_intf_list(il); + } + } + + ilog(LOG_ERR, "Failed to get %d consecutive ports on one local of logical '"STR_FORMAT"'", + num_ports, STR_FMT(&log->name)); + + return -1; + } } void free_socket_intf_list(struct intf_list *il) { socket_t *sock; diff --git a/daemon/rtpengine.pod b/daemon/rtpengine.pod index c28065358..de0ac489b 100644 --- a/daemon/rtpengine.pod +++ b/daemon/rtpengine.pod @@ -80,6 +80,14 @@ unavailable. In this case, startup of the daemon will fail with an error if this option is given. +=item B<-S>, B<--save-interface-ports> + +Will bind ports only on the first available local interface, of desired +family, of logical interface. If no ports available on any local interface +of desired family, give an error message. + +In this case, ICE will be broken. + =item B<-i>, B<--interface=>[IB]I[BI] Specifies a local network interface for RTP. diff --git a/include/main.h b/include/main.h index 5cfcf693d..cf715df82 100644 --- a/include/main.h +++ b/include/main.h @@ -61,6 +61,7 @@ struct rtpengine_config { int homer_protocol; int homer_id; int no_fallback; + int save_interface_ports; int port_min; int port_max; int redis_db; diff --git a/include/media_socket.h b/include/media_socket.h index 94c93af47..f5d8311d0 100644 --- a/include/media_socket.h +++ b/include/media_socket.h @@ -161,7 +161,7 @@ int is_local_endpoint(const struct intf_address *addr, unsigned int port); int __get_consecutive_ports(GQueue *out, unsigned int num_ports, unsigned int wanted_start_port, struct intf_spec *spec, const str *); -int get_consecutive_ports(GQueue *out, unsigned int num_ports, const struct logical_intf *log, const str *); +int get_consecutive_ports(GQueue *out, unsigned int num_ports, struct call_media *media); struct stream_fd *stream_fd_new(socket_t *fd, struct call *call, const struct local_intf *lif); void free_intf_list(struct intf_list *il);