GSocket: store the remote_address when connecting

This way, if g_socket_connect() is called with a GProxyAddress,
g_socket_get_remote_address() will later return that same address.

Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
This commit is contained in:
Dan Winship 2010-06-25 14:28:02 -04:00 committed by Nicolas Dufresne
parent b304a23af7
commit c32ef1d85e

View File

@ -145,6 +145,7 @@ struct _GSocketPrivate
gint listen_backlog; gint listen_backlog;
guint timeout; guint timeout;
GError *construct_error; GError *construct_error;
GSocketAddress *remote_address;
guint inited : 1; guint inited : 1;
guint blocking : 1; guint blocking : 1;
guint keepalive : 1; guint keepalive : 1;
@ -152,6 +153,7 @@ struct _GSocketPrivate
guint connected : 1; guint connected : 1;
guint listening : 1; guint listening : 1;
guint timed_out : 1; guint timed_out : 1;
guint connect_pending : 1;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
WSAEVENT event; WSAEVENT event;
int current_events; int current_events;
@ -629,6 +631,9 @@ g_socket_finalize (GObject *object)
!socket->priv->closed) !socket->priv->closed)
g_socket_close (socket, NULL); g_socket_close (socket, NULL);
if (socket->priv->remote_address)
g_object_unref (socket->priv->remote_address);
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
if (socket->priv->event != WSA_INVALID_EVENT) if (socket->priv->event != WSA_INVALID_EVENT)
{ {
@ -1245,15 +1250,28 @@ g_socket_get_remote_address (GSocket *socket,
g_return_val_if_fail (G_IS_SOCKET (socket), NULL); g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
if (getpeername (socket->priv->fd, (struct sockaddr *) &buffer, &len) < 0) if (socket->priv->connect_pending)
{ {
int errsv = get_socket_errno (); if (!g_socket_check_connect_result (socket, error))
g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv), return NULL;
_("could not get remote address: %s"), socket_strerror (errsv)); else
return NULL; socket->priv->connect_pending = FALSE;
} }
return g_socket_address_new_from_native (&buffer, len); if (!socket->priv->remote_address)
{
if (getpeername (socket->priv->fd, (struct sockaddr *) &buffer, &len) < 0)
{
int errsv = get_socket_errno ();
g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv),
_("could not get remote address: %s"), socket_strerror (errsv));
return NULL;
}
socket->priv->remote_address = g_socket_address_new_from_native (&buffer, len);
}
return g_object_ref (socket->priv->remote_address);
} }
/** /**
@ -1591,6 +1609,10 @@ g_socket_connect (GSocket *socket,
if (!g_socket_address_to_native (address, &buffer, sizeof buffer, error)) if (!g_socket_address_to_native (address, &buffer, sizeof buffer, error))
return FALSE; return FALSE;
if (socket->priv->remote_address)
g_object_unref (socket->priv->remote_address);
socket->priv->remote_address = g_object_ref (address);
while (1) while (1)
{ {
if (connect (socket->priv->fd, (struct sockaddr *) &buffer, if (connect (socket->priv->fd, (struct sockaddr *) &buffer,
@ -1617,8 +1639,11 @@ g_socket_connect (GSocket *socket,
g_prefix_error (error, _("Error connecting: ")); g_prefix_error (error, _("Error connecting: "));
} }
else else
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING, {
_("Connection in progress")); g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
_("Connection in progress"));
socket->priv->connect_pending = TRUE;
}
} }
else else
g_set_error (error, G_IO_ERROR, g_set_error (error, G_IO_ERROR,
@ -1674,6 +1699,11 @@ g_socket_check_connect_result (GSocket *socket,
{ {
g_set_error_literal (error, G_IO_ERROR, socket_io_error_from_errno (value), g_set_error_literal (error, G_IO_ERROR, socket_io_error_from_errno (value),
socket_strerror (value)); socket_strerror (value));
if (socket->priv->remote_address)
{
g_object_unref (socket->priv->remote_address);
socket->priv->remote_address = NULL;
}
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
@ -2168,6 +2198,11 @@ g_socket_close (GSocket *socket,
socket->priv->connected = FALSE; socket->priv->connected = FALSE;
socket->priv->closed = TRUE; socket->priv->closed = TRUE;
if (socket->priv->remote_address)
{
g_object_unref (socket->priv->remote_address);
socket->priv->remote_address = NULL;
}
return TRUE; return TRUE;
} }