GNOME Bugzilla – Bug 631316
GSocketClient: no way to know the local port before connecting
Last modified: 2011-12-22 20:46:29 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.
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
ahem http://github.com/danwinship/glib/commit/0255faa7659817e31cb8051d19120c1e5c8f1c60
That won't help as I need the port before knowing the address to which I'm going to connect. :\
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.
I've done that but that's pretty low level, some helper API would be nice.
(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...
(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.
(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.