Wednesday, April 25, 2012

glib/GIO Sockets and Binding on IPv4 and IPv6

Today I learned that it isn't possible to bind to the same port on both IPv4 and IPv6 in GIO:

#include <glib.h> #include <gio/gio.h> #include <stdlib.h> #include <stdio.h> int main(int argc, const char ** argv) { char * valid; unsigned long int port; GError * err = NULL; GSocketFamily gfamily = G_SOCKET_FAMILY_IPV4; GSocket * sockets[2]; GInetAddress * giaddress; GSocketAddress * gsaddress; int i; g_type_init(); if(argc == 1) { fprintf(stderr, "Usage: %s port\n", argv[0]); return 1; } port = strtoul(argv[1], &valid, 10); if(port == 0 || port > 0xFFFF || *valid != 0) { fprintf(stderr, "Invalid port: %s\n", argv[1]); return 1; } while(gfamily != G_SOCKET_FAMILY_INVALID) { i = (gfamily == G_SOCKET_FAMILY_IPV4) ? 0 : 1; printf("Family: %d, port: %lu\n", gfamily, port); sockets[i] = g_socket_new(gfamily, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, &err); if(sockets[i] == NULL || err != NULL) { fprintf(stderr, "Failed to create server socket: %s\n", err->message); g_error_free(err); if(sockets[i] != NULL) g_object_unref(sockets[i]); return 2; } giaddress = g_inet_address_new_any(gfamily); gsaddress = g_inet_socket_address_new(giaddress, port); if(!g_socket_bind(sockets[i], gsaddress, TRUE, &err) || err != NULL) { fprintf(stderr, "Failed to bind to port: %s\n", err->message); g_error_free(err); if(sockets[i] != NULL) g_object_unref(sockets[i]); if(gsaddress != NULL) g_object_unref(gsaddress); return 2; } if(!g_socket_listen(sockets[i], &err) || err != NULL) { fprintf(stderr, "Failed to listen on socket: %s\n", err->message); g_error_free(err); if(sockets[i] != NULL) g_object_unref(sockets[i]); if(gsaddress != NULL) g_object_unref(gsaddress); return 2; } gfamily = (gfamily == G_SOCKET_FAMILY_IPV4) ? G_SOCKET_FAMILY_IPV6 : G_SOCKET_FAMILY_INVALID; } for(i = 0; i < 2; i++) g_object_unref(sockets[i]); return 0; }

Typical output:

% ./gfail 3000 Family: 2, port: 3000 Family: 10, port: 3000 Failed to bind to port: Error binding to address: Address already in use

Weird.

Post a Comment