Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/arvgvdevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <arvgvcpprivate.h>
#include <arvgvspprivate.h>
#include <arvnetworkprivate.h>
#include <arvgvinterface.h>
#include <arvzip.h>
#include <arvstr.h>
#include <arvmiscprivate.h>
Expand Down Expand Up @@ -667,6 +668,7 @@ auto_packet_size (ArvGvDevice *gv_device, gboolean exit_early, GError **error)
char *buffer;
guint last_size = 0;
gboolean success;
char *bindtodevice_name = NULL;

g_return_val_if_fail (ARV_IS_GV_DEVICE (gv_device), 1500);

Expand Down Expand Up @@ -697,6 +699,21 @@ auto_packet_size (ArvGvDevice *gv_device, gboolean exit_early, GError **error)

interface_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (priv->io_data->interface_address));
socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, NULL);
#ifdef SO_BINDTODEVICE
bindtodevice_name = arv_gv_interface_dup_discovery_bindtodevice_name();
if (bindtodevice_name != NULL) {
if (setsockopt (g_socket_get_fd (socket), SOL_SOCKET, SO_BINDTODEVICE,
bindtodevice_name, strlen (bindtodevice_name)) != 0) {
arv_warning_interface ("[GvDevice::new] "
"Failed to bind socket to device %s: %s",
bindtodevice_name, g_strerror (errno));
} else {
arv_info_interface ("[GvDevice::new] "
"Socket bound to device %s", bindtodevice_name);
}
g_free(bindtodevice_name);
}
#endif
interface_socket_address = arv_socket_bind_with_range (socket, interface_address, 0, FALSE, NULL);
local_address = G_INET_SOCKET_ADDRESS (g_socket_get_local_address (socket, NULL));
port = g_inet_socket_address_get_port (local_address);
Expand Down Expand Up @@ -1989,6 +2006,7 @@ arv_gv_device_constructed (GObject *object)
char *address_string;
guint32 capabilities;
guint32 device_mode;
char *bindtodevice_name;

G_OBJECT_CLASS (arv_gv_device_parent_class)->constructed (object);

Expand Down Expand Up @@ -2016,6 +2034,21 @@ arv_gv_device_constructed (GObject *object)
io_data->socket = g_socket_new (G_SOCKET_FAMILY_IPV4,
G_SOCKET_TYPE_DATAGRAM,
G_SOCKET_PROTOCOL_UDP, NULL);
#ifdef SO_BINDTODEVICE
bindtodevice_name = arv_gv_interface_dup_discovery_bindtodevice_name();
if (bindtodevice_name != NULL) {
if (setsockopt (g_socket_get_fd (io_data->socket), SOL_SOCKET, SO_BINDTODEVICE,
bindtodevice_name, strlen (bindtodevice_name)) != 0) {
arv_warning_interface ("[GvDevice::new] "
"Failed to bind socket to device %s: %s",
bindtodevice_name, g_strerror (errno));
} else {
arv_info_interface ("[GvDevice::new] "
"Socket bound to device %s", bindtodevice_name);
}
g_free(bindtodevice_name);
}
#endif
io_data->interface_address = arv_socket_bind_with_range (io_data->socket, priv->interface_address, 0,
FALSE, &local_error);

Expand Down
103 changes: 96 additions & 7 deletions src/arvgvinterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ arv_gv_discover_socket_free (ArvGvDiscoverSocket *discover_socket)
}

