<commit_before>/* Aravis - Digital camera library
 *
 * Copyright © 2009-2010 <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: <NAME> <<EMAIL>>
 */

/**
 * SECTION: arvgvinterface
 * @short_description: Gigabit ethernet camera interface
 */

#include <arvgvinterface.h>
#include <arvgvdevice.h>
#include <arvgvcp.h>
#include <arvdebug.h>
#include <arvmisc.h>
#include <arvstr.h>
#include <glib/gprintf.h>
#include <gio/gio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <stdlib.h>
#include <string.h>

/* ArvGvDiscoverSocket implementation */

typedef struct {
	GSocketAddress *interface_address;
	GSocketAddress *broadcast_address;
	GSocket *socket;
} ArvGvDiscoverSocket;

static gboolean
arv_gv_discover_socket_set_broadcast (ArvGvDiscoverSocket *discover_socket, gboolean enable)
{
	int socket_fd;
	int result;

	socket_fd = g_socket_get_fd (discover_socket->socket);

	result = setsockopt (socket_fd, SOL_SOCKET, SO_BROADCAST, (char*)&enable, sizeof (enable));

	return result == 0;
}

typedef struct {
	unsigned int n_sockets;
	GSList *sockets;
	GPollFD *poll_fds;
} ArvGvDiscoverSocketList;

static ArvGvDiscoverSocketList *
arv_gv_discover_socket_list_new (void)
{
	ArvGvDiscoverSocketList *socket_list;
	GSList *iter;
	struct ifaddrs *ifap  = NULL;
	struct ifaddrs *ifap_iter;
	int i;

	socket_list = g_new0 (ArvGvDiscoverSocketList, 1);

	if (getifaddrs (&ifap) < 0)
		return socket_list;

	for (ifap_iter = ifap; ifap_iter != NULL; ifap_iter = ifap_iter->ifa_next) {
		if ((ifap_iter->ifa_flags & IFF_UP) != 0 &&
		    (ifap_iter->ifa_flags & IFF_POINTOPOINT) == 0 &&
		    (ifap_iter->ifa_addr->sa_family == AF_INET)) {
			ArvGvDiscoverSocket *discover_socket = g_new0 (ArvGvDiscoverSocket, 1);
			GSocketAddress *socket_address;
			GInetAddress *inet_address;
			char *inet_address_string;
			GError *error = NULL;

			socket_address = g_socket_address_new_from_native (ifap_iter->ifa_addr,
									   sizeof (struct sockaddr));
			inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (socket_address));
			inet_address_string = g_inet_address_to_string (inet_address);
			arv_debug_interface ("[GvDiscoverSocket::new] Add interface %s", inet_address_string);
			g_free (inet_address_string);
			discover_socket->interface_address = g_inet_socket_address_new (inet_address, 0);
			g_object_unref (socket_address);

			socket_address = g_socket_address_new_from_native (ifap_iter->ifa_broadaddr,
									   sizeof (struct sockaddr));
			inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (socket_address));
			discover_socket->broadcast_address = g_inet_socket_address_new (inet_address, ARV_GVCP_PORT);
			inet_address_string = g_inet_address_to_string (inet_address);
			arv_debug_interface ("[GvDiscoverSocket::new] Broadcast address is %s", inet_address_string);
			g_free (inet_address_string);
			g_object_unref (socket_address);

			discover_socket->socket = g_socket_new (G_SOCKET_FAMILY_IPV4,
								G_SOCKET_TYPE_DATAGRAM,
								G_SOCKET_PROTOCOL_UDP, NULL);
			g_socket_bind (discover_socket->socket, discover_socket->interface_address, TRUE, &error);

			socket_list->sockets = g_slist_prepend (socket_list->sockets, discover_socket);
			socket_list->n_sockets++;
		}
	}

	freeifaddrs (ifap);

	socket_list->poll_fds = g_new (GPollFD, socket_list->n_sockets);
	for (i = 0, iter = socket_list->sockets; iter != NULL; i++, iter = iter->next) {
		ArvGvDiscoverSocket *discover_socket = iter->data;

		socket_list->poll_fds[i].fd = g_socket_get_fd (discover_socket->socket);
		socket_list->poll_fds[i].events =  G_IO_IN;
		socket_list->poll_fds[i].revents = 0;
	}

	return socket_list;
}

