/** * soup_connection_connect_async: * @conn: the connection * @callback: callback to call when the connection succeeds or fails * @user_data: data for @callback * * Asynchronously connects @conn. **/ void soup_connection_connect_async (SoupConnection *conn, SoupConnectionCallback callback, gpointer user_data) { SoupConnectionAsyncConnectData *data; SoupConnectionPrivate *priv; g_return_if_fail (SOUP_IS_CONNECTION (conn)); priv = SOUP_CONNECTION_GET_PRIVATE (conn); g_return_if_fail (priv->socket == NULL); soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); data = g_slice_new (SoupConnectionAsyncConnectData); data->conn = conn; data->callback = callback; data->callback_data = user_data; priv->socket = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, priv->remote_addr, SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds, SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context, SOUP_SOCKET_TIMEOUT, priv->io_timeout, NULL); soup_socket_connect_async (priv->socket, NULL, socket_connect_result, data); }
gboolean soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable, GError **error) { SoupConnectionPrivate *priv; SoupAddress *remote_addr; g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE); priv = SOUP_CONNECTION_GET_PRIVATE (conn); g_return_val_if_fail (priv->socket == NULL, FALSE); soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); /* Set the protocol to ensure correct proxy resolution. */ remote_addr = g_object_new (SOUP_TYPE_ADDRESS, SOUP_ADDRESS_NAME, priv->remote_uri->host, SOUP_ADDRESS_PORT, priv->remote_uri->port, SOUP_ADDRESS_PROTOCOL, priv->remote_uri->scheme, NULL); priv->socket = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr, SOUP_SOCKET_SSL_FALLBACK, priv->ssl_fallback, SOUP_SOCKET_SOCKET_PROPERTIES, priv->socket_props, SOUP_SOCKET_FLAG_NONBLOCKING, FALSE, NULL); g_object_unref (remote_addr); g_signal_connect (priv->socket, "event", G_CALLBACK (re_emit_socket_event), conn); if (!soup_socket_connect_sync_internal (priv->socket, cancellable, error)) return FALSE; priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); if (priv->ssl && !priv->proxy_uri) { if (!soup_socket_handshake_sync (priv->socket, priv->remote_uri->host, cancellable, error)) return FALSE; } if (!priv->ssl || !priv->proxy_uri) { soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL); } soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT; start_idle_timer (conn); return TRUE; }
/** * soup_connection_connect_sync: * @conn: the connection * * Synchronously connects @conn. * * Return value: the soup status **/ guint soup_connection_connect_sync (SoupConnection *conn) { SoupConnectionPrivate *priv; guint status; g_return_val_if_fail (SOUP_IS_CONNECTION (conn), SOUP_STATUS_MALFORMED); priv = SOUP_CONNECTION_GET_PRIVATE (conn); g_return_val_if_fail (priv->socket == NULL, SOUP_STATUS_MALFORMED); soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); priv->socket = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, priv->remote_addr, SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds, SOUP_SOCKET_FLAG_NONBLOCKING, FALSE, SOUP_SOCKET_TIMEOUT, priv->io_timeout, NULL); status = soup_socket_connect_sync (priv->socket, NULL); if (!SOUP_STATUS_IS_SUCCESSFUL (status)) goto fail; g_signal_connect (priv->socket, "disconnected", G_CALLBACK (socket_disconnected), conn); if (priv->ssl_creds && !priv->tunnel_addr) { if (!soup_socket_start_ssl (priv->socket, NULL)) { status = SOUP_STATUS_SSL_FAILED; goto fail; } } if (SOUP_STATUS_IS_SUCCESSFUL (status)) { soup_connection_set_state (conn, SOUP_CONNECTION_IDLE); priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT; start_idle_timer (conn); } else { fail: if (priv->socket) { g_object_unref (priv->socket); priv->socket = NULL; } } if (priv->proxy_uri != NULL) status = soup_status_proxify (status); return status; }
static GObject * constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *server; SoupServerPrivate *priv; server = G_OBJECT_CLASS (soup_server_parent_class)->constructor ( type, n_construct_properties, construct_properties); if (!server) return NULL; priv = SOUP_SERVER_GET_PRIVATE (server); if (!priv->interface) { priv->interface = soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV4, priv->port); } if (priv->ssl_cert_file && priv->ssl_key_file) { priv->ssl_creds = soup_ssl_get_server_credentials ( priv->ssl_cert_file, priv->ssl_key_file); if (!priv->ssl_creds) { g_object_unref (server); return NULL; } } priv->listen_sock = soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, priv->interface, SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds, SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context, NULL); if (!soup_socket_listen (priv->listen_sock)) { g_object_unref (server); return NULL; } /* Re-resolve the interface address, in particular in case * the passed-in address had SOUP_ADDRESS_ANY_PORT. */ g_object_unref (priv->interface); priv->interface = soup_socket_get_local_address (priv->listen_sock); g_object_ref (priv->interface); priv->port = soup_address_get_port (priv->interface); return server; }
void soup_connection_connect_async (SoupConnection *conn, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SoupConnectionPrivate *priv; SoupAddress *remote_addr; GTask *task; g_return_if_fail (SOUP_IS_CONNECTION (conn)); priv = SOUP_CONNECTION_GET_PRIVATE (conn); g_return_if_fail (priv->socket == NULL); soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); /* Set the protocol to ensure correct proxy resolution. */ remote_addr = g_object_new (SOUP_TYPE_ADDRESS, SOUP_ADDRESS_NAME, priv->remote_uri->host, SOUP_ADDRESS_PORT, priv->remote_uri->port, SOUP_ADDRESS_PROTOCOL, priv->remote_uri->scheme, NULL); priv->socket = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr, SOUP_SOCKET_SSL_FALLBACK, priv->ssl_fallback, SOUP_SOCKET_SOCKET_PROPERTIES, priv->socket_props, NULL); g_object_unref (remote_addr); g_signal_connect (priv->socket, "event", G_CALLBACK (re_emit_socket_event), conn); soup_socket_properties_push_async_context (priv->socket_props); task = g_task_new (conn, cancellable, callback, user_data); soup_socket_connect_async_internal (priv->socket, cancellable, socket_connect_complete, task); soup_socket_properties_pop_async_context (priv->socket_props); }
int main (int argc, char **argv) { int opt, debug = 0, listener, sin_len, port, i; struct sockaddr_in sin; GThread *server; char writebuf[BUFSIZE], readbuf[BUFSIZE]; SoupAddress *addr; SoupSSLCredentials *creds; SoupSocket *sock; gsize n, total; SoupSocketIOStatus status; int connect_status; GError *error = NULL; g_thread_init (NULL); g_type_init (); /* On Windows, this will call WSAStartup() */ soup_socket_get_type (); while ((opt = getopt (argc, argv, "c:d:k:")) != -1) { switch (opt) { case 'c': ssl_cert_file = optarg; break; case 'd': debug = atoi (optarg); break; case 'k': ssl_key_file = optarg; break; case '?': fprintf (stderr, "Usage: %s [-d debuglevel] [-c ssl-cert-file] [-k ssl-key-file]\n", argv[0]); break; } } if (debug) { gnutls_global_set_log_function (debug_log); gnutls_global_set_log_level (debug); } /* Create server socket */ listener = socket (AF_INET, SOCK_STREAM, 0); if (listener == -1) { SOCKET_PRINT_ERROR ("creating listening socket"); exit (1); } memset (&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = ntohl (INADDR_LOOPBACK); if (bind (listener, (struct sockaddr *) &sin, sizeof (sin)) == -1) { SOCKET_PRINT_ERROR ("binding listening socket"); exit (1); } if (listen (listener, 1) == -1) { SOCKET_PRINT_ERROR ("listening on socket"); exit (1); } sin_len = sizeof (sin); getsockname (listener, (struct sockaddr *)&sin, (void *)&sin_len); port = ntohs (sin.sin_port); /* Create the client */ addr = soup_address_new ("127.0.0.1", port); creds = soup_ssl_get_client_credentials (NULL); sock = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, addr, SOUP_SOCKET_FLAG_NONBLOCKING, FALSE, SOUP_SOCKET_SSL_CREDENTIALS, creds, NULL); g_object_unref (addr); connect_status = soup_socket_connect_sync (sock, NULL); if (connect_status != SOUP_STATUS_OK) { g_error ("Could not create client socket: %s", soup_status_get_phrase (connect_status)); } soup_socket_start_ssl (sock, NULL); /* Now spawn server thread */ server = g_thread_create (server_thread, GINT_TO_POINTER (listener), TRUE, NULL); /* Synchronous client test */ for (i = 0; i < BUFSIZE; i++) writebuf[i] = i & 0xFF; total = 0; while (total < BUFSIZE) { status = soup_socket_write (sock, writebuf + total, BUFSIZE - total, &n, NULL, &error); if (status != SOUP_SOCKET_OK) g_error ("Sync write got status %d: %s", status, error ? error->message : "(unknown)"); total += n; } total = 0; while (total < BUFSIZE) { status = soup_socket_read (sock, readbuf + total, BUFSIZE - total, &n, NULL, &error); if (status != SOUP_SOCKET_OK) g_error ("Sync read got status %d: %s", status, error ? error->message : "(unknown)"); total += n; } if (memcmp (writebuf, readbuf, BUFSIZE) != 0) g_error ("Sync read didn't match write"); printf ("SYNCHRONOUS SSL TEST PASSED\n"); /* Switch socket to async and do it again */ g_object_set (sock, SOUP_SOCKET_FLAG_NONBLOCKING, TRUE, NULL); g_idle_add (start_writing, sock); loop = g_main_loop_new (NULL, TRUE); g_main_loop_run (loop); g_main_loop_unref (loop); g_main_context_unref (g_main_context_default ()); printf ("ASYNCHRONOUS SSL TEST PASSED\n"); g_object_unref (sock); soup_ssl_free_client_credentials (creds); g_thread_join (server); /* Success */ return 0; }