gboolean _g_inet_socket_address_is_equal (GInetSocketAddress *a, GInetSocketAddress *b) { GInetAddress *a_addr; GInetAddress *b_addr; char *a_str; char *b_str; gboolean result; if (!G_IS_INET_SOCKET_ADDRESS (a) || !G_IS_INET_SOCKET_ADDRESS (b)) return FALSE; if (g_inet_socket_address_get_port (a) != g_inet_socket_address_get_port (b)) return FALSE; a_addr = g_inet_socket_address_get_address (a); b_addr = g_inet_socket_address_get_address (b); a_str = g_inet_address_to_string (a_addr); b_str = g_inet_address_to_string (b_addr); /* TODO: find a better way to do inet address comparison */ result = g_strcmp0 (a_str, b_str) == 0; g_free (a_str); g_free (b_str); return result; }
static gchar * get_remote_address (GIOStream *io) { GSocketAddress *remote = NULL; GSocketConnection *connection = NULL; GIOStream *base; gchar *result = NULL; if (G_IS_TLS_CONNECTION (io)) { g_object_get (io, "base-io-stream", &base, NULL); if (G_IS_SOCKET_CONNECTION (base)) connection = g_object_ref (base); g_object_unref (base); } else if (G_IS_SOCKET_CONNECTION (io)) { connection = g_object_ref (io); } if (connection) remote = g_socket_connection_get_remote_address (connection, NULL); if (remote && G_IS_INET_SOCKET_ADDRESS (remote)) result = g_inet_address_to_string (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (remote))); if (remote) g_object_unref (remote); if (connection) g_object_unref (connection); return result; }
static void print_connectable_sockaddr (GSocketAddress *sockaddr, GError *error) { char *phys; if (error) { printf ("Error: %s\n", error->message); g_error_free (error); } else if (!G_IS_INET_SOCKET_ADDRESS (sockaddr)) { printf ("Error: Unexpected sockaddr type '%s'\n", g_type_name_from_instance ((GTypeInstance *)sockaddr)); g_object_unref (sockaddr); } else { GInetSocketAddress *isa = G_INET_SOCKET_ADDRESS (sockaddr); phys = g_inet_address_to_string (g_inet_socket_address_get_address (isa)); printf ("Address: %s%s%s:%d\n", strchr (phys, ':') ? "[" : "", phys, strchr (phys, ':') ? "]" : "", g_inet_socket_address_get_port (isa)); g_free (phys); g_object_unref (sockaddr); } }
static void do_lookup_by_name (GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable) { const char *hostname = task_data; struct addrinfo *res = NULL; GList *addresses; gint retval; retval = getaddrinfo (hostname, NULL, &addrinfo_hints, &res); if (retval == 0) { struct addrinfo *ai; GSocketAddress *sockaddr; GInetAddress *addr; addresses = NULL; for (ai = res; ai; ai = ai->ai_next) { sockaddr = g_socket_address_new_from_native (ai->ai_addr, ai->ai_addrlen); if (!sockaddr || !G_IS_INET_SOCKET_ADDRESS (sockaddr)) continue; addr = g_object_ref (g_inet_socket_address_get_address ((GInetSocketAddress *)sockaddr)); addresses = g_list_prepend (addresses, addr); g_object_unref (sockaddr); } if (addresses != NULL) { addresses = g_list_reverse (addresses); g_task_return_pointer (task, addresses, (GDestroyNotify)g_resolver_free_addresses); } else { /* All addresses failed to be converted to GSocketAddresses. */ g_task_return_new_error (task, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, _("Error resolving '%s': %s"), hostname, _("No valid addresses were found")); } } else { g_task_return_new_error (task, G_RESOLVER_ERROR, g_resolver_error_from_addrinfo_error (retval), _("Error resolving '%s': %s"), hostname, gai_strerror (retval)); } if (res) freeaddrinfo (res); }
static char * socket_address_to_string (GSocketAddress *address) { char *res = NULL; if (G_IS_INET_SOCKET_ADDRESS (address)) { GInetAddress *inet_address; char *str; int port; inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address)); str = g_inet_address_to_string (inet_address); port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address)); res = g_strdup_printf ("%s:%d", str, port); g_free (str); } #ifdef G_OS_UNIX else if (G_IS_UNIX_SOCKET_ADDRESS (address)) { GUnixSocketAddress *uaddr = G_UNIX_SOCKET_ADDRESS (address); res = g_strdup_printf ("%s:%s", unix_socket_address_types[g_unix_socket_address_get_address_type (uaddr)], g_unix_socket_address_get_path (uaddr)); } #endif return res; }
static void print_proxy_address (GSocketAddress *sockaddr) { GProxyAddress *proxy = NULL; if (sockaddr == NULL) { printf ("\tdirect://\n"); return; } if (G_IS_PROXY_ADDRESS (sockaddr)) { proxy = G_PROXY_ADDRESS (sockaddr); printf ("\t%s://", g_proxy_address_get_protocol(proxy)); } else { printf ("\tdirect://"); } if (G_IS_INET_SOCKET_ADDRESS (sockaddr)) { GInetAddress *inetaddr; guint port; gchar *addr; g_object_get (sockaddr, "address", &inetaddr, "port", &port, NULL); addr = g_inet_address_to_string (inetaddr); printf ("%s:%u", addr, port); g_free (addr); } if (proxy) { if (g_proxy_address_get_username(proxy)) printf (" (Username: %s Password: %s)", g_proxy_address_get_username(proxy), g_proxy_address_get_password(proxy)); printf (" (Hostname: %s, Port: %i)", g_proxy_address_get_destination_hostname (proxy), g_proxy_address_get_destination_port (proxy)); } printf ("\n"); }
static void g_tls_client_connection_gnutls_constructed (GObject *object) { GTlsClientConnectionGnutls *gnutls = G_TLS_CLIENT_CONNECTION_GNUTLS (object); GSocketConnection *base_conn; GSocketAddress *remote_addr; GInetAddress *iaddr; guint port; /* Create a TLS session ID. We base it on the IP address since * different hosts serving the same hostname/service will probably * not share the same session cache. We base it on the * server-identity because at least some servers will fail (rather * than just failing to resume the session) if we don't. * (https://bugs.launchpad.net/bugs/823325) */ g_object_get (G_OBJECT (gnutls), "base-io-stream", &base_conn, NULL); if (G_IS_SOCKET_CONNECTION (base_conn)) { remote_addr = g_socket_connection_get_remote_address (base_conn, NULL); if (G_IS_INET_SOCKET_ADDRESS (remote_addr)) { GInetSocketAddress *isaddr = G_INET_SOCKET_ADDRESS (remote_addr); const gchar *server_hostname; gchar *addrstr, *session_id; iaddr = g_inet_socket_address_get_address (isaddr); port = g_inet_socket_address_get_port (isaddr); addrstr = g_inet_address_to_string (iaddr); server_hostname = get_server_identity (gnutls); session_id = g_strdup_printf ("%s/%s/%d", addrstr, server_hostname ? server_hostname : "", port); gnutls->priv->session_id = g_bytes_new_take (session_id, strlen (session_id)); g_free (addrstr); } g_object_unref (remote_addr); } g_object_unref (base_conn); if (G_OBJECT_CLASS (g_tls_client_connection_gnutls_parent_class)->constructed) G_OBJECT_CLASS (g_tls_client_connection_gnutls_parent_class)->constructed (object); }
/** * g_vfs_ftp_connection_listen_data_connection: * @conn: a connection * @error: %NULL or location to take potential errors * * Initiates a listening socket that the FTP server can connect to. To accept * connections and initialize data transfers, use * g_vfs_ftp_connection_accept_data_connection(). * This function supports what is known as "active FTP", while * g_vfs_ftp_connection_open_data_connection() is to be used for "passive FTP". * * Returns: the actual address the socket is listening on or %NULL on error **/ GSocketAddress * g_vfs_ftp_connection_listen_data_connection (GVfsFtpConnection *conn, GError ** error) { GSocketAddress *local, *addr; g_return_val_if_fail (conn != NULL, NULL); g_return_val_if_fail (conn->data == NULL, NULL); g_vfs_ftp_connection_stop_listening (conn); local = g_socket_connection_get_local_address (conn->connection, error); if (local == NULL) return NULL; conn->listen_socket = g_socket_new (g_socket_address_get_family (local), G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, error); if (conn->listen_socket == NULL) return NULL; g_assert (G_IS_INET_SOCKET_ADDRESS (local)); addr = g_inet_socket_address_new (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (local)), 0); g_object_unref (local); if (!g_socket_bind (conn->listen_socket, addr, TRUE, error) || !g_socket_listen (conn->listen_socket, error) || !(local = g_socket_get_local_address (conn->listen_socket, error))) { g_object_unref (addr); g_vfs_ftp_connection_stop_listening (conn); return NULL; } g_object_unref (addr); return local; }
static void on_socket_client_event (GSocketClient *client, GSocketClientEvent event, GSocketConnectable *connectable, GIOStream *connection, gpointer user_data) { HotSshTab *self = HOTSSH_TAB (user_data); HotSshTabPrivate *priv = hotssh_tab_get_instance_private (self); switch (event) { case G_SOCKET_CLIENT_RESOLVING: set_status_printf (self, _("Resolving '%s'…"), priv->hostname); break; case G_SOCKET_CLIENT_CONNECTING: { GSocketConnection *socketconn = G_SOCKET_CONNECTION (connection); gs_unref_object GSocketAddress *remote_address = g_socket_connection_get_remote_address (socketconn, NULL); g_debug ("socket connecting remote=%p", remote_address); if (remote_address && G_IS_INET_SOCKET_ADDRESS (remote_address)) { GInetAddress *inetaddr = g_inet_socket_address_get_address ((GInetSocketAddress*)remote_address); gs_free char *inet_str = g_inet_address_to_string (inetaddr); set_status_printf (self, _("Connecting to '%s'…"), inet_str); } break; } default: break; } }
static gboolean on_socket_input (GSocket *socket, GIOCondition condition, gpointer user_data) { CockpitRequest *request = user_data; guchar first_byte; GInputVector vector[1] = { { &first_byte, 1 } }; gint flags = G_SOCKET_MSG_PEEK; gboolean redirect_tls; gboolean is_tls; GSocketAddress *addr; GInetAddress *inet; GError *error = NULL; GIOStream *tls_stream; gssize num_read; num_read = g_socket_receive_message (socket, NULL, /* out GSocketAddress */ vector, 1, NULL, /* out GSocketControlMessage */ NULL, /* out num_messages */ &flags, NULL, /* GCancellable* */ &error); if (num_read < 0) { /* Just wait and try again */ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_error_free (error); return TRUE; } if (!should_suppress_request_error (error)) g_warning ("couldn't read from socket: %s", error->message); cockpit_request_finish (request); g_error_free (error); return FALSE; } is_tls = TRUE; redirect_tls = FALSE; /* * TLS streams are guaranteed to start with octet 22.. this way we can distinguish them * from regular HTTP requests */ if (first_byte != 22 && first_byte != 0x80) { is_tls = FALSE; redirect_tls = TRUE; addr = g_socket_connection_get_remote_address (G_SOCKET_CONNECTION (request->io), NULL); if (G_IS_INET_SOCKET_ADDRESS (addr)) { inet = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr)); redirect_tls = !g_inet_address_get_is_loopback (inet); } g_clear_object (&addr); } if (is_tls) { tls_stream = g_tls_server_connection_new (request->io, request->web_server->certificate, &error); if (tls_stream == NULL) { g_warning ("couldn't create new TLS stream: %s", error->message); cockpit_request_finish (request); g_error_free (error); return FALSE; } g_object_unref (request->io); request->io = G_IO_STREAM (tls_stream); } else if (redirect_tls) { request->delayed_reply = 301; } start_request_input (request); /* No longer run *this* source */ return FALSE; }
static gboolean run (int argc, char **argv, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; g_autoptr(GOptionContext) context = NULL; const char *dirpath; OtTrivialHttpd appstruct = { 0, }; OtTrivialHttpd *app = &appstruct; glnx_unref_object SoupServer *server = NULL; g_autoptr(GFileMonitor) dirmon = NULL; context = g_option_context_new ("[DIR] - Simple webserver"); g_option_context_add_main_entries (context, options, NULL); app->root_dfd = -1; if (!g_option_context_parse (context, &argc, &argv, error)) goto out; if (argc > 1) dirpath = argv[1]; else dirpath = "."; if (!glnx_opendirat (AT_FDCWD, dirpath, TRUE, &app->root_dfd, error)) goto out; if (!(opt_random_500s_percentage >= 0 && opt_random_500s_percentage <= 99)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid --random-500s=%u", opt_random_500s_percentage); goto out; } if (opt_log) { GOutputStream *stream = NULL; if (g_strcmp0 (opt_log, "-") == 0) { if (opt_daemonize) { ot_util_usage_error (context, "Cannot use --log-file=- and --daemonize at the same time", error); goto out; } stream = G_OUTPUT_STREAM (g_unix_output_stream_new (STDOUT_FILENO, FALSE)); } else { g_autoptr(GFile) log_file = NULL; GFileOutputStream* log_stream; log_file = g_file_new_for_path (opt_log); log_stream = g_file_create (log_file, G_FILE_CREATE_PRIVATE, cancellable, error); if (!log_stream) goto out; stream = G_OUTPUT_STREAM (log_stream); } app->log = stream; } #if SOUP_CHECK_VERSION(2, 48, 0) server = soup_server_new (SOUP_SERVER_SERVER_HEADER, "ostree-httpd ", NULL); if (!soup_server_listen_all (server, opt_port, 0, error)) goto out; #else server = soup_server_new (SOUP_SERVER_PORT, opt_port, SOUP_SERVER_SERVER_HEADER, "ostree-httpd ", NULL); #endif soup_server_add_handler (server, NULL, httpd_callback, app, NULL); if (opt_port_file) { g_autofree char *portstr = NULL; #if SOUP_CHECK_VERSION(2, 48, 0) GSList *listeners = soup_server_get_listeners (server); g_autoptr(GSocket) listener = NULL; g_autoptr(GSocketAddress) addr = NULL; g_assert (listeners); listener = g_object_ref (listeners->data); g_slist_free (listeners); listeners = NULL; addr = g_socket_get_local_address (listener, error); if (!addr) goto out; g_assert (G_IS_INET_SOCKET_ADDRESS (addr)); portstr = g_strdup_printf ("%u\n", g_inet_socket_address_get_port ((GInetSocketAddress*)addr)); #else portstr = g_strdup_printf ("%u\n", soup_server_get_port (server)); #endif if (g_strcmp0 ("-", opt_port_file) == 0) { fputs (portstr, stdout); // not g_print - this must go to stdout, not a handler fflush (stdout); } else if (!g_file_set_contents (opt_port_file, portstr, strlen (portstr), error)) goto out; } #if !SOUP_CHECK_VERSION(2, 48, 0) soup_server_run_async (server); #endif if (opt_daemonize) { pid_t pid = fork(); if (pid == -1) { int errsv = errno; g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errsv), g_strerror (errsv)); goto out; } else if (pid > 0) { ret = TRUE; goto out; } /* Child, continue */ if (setsid () < 0) err (1, "setsid"); /* Daemonising: close stdout/stderr so $() et al work on us */ if (freopen("/dev/null", "r", stdin) == NULL) err (1, "freopen"); if (freopen("/dev/null", "w", stdout) == NULL) err (1, "freopen"); if (freopen("/dev/null", "w", stderr) == NULL) err (1, "freopen"); } else { /* Since we're used for testing purposes, let's just do this by * default. This ensures we exit when our parent does. */ if (prctl (PR_SET_PDEATHSIG, SIGTERM) != 0) { if (errno != ENOSYS) { glnx_set_error_from_errno (error); goto out; } } } app->running = TRUE; if (opt_autoexit) { gboolean is_symlink = FALSE; g_autoptr(GFile) root = NULL; g_autoptr(GFileInfo) info = NULL; root = g_file_new_for_path (dirpath); info = g_file_query_info (root, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error); if (!info) goto out; is_symlink = g_file_info_get_is_symlink (info); if (is_symlink) dirmon = g_file_monitor_file (root, 0, cancellable, error); else dirmon = g_file_monitor_directory (root, 0, cancellable, error); if (!dirmon) goto out; g_signal_connect (dirmon, "changed", G_CALLBACK (on_dir_changed), app); } httpd_log (app, "serving at root %s\n", dirpath); while (app->running) g_main_context_iteration (NULL, TRUE); ret = TRUE; out: if (app->root_dfd != -1) (void) close (app->root_dfd); g_clear_object (&app->log); return ret; }
/** * 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; }
static void return_result (GTask *task) { GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task); GSocketAddress *result; if (strcmp ("direct", priv->proxy_type) == 0) { result = priv->proxy_address; priv->proxy_address = NULL; } else { gchar *dest_hostname, *dest_protocol; GInetSocketAddress *inetsaddr; GInetAddress *inetaddr; guint16 port; if (!priv->supports_hostname) { GInetAddress *dest_ip; if (!priv->next_dest_ip) priv->next_dest_ip = priv->dest_ips; dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data); dest_hostname = g_inet_address_to_string (dest_ip); priv->next_dest_ip = g_list_next (priv->next_dest_ip); } else { dest_hostname = g_strdup (priv->dest_hostname); } dest_protocol = g_uri_parse_scheme (priv->dest_uri); g_return_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address)); inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address); inetaddr = g_inet_socket_address_get_address (inetsaddr); port = g_inet_socket_address_get_port (inetsaddr); result = g_object_new (G_TYPE_PROXY_ADDRESS, "address", inetaddr, "port", port, "protocol", priv->proxy_type, "destination-protocol", dest_protocol, "destination-hostname", dest_hostname, "destination-port", priv->dest_port, "username", priv->proxy_username, "password", priv->proxy_password, "uri", priv->proxy_uri, NULL); g_free (dest_hostname); g_free (dest_protocol); if (priv->supports_hostname || priv->next_dest_ip == NULL) { g_object_unref (priv->proxy_address); priv->proxy_address = NULL; } } g_task_return_pointer (task, result, g_object_unref); g_object_unref (task); }
static GSocketAddress * g_proxy_address_enumerator_next (GSocketAddressEnumerator *enumerator, GCancellable *cancellable, GError **error) { GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator); GSocketAddress *result = NULL; GError *first_error = NULL; if (priv->proxies == NULL) { GProxyResolver *resolver = g_proxy_resolver_get_default (); priv->proxies = g_proxy_resolver_lookup (resolver, priv->dest_uri, cancellable, error); priv->next_proxy = priv->proxies; if (priv->proxies == NULL) return NULL; } while (result == NULL && (*priv->next_proxy || priv->addr_enum)) { gchar *dest_hostname; gchar *dest_protocol; GInetSocketAddress *inetsaddr; GInetAddress *inetaddr; guint16 port; next_enumerator (priv); if (!priv->addr_enum) continue; if (priv->proxy_address == NULL) { priv->proxy_address = g_socket_address_enumerator_next ( priv->addr_enum, cancellable, first_error ? NULL : &first_error); } if (priv->proxy_address == NULL) { g_object_unref (priv->addr_enum); priv->addr_enum = NULL; if (priv->dest_ips) { g_resolver_free_addresses (priv->dest_ips); priv->dest_ips = NULL; } continue; } if (strcmp ("direct", priv->proxy_type) == 0) { result = priv->proxy_address; priv->proxy_address = NULL; continue; } if (!priv->supports_hostname) { GInetAddress *dest_ip; if (!priv->dest_ips) { GResolver *resolver; resolver = g_resolver_get_default(); priv->dest_ips = g_resolver_lookup_by_name (resolver, priv->dest_hostname, cancellable, first_error ? NULL : &first_error); g_object_unref (resolver); if (!priv->dest_ips) { g_object_unref (priv->proxy_address); priv->proxy_address = NULL; continue; } } if (!priv->next_dest_ip) priv->next_dest_ip = priv->dest_ips; dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data); dest_hostname = g_inet_address_to_string (dest_ip); priv->next_dest_ip = g_list_next (priv->next_dest_ip); } else { dest_hostname = g_strdup (priv->dest_hostname); } dest_protocol = g_uri_parse_scheme (priv->dest_uri); g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address), NULL); inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address); inetaddr = g_inet_socket_address_get_address (inetsaddr); port = g_inet_socket_address_get_port (inetsaddr); result = g_object_new (G_TYPE_PROXY_ADDRESS, "address", inetaddr, "port", port, "protocol", priv->proxy_type, "destination-protocol", dest_protocol, "destination-hostname", dest_hostname, "destination-port", priv->dest_port, "username", priv->proxy_username, "password", priv->proxy_password, "uri", priv->proxy_uri, NULL); g_free (dest_hostname); g_free (dest_protocol); if (priv->supports_hostname || priv->next_dest_ip == NULL) { g_object_unref (priv->proxy_address); priv->proxy_address = NULL; } } if (result == NULL && first_error) g_propagate_error (error, first_error); else if (first_error) g_error_free (first_error); return result; }
static gboolean g_network_monitor_base_can_reach (GNetworkMonitor *monitor, GSocketConnectable *connectable, GCancellable *cancellable, GError **error) { GNetworkMonitorBasePrivate *priv = G_NETWORK_MONITOR_BASE (monitor)->priv; GSocketAddressEnumerator *enumerator; GSocketAddress *addr; if (priv->have_ipv4_default_route && priv->have_ipv6_default_route) return TRUE; if (priv->networks->len == 0) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE, _("Network unreachable")); return FALSE; } enumerator = g_socket_connectable_proxy_enumerate (connectable); addr = g_socket_address_enumerator_next (enumerator, cancellable, error); if (!addr) { /* Either the user cancelled, or DNS resolution failed */ g_object_unref (enumerator); return FALSE; } while (addr) { if (G_IS_INET_SOCKET_ADDRESS (addr)) { GInetAddress *iaddr; int i; iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr)); for (i = 0; i < priv->networks->len; i++) { if (g_inet_address_mask_matches (priv->networks->pdata[i], iaddr)) { g_object_unref (addr); g_object_unref (enumerator); return TRUE; } } } g_object_unref (addr); addr = g_socket_address_enumerator_next (enumerator, cancellable, error); } g_object_unref (enumerator); if (error && !*error) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE, _("Host unreachable")); } return FALSE; }