static void arv_gv_interface_build_discover_infos_list (ArvGvInterface *gv_interface) { struct ifaddrs *ifap = NULL; struct ifaddrs *ifap_iter; int return_value; arv_gv_interface_free_discover_infos_list (gv_interface); return_value = getifaddrs (&ifap); if (return_value < 0) return; 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)) { ArvGvInterfaceDiscoverInfos *infos = g_new (ArvGvInterfaceDiscoverInfos, 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 ("[GvInterface::build_discover_infos_list] Add interface %s", inet_address_string); g_free (inet_address_string); infos->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)); infos->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 ("[GvInterface::build_discover_infos_list] Broadcast address is %s", inet_address_string); g_free (inet_address_string); g_object_unref (socket_address); infos->socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, NULL); g_socket_bind (infos->socket, infos->interface_address, TRUE, &error); gv_interface->priv->discover_infos_list = g_slist_prepend (gv_interface->priv->discover_infos_list, infos); gv_interface->priv->n_discover_infos++; } } freeifaddrs (ifap); }
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 != NULL) && (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_interface_receive_hello_packet (ArvGvInterface *gv_interface) { GPollFD *poll_fd; GSList *iter; char buffer[ARV_GV_INTERFACE_SOCKET_BUFFER_SIZE] __attribute__((may_alias)); int count; int i; if (gv_interface->priv->n_discover_infos ==0) return; poll_fd = g_new (GPollFD, gv_interface->priv->n_discover_infos); for (i = 0, iter = gv_interface->priv->discover_infos_list; iter != NULL; i++, iter = iter->next) { ArvGvInterfaceDiscoverInfos *infos = iter->data; poll_fd[i].fd = g_socket_get_fd (infos->socket); poll_fd[i].events = G_IO_IN; poll_fd[i].revents = 0; } do { if (g_poll (poll_fd, gv_interface->priv->n_discover_infos, ARV_GV_INTERFACE_DISCOVERY_TIMEOUT_MS) == 0) { g_free (poll_fd); return; } for (i = 0, iter = gv_interface->priv->discover_infos_list; iter != NULL; i++, iter = iter->next) { ArvGvInterfaceDiscoverInfos *infos = iter->data; do { g_socket_set_blocking (infos->socket, FALSE); count = g_socket_receive (infos->socket, buffer, ARV_GV_INTERFACE_SOCKET_BUFFER_SIZE, NULL, NULL); g_socket_set_blocking (infos->socket, TRUE); if (count > 0) { ArvGvcpPacket *packet = (ArvGvcpPacket *) buffer; if (g_ntohs (packet->header.command) == ARV_GVCP_COMMAND_DISCOVERY_ACK && g_ntohs (packet->header.id) == 0xffff) { ArvGvInterfaceDeviceInfos *device_infos; GInetAddress *interface_address; char *address_string; char *data = buffer + sizeof (ArvGvcpHeader); char *serial_number; char *manufacturer; char *key; arv_gvcp_packet_debug (packet, ARV_DEBUG_LEVEL_LOG); manufacturer = g_strndup (&data[ARV_GVBS_MANUFACTURER_NAME_OFFSET], ARV_GVBS_MANUFACTURER_NAME_SIZE); serial_number = g_strndup (&data[ARV_GVBS_SERIAL_NUMBER_OFFSET], ARV_GVBS_SERIAL_NUMBER_SIZE); key = g_strdup_printf ("%s-%s", manufacturer, serial_number); g_free (manufacturer); g_free (serial_number); interface_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (infos->interface_address)); device_infos = arv_gv_interface_device_infos_new (interface_address, data); address_string = g_inet_address_to_string (interface_address); arv_debug_interface ("[GvInterface::discovery] Device '%s' found " "(interface %s)", key, address_string); g_free (address_string); g_hash_table_insert (gv_interface->priv->devices, key, device_infos); g_hash_table_insert (gv_interface->priv->devices_by_mac, device_infos->mac_string, device_infos); } } } while (count > 0); } } while (1); }
static ArvGvDiscoverSocketList * arv_gv_discover_socket_list_new (void) { ArvGvDiscoverSocketList *socket_list; GInetAddress *broadcast_address; GSList *iter; const char *envar; struct ifaddrs *ifap = NULL; struct ifaddrs *ifap_iter; int i; socket_list = g_new0 (ArvGvDiscoverSocketList, 1); if (getifaddrs (&ifap) < 0) return socket_list; broadcast_address = g_inet_address_new_from_string ("255.255.255.255"); 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 != NULL) && (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->target_address = g_inet_socket_address_new (broadcast_address, ARV_GVCP_PORT); 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++; } } g_object_unref (broadcast_address); freeifaddrs (ifap); if ((envar=g_getenv("ARV_IPS"))!=NULL) { gchar **ips_alloc, **ips, *addr; ips_alloc = ips = g_strsplit(envar, ":", -1); for (addr = *ips; addr; addr = *++ips) { ArvGvDiscoverSocket *discover_socket; GSocketAddress *target_addr = g_inet_socket_address_new_from_string(addr, ARV_GVCP_PORT); if(!target_addr) continue; discover_socket = g_new0 (ArvGvDiscoverSocket, 1); discover_socket->target_address = target_addr; discover_socket->interface_address = g_inet_socket_address_new_from_string("0.0.0.0", ARV_GVCP_PORT); /* TODO, wrong */ discover_socket->socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, NULL); /* implict bind of wildcard w/ arbitrary port */ arv_debug_interface("[GvDiscoverSocket::new] Add unicast destination %s", addr); socket_list->sockets = g_slist_prepend (socket_list->sockets, discover_socket); socket_list->n_sockets++; } g_strfreev(ips_alloc); } 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_interface_discover (ArvGvInterface *gv_interface) { ArvGvDiscoverSocketList *socket_list; GSList *iter; char buffer[ARV_GV_INTERFACE_SOCKET_BUFFER_SIZE]; int count; int i; socket_list = arv_gv_discover_socket_list_new (); if (socket_list->n_sockets < 1) { arv_gv_discover_socket_list_free (socket_list); return; } arv_gv_discover_socket_list_send_discover_packet (socket_list); do { if (g_poll (socket_list->poll_fds, socket_list->n_sockets, ARV_GV_INTERFACE_DISCOVERY_TIMEOUT_MS) == 0) { arv_gv_discover_socket_list_free (socket_list); return; } for (i = 0, iter = socket_list->sockets; iter != NULL; i++, iter = iter->next) { ArvGvDiscoverSocket *discover_socket = iter->data; do { g_socket_set_blocking (discover_socket->socket, FALSE); count = g_socket_receive (discover_socket->socket, buffer, ARV_GV_INTERFACE_SOCKET_BUFFER_SIZE, NULL, NULL); g_socket_set_blocking (discover_socket->socket, TRUE); if (count > 0) { ArvGvcpPacket *packet = (ArvGvcpPacket *) buffer; if (g_ntohs (packet->header.command) == ARV_GVCP_COMMAND_DISCOVERY_ACK && g_ntohs (packet->header.id) == 0xffff) { ArvGvInterfaceDeviceInfos *device_infos; GInetAddress *interface_address; char *address_string; char *data = buffer + sizeof (ArvGvcpHeader); arv_gvcp_packet_debug (packet, ARV_DEBUG_LEVEL_LOG); interface_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (discover_socket->interface_address)); device_infos = arv_gv_interface_device_infos_new (interface_address, data); address_string = g_inet_address_to_string (interface_address); arv_debug_interface ("[GvInterface::discovery] Device '%s' found " "(interface %s) user_name '%s' - MAC_name '%s'", device_infos->name, address_string, device_infos->user_name, device_infos->mac_string); g_free (address_string); if (device_infos->name != NULL && device_infos->name[0] != '\0') { arv_gv_interface_device_infos_ref (device_infos); g_hash_table_replace (gv_interface->priv->devices, device_infos->name, device_infos); } if (device_infos->user_name != NULL && device_infos->user_name[0] != '\0') { arv_gv_interface_device_infos_ref (device_infos); g_hash_table_replace (gv_interface->priv->devices, device_infos->user_name, device_infos); } arv_gv_interface_device_infos_ref (device_infos); g_hash_table_replace (gv_interface->priv->devices, device_infos->mac_string, device_infos); arv_gv_interface_device_infos_unref (device_infos); } } } while (count > 0); } } while (1); }