static ArvGvDiscoverSocketList *
arv_gv_discover_socket_list_new (const char *discovery_interface)
arv_gv_discover_socket_list_new (const char *discovery_interface, const char* discovery_bindtodevice)
{
ArvGvDiscoverSocketList *socket_list;
GSList *iter;
Expand Down Expand Up @@ -123,6 +123,22 @@ arv_gv_discover_socket_list_new (const char *discovery_interface)
discover_socket->socket = g_socket_new (g_inet_address_get_family (inet_address),
G_SOCKET_TYPE_DATAGRAM,
G_SOCKET_PROTOCOL_UDP, NULL);

#ifdef SO_BINDTODEVICE
if (discovery_bindtodevice != NULL) {
if (setsockopt (g_socket_get_fd (discover_socket->socket), SOL_SOCKET, SO_BINDTODEVICE,
discovery_bindtodevice, strlen (discovery_bindtodevice)) != 0) {
arv_warning_interface ("[ArvGVInterface::discover_socket_list_new] "
"Failed to bind socket to device %s: %s",
discovery_bindtodevice, g_strerror (errno));
} else {
arv_info_interface ("[ArvGVInterface::discover_socket_list_new] "
"Socket bound to device %s", discovery_bindtodevice);
}
}
#endif


arv_socket_set_recv_buffer_size (g_socket_get_fd (discover_socket->socket), buffer_size);

discover_socket->interface_address = arv_socket_bind_with_range (discover_socket->socket, inet_address,
Expand Down Expand Up @@ -348,6 +364,7 @@ typedef struct {

GMutex mutex;
char *discovery_interface;
char *discovery_bindtodevice;
} ArvGvInterfacePrivate;

struct _ArvGvInterface {
Expand All @@ -363,7 +380,7 @@ struct _ArvGvInterfaceClass {
G_DEFINE_TYPE_WITH_CODE (ArvGvInterface, arv_gv_interface, ARV_TYPE_INTERFACE, G_ADD_PRIVATE (ArvGvInterface))

static ArvGvInterfaceDeviceInfos *
_discover (GHashTable *devices, const char *device_id, gboolean allow_broadcast_discovery_ack, const char *discovery_interface)
_discover (GHashTable *devices, const char *device_id, gboolean allow_broadcast_discovery_ack, const char *discovery_interface, const char* discovery_bindtodevice)
{
ArvGvDiscoverSocketList *socket_list;
GSList *iter;
Expand All @@ -376,7 +393,7 @@ _discover (GHashTable *devices, const char *device_id, gboolean allow_broadcast_
if (devices != NULL)
g_hash_table_remove_all (devices);

socket_list = arv_gv_discover_socket_list_new (discovery_interface);
socket_list = arv_gv_discover_socket_list_new (discovery_interface, discovery_bindtodevice);

if (socket_list->n_sockets < 1) {
arv_gv_discover_socket_list_free (socket_list);
Expand Down Expand Up @@ -494,10 +511,12 @@ arv_gv_interface_discover (ArvGvInterface *gv_interface)
{
int flags = arv_interface_get_flags (ARV_INTERFACE(gv_interface));
char *discovery_interface;
char *discovery_bindtodevice;

discovery_interface = arv_gv_interface_dup_discovery_interface_name();
discovery_bindtodevice = arv_gv_interface_dup_discovery_bindtodevice_name();
_discover (gv_interface->priv->devices, NULL, flags & ARV_GV_INTERFACE_FLAGS_ALLOW_BROADCAST_DISCOVERY_ACK,
discovery_interface);
discovery_interface, discovery_bindtodevice);
g_free (discovery_interface);
}

Expand Down Expand Up @@ -567,6 +586,7 @@ arv_gv_interface_camera_locate (ArvGvInterface *gv_interface, GInetAddress *devi
GList *iface_iter;
struct sockaddr_in device_sockaddr;
char *discovery_interface;
char *discovery_bindtodevice;

device_socket_address = g_inet_socket_address_new(device_address, ARV_GVCP_PORT);

Expand Down Expand Up @@ -596,7 +616,8 @@ arv_gv_interface_camera_locate (ArvGvInterface *gv_interface, GInetAddress *devi
}

discovery_interface = arv_gv_interface_dup_discovery_interface_name();
socket_list = arv_gv_discover_socket_list_new (discovery_interface);
discovery_bindtodevice = arv_gv_interface_dup_discovery_bindtodevice_name();
socket_list = arv_gv_discover_socket_list_new (discovery_interface, discovery_bindtodevice);
g_free (discovery_interface);

if (socket_list->n_sockets < 1) {
Expand Down Expand Up @@ -686,6 +707,7 @@ _open_device (ArvInterface *interface, GHashTable *devices, const char *device_i
device_infos = g_hash_table_lookup (devices, device_id);

if (device_infos == NULL) {
arv_info_interface ("[GvDevice::_open device] Device info not found, seeing if ID (%s) is an address", device_id);
struct addrinfo hints;
struct addrinfo *servinfo, *endpoint;

Expand Down Expand Up @@ -746,6 +768,7 @@ arv_gv_interface_open_device (ArvInterface *interface, const char *device_id, GE
ArvDevice *device;
ArvGvInterfaceDeviceInfos *device_infos;
char *discovery_interface;
char *discovery_bindtodevice;
GError *local_error = NULL;
int flags;

Expand All @@ -758,8 +781,9 @@ arv_gv_interface_open_device (ArvInterface *interface, const char *device_id, GE

flags = arv_interface_get_flags (interface);
discovery_interface = arv_gv_interface_dup_discovery_interface_name();
discovery_bindtodevice = arv_gv_interface_dup_discovery_bindtodevice_name();
device_infos = _discover (NULL, device_id, flags & ARV_GVCP_DISCOVERY_PACKET_FLAGS_ALLOW_BROADCAST_ACK,
discovery_interface);
discovery_interface, discovery_bindtodevice);
g_free (discovery_interface);

if (device_infos != NULL) {
Expand Down Expand Up @@ -853,6 +877,70 @@ arv_gv_interface_dup_discovery_interface_name (void)
return discovery_interface;
}

/*
* arv_gv_interface_set_discovery_bindtodevice_name:
* @bindtodevice_name: (nullable): name of the device to bind the discovery to
*
* Set the name of the device to bind the discovery to. If bindtodevice_name is %NULL, a discovery will be performed on every
* interfaces, which is the default behaviour.
*
* A call to [func@Aravis.update_device_list] may be necessary after the discovery interface has changed, in order to
* forget the previously discovered devices.
*
* Since: 0.8.34
*/

void
arv_gv_interface_set_discovery_bindtodevice_name (const char *bindtodevice_name)
{
ArvInterface *interface;

g_mutex_lock (&arv_gv_interface_mutex);

interface = _get_instance();
if (interface != NULL) {
ArvGvInterfacePrivate *priv = ARV_GV_INTERFACE (interface)->priv;

g_mutex_lock (&priv->mutex);
g_clear_pointer (&priv->discovery_bindtodevice, g_free);
priv->discovery_bindtodevice = g_strdup (bindtodevice_name);
g_mutex_unlock (&priv->mutex);
}

g_mutex_unlock (&arv_gv_interface_mutex);
}

/*
* arv_gv_interface_dup_discovery_bindtodevice_name:
*
* Returns: the name of the device used for device discovery, %NULL if discovery is performed on all the available
* interfaces.
*
* Since: 0.8.34
*/

char *
arv_gv_interface_dup_discovery_bindtodevice_name (void)
{
ArvInterface *interface;
char *discovery_bindtodevice = NULL;

g_mutex_lock (&arv_gv_interface_mutex);

interface = _get_instance();
if (interface != NULL) {
ArvGvInterfacePrivate *priv = ARV_GV_INTERFACE (interface)->priv;

g_mutex_lock (&priv->mutex);
discovery_bindtodevice = g_strdup (priv->discovery_bindtodevice);
g_mutex_unlock (&priv->mutex);
}

g_mutex_unlock (&arv_gv_interface_mutex);

return discovery_bindtodevice;
}

/**
* arv_gv_interface_get_instance:
*
Expand Down Expand Up @@ -897,7 +985,7 @@ arv_gv_interface_init (ArvGvInterface *gv_interface)
(GDestroyNotify) arv_gv_interface_device_infos_unref);
g_mutex_init(&gv_interface->priv->mutex);
gv_interface->priv->discovery_interface = NULL;

gv_interface->priv->discovery_bindtodevice = NULL;
}

static void
Expand All @@ -908,6 +996,7 @@ arv_gv_interface_finalize (GObject *object)
g_hash_table_unref (gv_interface->priv->devices);
gv_interface->priv->devices = NULL;
g_clear_pointer (&gv_interface->priv->discovery_interface, g_free);
g_clear_pointer (&gv_interface->priv->discovery_bindtodevice, g_free);
g_mutex_clear (&gv_interface->priv->mutex);

G_OBJECT_CLASS (arv_gv_interface_parent_class)->finalize (object);
Expand Down
2 changes: 2 additions & 0 deletions src/arvgvinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ ARV_API G_DECLARE_FINAL_TYPE (ArvGvInterface, arv_gv_interface, ARV, GV_INTERFAC
ARV_API ArvInterface * arv_gv_interface_get_instance (void);
ARV_API void arv_gv_interface_set_discovery_interface_name (const char *discovery_interface);
ARV_API char * arv_gv_interface_dup_discovery_interface_name (void);
ARV_API void arv_gv_interface_set_discovery_bindtodevice_name(const char *bindtodevice_name);
ARV_API char * arv_gv_interface_dup_discovery_bindtodevice_name(void);

G_END_DECLS

Expand Down
17 changes: 17 additions & 0 deletions src/arvgvstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <arvbufferprivate.h>
#include <arvfeatures.h>
#include <arvparamsprivate.h>
#include <arvgvinterface.h>
#include <arvgvspprivate.h>
#include <arvgvcpprivate.h>
#include <arvdebug.h>
Expand Down Expand Up @@ -1599,6 +1600,7 @@ arv_gv_stream_constructed (GObject *object)
const guint8 *address_bytes;
GInetSocketAddress *local_address;
guint packet_size;
char *bindtodevice_name;

G_OBJECT_CLASS (arv_gv_stream_parent_class)->constructed (object);

Expand Down Expand Up @@ -1659,6 +1661,21 @@ arv_gv_stream_constructed (GObject *object)
(G_INET_SOCKET_ADDRESS (arv_gv_device_get_device_address (priv->gv_device)));

priv->thread_data->socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, NULL);
#ifdef SO_BINDTODEVICE
bindtodevice_name = arv_gv_interface_dup_discovery_bindtodevice_name();
if (bindtodevice_name != NULL) {
if (setsockopt (g_socket_get_fd (priv->thread_data->socket), SOL_SOCKET, SO_BINDTODEVICE,
bindtodevice_name, strlen (bindtodevice_name)) != 0) {
arv_warning_interface ("[GvDevice::new] "
"Failed to bind socket to device %s: %s",
bindtodevice_name, g_strerror (errno));
} else {
arv_info_interface ("[GvDevice::new] "
"Socket bound to device %s", bindtodevice_name);
}
g_free(bindtodevice_name);
}
#endif
priv->thread_data->device_address = g_object_ref (device_address);
priv->thread_data->interface_address = g_object_ref (interface_address);
priv->thread_data->device_socket_address = g_inet_socket_address_new (device_address, ARV_GVCP_PORT);
Expand Down
Loading