442
442
soup_connection_event (conn, event, connection);
446
SoupConnection *conn;
447
SoupConnectionCallback callback;
448
gpointer callback_data;
449
GCancellable *cancellable;
451
} SoupConnectionAsyncConnectData;
454
socket_connect_finished (SoupSocket *socket, guint status, gpointer user_data)
446
socket_connect_finished (GTask *task, SoupSocket *sock, GError *error)
456
SoupConnectionAsyncConnectData *data = user_data;
457
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn);
459
g_signal_handler_disconnect (socket, data->event_id);
461
if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
448
SoupConnection *conn = g_task_get_source_object (task);
449
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
451
if (priv->async_context && !priv->use_thread_context)
452
g_main_context_pop_thread_default (priv->async_context);
454
g_signal_handlers_disconnect_by_func (sock, G_CALLBACK (re_emit_socket_event), conn);
462
457
if (priv->ssl && !priv->proxy_uri) {
463
soup_connection_event (data->conn,
458
soup_connection_event (conn,
464
459
G_SOCKET_CLIENT_TLS_HANDSHAKED,
467
462
if (!priv->ssl || !priv->proxy_uri) {
468
soup_connection_event (data->conn,
463
soup_connection_event (conn,
469
464
G_SOCKET_CLIENT_COMPLETE,
473
soup_connection_set_state (data->conn, SOUP_CONNECTION_IN_USE);
468
soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE);
474
469
priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT;
475
start_idle_timer (data->conn);
476
} else if (status == SOUP_STATUS_TLS_FAILED) {
477
priv->ssl_fallback = TRUE;
478
status = SOUP_STATUS_TRY_AGAIN;
481
if (data->callback) {
482
if (priv->proxy_uri != NULL)
483
status = soup_status_proxify (status);
484
data->callback (data->conn, status, data->callback_data);
486
g_object_unref (data->conn);
487
if (data->cancellable)
488
g_object_unref (data->cancellable);
489
g_slice_free (SoupConnectionAsyncConnectData, data);
493
socket_connect_result (SoupSocket *sock, guint status, gpointer user_data)
495
SoupConnectionAsyncConnectData *data = user_data;
496
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn);
498
if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
499
socket_connect_finished (sock, status, data);
470
start_idle_timer (conn);
472
g_task_return_boolean (task, TRUE);
474
g_task_return_error (task, error);
475
g_object_unref (task);
479
socket_handshake_complete (GObject *object, GAsyncResult *result, gpointer user_data)
481
SoupSocket *sock = SOUP_SOCKET (object);
482
GTask *task = user_data;
483
GError *error = NULL;
485
soup_socket_handshake_finish (sock, result, &error);
486
socket_connect_finished (task, sock, error);
490
socket_connect_complete (GObject *object, GAsyncResult *result, gpointer user_data)
492
SoupSocket *sock = SOUP_SOCKET (object);
493
GTask *task = user_data;
494
SoupConnection *conn = g_task_get_source_object (task);
495
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
496
GError *error = NULL;
498
if (!soup_socket_connect_finish_internal (sock, result, &error)) {
499
socket_connect_finished (task, sock, error);
503
priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket);
503
priv->proxy_uri = soup_socket_get_http_proxy_uri (sock);
505
505
if (priv->ssl && !priv->proxy_uri) {
506
if (soup_socket_start_ssl (sock, data->cancellable)) {
507
soup_connection_event (data->conn,
508
G_SOCKET_CLIENT_TLS_HANDSHAKING,
510
soup_socket_handshake_async (sock, data->cancellable,
511
socket_connect_finished, data);
506
soup_connection_event (conn,
507
G_SOCKET_CLIENT_TLS_HANDSHAKING,
515
status = SOUP_STATUS_SSL_FAILED;
510
soup_socket_handshake_async (sock, priv->remote_uri->host,
511
g_task_get_cancellable (task),
512
socket_handshake_complete, task);
518
socket_connect_finished (sock, status, data);
516
socket_connect_finished (task, sock, NULL);
522
soup_connection_connect_async (SoupConnection *conn,
523
GCancellable *cancellable,
524
SoupConnectionCallback callback,
520
soup_connection_connect_async (SoupConnection *conn,
521
GCancellable *cancellable,
522
GAsyncReadyCallback callback,
527
SoupConnectionAsyncConnectData *data;
528
525
SoupConnectionPrivate *priv;
529
526
SoupAddress *remote_addr;
531
529
g_return_if_fail (SOUP_IS_CONNECTION (conn));
532
530
priv = SOUP_CONNECTION_GET_PRIVATE (conn);
535
533
soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING);
537
data = g_slice_new (SoupConnectionAsyncConnectData);
538
data->conn = g_object_ref (conn);
539
data->callback = callback;
540
data->callback_data = user_data;
541
data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
535
/* Set the protocol to ensure correct proxy resolution. */
537
g_object_new (SOUP_TYPE_ADDRESS,
538
SOUP_ADDRESS_NAME, priv->remote_uri->host,
539
SOUP_ADDRESS_PORT, priv->remote_uri->port,
540
SOUP_ADDRESS_PROTOCOL, priv->remote_uri->scheme,
543
remote_addr = soup_address_new (priv->remote_uri->host,
544
priv->remote_uri->port);
546
544
soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr,
547
545
SOUP_SOCKET_SSL_CREDENTIALS, priv->tlsdb,
557
555
g_object_unref (remote_addr);
559
data->event_id = g_signal_connect (priv->socket, "event",
560
G_CALLBACK (re_emit_socket_event),
563
soup_socket_connect_async (priv->socket, data->cancellable,
564
socket_connect_result, data);
568
soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable)
557
g_signal_connect (priv->socket, "event",
558
G_CALLBACK (re_emit_socket_event), conn);
560
if (priv->async_context && !priv->use_thread_context)
561
g_main_context_push_thread_default (priv->async_context);
562
task = g_task_new (conn, cancellable, callback, user_data);
564
soup_socket_connect_async_internal (priv->socket, cancellable,
565
socket_connect_complete, task);
569
soup_connection_connect_finish (SoupConnection *conn,
570
GAsyncResult *result,
573
return g_task_propagate_boolean (G_TASK (result), error);
577
soup_connection_connect_sync (SoupConnection *conn,
578
GCancellable *cancellable,
570
581
SoupConnectionPrivate *priv;
571
guint status, event_id = 0;
572
583
SoupAddress *remote_addr;
584
gboolean success = TRUE;
574
g_return_val_if_fail (SOUP_IS_CONNECTION (conn), SOUP_STATUS_MALFORMED);
586
g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE);
575
587
priv = SOUP_CONNECTION_GET_PRIVATE (conn);
576
g_return_val_if_fail (priv->socket == NULL, SOUP_STATUS_MALFORMED);
588
g_return_val_if_fail (priv->socket == NULL, FALSE);
578
590
soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING);
580
remote_addr = soup_address_new (priv->remote_uri->host, priv->remote_uri->port);
592
/* Set the protocol to ensure correct proxy resolution. */
594
g_object_new (SOUP_TYPE_ADDRESS,
595
SOUP_ADDRESS_NAME, priv->remote_uri->host,
596
SOUP_ADDRESS_PORT, priv->remote_uri->port,
597
SOUP_ADDRESS_PROTOCOL, priv->remote_uri->scheme,
582
601
soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr,
583
602
SOUP_SOCKET_PROXY_RESOLVER, priv->proxy_resolver,
594
613
event_id = g_signal_connect (priv->socket, "event",
595
614
G_CALLBACK (re_emit_socket_event), conn);
596
status = soup_socket_connect_sync (priv->socket, cancellable);
598
if (!SOUP_STATUS_IS_SUCCESSFUL (status))
615
if (!soup_socket_connect_sync_internal (priv->socket, cancellable, error)) {
601
620
priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket);
603
622
if (priv->ssl && !priv->proxy_uri) {
604
if (!soup_socket_start_ssl (priv->socket, cancellable))
605
status = SOUP_STATUS_SSL_FAILED;
607
soup_connection_event (conn,
608
G_SOCKET_CLIENT_TLS_HANDSHAKING,
610
status = soup_socket_handshake_sync (priv->socket, cancellable);
611
if (status == SOUP_STATUS_OK) {
612
soup_connection_event (conn,
613
G_SOCKET_CLIENT_TLS_HANDSHAKED,
615
} else if (status == SOUP_STATUS_TLS_FAILED) {
616
priv->ssl_fallback = TRUE;
617
status = SOUP_STATUS_TRY_AGAIN;
622
if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
623
if (!priv->ssl || !priv->proxy_uri) {
624
soup_connection_event (conn,
625
G_SOCKET_CLIENT_COMPLETE,
628
soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE);
629
priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT;
630
start_idle_timer (conn);
623
soup_connection_event (conn,
624
G_SOCKET_CLIENT_TLS_HANDSHAKING,
626
if (!soup_socket_handshake_sync (priv->socket,
627
priv->remote_uri->host,
628
cancellable, error)) {
632
soup_connection_event (conn,
633
G_SOCKET_CLIENT_TLS_HANDSHAKED,
637
if (!priv->ssl || !priv->proxy_uri) {
638
soup_connection_event (conn,
639
G_SOCKET_CLIENT_COMPLETE,
642
soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE);
643
priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT;
644
start_idle_timer (conn);
634
647
if (priv->socket && event_id)
635
648
g_signal_handler_disconnect (priv->socket, event_id);
637
if (priv->proxy_uri != NULL)
638
status = soup_status_proxify (status);
650
661
return priv->ssl && priv->proxy_uri != NULL;
654
soup_connection_start_ssl_sync (SoupConnection *conn,
655
GCancellable *cancellable)
665
soup_connection_start_ssl_sync (SoupConnection *conn,
666
GCancellable *cancellable,
657
669
SoupConnectionPrivate *priv;
660
671
g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE);
661
672
priv = SOUP_CONNECTION_GET_PRIVATE (conn);
663
if (!soup_socket_start_proxy_ssl (priv->socket,
664
priv->remote_uri->host,
666
return SOUP_STATUS_SSL_FAILED;
668
674
soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, NULL);
669
status = soup_socket_handshake_sync (priv->socket, cancellable);
670
if (status == SOUP_STATUS_OK) {
675
if (soup_socket_handshake_sync (priv->socket, priv->remote_uri->host,
676
cancellable, error)) {
671
677
soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL);
672
678
soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL);
673
} else if (status == SOUP_STATUS_TLS_FAILED) {
674
priv->ssl_fallback = TRUE;
675
status = SOUP_STATUS_TRY_AGAIN;
682
start_ssl_completed (SoupSocket *socket, guint status, gpointer user_data)
684
SoupConnectionAsyncConnectData *data = user_data;
685
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn);
687
if (status == SOUP_STATUS_OK) {
688
soup_connection_event (data->conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL);
689
soup_connection_event (data->conn, G_SOCKET_CLIENT_COMPLETE, NULL);
690
} else if (status == SOUP_STATUS_TLS_FAILED) {
691
priv->ssl_fallback = TRUE;
692
status = SOUP_STATUS_TRY_AGAIN;
695
data->callback (data->conn, status, data->callback_data);
696
g_object_unref (data->conn);
697
g_slice_free (SoupConnectionAsyncConnectData, data);
701
idle_start_ssl_completed (gpointer user_data)
703
SoupConnectionAsyncConnectData *data = user_data;
705
start_ssl_completed (NULL, SOUP_STATUS_SSL_FAILED, data);
685
start_ssl_completed (GObject *object, GAsyncResult *result, gpointer user_data)
687
GTask *task = user_data;
688
SoupConnection *conn = g_task_get_source_object (task);
689
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
690
GError *error = NULL;
692
if (priv->async_context && !priv->use_thread_context)
693
g_main_context_pop_thread_default (priv->async_context);
695
if (soup_socket_handshake_finish (priv->socket, result, &error)) {
696
soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL);
697
soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL);
698
g_task_return_boolean (task, TRUE);
700
g_task_return_error (task, error);
701
g_object_unref (task);
710
soup_connection_start_ssl_async (SoupConnection *conn,
711
GCancellable *cancellable,
712
SoupConnectionCallback callback,
705
soup_connection_start_ssl_async (SoupConnection *conn,
706
GCancellable *cancellable,
707
GAsyncReadyCallback callback,
715
710
SoupConnectionPrivate *priv;
716
SoupConnectionAsyncConnectData *data;
717
GMainContext *async_context;
719
713
g_return_if_fail (SOUP_IS_CONNECTION (conn));
720
714
priv = SOUP_CONNECTION_GET_PRIVATE (conn);
722
data = g_slice_new (SoupConnectionAsyncConnectData);
723
data->conn = g_object_ref (conn);
724
data->callback = callback;
725
data->callback_data = user_data;
727
if (priv->use_thread_context)
728
async_context = g_main_context_get_thread_default ();
730
async_context = priv->async_context;
732
if (!soup_socket_start_proxy_ssl (priv->socket,
733
priv->remote_uri->host,
735
soup_add_completion (async_context,
736
idle_start_ssl_completed, data);
740
716
soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, NULL);
741
soup_socket_handshake_async (priv->socket, cancellable,
742
start_ssl_completed, data);
718
if (priv->async_context && !priv->use_thread_context)
719
g_main_context_push_thread_default (priv->async_context);
720
task = g_task_new (conn, cancellable, callback, user_data);
722
soup_socket_handshake_async (priv->socket, priv->remote_uri->host,
723
cancellable, start_ssl_completed, task);
727
soup_connection_start_ssl_finish (SoupConnection *conn,
728
GAsyncResult *result,
731
return g_task_propagate_boolean (G_TASK (result), error);