static void add_network (GNetworkMonitorNetlink *nl, GSocketFamily family, gint dest_len, guint8 *dest, guint8 *gateway) { GInetAddress *dest_addr; GInetAddressMask *network; if (dest) dest_addr = g_inet_address_new_from_bytes (dest, family); else dest_addr = g_inet_address_new_any (family); network = g_inet_address_mask_new (dest_addr, dest_len, NULL); g_object_unref (dest_addr); g_return_if_fail (network != NULL); if (nl->priv->dump_networks) g_ptr_array_add (nl->priv->dump_networks, network); else { g_network_monitor_base_add_network (G_NETWORK_MONITOR_BASE (nl), network); g_object_unref (network); } }
static void remove_network (GNetworkMonitorNetlink *nl, GSocketFamily family, gint dest_len, guint8 *dest, guint8 *gateway) { GInetAddress *dest_addr; GInetAddressMask *network; if (dest) dest_addr = g_inet_address_new_from_bytes (dest, family); else dest_addr = g_inet_address_new_any (family); network = g_inet_address_mask_new (dest_addr, dest_len, NULL); g_object_unref (dest_addr); g_return_if_fail (network != NULL); if (nl->priv->dump_networks) { GInetAddressMask **dump_networks = (GInetAddressMask **)nl->priv->dump_networks->pdata; int i; for (i = 0; i < nl->priv->dump_networks->len; i++) { if (g_inet_address_mask_equal (network, dump_networks[i])) g_ptr_array_remove_index_fast (nl->priv->dump_networks, i--); } g_object_unref (network); } else { g_network_monitor_base_remove_network (G_NETWORK_MONITOR_BASE (nl), network); g_object_unref (network); } }
int main (int argc, char *argv[]) { GSocket *socket, *new_socket, *recv_socket; GSocketAddress *src_address; GSocketAddress *address; GSocketType socket_type; GSocketFamily socket_family; GError *error = NULL; GOptionContext *context; GCancellable *cancellable; char *display_addr; GTlsCertificate *tlscert = NULL; GIOStream *connection; GInputStream *istream; GOutputStream *ostream; g_type_init (); context = g_option_context_new (" - Test GSocket server stuff"); g_option_context_add_main_entries (context, cmd_entries, NULL); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_printerr ("%s: %s\n", argv[0], error->message); return 1; } if (unix_socket && argc != 2) { g_printerr ("%s: %s\n", argv[0], "Need to specify unix socket name"); return 1; } if (cancel_timeout) { GThread *thread; cancellable = g_cancellable_new (); thread = g_thread_new ("cancel", cancel_thread, cancellable); g_thread_unref (thread); } else { cancellable = NULL; } if (tls_cert_file) { if (use_udp) { g_printerr ("DTLS (TLS over UDP) is not supported"); return 1; } tlscert = g_tls_certificate_new_from_file (tls_cert_file, &error); if (!tlscert) { g_printerr ("Could not read server certificate '%s': %s\n", tls_cert_file, error->message); return 1; } } loop = g_main_loop_new (NULL, FALSE); if (use_udp) socket_type = G_SOCKET_TYPE_DATAGRAM; else socket_type = G_SOCKET_TYPE_STREAM; if (unix_socket) socket_family = G_SOCKET_FAMILY_UNIX; else socket_family = G_SOCKET_FAMILY_IPV4; socket = g_socket_new (socket_family, socket_type, 0, &error); if (socket == NULL) { g_printerr ("%s: %s\n", argv[0], error->message); return 1; } if (non_blocking) g_socket_set_blocking (socket, FALSE); if (unix_socket) { src_address = socket_address_from_string (argv[1]); if (src_address == NULL) { g_printerr ("%s: Could not parse '%s' as unix socket name\n", argv[0], argv[1]); return 1; } } else { src_address = g_inet_socket_address_new (g_inet_address_new_any (G_SOCKET_FAMILY_IPV4), port); } if (!g_socket_bind (socket, src_address, !dont_reuse_address, &error)) { g_printerr ("Can't bind socket: %s\n", error->message); return 1; } g_object_unref (src_address); if (!use_udp) { if (!g_socket_listen (socket, &error)) { g_printerr ("Can't listen on socket: %s\n", error->message); return 1; } address = g_socket_get_local_address (socket, &error); if (!address) { g_printerr ("Error getting local address: %s\n", error->message); return 1; } display_addr = socket_address_to_string (address); g_print ("listening on %s...\n", display_addr); g_free (display_addr); ensure_socket_condition (socket, G_IO_IN, cancellable); new_socket = g_socket_accept (socket, cancellable, &error); if (!new_socket) { g_printerr ("Error accepting socket: %s\n", error->message); return 1; } if (non_blocking) g_socket_set_blocking (new_socket, FALSE); if (read_timeout) g_socket_set_timeout (new_socket, read_timeout); address = g_socket_get_remote_address (new_socket, &error); if (!address) { g_printerr ("Error getting remote address: %s\n", error->message); return 1; } display_addr = socket_address_to_string (address); g_print ("got a new connection from %s\n", display_addr); g_free(display_addr); g_object_unref (address); recv_socket = new_socket; connection = G_IO_STREAM (g_socket_connection_factory_create_connection (recv_socket)); g_object_unref (new_socket); } else { recv_socket = socket; connection = NULL; } if (tlscert) { GIOStream *tls_conn; tls_conn = g_tls_server_connection_new (connection, tlscert, &error); if (!tls_conn) { g_printerr ("Could not create TLS connection: %s\n", error->message); return 1; } if (!g_tls_connection_handshake (G_TLS_CONNECTION (tls_conn), cancellable, &error)) { g_printerr ("Error during TLS handshake: %s\n", error->message); return 1; } g_object_unref (connection); connection = tls_conn; } if (connection) { istream = g_io_stream_get_input_stream (connection); ostream = g_io_stream_get_output_stream (connection); } else { g_assert (use_udp); istream = NULL; ostream = NULL; } while (TRUE) { gchar buffer[4096]; gssize size; gsize to_send; if (use_udp) { ensure_socket_condition (recv_socket, G_IO_IN, cancellable); size = g_socket_receive_from (recv_socket, &address, buffer, sizeof buffer, cancellable, &error); } else { ensure_connection_condition (connection, G_IO_IN, cancellable); size = g_input_stream_read (istream, buffer, sizeof buffer, cancellable, &error); } if (size < 0) { g_printerr ("Error receiving from socket: %s\n", error->message); return 1; } if (size == 0) break; g_print ("received %" G_GSSIZE_FORMAT " bytes of data", size); if (use_udp) g_print (" from %s", socket_address_to_string (address)); g_print ("\n"); if (verbose) g_print ("-------------------------\n" "%.*s\n" "-------------------------\n", (int)size, buffer); to_send = size; #ifdef __QNXNTO__ if (delay_) #else if (delay) #endif { #ifdef __QNXNTO__ if (verbose) g_print ("delaying %d seconds before response\n", delay_); g_usleep (1000 * 1000 * delay_); #else if (verbose) g_print ("delaying %d seconds before response\n", delay); g_usleep (1000 * 1000 * delay); #endif } while (to_send > 0) { if (use_udp) { ensure_socket_condition (recv_socket, G_IO_OUT, cancellable); size = g_socket_send_to (recv_socket, address, buffer, to_send, cancellable, &error); } else { ensure_connection_condition (connection, G_IO_OUT, cancellable); size = g_output_stream_write (ostream, buffer, to_send, cancellable, &error); } if (size < 0) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_print ("socket send would block, handling\n"); g_error_free (error); error = NULL; continue; } else { g_printerr ("Error sending to socket: %s\n", error->message); return 1; } } g_print ("sent %" G_GSSIZE_FORMAT " bytes of data\n", size); if (size == 0) { g_printerr ("Unexpected short write\n"); return 1; } to_send -= size; } } g_print ("connection closed\n"); if (connection) { if (!g_io_stream_close (connection, NULL, &error)) { g_printerr ("Error closing connection stream: %s\n", error->message); return 1; } g_object_unref (connection); } if (!g_socket_close (socket, &error)) { g_printerr ("Error closing master socket: %s\n", error->message); return 1; } g_object_unref (socket); return 0; }
static void _j4status_io_server_add(J4statusIOContext *self, const gchar *server_desc) { GSocketAddress *address = NULL; const gchar *path = NULL; if ( g_str_has_prefix(server_desc, "tcp:") ) { GInetAddress *inet_address; const gchar *uri = server_desc + strlen("tcp:"); gchar *port_str = g_utf8_strrchr(uri, -1, ':'); if ( port_str == NULL ) { /* No host, only port */ port_str = (gchar *) uri; /* If you want IPv4, just use "0.0.0.0" */ inet_address = g_inet_address_new_any(G_SOCKET_FAMILY_IPV6); } else { *port_str = '\0'; ++port_str; inet_address = g_inet_address_new_from_string(uri); } guint64 port; port = g_ascii_strtoull(port_str, NULL, 10); if ( port > 65535 ) return; address = g_inet_socket_address_new(inet_address, port); } #ifdef G_OS_UNIX if ( g_str_has_prefix(server_desc, "unix:") ) { path = server_desc + strlen("unix:"); address = g_unix_socket_address_new(path); } #endif /* G_OS_UNIX */ if ( address == NULL ) return; gboolean need_free_server = _j4status_io_add_server(self); GError *error = NULL; gboolean r; r = g_socket_listener_add_address(G_SOCKET_LISTENER(self->server), address, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, NULL, NULL, &error); g_object_unref(address); if ( r ) { if ( path != NULL ) self->paths_to_unlink = g_list_prepend(self->paths_to_unlink, g_strdup(path)); return; } g_warning("Couldn't add listener for '%s': %s", server_desc, error->message); g_clear_error(&error); if ( need_free_server ) { g_object_unref(self->server); self->server = NULL; } }
/* 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; } }
/** * g_socket_listener_add_any_inet_port: * @listener: a #GSocketListener * @source_object: (allow-none): Optional #GObject identifying this source * @error: a #GError location to store the error occurring, or %NULL to * ignore. * * Listens for TCP connections on any available port number for both * IPv6 and IPv4 (if each is available). * * This is useful if you need to have a socket for incoming connections * but don't care about the specific port number. * * @source_object will be passed out in the various calls * to accept to identify this particular source, which is * useful if you're listening on multiple addresses and do * different things depending on what address is connected to. * * Returns: the port number, or 0 in case of failure. * * Since: 2.24 **/ guint16 g_socket_listener_add_any_inet_port (GSocketListener *listener, GObject *source_object, GError **error) { GSList *sockets_to_close = NULL; guint16 candidate_port = 0; GSocket *socket6 = NULL; GSocket *socket4 = NULL; gint attempts = 37; /* * multi-step process: * - first, create an IPv6 socket. * - if that fails, create an IPv4 socket and bind it to port 0 and * that's it. no retries if that fails (why would it?). * - if our IPv6 socket also speaks IPv4 then we are done. * - if not, then we need to create a IPv4 socket with the same port * number. this might fail, of course. so we try this a bunch of * times -- leaving the old IPv6 sockets open so that we get a * different port number to try each time. * - if all that fails then just give up. */ while (attempts--) { GInetAddress *inet_address; GSocketAddress *address; gboolean result; g_assert (socket6 == NULL); socket6 = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, NULL); if (socket6 != NULL) { inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6); address = g_inet_socket_address_new (inet_address, 0); g_object_unref (inet_address); result = g_socket_bind (socket6, address, TRUE, error); g_object_unref (address); if (!result || !(address = g_socket_get_local_address (socket6, error))) { g_object_unref (socket6); socket6 = NULL; break; } g_assert (G_IS_INET_SOCKET_ADDRESS (address)); candidate_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address)); g_assert (candidate_port != 0); g_object_unref (address); if (g_socket_speaks_ipv4 (socket6)) break; } g_assert (socket4 == NULL); socket4 = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, socket6 ? NULL : error); if (socket4 == NULL) /* IPv4 not supported. * if IPv6 is supported then candidate_port will be non-zero * (and the error parameter above will have been NULL) * if IPv6 is unsupported then candidate_port will be zero * (and error will have been set by the above call) */ break; inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4); address = g_inet_socket_address_new (inet_address, candidate_port); g_object_unref (inet_address); /* a note on the 'error' clause below: * * if candidate_port is 0 then we report the error right away * since it is strange that this binding would fail at all. * otherwise, we ignore the error message (ie: NULL). * * the exception to this rule is the last time through the loop * (ie: attempts == 0) in which case we want to set the error * because failure here means that the entire call will fail and * we need something to show to the user. * * an english summary of the situation: "if we gave a candidate * port number AND we have more attempts to try, then ignore the * error for now". */ result = g_socket_bind (socket4, address, TRUE, (candidate_port && attempts) ? NULL : error); g_object_unref (address); if (candidate_port) { g_assert (socket6 != NULL); if (result) /* got our candidate port successfully */ break; else /* we failed to bind to the specified port. try again. */ { g_object_unref (socket4); socket4 = NULL; /* keep this open so we get a different port number */ sockets_to_close = g_slist_prepend (sockets_to_close, socket6); candidate_port = 0; socket6 = NULL; } } else /* we didn't tell it a port. this means two things. * - if we failed, then something really bad happened. * - if we succeeded, then we need to find out the port number. */ { g_assert (socket6 == NULL); if (!result || !(address = g_socket_get_local_address (socket4, error))) { g_object_unref (socket4); socket4 = NULL; break; } g_assert (G_IS_INET_SOCKET_ADDRESS (address)); candidate_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address)); g_assert (candidate_port != 0); g_object_unref (address); break; } } /* should only be non-zero if we have a socket */ g_assert ((candidate_port != 0) == (socket4 || socket6)); while (sockets_to_close) { g_object_unref (sockets_to_close->data); sockets_to_close = g_slist_delete_link (sockets_to_close, sockets_to_close); } /* now we actually listen() the sockets and add them to the listener */ if (socket6 != NULL) { g_socket_set_listen_backlog (socket6, listener->priv->listen_backlog); if (!g_socket_listen (socket6, error)) { g_object_unref (socket6); if (socket4) g_object_unref (socket4); return 0; } if (source_object) g_object_set_qdata_full (G_OBJECT (socket6), source_quark, g_object_ref (source_object), g_object_unref); g_ptr_array_add (listener->priv->sockets, socket6); } if (socket4 != NULL) { g_socket_set_listen_backlog (socket4, listener->priv->listen_backlog); if (!g_socket_listen (socket4, error)) { g_object_unref (socket4); if (socket6) g_object_unref (socket6); return 0; } if (source_object) g_object_set_qdata_full (G_OBJECT (socket4), source_quark, g_object_ref (source_object), g_object_unref); g_ptr_array_add (listener->priv->sockets, socket4); } if ((socket4 != NULL || socket6 != NULL) && G_SOCKET_LISTENER_GET_CLASS (listener)->changed) G_SOCKET_LISTENER_GET_CLASS (listener)->changed (listener); return candidate_port; }
/* create a socket for sending to remote machine */ static gboolean gst_multiudpsink_start (GstBaseSink * bsink) { GstMultiUDPSink *sink; GList *clients; GstUDPClient *client; GError *err = NULL; sink = GST_MULTIUDPSINK (bsink); sink->external_socket = FALSE; if (sink->socket) { GST_DEBUG_OBJECT (sink, "using configured socket"); if (g_socket_get_family (sink->socket) == G_SOCKET_FAMILY_IPV6) { sink->used_socket_v6 = G_SOCKET (g_object_ref (sink->socket)); sink->external_socket = TRUE; } else { sink->used_socket = G_SOCKET (g_object_ref (sink->socket)); sink->external_socket = TRUE; } } if (sink->socket_v6) { GST_DEBUG_OBJECT (sink, "using configured IPv6 socket"); g_return_val_if_fail (g_socket_get_family (sink->socket) != G_SOCKET_FAMILY_IPV6, FALSE); if (sink->used_socket_v6 && sink->used_socket_v6 != sink->socket_v6) { GST_ERROR_OBJECT (sink, "Provided different IPv6 sockets in socket and socket-v6 properties"); return FALSE; } sink->used_socket_v6 = G_SOCKET (g_object_ref (sink->socket_v6)); sink->external_socket = TRUE; } if (!sink->used_socket && !sink->used_socket_v6) { GSocketAddress *bind_addr; GInetAddress *bind_iaddr; if (sink->bind_address) { GSocketFamily family; bind_iaddr = g_inet_address_new_from_string (sink->bind_address); if (!bind_iaddr) { GList *results; GResolver *resolver; resolver = g_resolver_get_default (); results = g_resolver_lookup_by_name (resolver, sink->bind_address, sink->cancellable, &err); if (!results) { g_object_unref (resolver); goto name_resolve; } bind_iaddr = G_INET_ADDRESS (g_object_ref (results->data)); g_resolver_free_addresses (results); g_object_unref (resolver); } bind_addr = g_inet_socket_address_new (bind_iaddr, sink->bind_port); g_object_unref (bind_iaddr); family = g_socket_address_get_family (G_SOCKET_ADDRESS (bind_addr)); if ((sink->used_socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &err)) == NULL) { g_object_unref (bind_addr); goto no_socket; } g_socket_bind (sink->used_socket, bind_addr, TRUE, &err); if (err != NULL) goto bind_error; } else { /* create sender sockets if none available */ if ((sink->used_socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &err)) == NULL) goto no_socket; bind_iaddr = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4); bind_addr = g_inet_socket_address_new (bind_iaddr, sink->bind_port); g_socket_bind (sink->used_socket, bind_addr, TRUE, &err); g_object_unref (bind_addr); g_object_unref (bind_iaddr); if (err != NULL) goto bind_error; if ((sink->used_socket_v6 = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &err)) == NULL) { GST_INFO_OBJECT (sink, "Failed to create IPv6 socket: %s", err->message); g_clear_error (&err); } else { bind_iaddr = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6); bind_addr = g_inet_socket_address_new (bind_iaddr, sink->bind_port); g_socket_bind (sink->used_socket_v6, bind_addr, TRUE, &err); g_object_unref (bind_addr); g_object_unref (bind_iaddr); if (err != NULL) goto bind_error; } } } #ifdef SO_SNDBUF { socklen_t len; gint sndsize, ret; len = sizeof (sndsize); if (sink->buffer_size != 0) { sndsize = sink->buffer_size; GST_DEBUG_OBJECT (sink, "setting udp buffer of %d bytes", sndsize); /* 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 (sink->used_socket) { ret = setsockopt (g_socket_get_fd (sink->used_socket), SOL_SOCKET, SO_SNDBUF, (void *) &sndsize, len); if (ret != 0) { GST_ELEMENT_WARNING (sink, RESOURCE, SETTINGS, (NULL), ("Could not create a buffer of requested %d bytes, %d: %s", sndsize, ret, g_strerror (errno))); } } if (sink->used_socket_v6) { ret = setsockopt (g_socket_get_fd (sink->used_socket_v6), SOL_SOCKET, SO_SNDBUF, (void *) &sndsize, len); if (ret != 0) { GST_ELEMENT_WARNING (sink, RESOURCE, SETTINGS, (NULL), ("Could not create a buffer of requested %d bytes, %d: %s", sndsize, ret, g_strerror (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) */ if (sink->used_socket) { ret = getsockopt (g_socket_get_fd (sink->used_socket), SOL_SOCKET, SO_SNDBUF, (void *) &sndsize, &len); if (ret == 0) GST_DEBUG_OBJECT (sink, "have UDP buffer of %d bytes", sndsize); else GST_DEBUG_OBJECT (sink, "could not get UDP buffer size"); } if (sink->used_socket_v6) { ret = getsockopt (g_socket_get_fd (sink->used_socket_v6), SOL_SOCKET, SO_SNDBUF, (void *) &sndsize, &len); if (ret == 0) GST_DEBUG_OBJECT (sink, "have UDPv6 buffer of %d bytes", sndsize); else GST_DEBUG_OBJECT (sink, "could not get UDPv6 buffer size"); } } #endif #ifdef SO_BINDTODEVICE if (sink->multi_iface) { if (sink->used_socket) { setsockopt (g_socket_get_fd (sink->used_socket), SOL_SOCKET, SO_BINDTODEVICE, sink->multi_iface, strlen (sink->multi_iface)); } if (sink->used_socket_v6) { setsockopt (g_socket_get_fd (sink->used_socket_v6), SOL_SOCKET, SO_BINDTODEVICE, sink->multi_iface, strlen (sink->multi_iface)); } } #endif if (sink->used_socket) g_socket_set_broadcast (sink->used_socket, TRUE); if (sink->used_socket_v6) g_socket_set_broadcast (sink->used_socket_v6, TRUE); sink->bytes_to_serve = 0; sink->bytes_served = 0; gst_multiudpsink_setup_qos_dscp (sink, sink->used_socket); gst_multiudpsink_setup_qos_dscp (sink, sink->used_socket_v6); /* look for multicast clients and join multicast groups appropriately set also ttl and multicast loopback delivery appropriately */ for (clients = sink->clients; clients; clients = g_list_next (clients)) { client = (GstUDPClient *) clients->data; if (!gst_multiudpsink_configure_client (sink, client)) return FALSE; } return TRUE; /* ERRORS */ no_socket: { GST_ELEMENT_ERROR (sink, RESOURCE, FAILED, (NULL), ("Could not create socket: %s", err->message)); g_clear_error (&err); return FALSE; } bind_error: { GST_ELEMENT_ERROR (sink, RESOURCE, FAILED, (NULL), ("Failed to bind socket: %s", err->message)); g_clear_error (&err); return FALSE; } name_resolve: { GST_ELEMENT_ERROR (sink, RESOURCE, FAILED, (NULL), ("Failed to resolve bind address %s: %s", sink->bind_address, err->message)); g_clear_error (&err); return FALSE; } }
ArvStream * arv_gv_stream_new (GInetAddress *device_address, guint16 port, ArvStreamCallback callback, void *user_data, guint64 timestamp_tick_frequency, guint packet_size) { ArvGvStream *gv_stream; ArvStream *stream; GInetAddress *incoming_inet_address; ArvGvStreamThreadData *thread_data; g_return_val_if_fail (G_IS_INET_ADDRESS (device_address), NULL); g_return_val_if_fail (packet_size > ARV_GVSP_PACKET_PROTOCOL_OVERHEAD, NULL); gv_stream = g_object_new (ARV_TYPE_GV_STREAM, NULL); stream = ARV_STREAM (gv_stream); gv_stream->socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, NULL); incoming_inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4); gv_stream->incoming_address = g_inet_socket_address_new (incoming_inet_address, port); g_object_unref (incoming_inet_address); g_socket_bind (gv_stream->socket, gv_stream->incoming_address, TRUE, NULL); thread_data = g_new (ArvGvStreamThreadData, 1); thread_data->stream = stream; thread_data->callback = callback; thread_data->user_data = user_data; thread_data->socket = gv_stream->socket; thread_data->device_address = g_inet_socket_address_new (device_address, ARV_GVCP_PORT); thread_data->packet_resend = ARV_GV_STREAM_PACKET_RESEND_ALWAYS; thread_data->packet_timeout_us = ARV_GV_STREAM_PACKET_TIMEOUT_US_DEFAULT; thread_data->frame_retention_us = ARV_GV_STREAM_FRAME_RETENTION_US_DEFAULT; thread_data->timestamp_tick_frequency = timestamp_tick_frequency; thread_data->data_size = packet_size - ARV_GVSP_PACKET_PROTOCOL_OVERHEAD; thread_data->cancel = FALSE; thread_data->packet_id = 65300; thread_data->last_frame_id = 0; thread_data->n_completed_buffers = 0; thread_data->n_failures = 0; thread_data->n_underruns = 0; thread_data->n_aborteds = 0; thread_data->n_timeouts = 0; thread_data->n_missing_frames = 0; thread_data->n_size_mismatch_errors = 0; thread_data->n_received_packets = 0; thread_data->n_missing_packets = 0; thread_data->n_error_packets = 0; thread_data->n_ignored_packets = 0; thread_data->n_resent_packets = 0; thread_data->n_resend_requests = 0; thread_data->n_duplicated_packets = 0; thread_data->statistic = arv_statistic_new (1, 5000, 200, 0); thread_data->statistic_count = 0; arv_statistic_set_name (thread_data->statistic, 0, "Buffer reception time"); thread_data->socket_buffer_option = ARV_GV_STREAM_SOCKET_BUFFER_FIXED; thread_data->socket_buffer_size = 0; thread_data->current_socket_buffer_size = 0; gv_stream->thread_data = thread_data; gv_stream->thread = arv_g_thread_new ("arv_gv_stream", arv_gv_stream_thread, gv_stream->thread_data); return ARV_STREAM (gv_stream); }
/** * g_socket_listener_add_inet_port: * @listener: a #GSocketListener * @port: an IP port number (non-zero) * @source_object: (allow-none): Optional #GObject identifying this source * @error: #GError for error reporting, or %NULL to ignore. * * Helper function for g_socket_listener_add_address() that * creates a TCP/IP socket listening on IPv4 and IPv6 (if * supported) on the specified port on all interfaces. * * @source_object will be passed out in the various calls * to accept to identify this particular source, which is * useful if you're listening on multiple addresses and do * different things depending on what address is connected to. * * Returns: %TRUE on success, %FALSE on error. * * Since: 2.22 */ gboolean g_socket_listener_add_inet_port (GSocketListener *listener, guint16 port, GObject *source_object, GError **error) { gboolean need_ipv4_socket = TRUE; GSocket *socket4 = NULL; GSocket *socket6; g_return_val_if_fail (listener != NULL, FALSE); g_return_val_if_fail (port != 0, FALSE); if (!check_listener (listener, error)) return FALSE; /* first try to create an IPv6 socket */ socket6 = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, NULL); if (socket6 != NULL) /* IPv6 is supported on this platform, so if we fail now it is * a result of being unable to bind to our port. Don't fail * silently as a result of this! */ { GInetAddress *inet_address; GSocketAddress *address; gboolean result; inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6); address = g_inet_socket_address_new (inet_address, port); g_object_unref (inet_address); g_socket_set_listen_backlog (socket6, listener->priv->listen_backlog); result = g_socket_bind (socket6, address, TRUE, error) && g_socket_listen (socket6, error); g_object_unref (address); if (!result) { g_object_unref (socket6); return FALSE; } if (source_object) g_object_set_qdata_full (G_OBJECT (socket6), source_quark, g_object_ref (source_object), g_object_unref); /* If this socket already speaks IPv4 then we are done. */ if (g_socket_speaks_ipv4 (socket6)) need_ipv4_socket = FALSE; } if (need_ipv4_socket) /* We are here for exactly one of the following reasons: * * - our platform doesn't support IPv6 * - we successfully created an IPv6 socket but it's V6ONLY * * In either case, we need to go ahead and create an IPv4 socket * and fail the call if we can't bind to it. */ { socket4 = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, error); if (socket4 != NULL) /* IPv4 is supported on this platform, so if we fail now it is * a result of being unable to bind to our port. Don't fail * silently as a result of this! */ { GInetAddress *inet_address; GSocketAddress *address; gboolean result; inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4); address = g_inet_socket_address_new (inet_address, port); g_object_unref (inet_address); g_socket_set_listen_backlog (socket4, listener->priv->listen_backlog); result = g_socket_bind (socket4, address, TRUE, error) && g_socket_listen (socket4, error); g_object_unref (address); if (!result) { g_object_unref (socket4); if (socket6 != NULL) g_object_unref (socket6); return FALSE; } if (source_object) g_object_set_qdata_full (G_OBJECT (socket4), source_quark, g_object_ref (source_object), g_object_unref); } else /* Ok. So IPv4 is not supported on this platform. If we * succeeded at creating an IPv6 socket then that's OK, but * otherwise we need to tell the user we failed. */ { if (socket6 != NULL) g_clear_error (error); else return FALSE; } } g_assert (socket6 != NULL || socket4 != NULL); if (socket6 != NULL) g_ptr_array_add (listener->priv->sockets, socket6); if (socket4 != NULL) g_ptr_array_add (listener->priv->sockets, socket4); if (G_SOCKET_LISTENER_GET_CLASS (listener)->changed) G_SOCKET_LISTENER_GET_CLASS (listener)->changed (listener); return TRUE; }
static VALUE rg_s_new_any(G_GNUC_UNUSED VALUE self, VALUE family) { return GOBJ2RVAL_UNREF(g_inet_address_new_any(RVAL2GSOCKETFAMILY(family))); }
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; } }
/* 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; } }
int main (int argc, char *argv[]) { GSocket *socket, *new_socket, *recv_socket; GSocketAddress *src_address; GSocketAddress *address; GSocketType socket_type; GError *error = NULL; GOptionContext *context; GCancellable *cancellable; g_thread_init (NULL); g_type_init (); context = g_option_context_new (" - Test GSocket server stuff"); g_option_context_add_main_entries (context, cmd_entries, NULL); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_printerr ("%s: %s\n", argv[0], error->message); return 1; } if (cancel_timeout) { cancellable = g_cancellable_new (); g_thread_create (cancel_thread, cancellable, FALSE, NULL); } else { cancellable = NULL; } loop = g_main_loop_new (NULL, FALSE); if (use_udp) socket_type = G_SOCKET_TYPE_DATAGRAM; else socket_type = G_SOCKET_TYPE_STREAM; socket = g_socket_new (G_SOCKET_FAMILY_IPV4, socket_type, 0, &error); if (socket == NULL) { g_printerr ("%s: %s\n", argv[0], error->message); return 1; } if (non_blocking) g_socket_set_blocking (socket, FALSE); src_address = g_inet_socket_address_new (g_inet_address_new_any (G_SOCKET_FAMILY_IPV4), port); if (!g_socket_bind (socket, src_address, !dont_reuse_address, &error)) { g_printerr ("Can't bind socket: %s\n", error->message); return 1; } if (!use_udp) { if (!g_socket_listen (socket, &error)) { g_printerr ("Can't listen on socket: %s\n", error->message); return 1; } g_print ("listening on port %d...\n", port); ensure_condition (socket, "accept", cancellable, G_IO_IN); new_socket = g_socket_accept (socket, &error); if (!new_socket) { g_printerr ("Error accepting socket: %s\n", error->message); return 1; } if (non_blocking) g_socket_set_blocking (new_socket, FALSE); address = g_socket_get_remote_address (new_socket, &error); if (!address) { g_printerr ("Error getting remote address: %s\n", error->message); return 1; } g_print ("got a new connection from %s (blocking: %d)\n", socket_address_to_string (address), g_socket_get_blocking (new_socket)); recv_socket = new_socket; } else { recv_socket = socket; new_socket = NULL; } while (TRUE) { gchar buffer[4096] = { }; gssize size; gsize to_send; ensure_condition (recv_socket, "receive", cancellable, G_IO_IN); if (use_udp) size = g_socket_receive_from (recv_socket, &address, buffer, sizeof buffer, &error); else size = g_socket_receive (recv_socket, buffer, sizeof buffer, &error); if (size < 0) { g_printerr ("Error receiving from socket: %s\n", error->message); return 1; } if (size == 0) break; g_print ("received %" G_GSSIZE_FORMAT " bytes of data", size); if (use_udp) g_print (" from %s", socket_address_to_string (address)); g_print ("\n"); if (verbose) g_print ("-------------------------\n" "%.*s\n" "-------------------------\n", (int)size, buffer); to_send = size; while (to_send > 0) { ensure_condition (recv_socket, "send", cancellable, G_IO_OUT); if (use_udp) size = g_socket_send_to (recv_socket, address, buffer, to_send, &error); else size = g_socket_send (recv_socket, buffer, to_send, &error); if (size < 0) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_print ("socket send would block, handling\n"); g_error_free (error); error = NULL; continue; } else { g_printerr ("Error sending to socket: %s\n", error->message); return 1; } } g_print ("sent %" G_GSSIZE_FORMAT " bytes of data\n", size); if (size == 0) { g_printerr ("Unexpected short write\n"); return 1; } to_send -= size; } } g_print ("connection closed\n"); if (new_socket) { if (!g_socket_close (new_socket, &error)) { g_printerr ("Error closing connection socket: %s\n", error->message); return 1; } g_object_unref (G_OBJECT (new_socket)); } if (!g_socket_close (socket, &error)) { g_printerr ("Error closing master socket: %s\n", error->message); return 1; } g_object_unref (G_OBJECT (socket)); return 0; }
int main(int argc, char **argv) { int i; //Get process id ProcessID= getpid(); // default password AppPass = defaultAppPass; // try environment variable first, set to default if failed IvyBus = getenv("IVYBUS"); if (IvyBus == NULL) IvyBus = defaultIvyBus; // Parse options for (i = 1; i < argc; ++i) { if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { print_help(); exit(0); } else if (strcmp(argv[i], "-t") == 0) { tcp_port = atoi(argv[++i]); } else if (strcmp(argv[i], "-u") == 0) { udp_port = atoi(argv[++i]); } else if (strcmp(argv[i], "-b") == 0) { IvyBus = argv[++i]; } else if (strcmp(argv[i], "-p") == 0) { AppPass = argv[++i]; } else if (strcmp(argv[i], "-v") == 0) { verbose = 1; } else if (strcmp(argv[i], "-utcp") == 0) { uTCP = 1; } else { printf("App Server: Unknown option\n"); print_help(); exit(0); } } if (verbose) { printf("### Paparazzi App Server ###\n"); printf("Server listen port (TCP) : %d\n", tcp_port); if (uTCP) { printf("Server using TCP communication..\n"); }else{ printf("Server broadcast port (UDP) : %d\n", udp_port); } printf("Control Pass : %s\n", AppPass); printf("Ivy Bus : %s\n", IvyBus); fflush(stdout); } //Create tcp listener #if !GLIB_CHECK_VERSION (2, 35, 1) // init GLib type system (only for older version) g_type_init(); #endif GSocketService *service = g_socket_service_new(); GInetAddress *address = g_inet_address_new_any(G_SOCKET_FAMILY_IPV6); //G_SOCKET_FAMILY_IPV4 could be used GSocketAddress *socket_address = g_inet_socket_address_new(address, tcp_port); //Add listener g_socket_listener_add_address(G_SOCKET_LISTENER(service), socket_address, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL, NULL, NULL); g_object_unref(socket_address); g_object_unref(address); g_socket_service_start(service); //Connect listening signal g_signal_connect(service, "incoming", G_CALLBACK(new_connection), NULL); //Here comes the ivy bindings IvyInit ("PPRZ_App_Server", "Papparazzi App Server Ready!", NULL, NULL, NULL, NULL); IvyBindMsg(Ivy_All_Msgs, NULL, "(^ground (\\S*) (\\S*) .*)"); IvyBindMsg(on_app_server_NEW_AC, NULL, "ground NEW_AIRCRAFT (\\S*)"); IvyBindMsg(on_app_server_GET_CONFIG, NULL, "(\\S*) ground CONFIG (\\S*) (\\S*) (\\S*) (\\S*) (\\S*) (\\S*) (\\S*)"); IvyBindMsg(on_app_server_AIRCRAFTS, NULL, "(\\S*) ground AIRCRAFTS (\\S*)"); IvyStart(IvyBus); GMainLoop *loop = g_main_loop_new(NULL, FALSE); if (verbose) { printf("Starting App Server\n"); fflush(stdout); } IvySendMsg("app_server"); g_timeout_add(100, request_ac_list, NULL); g_main_loop_run(loop); if (verbose) { printf("Stoping App Server\n"); fflush(stdout); } return 0; }
int main(int argc, char **argv) { int i; // default password AppPass = defaultAppPass; // try environment variable first, set to default if failed IvyBus = getenv("IVYBUS"); if (IvyBus == NULL) IvyBus = defaultIvyBus; // Look for paparazzi folder (PAPARAZZI_HOME or assume local path by default) char* PprzFolder = getenv("PAPARAZZI_HOME"); if (PprzFolder == NULL) PprzFolder = defaultPprzFolder; // Parse options for (i = 1; i < argc; ++i) { if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { print_help(); exit(0); } else if (strcmp(argv[i], "-t") == 0) { tcp_port = atoi(argv[++i]); } else if (strcmp(argv[i], "-u") == 0) { udp_port = atoi(argv[++i]); } else if (strcmp(argv[i], "-b") == 0) { IvyBus = argv[++i]; } else if (strcmp(argv[i], "-p") == 0) { AppPass = argv[++i]; } else if (strcmp(argv[i], "-v") == 0) { verbose = 1; } else { printf("App Server: Unknown option\n"); print_help(); exit(0); } } if (verbose) { printf("### Paparazzi App Server ###\n"); printf("Using Paparazzi Folder : %s\n", PprzFolder); printf("Server listen port (TCP) : %d\n", tcp_port); printf("Server broadcast port (UDP) : %d\n", udp_port); printf("Control Pass : %s\n", AppPass); printf("Ivy Bus : %s\n", IvyBus); fflush(stdout); } //Parse conf.xml parse_ac_data(PprzFolder); //Create tcp listener #if !GLIB_CHECK_VERSION (2, 35, 1) // init GLib type system (only for older version) g_type_init(); #endif GSocketService *service = g_socket_service_new(); GInetAddress *address = g_inet_address_new_any(G_SOCKET_FAMILY_IPV6); //G_SOCKET_FAMILY_IPV4 could be used GSocketAddress *socket_address = g_inet_socket_address_new(address, tcp_port); //Add listener g_socket_listener_add_address(G_SOCKET_LISTENER(service), socket_address, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL, NULL, NULL); g_object_unref(socket_address); g_object_unref(address); g_socket_service_start(service); //Connect listening signal g_signal_connect(service, "incoming", G_CALLBACK(new_connection), NULL); //Here comes the ivy bindings IvyInit ("PPRZ_App_Server", "Papparazzi App Server Ready", NULL, NULL, NULL, NULL); IvyBindMsg(Ivy_All_Msgs, NULL, "(^ground .*)"); IvyBindMsg(Ivy_All_Msgs, NULL, "(^\\S* AIRSPEED (\\S*) (\\S*) (\\S*) (\\S*))"); IvyStart(IvyBus); GMainLoop *loop = g_main_loop_new(NULL, FALSE); if (verbose) { printf("Starting App Server\n"); fflush(stdout); } g_main_loop_run(loop); if (verbose) { printf("Stoping App Server\n"); fflush(stdout); } return 0; }
/* 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; } }