static void
arv_gv_discover_socket_list_free (ArvGvDiscoverSocketList *socket_list)
{
	GSList *iter;

	g_return_if_fail (socket_list != NULL);

	for (iter = socket_list->sockets; iter != NULL; iter = iter->next) {
		ArvGvDiscoverSocket *discover_socket = iter->data;

		g_object_unref (discover_socket->interface_address);
		g_object_unref (discover_socket->broadcast_address);
		g_object_unref (discover_socket->socket);
		g_free (discover_socket);
	}
	g_slist_free (socket_list->sockets);
	g_free (socket_list->poll_fds);

	socket_list->sockets = NULL;
	socket_list->n_sockets = 0;
	socket_list->poll_fds = NULL;

	g_free (socket_list);
}

static void
arv_gv_discover_socket_list_send_discover_packet (ArvGvDiscoverSocketList *socket_list)
{
	ArvGvcpPacket *packet;
	GSList *iter;
	size_t size;

	packet = arv_gvcp_packet_new_discovery_cmd (&size);

	for (iter = socket_list->sockets; iter != NULL; iter = iter->next) {
		ArvGvDiscoverSocket *discover_socket = iter->data;
		GError *error = NULL;

		arv_gv_discover_socket_set_broadcast (discover_socket, TRUE);
		g_socket_send_to (discover_socket->socket,
				  discover_socket->broadcast_address,
				  (const char *) packet, size,
				  NULL, &error);
		if (error != NULL) {
			arv_warning_interface ("[ArvGVInterface::send_discover_packet] Error: %s", error->message);
			g_error_free (error);
		}
		arv_gv_discover_socket_set_broadcast (discover_socket, FALSE);
	}

	arv_gvcp_packet_free (packet);
}

/* ArvGvInterfaceDeviceInfos implementation */

typedef struct {
	char *name;
	char *user_name;
	char *manufacturer;
	char *serial_number;
	char *mac_string;

	GInetAddress *interface_address;

	guchar discovery_data[ARV_GVBS_DISCOVERY_DATA_SIZE];

	volatile gint ref_count;
} ArvGvInterfaceDeviceInfos;

static ArvGvInterfaceDeviceInfos *
arv_gv_interface_device_infos_new (GInetAddress *interface_address,
				   void *discovery_data)<commit_msg>gv_interface: use 255.255.255.255 as broadcast address for device discovery.<commit_after>/* Aravis - Digital camera library
 *
 * Copyright © 2009-2010 <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: <NAME> <<EMAIL>>
 */

/**
 * SECTION: arvgvinterface
 * @short_description: Gigabit ethernet camera interface
 */

#include <arvgvinterface.h>
#include <arvgvdevice.h>
#include <arvgvcp.h>
#include <arvdebug.h>
#include <arvmisc.h>
#include <arvstr.h>
#include <glib/gprintf.h>
#include <gio/gio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <stdlib.h>
#include <string.h>

/* ArvGvDiscoverSocket implementation */

typedef struct {
	GSocketAddress *interface_address;
	GSocket *socket;
} ArvGvDiscoverSocket;

static gboolean
arv_gv_discover_socket_set_broadcast (ArvGvDiscoverSocket *discover_socket, gboolean enable)
{
	int socket_fd;
	int result;

	socket_fd = g_socket_get_fd (discover_socket->socket);

	result = setsockopt (socket_fd, SOL_SOCKET, SO_BROADCAST, (char*)&enable, sizeof (enable));

	return result == 0;
}

typedef struct {
	unsigned int n_sockets;
	GSList *sockets;
	GPollFD *poll_fds;
} ArvGvDiscoverSocketList;

