Skip to content
Draft
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
49 changes: 44 additions & 5 deletions src/arvgvdevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -1983,11 +1983,17 @@ arv_gv_device_constructed (GObject *object)
char *address_string;
guint32 capabilities;
guint32 device_mode;
GInetAddress *any_address;
int socket_fd;
struct ifaddrs *addrs, *iap;
struct sockaddr_in *sa;
char buf[32];
char interface_name[32];

G_OBJECT_CLASS (arv_gv_device_parent_class)->constructed (object);
G_OBJECT_CLASS (arv_gv_device_parent_class)->constructed (object);

if (!G_IS_INET_ADDRESS (priv->interface_address) ||
!G_IS_INET_ADDRESS (priv->device_address)) {
!G_IS_INET_ADDRESS (priv->device_address)) {
arv_device_take_init_error (ARV_DEVICE (object), g_error_new (ARV_DEVICE_ERROR, ARV_DEVICE_ERROR_INVALID_PARAMETER,
"Invalid interface or device address"));
return;
Expand All @@ -2010,18 +2016,51 @@ 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);
io_data->interface_address = arv_socket_bind_with_range (io_data->socket, priv->interface_address, 0,
// we have to grab the interface name
if (getifaddrs (&addrs) <0) {
arv_device_take_init_error (ARV_DEVICE (object),
g_error_new (ARV_DEVICE_ERROR, ARV_DEVICE_ERROR_NOT_CONNECTED,
"Couldn't get available interfaces"));
return;
}

for (iap = addrs; iap != NULL; iap = iap->ifa_next) {
if ((iap->ifa_flags & IFF_UP) != 0 &&
(iap->ifa_flags & IFF_POINTOPOINT) == 0 &&
(iap->ifa_addr != NULL) &&
(iap->ifa_addr->sa_family == AF_INET)) {

sa = (struct sockaddr_in *)(iap->ifa_addr);
inet_ntop(iap->ifa_addr->sa_family, (void *)&(sa->sin_addr), buf, sizeof(buf));
if (!strcmp(g_inet_address_to_string (priv->interface_address), buf)) {
sprintf(interface_name, "%s", iap->ifa_name);
}
}
}

freeifaddrs (addrs);

socket_fd = g_socket_get_fd(io_data->socket);
if (setsockopt (socket_fd, SOL_SOCKET, SO_BINDTODEVICE, interface_name, strlen (interface_name)) == 0) {
any_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
io_data->interface_address = arv_socket_bind_with_range (io_data->socket, any_address, 0,
FALSE, &local_error);
g_object_unref (any_address);
} else {
io_data->interface_address = arv_socket_bind_with_range (io_data->socket, priv->interface_address, 0,
FALSE, &local_error);
}


if (io_data->interface_address == NULL) {
if (local_error == NULL)
local_error = g_error_new (ARV_DEVICE_ERROR, ARV_DEVICE_ERROR_UNKNOWN,
"Unknown error trying to bind device interface");
"Unknown error trying to bind device interface");
arv_device_take_init_error (ARV_DEVICE (gv_device), local_error);

return;
}


io_data->buffer = g_malloc (ARV_GV_DEVICE_BUFFER_SIZE);
io_data->gvcp_n_retries = ARV_GV_DEVICE_GVCP_N_RETRIES_DEFAULT;
io_data->gvcp_timeout_ms = ARV_GV_DEVICE_GVCP_TIMEOUT_MS_DEFAULT;
Expand Down
50 changes: 31 additions & 19 deletions src/arvgvinterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,22 @@ arv_gv_discover_socket_list_new (void)
ArvGvDiscoverSocket *discover_socket = g_new0 (ArvGvDiscoverSocket, 1);
GSocketAddress *socket_address;
GSocketAddress *socket_broadcast;
GInetAddress *any_address;
GInetAddress *inet_address;
GInetAddress *inet_broadcast;
char *inet_address_string;
char *inet_broadcast_string;
GError *error = NULL;
gint buffer_size = ARV_GV_INTERFACE_DISCOVERY_SOCKET_BUFFER_SIZE;
int socket_fd;
const char *interface_name;

socket_address = g_socket_address_new_from_native (arv_network_interface_get_addr(iface_iter->data),
sizeof (struct sockaddr));
socket_broadcast = g_socket_address_new_from_native (arv_network_interface_get_broadaddr(iface_iter->data),
sizeof (struct sockaddr));
inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (socket_address));
inet_broadcast = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (socket_broadcast));
inet_broadcast = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (socket_broadcast));
inet_address_string = g_inet_address_to_string (inet_address);
inet_broadcast_string = g_inet_address_to_string (inet_broadcast);
arv_info_interface ("[GvDiscoverSocket::new] Add interface %s (%s)", inet_address_string, inet_broadcast_string);
Expand All @@ -118,23 +122,31 @@ arv_gv_discover_socket_list_new (void)
G_SOCKET_TYPE_DATAGRAM,
G_SOCKET_PROTOCOL_UDP, NULL);
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,
0, FALSE, &error);

g_object_unref (socket_address);
g_object_unref (socket_broadcast);

if (G_IS_INET_SOCKET_ADDRESS (discover_socket->interface_address)) {
socket_list->sockets = g_slist_prepend (socket_list->sockets, discover_socket);
socket_list->n_sockets++;
} else {
arv_warning_interface ("Failed to bind discovery socket: %s",
error != NULL ? error->message : "Unknown reason");
arv_gv_discover_socket_free (discover_socket);
}
}
g_list_free_full (ifaces, (GDestroyNotify) arv_network_interface_free);
interface_name = arv_network_interface_get_name (iface_iter->data);
socket_fd = g_socket_get_fd(discover_socket->socket);
if (setsockopt (socket_fd, SOL_SOCKET, SO_BINDTODEVICE, interface_name, strlen (interface_name)) == 0) {
any_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
discover_socket->interface_address = arv_socket_bind_with_range (discover_socket->socket, any_address,
0, FALSE, &error);
g_object_unref (any_address);
} else {
discover_socket->interface_address = arv_socket_bind_with_range (discover_socket->socket, inet_address,
0, FALSE, &error);

g_object_unref (socket_address);
g_object_unref (socket_broadcast);

if (G_IS_INET_SOCKET_ADDRESS (discover_socket->interface_address)) {
socket_list->sockets = g_slist_prepend (socket_list->sockets, discover_socket);
socket_list->n_sockets++;
} else {
arv_warning_interface ("Failed to bind discovery socket: %s",
error != NULL ? error->message : "Unknown reason");
arv_gv_discover_socket_free (discover_socket);
}
}
}
g_list_free_full (ifaces, (GDestroyNotify) arv_network_interface_free);

socket_list->poll_fds = g_new (GPollFD, socket_list->n_sockets);
for (i = 0, iter = socket_list->sockets; iter != NULL; i++, iter = iter->next) {
Expand Down Expand Up @@ -812,4 +824,4 @@ arv_gv_interface_class_init (ArvGvInterfaceClass *gv_interface_class)

interface_class->update_device_list = arv_gv_interface_update_device_list;
interface_class->open_device = arv_gv_interface_open_device;
}
}
Loading