mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-12 02:15:31 +00:00
addresspool: return reason of failure
Let gst_rtsp_address_pool_reserve_address() return the reason why the address could not be reserved. Fixes https://bugzilla.gnome.org/show_bug.cgi?id=708229
This commit is contained in:
parent
c7bed54b87
commit
7b0ad7c25f
4 changed files with 160 additions and 85 deletions
|
@ -585,64 +585,26 @@ gst_rtsp_address_pool_dump (GstRTSPAddressPool * pool)
|
|||
g_mutex_unlock (&priv->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_address_pool_reserve_address:
|
||||
* @pool: a #GstRTSPAddressPool
|
||||
* @address: The IP address to reserve
|
||||
* @port: The first port to reserve
|
||||
* @n_ports: The number of ports
|
||||
* @ttl: The requested ttl
|
||||
*
|
||||
* Take a specific address and ports from @pool. @n_ports consecutive
|
||||
* ports will be allocated of which the first one can be found in
|
||||
* @port.
|
||||
*
|
||||
* If @ttl is 0, @address should be a unicast address. If @ttl > 0, @address
|
||||
* should be a valid multicast address.
|
||||
*
|
||||
* Returns: a #GstRTSPAddress that should be freed with gst_rtsp_address_free
|
||||
* after use or %NULL when no address could be acquired.
|
||||
*/
|
||||
GstRTSPAddress *
|
||||
gst_rtsp_address_pool_reserve_address (GstRTSPAddressPool * pool,
|
||||
const gchar * address, guint port, guint n_ports, guint ttl)
|
||||
static GList *
|
||||
find_address_in_ranges (GList * addresses, Addr * addr, guint port,
|
||||
guint n_ports, guint ttl)
|
||||
{
|
||||
GstRTSPAddressPoolPrivate *priv;
|
||||
Addr input_addr;
|
||||
GList *walk, *next;
|
||||
AddrRange *result;
|
||||
GstRTSPAddress *addr;
|
||||
gboolean is_multicast;
|
||||
|
||||
g_return_val_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool), NULL);
|
||||
g_return_val_if_fail (address != NULL, NULL);
|
||||
g_return_val_if_fail (port > 0, NULL);
|
||||
g_return_val_if_fail (n_ports > 0, NULL);
|
||||
|
||||
priv = pool->priv;
|
||||
result = NULL;
|
||||
addr = NULL;
|
||||
is_multicast = ttl != 0;
|
||||
|
||||
if (!fill_address (address, port, &input_addr, is_multicast))
|
||||
goto invalid;
|
||||
|
||||
g_mutex_lock (&priv->lock);
|
||||
/* go over available ranges */
|
||||
for (walk = priv->addresses; walk; walk = next) {
|
||||
for (walk = addresses; walk; walk = next) {
|
||||
AddrRange *range;
|
||||
gint skip_port, skip_addr;
|
||||
|
||||
range = walk->data;
|
||||
next = walk->next;
|
||||
|
||||
/* Not the right type of address */
|
||||
if (range->min.size != input_addr.size)
|
||||
if (range->min.size != addr->size)
|
||||
continue;
|
||||
|
||||
/* Check that the address is in the interval */
|
||||
if (memcmp (range->min.bytes, input_addr.bytes, input_addr.size) > 0 ||
|
||||
memcmp (range->max.bytes, input_addr.bytes, input_addr.size) < 0)
|
||||
if (memcmp (range->min.bytes, addr->bytes, addr->size) > 0 ||
|
||||
memcmp (range->max.bytes, addr->bytes, addr->size) < 0)
|
||||
continue;
|
||||
|
||||
/* Make sure the requested ports are inside the range */
|
||||
|
@ -652,38 +614,112 @@ gst_rtsp_address_pool_reserve_address (GstRTSPAddressPool * pool,
|
|||
if (ttl != range->ttl)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return walk;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_address_pool_reserve_address:
|
||||
* @pool: a #GstRTSPAddressPool
|
||||
* @ip_address: The IP address to reserve
|
||||
* @port: The first port to reserve
|
||||
* @n_ports: The number of ports
|
||||
* @ttl: The requested ttl
|
||||
* @address: (out) storage for a #GstRTSPAddress
|
||||
*
|
||||
* Take a specific address and ports from @pool. @n_ports consecutive
|
||||
* ports will be allocated of which the first one can be found in
|
||||
* @port.
|
||||
*
|
||||
* If @ttl is 0, @address should be a unicast address. If @ttl > 0, @address
|
||||
* should be a valid multicast address.
|
||||
*
|
||||
* Returns: #GST_RTSP_ADDRESS_POOL_OK if an address was reserved. The address
|
||||
* is returned in @address and should be freed with gst_rtsp_address_free
|
||||
* after use.
|
||||
*/
|
||||
GstRTSPAddressPoolResult
|
||||
gst_rtsp_address_pool_reserve_address (GstRTSPAddressPool * pool,
|
||||
const gchar * ip_address, guint port, guint n_ports, guint ttl,
|
||||
GstRTSPAddress ** address)
|
||||
{
|
||||
GstRTSPAddressPoolPrivate *priv;
|
||||
Addr input_addr;
|
||||
GList *list;
|
||||
AddrRange *addr_range;
|
||||
GstRTSPAddress *addr;
|
||||
gboolean is_multicast;
|
||||
GstRTSPAddressPoolResult result;
|
||||
|
||||
g_return_val_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool),
|
||||
GST_RTSP_ADDRESS_POOL_EINVAL);
|
||||
g_return_val_if_fail (ip_address != NULL, GST_RTSP_ADDRESS_POOL_EINVAL);
|
||||
g_return_val_if_fail (port > 0, GST_RTSP_ADDRESS_POOL_EINVAL);
|
||||
g_return_val_if_fail (n_ports > 0, GST_RTSP_ADDRESS_POOL_EINVAL);
|
||||
g_return_val_if_fail (address != NULL, GST_RTSP_ADDRESS_POOL_EINVAL);
|
||||
|
||||
priv = pool->priv;
|
||||
addr_range = NULL;
|
||||
addr = NULL;
|
||||
is_multicast = ttl != 0;
|
||||
|
||||
if (!fill_address (ip_address, port, &input_addr, is_multicast))
|
||||
goto invalid;
|
||||
|
||||
g_mutex_lock (&priv->lock);
|
||||
list = find_address_in_ranges (priv->addresses, &input_addr, port, n_ports,
|
||||
ttl);
|
||||
if (list != NULL) {
|
||||
AddrRange *range = list->data;
|
||||
gint skip_port, skip_addr;
|
||||
|
||||
skip_addr = diff_address (&input_addr, &range->min);
|
||||
skip_port = port - range->min.port;
|
||||
|
||||
/* we found a range, remove from the list */
|
||||
priv->addresses = g_list_delete_link (priv->addresses, walk);
|
||||
priv->addresses = g_list_delete_link (priv->addresses, list);
|
||||
/* now split and exit our loop */
|
||||
result = split_range (pool, range, skip_addr, skip_port, n_ports);
|
||||
priv->allocated = g_list_prepend (priv->allocated, result);
|
||||
break;
|
||||
addr_range = split_range (pool, range, skip_addr, skip_port, n_ports);
|
||||
priv->allocated = g_list_prepend (priv->allocated, addr_range);
|
||||
}
|
||||
|
||||
if (addr_range) {
|
||||
addr = g_slice_new0 (GstRTSPAddress);
|
||||
addr->pool = g_object_ref (pool);
|
||||
addr->address = get_address_string (&addr_range->min);
|
||||
addr->n_ports = n_ports;
|
||||
addr->port = addr_range->min.port;
|
||||
addr->ttl = addr_range->ttl;
|
||||
addr->priv = addr_range;
|
||||
|
||||
result = GST_RTSP_ADDRESS_POOL_OK;
|
||||
GST_DEBUG_OBJECT (pool, "reserved address %s:%u ttl %u", addr->address,
|
||||
addr->port, addr->ttl);
|
||||
} else {
|
||||
/* We failed to reserve the address. Check if it was because the address
|
||||
* was already in use or if it wasn't in the pool to begin with */
|
||||
list = find_address_in_ranges (priv->allocated, &input_addr, port, n_ports,
|
||||
ttl);
|
||||
if (list != NULL) {
|
||||
result = GST_RTSP_ADDRESS_POOL_ERESERVED;
|
||||
} else {
|
||||
result = GST_RTSP_ADDRESS_POOL_ERANGE;
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (&priv->lock);
|
||||
|
||||
if (result) {
|
||||
addr = g_slice_new0 (GstRTSPAddress);
|
||||
addr->pool = g_object_ref (pool);
|
||||
addr->address = get_address_string (&result->min);
|
||||
addr->n_ports = n_ports;
|
||||
addr->port = result->min.port;
|
||||
addr->ttl = result->ttl;
|
||||
addr->priv = result;
|
||||
|
||||
GST_DEBUG_OBJECT (pool, "reserved address %s:%u ttl %u", addr->address,
|
||||
addr->port, addr->ttl);
|
||||
}
|
||||
return addr;
|
||||
*address = addr;
|
||||
return result;
|
||||
|
||||
/* ERRORS */
|
||||
invalid:
|
||||
{
|
||||
GST_ERROR_OBJECT (pool, "invalid address %s:%u/%u/%u", address,
|
||||
GST_ERROR_OBJECT (pool, "invalid address %s:%u/%u/%u", ip_address,
|
||||
port, n_ports, ttl);
|
||||
return NULL;
|
||||
*address = NULL;
|
||||
return GST_RTSP_ADDRESS_POOL_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,27 @@ G_BEGIN_DECLS
|
|||
#define GST_RTSP_ADDRESS_POOL_CAST(obj) ((GstRTSPAddressPool*)(obj))
|
||||
#define GST_RTSP_ADDRESS_POOL_CLASS_CAST(klass) ((GstRTSPAddressPoolClass*)(klass))
|
||||
|
||||
/**
|
||||
* GstRTSPAddressPoolResult:
|
||||
* @GST_RTSP_ADDRESS_POOL_OK: no error
|
||||
* @GST_RTSP_ADDRESS_POOL_EINVAL:invalid arguments were provided to a function
|
||||
* @GST_RTSP_ADDRESS_POOL_ERESERVED: the addres has already been reserved
|
||||
* @GST_RTSP_ADDRESS_POOL_ERANGE: the address is not in the pool
|
||||
* @GST_RTSP_ADDRESS_POOL_ELAST: last error
|
||||
*
|
||||
* Result codes from RTSP address pool functions.
|
||||
*/
|
||||
typedef enum {
|
||||
GST_RTSP_ADDRESS_POOL_OK = 0,
|
||||
/* errors */
|
||||
GST_RTSP_ADDRESS_POOL_EINVAL = -1,
|
||||
GST_RTSP_ADDRESS_POOL_ERESERVED = -2,
|
||||
GST_RTSP_ADDRESS_POOL_ERANGE = -3,
|
||||
|
||||
GST_RTSP_ADDRESS_POOL_ELAST = -4,
|
||||
} GstRTSPAddressPoolResult;
|
||||
|
||||
|
||||
typedef struct _GstRTSPAddress GstRTSPAddress;
|
||||
|
||||
typedef struct _GstRTSPAddressPool GstRTSPAddressPool;
|
||||
|
@ -143,11 +164,12 @@ GstRTSPAddress * gst_rtsp_address_pool_acquire_address (GstRTSPAddressPool
|
|||
GstRTSPAddressFlags flags,
|
||||
gint n_ports);
|
||||
|
||||
GstRTSPAddress * gst_rtsp_address_pool_reserve_address (GstRTSPAddressPool * pool,
|
||||
const gchar *address,
|
||||
GstRTSPAddressPoolResult gst_rtsp_address_pool_reserve_address (GstRTSPAddressPool * pool,
|
||||
const gchar *ip_address,
|
||||
guint port,
|
||||
guint n_ports,
|
||||
guint ttl);
|
||||
guint ttl,
|
||||
GstRTSPAddress ** address);
|
||||
|
||||
gboolean gst_rtsp_address_pool_has_unicast_addresses (GstRTSPAddressPool * pool);
|
||||
|
||||
|
|
|
@ -730,12 +730,14 @@ gst_rtsp_stream_reserve_address (GstRTSPStream * stream,
|
|||
|
||||
g_mutex_lock (&priv->lock);
|
||||
if (*addrp == NULL) {
|
||||
GstRTSPAddressPoolResult res;
|
||||
|
||||
if (priv->pool == NULL)
|
||||
goto no_pool;
|
||||
|
||||
*addrp = gst_rtsp_address_pool_reserve_address (priv->pool, address,
|
||||
port, n_ports, ttl);
|
||||
if (*addrp == NULL)
|
||||
res = gst_rtsp_address_pool_reserve_address (priv->pool, address,
|
||||
port, n_ports, ttl, addrp);
|
||||
if (res != GST_RTSP_ADDRESS_POOL_OK)
|
||||
goto no_address;
|
||||
} else {
|
||||
if (strcmp ((*addrp)->address, address) ||
|
||||
|
|
|
@ -25,6 +25,7 @@ GST_START_TEST (test_pool)
|
|||
{
|
||||
GstRTSPAddressPool *pool;
|
||||
GstRTSPAddress *addr, *addr2, *addr3;
|
||||
GstRTSPAddressPoolResult res;
|
||||
|
||||
pool = gst_rtsp_address_pool_new ();
|
||||
|
||||
|
@ -126,47 +127,61 @@ GST_START_TEST (test_pool)
|
|||
fail_unless (gst_rtsp_address_pool_add_range (pool,
|
||||
"233.252.1.1", "233.252.1.1", 5000, 5001, 1));
|
||||
|
||||
addr = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 3,
|
||||
1);
|
||||
res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 3,
|
||||
1, &addr);
|
||||
fail_unless (res == GST_RTSP_ADDRESS_POOL_ERANGE);
|
||||
fail_unless (addr == NULL);
|
||||
|
||||
addr = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.2", 5000, 2,
|
||||
1);
|
||||
res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.2", 5000, 2,
|
||||
1, &addr);
|
||||
fail_unless (res == GST_RTSP_ADDRESS_POOL_ERANGE);
|
||||
fail_unless (addr == NULL);
|
||||
|
||||
addr = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 500, 2, 1);
|
||||
res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 500, 2, 1,
|
||||
&addr);
|
||||
fail_unless (res == GST_RTSP_ADDRESS_POOL_ERANGE);
|
||||
fail_unless (addr == NULL);
|
||||
|
||||
addr = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 2,
|
||||
2);
|
||||
res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 2,
|
||||
2, &addr);
|
||||
fail_unless (res == GST_RTSP_ADDRESS_POOL_ERANGE);
|
||||
fail_unless (addr == NULL);
|
||||
|
||||
addr = gst_rtsp_address_pool_reserve_address (pool, "2000::1", 5000, 2, 2);
|
||||
res = gst_rtsp_address_pool_reserve_address (pool, "2000::1", 5000, 2, 2,
|
||||
&addr);
|
||||
fail_unless (res == GST_RTSP_ADDRESS_POOL_EINVAL);
|
||||
fail_unless (addr == NULL);
|
||||
|
||||
addr = gst_rtsp_address_pool_reserve_address (pool, "1.1", 5000, 2, 2);
|
||||
res = gst_rtsp_address_pool_reserve_address (pool, "1.1", 5000, 2, 2, &addr);
|
||||
fail_unless (res == GST_RTSP_ADDRESS_POOL_EINVAL);
|
||||
fail_unless (addr == NULL);
|
||||
|
||||
addr = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 2,
|
||||
1);
|
||||
res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 2,
|
||||
1, &addr);
|
||||
fail_unless (res == GST_RTSP_ADDRESS_POOL_OK);
|
||||
fail_unless (addr != NULL);
|
||||
fail_unless (addr->port == 5000);
|
||||
fail_unless (!strcmp (addr->address, "233.252.1.1"));
|
||||
|
||||
res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 2,
|
||||
1, &addr2);
|
||||
fail_unless (res == GST_RTSP_ADDRESS_POOL_ERESERVED);
|
||||
fail_unless (addr2 == NULL);
|
||||
|
||||
gst_rtsp_address_free (addr);
|
||||
gst_rtsp_address_pool_clear (pool);
|
||||
|
||||
fail_unless (gst_rtsp_address_pool_add_range (pool,
|
||||
"233.252.1.1", "233.252.1.3", 5000, 5001, 1));
|
||||
|
||||
addr = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 2,
|
||||
1);
|
||||
res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.1", 5000, 2,
|
||||
1, &addr);
|
||||
fail_unless (addr != NULL);
|
||||
fail_unless (addr->port == 5000);
|
||||
fail_unless (!strcmp (addr->address, "233.252.1.1"));
|
||||
|
||||
addr2 = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.3", 5000, 2,
|
||||
1);
|
||||
res = gst_rtsp_address_pool_reserve_address (pool, "233.252.1.3", 5000, 2,
|
||||
1, &addr2);
|
||||
fail_unless (addr2 != NULL);
|
||||
fail_unless (addr2->port == 5000);
|
||||
fail_unless (!strcmp (addr2->address, "233.252.1.3"));
|
||||
|
|
Loading…
Reference in a new issue