static gboolean xingzhe_comes(GSocketService *service, GSocketConnection *connection, GObject *src_obj, gpointer user_data) { GSocketAddress *addr; GInetAddress *ip_addr; gchar *str; GSocketFamily ip_type; addr = g_socket_connection_get_remote_address(connection, NULL); ip_addr = g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(addr)); ip_type = g_inet_address_get_family(ip_addr); // gdk_threads_enter(); g_printf("[WATCHER] Here comes an monkey: "); str = g_inet_address_to_string(ip_addr); g_printf(str); g_printf("\n"); // gdk_threads_leave(); return TRUE; }
static void kms_rtp_endpoint_set_addr (KmsRtpEndpoint * self) { GList *ips, *l; gboolean done = FALSE; ips = nice_interfaces_get_local_ips (FALSE); for (l = ips; l != NULL && !done; l = l->next) { GInetAddress *addr; gboolean is_ipv6 = FALSE; addr = g_inet_address_new_from_string (l->data); if (G_IS_INET_ADDRESS (addr)) { switch (g_inet_address_get_family (addr)) { case G_SOCKET_FAMILY_INVALID: case G_SOCKET_FAMILY_UNIX: /* Ignore this addresses */ break; case G_SOCKET_FAMILY_IPV6: is_ipv6 = TRUE; case G_SOCKET_FAMILY_IPV4: { gchar *addr_str; gboolean use_ipv6; g_object_get (self, "use-ipv6", &use_ipv6, NULL); if (is_ipv6 != use_ipv6) { GST_DEBUG_OBJECT (self, "No valid address type: %d", is_ipv6); break; } addr_str = g_inet_address_to_string (addr); if (addr_str != NULL) { KmsBaseSdpEndpoint *base_sdp = KMS_BASE_SDP_ENDPOINT (self); KmsSdpAgent *agent = kms_base_sdp_endpoint_get_sdp_agent (base_sdp); g_object_set (agent, "addr", addr_str, NULL); g_free (addr_str); done = TRUE; } break; } } } if (G_IS_OBJECT (addr)) { g_object_unref (addr); } } g_list_free_full (ips, g_free); if (!done) { GST_WARNING_OBJECT (self, "Addr not set"); } }
void arv_fake_camera_set_inet_address (ArvFakeCamera *camera, GInetAddress *address) { const guint8 *bytes; g_return_if_fail (ARV_IS_FAKE_CAMERA (camera)); g_return_if_fail (G_IS_INET_ADDRESS (address)); g_return_if_fail (g_inet_address_get_family (address) == G_SOCKET_FAMILY_IPV4); bytes = g_inet_address_to_bytes (address); arv_fake_camera_write_memory (camera, ARV_GVBS_CURRENT_IP_ADDRESS_OFFSET, g_inet_address_get_native_size (address), (char *) bytes); }
/* create a socket for sending to remote machine */ static gboolean gst_udpsrc_start (GstBaseSrc * bsrc) { GstUDPSrc *src; GInetAddress *addr, *bind_addr; GSocketAddress *bind_saddr; GResolver *resolver; GError *err = NULL; src = GST_UDPSRC (bsrc); if (src->socket == NULL) { /* need to allocate a socket */ GST_DEBUG_OBJECT (src, "allocating socket for %s:%d", src->host, src->port); addr = g_inet_address_new_from_string (src->host); if (!addr) { GList *results; GST_DEBUG_OBJECT (src, "resolving IP address for host %s", src->host); resolver = g_resolver_get_default (); results = g_resolver_lookup_by_name (resolver, src->host, src->cancellable, &err); if (!results) goto name_resolve; addr = G_INET_ADDRESS (g_object_ref (results->data)); g_resolver_free_addresses (results); g_object_unref (resolver); } #ifndef GST_DISABLE_GST_DEBUG { gchar *ip = g_inet_address_to_string (addr); GST_DEBUG_OBJECT (src, "IP address for host %s is %s", src->host, ip); g_free (ip); } #endif if ((src->used_socket = g_socket_new (g_inet_address_get_family (addr), G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &err)) == NULL) goto no_socket; src->external_socket = FALSE; GST_DEBUG_OBJECT (src, "got socket %p", src->used_socket); if (src->addr) g_object_unref (src->addr); src->addr = G_INET_SOCKET_ADDRESS (g_inet_socket_address_new (addr, src->port)); GST_DEBUG_OBJECT (src, "binding on port %d", src->port); if (g_inet_address_get_is_multicast (addr)) bind_addr = g_inet_address_new_any (g_inet_address_get_family (addr)); else bind_addr = G_INET_ADDRESS (g_object_ref (addr)); g_object_unref (addr); bind_saddr = g_inet_socket_address_new (bind_addr, src->port); g_object_unref (bind_addr); if (!g_socket_bind (src->used_socket, bind_saddr, src->reuse, &err)) goto bind_error; g_object_unref (bind_saddr); } else { GST_DEBUG_OBJECT (src, "using provided socket %p", src->socket); /* we use the configured socket, try to get some info about it */ src->used_socket = G_SOCKET (g_object_ref (src->socket)); src->external_socket = TRUE; if (src->addr) g_object_unref (src->addr); src->addr = G_INET_SOCKET_ADDRESS (g_socket_get_local_address (src->used_socket, &err)); if (!src->addr) goto getsockname_error; } #if GLIB_CHECK_VERSION (2, 35, 7) { gint val = 0; if (src->buffer_size != 0) { GError *opt_err = NULL; GST_INFO_OBJECT (src, "setting udp buffer of %d bytes", src->buffer_size); /* set buffer size, Note that on Linux this is typically limited to a * maximum of around 100K. Also a minimum of 128 bytes is required on * Linux. */ if (!g_socket_set_option (src->used_socket, SOL_SOCKET, SO_RCVBUF, src->buffer_size, &opt_err)) { GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL), ("Could not create a buffer of requested %d bytes: %s", src->buffer_size, opt_err->message)); g_error_free (opt_err); opt_err = NULL; } } /* read the value of the receive buffer. Note that on linux this returns * 2x the value we set because the kernel allocates extra memory for * metadata. The default on Linux is about 100K (which is about 50K * without metadata) */ if (g_socket_get_option (src->used_socket, SOL_SOCKET, SO_RCVBUF, &val, NULL)) { GST_INFO_OBJECT (src, "have udp buffer of %d bytes", val); } else { GST_DEBUG_OBJECT (src, "could not get udp buffer size"); } } #elif defined (SO_RCVBUF) { gint rcvsize, ret; socklen_t len; len = sizeof (rcvsize); if (src->buffer_size != 0) { rcvsize = src->buffer_size; GST_DEBUG_OBJECT (src, "setting udp buffer of %d bytes", rcvsize); /* set buffer size, Note that on Linux this is typically limited to a * maximum of around 100K. Also a minimum of 128 bytes is required on * Linux. */ ret = setsockopt (g_socket_get_fd (src->used_socket), SOL_SOCKET, SO_RCVBUF, (void *) &rcvsize, len); if (ret != 0) { GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL), ("Could not create a buffer of requested %d bytes, %d: %s (%d)", rcvsize, ret, g_strerror (errno), errno)); } } /* read the value of the receive buffer. Note that on linux this returns 2x the * value we set because the kernel allocates extra memory for metadata. * The default on Linux is about 100K (which is about 50K without metadata) */ ret = getsockopt (g_socket_get_fd (src->used_socket), SOL_SOCKET, SO_RCVBUF, (void *) &rcvsize, &len); if (ret == 0) GST_DEBUG_OBJECT (src, "have udp buffer of %d bytes", rcvsize); else GST_DEBUG_OBJECT (src, "could not get udp buffer size"); } #else if (src->buffer_size != 0) { GST_WARNING_OBJECT (src, "don't know how to set udp buffer size on this " "OS. Consider upgrading your GLib to >= 2.35.7 and re-compiling the " "GStreamer udp plugin"); } #endif g_socket_set_broadcast (src->used_socket, TRUE); if (src->auto_multicast && g_inet_address_get_is_multicast (g_inet_socket_address_get_address (src->addr))) { GST_DEBUG_OBJECT (src, "joining multicast group %s", src->host); if (!g_socket_join_multicast_group (src->used_socket, g_inet_socket_address_get_address (src->addr), FALSE, src->multi_iface, &err)) goto membership; } /* NOTE: sockaddr_in.sin_port works for ipv4 and ipv6 because sin_port * follows ss_family on both */ { GInetSocketAddress *addr; guint16 port; addr = G_INET_SOCKET_ADDRESS (g_socket_get_local_address (src->used_socket, &err)); if (!addr) goto getsockname_error; port = g_inet_socket_address_get_port (addr); GST_DEBUG_OBJECT (src, "bound, on port %d", port); if (port != src->port) { src->port = port; GST_DEBUG_OBJECT (src, "notifying port %d", port); g_object_notify (G_OBJECT (src), "port"); } g_object_unref (addr); } return TRUE; /* ERRORS */ name_resolve: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("Name resolval failed: %s", err->message)); g_clear_error (&err); g_object_unref (resolver); return FALSE; } no_socket: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("no socket error: %s", err->message)); g_clear_error (&err); g_object_unref (addr); return FALSE; } bind_error: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("bind failed: %s", err->message)); g_clear_error (&err); g_object_unref (bind_saddr); gst_udpsrc_stop (GST_BASE_SRC (src)); return FALSE; } membership: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("could add membership: %s", err->message)); g_clear_error (&err); gst_udpsrc_stop (GST_BASE_SRC (src)); return FALSE; } getsockname_error: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("getsockname failed: %s", err->message)); g_clear_error (&err); gst_udpsrc_stop (GST_BASE_SRC (src)); return FALSE; } }
static int _SSL_check_subject_altname (X509 *cert, const char *host) { STACK_OF(GENERAL_NAME) *altname_stack = NULL; GInetAddress *addr; GSocketFamily family; int type = GEN_DNS; int count, i; int rv = -1; altname_stack = X509_get_ext_d2i (cert, NID_subject_alt_name, NULL, NULL); if (altname_stack == NULL) return -1; addr = g_inet_address_new_from_string (host); if (addr != NULL) { family = g_inet_address_get_family (addr); if (family == G_SOCKET_FAMILY_IPV4 || family == G_SOCKET_FAMILY_IPV6) type = GEN_IPADD; } count = sk_GENERAL_NAME_num(altname_stack); for (i = 0; i < count; i++) { GENERAL_NAME *altname; altname = sk_GENERAL_NAME_value (altname_stack, i); if (altname->type != type) continue; if (type == GEN_DNS) { unsigned char *data; int format; format = ASN1_STRING_type (altname->d.dNSName); if (format == V_ASN1_IA5STRING) { data = ASN1_STRING_data (altname->d.dNSName); if (ASN1_STRING_length (altname->d.dNSName) != (int)strlen(data)) { g_warning("NUL byte in subjectAltName, probably a malicious certificate.\n"); rv = -2; break; } if (_SSL_match_hostname (data, host) == 0) { rv = 0; break; } } else g_warning ("unhandled subjectAltName dNSName encoding (%d)\n", format); } else if (type == GEN_IPADD) { unsigned char *data; const guint8 *addr_bytes; int datalen, addr_len; datalen = ASN1_STRING_length (altname->d.iPAddress); data = ASN1_STRING_data (altname->d.iPAddress); addr_bytes = g_inet_address_to_bytes (addr); addr_len = (int)g_inet_address_get_native_size (addr); if (datalen == addr_len && memcmp (data, addr_bytes, addr_len) == 0) { rv = 0; break; } } } if (addr != NULL) g_object_unref (addr); sk_GENERAL_NAME_free (altname_stack); return rv; }
static gboolean gst_net_client_internal_clock_start (GstNetClientInternalClock * self) { GSocketAddress *servaddr; GSocketAddress *myaddr; GSocketAddress *anyaddr; GInetAddress *inetaddr; GSocket *socket; GError *error = NULL; GSocketFamily family; GPollFD dummy_pollfd; GResolver *resolver = NULL; GError *err = NULL; g_return_val_if_fail (self->address != NULL, FALSE); g_return_val_if_fail (self->servaddr == NULL, FALSE); /* create target address */ inetaddr = g_inet_address_new_from_string (self->address); if (inetaddr == NULL) { GList *results; resolver = g_resolver_get_default (); results = g_resolver_lookup_by_name (resolver, self->address, NULL, &err); if (!results) goto failed_to_resolve; inetaddr = G_INET_ADDRESS (g_object_ref (results->data)); g_resolver_free_addresses (results); g_object_unref (resolver); } family = g_inet_address_get_family (inetaddr); servaddr = g_inet_socket_address_new (inetaddr, self->port); g_object_unref (inetaddr); g_assert (servaddr != NULL); GST_DEBUG_OBJECT (self, "will communicate with %s:%d", self->address, self->port); socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error); if (socket == NULL) goto no_socket; GST_DEBUG_OBJECT (self, "binding socket"); inetaddr = g_inet_address_new_any (family); anyaddr = g_inet_socket_address_new (inetaddr, 0); g_socket_bind (socket, anyaddr, TRUE, &error); g_object_unref (anyaddr); g_object_unref (inetaddr); if (error != NULL) goto bind_error; /* check address we're bound to, mostly for debugging purposes */ myaddr = g_socket_get_local_address (socket, &error); if (myaddr == NULL) goto getsockname_error; GST_DEBUG_OBJECT (self, "socket opened on UDP port %d", g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (myaddr))); g_object_unref (myaddr); self->cancel = g_cancellable_new (); self->made_cancel_fd = g_cancellable_make_pollfd (self->cancel, &dummy_pollfd); self->socket = socket; self->servaddr = G_SOCKET_ADDRESS (servaddr); self->thread = g_thread_try_new ("GstNetClientInternalClock", gst_net_client_internal_clock_thread, self, &error); if (error != NULL) goto no_thread; return TRUE; /* ERRORS */ no_socket: { GST_ERROR_OBJECT (self, "socket_new() failed: %s", error->message); g_error_free (error); return FALSE; } bind_error: { GST_ERROR_OBJECT (self, "bind failed: %s", error->message); g_error_free (error); g_object_unref (socket); return FALSE; } getsockname_error: { GST_ERROR_OBJECT (self, "get_local_address() failed: %s", error->message); g_error_free (error); g_object_unref (socket); return FALSE; } failed_to_resolve: { GST_ERROR_OBJECT (self, "resolving '%s' failed: %s", self->address, err->message); g_clear_error (&err); g_object_unref (resolver); return FALSE; } no_thread: { GST_ERROR_OBJECT (self, "could not create thread: %s", error->message); g_object_unref (self->servaddr); self->servaddr = NULL; g_object_unref (self->socket); self->socket = NULL; g_error_free (error); return FALSE; } }
static gboolean gssdp_socket_source_do_init (GInitable *initable, G_GNUC_UNUSED GCancellable *cancellable, GError **error) { GSSDPSocketSource *self = NULL; GInetAddress *iface_address = NULL; GSocketAddress *bind_address = NULL; GInetAddress *group = NULL; GError *inner_error = NULL; GSocketFamily family; gboolean success = FALSE; self = GSSDP_SOCKET_SOURCE (initable); iface_address = g_inet_address_new_from_string (self->priv->host_ip); if (iface_address == NULL) { g_set_error (error, GSSDP_ERROR, GSSDP_ERROR_FAILED, "Invalid host ip: %s", self->priv->host_ip); goto error; } family = g_inet_address_get_family (iface_address); if (family == G_SOCKET_FAMILY_IPV4) group = g_inet_address_new_from_string (SSDP_ADDR); else { g_set_error_literal (error, GSSDP_ERROR, GSSDP_ERROR_FAILED, "IPv6 address"); goto error; } /* Create socket */ self->priv->socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &inner_error); if (!self->priv->socket) { g_propagate_prefixed_error (error, inner_error, "Could not create socket"); goto error; } /* Enable broadcasting */ if (!gssdp_socket_enable_broadcast (self->priv->socket, TRUE, &inner_error)) { g_propagate_prefixed_error (error, inner_error, "Failed to enable broadcast"); goto error; } /* TTL */ if (!self->priv->ttl) /* UDA/1.0 says 4, UDA/1.1 says 2 */ self->priv->ttl = 4; if (!gssdp_socket_set_ttl (self->priv->socket, self->priv->ttl, &inner_error)) { g_propagate_prefixed_error (error, inner_error, "Failed to set TTL to %u", self->priv->ttl); goto error; } /* Set up additional things according to the type of socket desired */ if (self->priv->type == GSSDP_SOCKET_SOURCE_TYPE_MULTICAST) { /* Enable multicast loopback */ if (!gssdp_socket_enable_loop (self->priv->socket, TRUE, &inner_error)) { g_propagate_prefixed_error ( error, inner_error, "Failed to enable loop-back"); goto error; } if (!gssdp_socket_mcast_interface_set (self->priv->socket, iface_address, &inner_error)) { g_propagate_prefixed_error ( error, inner_error, "Failed to set multicast interface"); goto error; } #ifdef G_OS_WIN32 bind_address = g_inet_socket_address_new (iface_address, SSDP_PORT); #else bind_address = g_inet_socket_address_new (group, SSDP_PORT); #endif } else { guint port = SSDP_PORT; /* Use user-supplied or random port for the socket source used * by M-SEARCH */ if (self->priv->type == GSSDP_SOCKET_SOURCE_TYPE_SEARCH) port = self->priv->port; bind_address = g_inet_socket_address_new (iface_address, port); } /* Normally g_socket_bind does this, but it is disabled on * windows since SO_REUSEADDR has different semantics * there, also we nees SO_REUSEPORT on OpenBSD. This is a nop * everywhere else. */ if (!gssdp_socket_reuse_address (self->priv->socket, TRUE, &inner_error)) { g_propagate_prefixed_error ( error, inner_error, "Failed to enable reuse"); goto error; } /* Bind to requested port and address */ if (!g_socket_bind (self->priv->socket, bind_address, TRUE, &inner_error)) { g_propagate_prefixed_error (error, inner_error, "Failed to bind socket"); goto error; } if (self->priv->type == GSSDP_SOCKET_SOURCE_TYPE_MULTICAST) { /* Subscribe to multicast channel */ if (!gssdp_socket_mcast_group_join (self->priv->socket, group, iface_address, &inner_error)) { char *address = g_inet_address_to_string (group); g_propagate_prefixed_error (error, inner_error, "Failed to join group %s", address); g_free (address); goto error; } } self->priv->source = g_socket_create_source (self->priv->socket, G_IO_IN | G_IO_ERR, NULL); success = TRUE; error: if (iface_address != NULL) g_object_unref (iface_address); if (bind_address != NULL) g_object_unref (bind_address); if (group != NULL) g_object_unref (group); if (!success) /* Be aware that inner_error has already been free'd by * g_propagate_error(), so we cannot access its contents * anymore. */ if (error == NULL) g_warning ("Failed to create socket source"); return success; }
makiDCCSend* maki_dcc_send_new_out (makiServer* serv, makiUser* user, const gchar* path) { guint i; gchar* basename; GInetAddress* inet_address; struct stat stbuf; makiInstance* inst = maki_instance_get_default(); makiNetwork* net = maki_instance_network(inst); makiDCCSend* dcc; dcc = g_new(makiDCCSend, 1); dcc->server = serv; dcc->id = maki_instance_get_dcc_send_id(inst); dcc->user = maki_user_ref(user); dcc->channel.file = NULL; dcc->channel.connection = NULL; dcc->path = g_strdup(path); dcc->position = 0; dcc->size = 0; dcc->resume = 0; dcc->address = 0; dcc->port = 0; dcc->token = 0; dcc->status = 0; dcc->d.out.ack.position = 0; dcc->d.out.ack.offset = 0; dcc->d.out.wait = FALSE; for (i = 0; i < s_out_num; i++) { dcc->d.out.sources[i] = 0; } dcc->d.out.upnp = FALSE; if (stat(dcc->path, &stbuf) != 0) { goto error; } dcc->size = stbuf.st_size; for (dcc->port = maki_instance_config_get_integer(inst, "dcc", "port_first"); dcc->port <= maki_instance_config_get_integer(inst, "dcc", "port_last"); dcc->port++) { if ((dcc->channel.connection = i_io_channel_unix_new_listen(NULL, dcc->port, TRUE)) != NULL) { break; } } if (dcc->channel.connection == NULL) { goto error; } g_io_channel_set_close_on_unref(dcc->channel.connection, TRUE); g_io_channel_set_encoding(dcc->channel.connection, NULL, NULL); if ((inet_address = maki_network_external_address(net)) != NULL) { if (g_inet_address_get_family(inet_address) == G_SOCKET_FAMILY_IPV4) { dcc->address = ntohl(*((guint32 const*)g_inet_address_to_bytes(inet_address))); } g_object_unref(inet_address); } else { makiNetworkAddress addr; socklen_t addrlen = sizeof(addr); getsockname(g_io_channel_unix_get_fd(dcc->channel.connection), &(addr.sa), &addrlen); dcc->address = ntohl(addr.sin.sin_addr.s_addr); } if ((dcc->channel.file = g_io_channel_new_file(dcc->path, "r", NULL)) == NULL) { goto error; } g_io_channel_set_close_on_unref(dcc->channel.file, TRUE); g_io_channel_set_encoding(dcc->channel.file, NULL, NULL); g_io_channel_set_buffered(dcc->channel.file, FALSE); dcc->d.out.upnp = maki_network_upnp_add_port(net, dcc->port, "maki DCC Send"); basename = g_path_get_basename(dcc->path); if (strstr(basename, " ") == NULL) { maki_server_send_printf(serv, "PRIVMSG %s :\001DCC SEND %s %" G_GUINT32_FORMAT " %" G_GUINT16_FORMAT " %" G_GUINT64_FORMAT "\001", maki_user_nick(dcc->user), basename, dcc->address, dcc->port, dcc->size); } else { maki_server_send_printf(serv, "PRIVMSG %s :\001DCC SEND \"%s\" %" G_GUINT32_FORMAT " %" G_GUINT16_FORMAT " %" G_GUINT64_FORMAT "\001", maki_user_nick(dcc->user), basename, dcc->address, dcc->port, dcc->size); } g_free(basename); dcc->d.out.sources[s_out_listen] = g_io_add_watch(dcc->channel.connection, G_IO_IN | G_IO_HUP | G_IO_ERR, maki_dcc_send_out_listen, dcc); maki_dcc_send_emit(dcc); return dcc; error: maki_dcc_send_free(dcc); return NULL; }
/* create a socket for sending to remote machine */ static gboolean gst_udpsrc_open (GstUDPSrc * src) { GInetAddress *addr, *bind_addr; GSocketAddress *bind_saddr; GError *err = NULL; if (src->socket == NULL) { /* need to allocate a socket */ GST_DEBUG_OBJECT (src, "allocating socket for %s:%d", src->address, src->port); addr = gst_udpsrc_resolve (src, src->address); if (!addr) goto name_resolve; if ((src->used_socket = g_socket_new (g_inet_address_get_family (addr), G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &err)) == NULL) goto no_socket; src->external_socket = FALSE; GST_DEBUG_OBJECT (src, "got socket %p", src->used_socket); if (src->addr) g_object_unref (src->addr); src->addr = G_INET_SOCKET_ADDRESS (g_inet_socket_address_new (addr, src->port)); GST_DEBUG_OBJECT (src, "binding on port %d", src->port); /* On Windows it's not possible to bind to a multicast address * but the OS will make sure to filter out all packets that * arrive not for the multicast address the socket joined. * * On Linux and others it is necessary to bind to a multicast * address to let the OS filter out all packets that are received * on the same port but for different addresses than the multicast * address */ #ifdef G_OS_WIN32 if (g_inet_address_get_is_multicast (addr)) bind_addr = g_inet_address_new_any (g_inet_address_get_family (addr)); else #endif bind_addr = G_INET_ADDRESS (g_object_ref (addr)); g_object_unref (addr); bind_saddr = g_inet_socket_address_new (bind_addr, src->port); g_object_unref (bind_addr); if (!g_socket_bind (src->used_socket, bind_saddr, src->reuse, &err)) goto bind_error; g_object_unref (bind_saddr); } else { GST_DEBUG_OBJECT (src, "using provided socket %p", src->socket); /* we use the configured socket, try to get some info about it */ src->used_socket = G_SOCKET (g_object_ref (src->socket)); src->external_socket = TRUE; if (src->addr) g_object_unref (src->addr); src->addr = G_INET_SOCKET_ADDRESS (g_socket_get_local_address (src->used_socket, &err)); if (!src->addr) goto getsockname_error; } #if GLIB_CHECK_VERSION (2, 35, 7) { gint val = 0; if (src->buffer_size != 0) { GError *opt_err = NULL; GST_INFO_OBJECT (src, "setting udp buffer of %d bytes", src->buffer_size); /* set buffer size, Note that on Linux this is typically limited to a * maximum of around 100K. Also a minimum of 128 bytes is required on * Linux. */ if (!g_socket_set_option (src->used_socket, SOL_SOCKET, SO_RCVBUF, src->buffer_size, &opt_err)) { GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL), ("Could not create a buffer of requested %d bytes: %s", src->buffer_size, opt_err->message)); g_error_free (opt_err); opt_err = NULL; } } /* read the value of the receive buffer. Note that on linux this returns * 2x the value we set because the kernel allocates extra memory for * metadata. The default on Linux is about 100K (which is about 50K * without metadata) */ if (g_socket_get_option (src->used_socket, SOL_SOCKET, SO_RCVBUF, &val, NULL)) { GST_INFO_OBJECT (src, "have udp buffer of %d bytes", val); } else { GST_DEBUG_OBJECT (src, "could not get udp buffer size"); } } #elif defined (SO_RCVBUF) { gint rcvsize, ret; socklen_t len; len = sizeof (rcvsize); if (src->buffer_size != 0) { rcvsize = src->buffer_size; GST_DEBUG_OBJECT (src, "setting udp buffer of %d bytes", rcvsize); /* set buffer size, Note that on Linux this is typically limited to a * maximum of around 100K. Also a minimum of 128 bytes is required on * Linux. */ ret = setsockopt (g_socket_get_fd (src->used_socket), SOL_SOCKET, SO_RCVBUF, (void *) &rcvsize, len); if (ret != 0) { GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL), ("Could not create a buffer of requested %d bytes, %d: %s (%d)", rcvsize, ret, g_strerror (errno), errno)); } } /* read the value of the receive buffer. Note that on linux this returns 2x the * value we set because the kernel allocates extra memory for metadata. * The default on Linux is about 100K (which is about 50K without metadata) */ ret = getsockopt (g_socket_get_fd (src->used_socket), SOL_SOCKET, SO_RCVBUF, (void *) &rcvsize, &len); if (ret == 0) GST_DEBUG_OBJECT (src, "have udp buffer of %d bytes", rcvsize); else GST_DEBUG_OBJECT (src, "could not get udp buffer size"); } #else if (src->buffer_size != 0) { GST_WARNING_OBJECT (src, "don't know how to set udp buffer size on this " "OS. Consider upgrading your GLib to >= 2.35.7 and re-compiling the " "GStreamer udp plugin"); } #endif g_socket_set_broadcast (src->used_socket, TRUE); if (src->auto_multicast && g_inet_address_get_is_multicast (g_inet_socket_address_get_address (src->addr))) { GST_DEBUG_OBJECT (src, "joining multicast group %s", src->address); if (!g_socket_join_multicast_group (src->used_socket, g_inet_socket_address_get_address (src->addr), FALSE, src->multi_iface, &err)) goto membership; } /* NOTE: sockaddr_in.sin_port works for ipv4 and ipv6 because sin_port * follows ss_family on both */ { GInetSocketAddress *addr; guint16 port; addr = G_INET_SOCKET_ADDRESS (g_socket_get_local_address (src->used_socket, &err)); if (!addr) goto getsockname_error; port = g_inet_socket_address_get_port (addr); GST_DEBUG_OBJECT (src, "bound, on port %d", port); if (port != src->port) { src->port = port; GST_DEBUG_OBJECT (src, "notifying port %d", port); g_object_notify (G_OBJECT (src), "port"); } g_object_unref (addr); } src->allocator = NULL; gst_allocation_params_init (&src->params); src->max_size = 0; return TRUE; /* ERRORS */ name_resolve: { return FALSE; } no_socket: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("no socket error: %s", err->message)); g_clear_error (&err); g_object_unref (addr); return FALSE; } bind_error: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("bind failed: %s", err->message)); g_clear_error (&err); g_object_unref (bind_saddr); gst_udpsrc_close (src); return FALSE; } membership: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("could add membership: %s", err->message)); g_clear_error (&err); gst_udpsrc_close (src); return FALSE; } getsockname_error: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("getsockname failed: %s", err->message)); g_clear_error (&err); gst_udpsrc_close (src); return FALSE; } }
/* create a socket for sending to remote machine */ static gboolean gst_udpsrc_open (GstUDPSrc * src) { GInetAddress *addr, *bind_addr; GSocketAddress *bind_saddr; GError *err = NULL; gst_udpsrc_create_cancellable (src); if (src->socket == NULL) { /* need to allocate a socket */ GST_DEBUG_OBJECT (src, "allocating socket for %s:%d", src->address, src->port); addr = gst_udpsrc_resolve (src, src->address); if (!addr) goto name_resolve; if ((src->used_socket = g_socket_new (g_inet_address_get_family (addr), G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &err)) == NULL) goto no_socket; src->external_socket = FALSE; GST_DEBUG_OBJECT (src, "got socket %p", src->used_socket); if (src->addr) g_object_unref (src->addr); src->addr = G_INET_SOCKET_ADDRESS (g_inet_socket_address_new (addr, src->port)); GST_DEBUG_OBJECT (src, "binding on port %d", src->port); /* On Windows it's not possible to bind to a multicast address * but the OS will make sure to filter out all packets that * arrive not for the multicast address the socket joined. * * On Linux and others it is necessary to bind to a multicast * address to let the OS filter out all packets that are received * on the same port but for different addresses than the multicast * address */ #ifdef G_OS_WIN32 if (g_inet_address_get_is_multicast (addr)) bind_addr = g_inet_address_new_any (g_inet_address_get_family (addr)); else #endif bind_addr = G_INET_ADDRESS (g_object_ref (addr)); g_object_unref (addr); bind_saddr = g_inet_socket_address_new (bind_addr, src->port); g_object_unref (bind_addr); if (!g_socket_bind (src->used_socket, bind_saddr, src->reuse, &err)) goto bind_error; g_object_unref (bind_saddr); g_socket_set_multicast_loopback (src->used_socket, src->loop); } else { GInetSocketAddress *local_addr; GST_DEBUG_OBJECT (src, "using provided socket %p", src->socket); /* we use the configured socket, try to get some info about it */ src->used_socket = G_SOCKET (g_object_ref (src->socket)); src->external_socket = TRUE; local_addr = G_INET_SOCKET_ADDRESS (g_socket_get_local_address (src->used_socket, &err)); if (!local_addr) goto getsockname_error; /* See above for the reasons. Without this we would behave different on * Windows and Linux, joining multicast groups below for provided sockets * on Linux but not on Windows */ #ifdef G_OS_WIN32 addr = gst_udpsrc_resolve (src, src->address); if (!addr) goto name_resolve; if (!src->auto_multicast || !g_inet_address_get_is_any (g_inet_socket_address_get_address (local_addr)) || !g_inet_address_get_is_multicast (addr)) { g_object_unref (addr); #endif if (src->addr) g_object_unref (src->addr); src->addr = local_addr; #ifdef G_OS_WIN32 } else { g_object_unref (local_addr); if (src->addr) g_object_unref (src->addr); src->addr = G_INET_SOCKET_ADDRESS (g_inet_socket_address_new (addr, src->port)); g_object_unref (addr); } #endif } { gint val = 0; if (src->buffer_size != 0) { GError *opt_err = NULL; GST_INFO_OBJECT (src, "setting udp buffer of %d bytes", src->buffer_size); /* set buffer size, Note that on Linux this is typically limited to a * maximum of around 100K. Also a minimum of 128 bytes is required on * Linux. */ if (!g_socket_set_option (src->used_socket, SOL_SOCKET, SO_RCVBUF, src->buffer_size, &opt_err)) { GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL), ("Could not create a buffer of requested %d bytes: %s", src->buffer_size, opt_err->message)); g_error_free (opt_err); opt_err = NULL; } } /* read the value of the receive buffer. Note that on linux this returns * 2x the value we set because the kernel allocates extra memory for * metadata. The default on Linux is about 100K (which is about 50K * without metadata) */ if (g_socket_get_option (src->used_socket, SOL_SOCKET, SO_RCVBUF, &val, NULL)) { GST_INFO_OBJECT (src, "have udp buffer of %d bytes", val); } else { GST_DEBUG_OBJECT (src, "could not get udp buffer size"); } } g_socket_set_broadcast (src->used_socket, TRUE); if (src->auto_multicast && g_inet_address_get_is_multicast (g_inet_socket_address_get_address (src->addr))) { GST_DEBUG_OBJECT (src, "joining multicast group %s", src->address); if (!g_socket_join_multicast_group (src->used_socket, g_inet_socket_address_get_address (src->addr), FALSE, src->multi_iface, &err)) goto membership; } /* NOTE: sockaddr_in.sin_port works for ipv4 and ipv6 because sin_port * follows ss_family on both */ { GInetSocketAddress *addr; guint16 port; addr = G_INET_SOCKET_ADDRESS (g_socket_get_local_address (src->used_socket, &err)); if (!addr) goto getsockname_error; port = g_inet_socket_address_get_port (addr); GST_DEBUG_OBJECT (src, "bound, on port %d", port); if (port != src->port) { src->port = port; GST_DEBUG_OBJECT (src, "notifying port %d", port); g_object_notify (G_OBJECT (src), "port"); } g_object_unref (addr); } src->allocator = NULL; gst_allocation_params_init (&src->params); src->max_size = 0; return TRUE; /* ERRORS */ name_resolve: { return FALSE; } no_socket: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("no socket error: %s", err->message)); g_clear_error (&err); g_object_unref (addr); return FALSE; } bind_error: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("bind failed: %s", err->message)); g_clear_error (&err); g_object_unref (bind_saddr); gst_udpsrc_close (src); return FALSE; } membership: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("could add membership: %s", err->message)); g_clear_error (&err); gst_udpsrc_close (src); return FALSE; } getsockname_error: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("getsockname failed: %s", err->message)); g_clear_error (&err); gst_udpsrc_close (src); return FALSE; } }