KmsSCTPResult kms_sctp_connection_bind (KmsSCTPConnection * conn, GCancellable * cancellable, GError ** err) { gint bound_port; g_return_val_if_fail (conn != NULL, KMS_SCTP_ERROR); g_return_val_if_fail (conn->socket != NULL, KMS_SCTP_ERROR); g_return_val_if_fail (conn->saddr != NULL, KMS_SCTP_ERROR); /* bind it */ GST_DEBUG ("binding server socket"); if (!g_socket_bind (conn->socket, conn->saddr, TRUE, err)) return KMS_SCTP_ERROR; g_socket_set_listen_backlog (conn->socket, SCTP_BACKLOG); if (!g_socket_listen (conn->socket, err)) return KMS_SCTP_ERROR; bound_port = kms_sctp_connection_get_bound_port (conn); if (bound_port > 0) { GST_DEBUG ("listening on port %d", bound_port); } return KMS_SCTP_OK; }
/** * g_socket_listener_add_address: * @listener: a #GSocketListener * @address: a #GSocketAddress * @type: a #GSocketType * @protocol: a #GSocketProtocol * @source_object: (allow-none): Optional #GObject identifying this source * @effective_address: (out) (allow-none): location to store the address that was bound to, or %NULL. * @error: #GError for error reporting, or %NULL to ignore. * * Creates a socket of type @type and protocol @protocol, binds * it to @address and adds it to the set of sockets we're accepting * sockets from. * * Note that adding an IPv6 address, depending on the platform, * may or may not result in a listener that also accepts IPv4 * connections. For more deterministic behavior, see * g_socket_listener_add_inet_port(). * * @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. * * If successful and @effective_address is non-%NULL then it will * be set to the address that the binding actually occurred at. This * is helpful for determining the port number that was used for when * requesting a binding to port 0 (ie: "any port"). This address, if * requested, belongs to the caller and must be freed. * * Returns: %TRUE on success, %FALSE on error. * * Since: 2.22 */ gboolean g_socket_listener_add_address (GSocketListener *listener, GSocketAddress *address, GSocketType type, GSocketProtocol protocol, GObject *source_object, GSocketAddress **effective_address, GError **error) { GSocketAddress *local_address; GSocketFamily family; GSocket *socket; if (!check_listener (listener, error)) return FALSE; family = g_socket_address_get_family (address); socket = g_socket_new (family, type, protocol, error); if (socket == NULL) return FALSE; g_socket_set_listen_backlog (socket, listener->priv->listen_backlog); if (!g_socket_bind (socket, address, TRUE, error) || !g_socket_listen (socket, error)) { g_object_unref (socket); return FALSE; } local_address = NULL; if (effective_address) { local_address = g_socket_get_local_address (socket, error); if (local_address == NULL) { g_object_unref (socket); return FALSE; } } if (!g_socket_listener_add_socket (listener, socket, source_object, error)) { if (local_address) g_object_unref (local_address); g_object_unref (socket); return FALSE; } if (effective_address) *effective_address = local_address; g_object_unref (socket); /* add_socket refs this */ return TRUE; }
/** * g_socket_listener_set_backlog: * @listener: a #GSocketListener * @listen_backlog: an integer * * Sets the listen backlog on the sockets in the listener. * * See g_socket_set_listen_backlog() for details * * Since: 2.22 */ void g_socket_listener_set_backlog (GSocketListener *listener, int listen_backlog) { GSocket *socket; int i; if (listener->priv->closed) return; listener->priv->listen_backlog = listen_backlog; for (i = 0; i < listener->priv->sockets->len; i++) { socket = listener->priv->sockets->pdata[i]; g_socket_set_listen_backlog (socket, listen_backlog); } }
static GSocket * gst_switch_server_listen (GstSwitchServer *srv, gint port, gint *bound_port) { GError *err = NULL; GInetAddress *addr; GSocket *socket = NULL; GSocketAddress *saddr; GResolver *resolver; gchar *ip; *bound_port = 0; /* look up name if we need to */ addr = g_inet_address_new_from_string (srv->host); if (!addr) { GList *results; resolver = g_resolver_get_default (); results = g_resolver_lookup_by_name (resolver, srv->host, srv->cancellable, &err); if (!results) goto resolve_no_name; addr = G_INET_ADDRESS (g_object_ref (results->data)); g_resolver_free_addresses (results); g_object_unref (resolver); } ip = g_inet_address_to_string (addr); saddr = g_inet_socket_address_new (addr, port); g_object_unref (addr); /* create the server listener socket */ socket = g_socket_new (g_socket_address_get_family (saddr), G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, &err); if (!socket) goto socket_new_failed; /* bind it */ if (!g_socket_bind (socket, saddr, TRUE, &err)) goto socket_bind_failed; g_object_unref (saddr); /* listen on the socket */ g_socket_set_listen_backlog (socket, GST_SWITCH_SERVER_LISTEN_BACKLOG); if (!g_socket_listen (socket, &err)) goto socket_listen_failed; if (port == 0) { saddr = g_socket_get_local_address (socket, NULL); *bound_port = g_inet_socket_address_get_port ((GInetSocketAddress *) saddr); g_object_unref (saddr); } else { *bound_port = port; } INFO ("Listening on %s (%s:%d)", srv->host, ip, *bound_port); g_free (ip); //g_atomic_int_set (&srv->bound_port, bound_port); //g_object_notify (G_OBJECT (src), "bound-port"); return socket; /* Errors Handling */ resolve_no_name: { ERROR ("resolve: %s", err->message); g_object_unref (resolver); g_object_unref (addr); return NULL; } socket_new_failed: { ERROR ("new socket: %s", err->message); g_clear_error (&err); g_object_unref (saddr); g_free (ip); return NULL; } socket_bind_failed: { ERROR ("bind socket: %s", err->message); g_clear_error (&err); g_object_unref (saddr); g_free (ip); return NULL; } socket_listen_failed: { ERROR ("listen socket: %s", err->message); g_clear_error (&err); g_object_unref (saddr); g_free (ip); return NULL; } }
static gboolean gst_tcp_mix_src_listen (GstTCPMixSrc * src, GstTCPMixSrcPad * pad) { GError *err = NULL; GInetAddress *addr; GSocketAddress *saddr; GResolver *resolver; gint bound_port = 0; gchar *ip; /* look up name if we need to */ addr = g_inet_address_new_from_string (src->host); if (!addr) { GList *results; resolver = g_resolver_get_default (); results = g_resolver_lookup_by_name (resolver, src->host, src->cancellable, &err); if (!results) goto resolve_no_name; addr = G_INET_ADDRESS (g_object_ref (results->data)); g_resolver_free_addresses (results); g_object_unref (resolver); } /* get IP address */ ip = g_inet_address_to_string (addr); saddr = g_inet_socket_address_new (addr, src->server_port); g_object_unref (addr); /* create the server listener socket */ src->server_socket = g_socket_new (g_socket_address_get_family (saddr), G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, &err); if (!src->server_socket) goto socket_new_failed; /* bind it */ if (!g_socket_bind (src->server_socket, saddr, TRUE, &err)) goto socket_bind_failed; g_object_unref (saddr); g_socket_set_listen_backlog (src->server_socket, TCP_BACKLOG); if (!g_socket_listen (src->server_socket, &err)) goto socket_listen_failed; GST_OBJECT_FLAG_SET (src, GST_TCP_MIX_SRC_OPEN); if (src->server_port == 0) { saddr = g_socket_get_local_address (src->server_socket, NULL); bound_port = g_inet_socket_address_get_port ((GInetSocketAddress *) saddr); g_object_unref (saddr); } else { bound_port = src->server_port; } GST_DEBUG_OBJECT (src, "Listening on %s (%s:%d)", src->host, ip, bound_port); g_free (ip); g_atomic_int_set (&src->bound_port, bound_port); g_object_notify (G_OBJECT (src), "bound-port"); return TRUE; /* Handling Errors */ resolve_no_name: { if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { GST_DEBUG_OBJECT (src, "Cancelled name resolval"); } else { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Failed to resolve host '%s': %s", src->host, err->message)); } g_clear_error (&err); g_object_unref (resolver); return FALSE; } socket_new_failed: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Failed to create socket: %s", err->message)); g_clear_error (&err); g_object_unref (saddr); return FALSE; } socket_bind_failed: { if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { GST_DEBUG_OBJECT (src, "Cancelled binding"); } else { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Failed to bind on host '%s:%d': %s", src->host, src->server_port, err->message)); } g_clear_error (&err); g_object_unref (saddr); gst_tcp_mix_src_stop (src, pad); return FALSE; } socket_listen_failed: { if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { GST_DEBUG_OBJECT (src, "Cancelled listening"); } else { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Failed to listen on host '%s:%d': %s", src->host, src->server_port, err->message)); } g_clear_error (&err); gst_tcp_mix_src_stop (src, pad); 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; }
/** * 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; }
/* set up server */ static gboolean gst_tcp_server_src_start (GstBaseSrc * bsrc) { GstTCPServerSrc *src = GST_TCP_SERVER_SRC (bsrc); GError *err = NULL; GInetAddress *addr; GSocketAddress *saddr; GResolver *resolver; /* look up name if we need to */ addr = g_inet_address_new_from_string (src->host); if (!addr) { GList *results; 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 saddr = g_inet_socket_address_new (addr, src->server_port); g_object_unref (addr); /* create the server listener socket */ src->server_socket = g_socket_new (g_socket_address_get_family (saddr), G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, &err); if (!src->server_socket) goto no_socket; GST_DEBUG_OBJECT (src, "opened receiving server socket"); /* bind it */ GST_DEBUG_OBJECT (src, "binding server socket to address"); if (!g_socket_bind (src->server_socket, saddr, TRUE, &err)) goto bind_failed; g_object_unref (saddr); GST_DEBUG_OBJECT (src, "listening on server socket"); g_socket_set_listen_backlog (src->server_socket, TCP_BACKLOG); if (!g_socket_listen (src->server_socket, &err)) goto listen_failed; GST_OBJECT_FLAG_SET (src, GST_TCP_SERVER_SRC_OPEN); return TRUE; /* ERRORS */ no_socket: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Failed to create socket: %s", err->message)); g_clear_error (&err); g_object_unref (saddr); return FALSE; } name_resolve: { if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { GST_DEBUG_OBJECT (src, "Cancelled name resolval"); } else { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Failed to resolve host '%s': %s", src->host, err->message)); } g_clear_error (&err); g_object_unref (resolver); return FALSE; } bind_failed: { if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { GST_DEBUG_OBJECT (src, "Cancelled binding"); } else { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Failed to bind on host '%s:%d': %s", src->host, src->server_port, err->message)); } g_clear_error (&err); g_object_unref (saddr); gst_tcp_server_src_stop (GST_BASE_SRC (src)); return FALSE; } listen_failed: { if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { GST_DEBUG_OBJECT (src, "Cancelled listening"); } else { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Failed to listen on host '%s:%d': %s", src->host, src->server_port, err->message)); } g_clear_error (&err); gst_tcp_server_src_stop (GST_BASE_SRC (src)); return FALSE; } }