After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 631316 - GSocketClient: no way to know the local port before connecting
GSocketClient: no way to know the local port before connecting
Status: RESOLVED WONTFIX
Product: glib
Classification: Platform
Component: network
2.22.x
Other Linux
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2010-10-04 13:43 UTC by Guillaume Desmottes
Modified: 2011-12-22 20:46 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Guillaume Desmottes 2010-10-04 13:43:34 UTC
In Telepathy, I need to know the local port of an Inet socket before trying to connect (to pass it to another process over D-Bus). This is usually done by doing something like that:

    sock = socket (AF_INET, SOCK_STREAM, 0);
    bind (sock, addr={ AF_INET, sin_port=0, sin_addr=IN_ADDR_ANY }, addr_len);
    getsockname (sock, &real_addr, real_addr_len);

I tried to "port" this pseudocode using GIO API and did:

      GSocketAddress *adr;
      GInetAddress *tmp;
      guint16 port;

      tmp = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
      adr = g_inet_socket_address_new (tmp, 0);
      g_socket_client_set_local_address (client, adr);

      g_object_unref (adr);
      g_object_unref (tmp);

      adr = g_socket_client_get_local_address (client);
      port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (adr));
      g_print ("port: %u\n", port);

but that doesn't work (port is always 0). That's because GIO doesn't bind the socket before we actually start to connect. It would be very useful to be able to let the kernel allocates a port and then get it back without starting the connection proccess.
Comment 1 Dan Winship 2010-10-04 14:15:28 UTC
It's not that it doesn't bind the socket until you call _connect, it's that it doesn't *create* the socket until until you call _connect. And that's by design; GSocketClients are reusable, so there isn't any "the socket" other than in the context of a specific _connect call.

Not sure what to do here... maybe something like http://github.com/danwinship/glib/commit/0255faa7659817e31cb8051d19120c1e5c8f1c60could help
Comment 3 Guillaume Desmottes 2010-10-04 14:22:10 UTC
That won't help as I need the port before knowing the address to which I'm going to connect. :\
Comment 4 Dan Winship 2010-10-04 14:29:19 UTC
ah in that case I don't think there's any way you can use GSocketClient; you'd have to use GSocket directly to make the connection and then g_socket_connection_factory_create_connection() to make a GSocketConnection from it.
Comment 5 Guillaume Desmottes 2010-10-05 13:21:39 UTC
I've done that but that's pretty low level, some helper API would be nice.
Comment 6 Dan Winship 2011-04-09 17:22:50 UTC
(In reply to comment #5)
> I've done that but that's pretty low level, some helper API would be nice.

OK, one helper API that might make sense would be to add:

    gboolean g_socket_connection_connect (GSocketConnection  *conn,
                                          GSocketAddress     *addr,
                                          GCancellable       *cancellable,
                                          GError            **error);

(and the corresponding async variant). The sync version would be trivial, the async version would correspond to the g_socket_client_enumerator_callback()-to-g_socket_client_socket_callback() piece of GSocketClient. Then you'd at least have a gio-ish connection API, rather than having to use the sockets-ish one.

(We'd also want g_socket_connection_is_connected() in that case.)

Other than that, I'm not sure there's a lot that would make sense to do; what you're doing is itself pretty low level, so you're going to have to use some amount of low-level API...
Comment 7 Guillaume Desmottes 2011-04-12 15:57:41 UTC
(In reply to comment #6)
> Other than that, I'm not sure there's a lot that would make sense to do; what
> you're doing is itself pretty low level, so you're going to have to use some
> amount of low-level API...

Fair enough; feel free to WONTFIX if you think that's not worth it.
Comment 8 Dan Winship 2011-12-22 20:46:29 UTC
(In reply to comment #6)
> OK, one helper API that might make sense would be to add:
> 
>     gboolean g_socket_connection_connect (GSocketConnection  *conn,
>                                           GSocketAddress     *addr,
>                                           GCancellable       *cancellable,
>                                           GError            **error);
> 
> (and the corresponding async variant).

This is done now... the rest is WONTFIX.