static ArvGvDiscoverSocketList *
arv_gv_discover_socket_list_new (void)
{
	ArvGvDiscoverSocketList *socket_list;
	GSList *iter;
	struct ifaddrs *ifap  = NULL;
	struct ifaddrs *ifap_iter;
	int i;

	socket_list = g_new0 (ArvGvDiscoverSocketList, 1);

	if (getifaddrs (&ifap) < 0)
		return socket_list;

	for (ifap_iter = ifap; ifap_iter != NULL; ifap_iter = ifap_iter->ifa_next) {
		if ((ifap_iter->ifa_flags & IFF_UP) != 0 &&
		    (ifap_iter->ifa_flags & IFF_POINTOPOINT) == 0 &&
		    (ifap_iter->ifa_addr->sa_family == AF_INET)) {
			ArvGvDiscoverSocket *discover_socket = g_new0 (ArvGvDiscoverSocket, 1);
			GSocketAddress *socket_address;
			GInetAddress *inet_address;
			char *inet_address_string;
			GError *error = NULL;

			socket_address = g_socket_address_new_from_native (ifap_iter->ifa_addr,
									   sizeof (struct sockaddr));
			inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (socket_address));
			inet_address_string = g_inet_address_to_string (inet_address);
			arv_debug_interface ("[GvDiscoverSocket::new] Add interface %s", inet_address_string);
			g_free (inet_address_string);
			discover_socket->interface_address = g_inet_socket_address_new (inet_address, 0);
			g_object_unref (socket_address);

			discover_socket->socket = g_socket_new (G_SOCKET_FAMILY_IPV4,
								G_SOCKET_TYPE_DATAGRAM,
								G_SOCKET_PROTOCOL_UDP, NULL);
			g_socket_bind (discover_socket->socket, discover_socket->interface_address, TRUE, &error);

			socket_list->sockets = g_slist_prepend (socket_list->sockets, discover_socket);
			socket_list->n_sockets++;
		}
	}

	freeifaddrs (ifap);

	socket_list->poll_fds = g_new (GPollFD, socket_list->n_sockets);
	for (i = 0, iter = socket_list->sockets; iter != NULL; i++, iter = iter->next) {
		ArvGvDiscoverSocket *discover_socket = iter->data;

		socket_list->poll_fds[i].fd = g_socket_get_fd (discover_socket->socket);
		socket_list->poll_fds[i].events =  G_IO_IN;
		socket_list->poll_fds[i].revents = 0;
	}

	return socket_list;
}

static void
arv_gv_discover_socket_list_free (ArvGvDiscoverSocketList *socket_list)
{
	GSList *iter;

	g_return_if_fail (socket_list != NULL);

	for (iter = socket_list->sockets; iter != NULL; iter = iter->next) {
		ArvGvDiscoverSocket *discover_socket = iter->data;

		g_object_unref (discover_socket->interface_address);
		g_object_unref (discover_socket->socket);
		g_free (discover_socket);
	}
	g_slist_free (socket_list->sockets);
	g_free (socket_list->poll_fds);

	socket_list->sockets = NULL;
	socket_list->n_sockets = 0;
	socket_list->poll_fds = NULL;

	g_free (socket_list);
}

static void
arv_gv_discover_socket_list_send_discover_packet (ArvGvDiscoverSocketList *socket_list)
{
	GInetAddress *broadcast_address;
	GSocketAddress *broadcast_socket_address;
	ArvGvcpPacket *packet;
	GSList *iter;
	size_t size;

	packet = arv_gvcp_packet_new_discovery_cmd (&size);

	broadcast_address = g_inet_address_new_from_string ("255.255.255.255");
	broadcast_socket_address = g_inet_socket_address_new (broadcast_address, ARV_GVCP_PORT);
	g_object_unref (broadcast_address);

	for (iter = socket_list->sockets; iter != NULL; iter = iter->next) {
		ArvGvDiscoverSocket *discover_socket = iter->data;
		GError *error = NULL;

		arv_gv_discover_socket_set_broadcast (discover_socket, TRUE);
		g_socket_send_to (discover_socket->socket,
				  broadcast_socket_address,
				  (const char *) packet, size,
				  NULL, &error);
		if (error != NULL) {
			arv_warning_interface ("[ArvGVInterface::send_discover_packet] Error: %s", error->message);
			g_error_free (error);
		}
		arv_gv_discover_socket_set_broadcast (discover_socket, FALSE);
	}

	g_object_unref (broadcast_socket_address);

	arv_gvcp_packet_free (packet);
}

/* ArvGvInterfaceDeviceInfos implementation */

typedef struct {
	char *name;
	char *user_name;
	char *manufacturer;
	char *serial_number;
	char *mac_string;

	GInetAddress *interface_address;

	guchar discovery_data[ARV_GVBS_DISCOVERY_DATA_SIZE];

	volatile gint ref_count;
} ArvGvInterfaceDeviceInfos;

static ArvGvInterfaceDeviceInfos *
arv_gv_interface_device_infos_new (GInetAddress *interface_address,
				   void *discovery_data)
{'fraction_non_alphanumeric': 0.1012750161394448, 'fraction_numerical': 0.007746933505487412, 'mean_word_length': 5.4279045643153525, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 119, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5590613', 'n_tokens_mistral': 4823, 'n_tokens_neox': 4426, 'n_words': 966}