Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discover dhcp camera outside subnet #819

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
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