Porting to the new SDL_net API

To support IPv6, the API for SDL_net has been changed. This summarises the differences between the SDL_net 1.2.x and SDL_net 1.3.x.

IPaddress

The IPaddress structure is now not an IPv4 address, but rather an abstracted "superclass" structure. The structure may hold an IPv4 address, or a IPv6 address, depending on its type. This means that you can no longer use "address.host" as you could previously.

The first member of the new IPaddress structure is "type". This indicates the type of address. These types are:

typedef enum {
        SDLNET_ANY,
        SDLNET_IPV4,
        SDLNET_IPV6,
} SDLNet_AddrType;              
ie. IPv4 addresses have address.type == SDLNET_IPV4, IPv6 addresses have address.type == SDLNET_IPV6. If you want to access the address data, you must cast to the particular address structure (IPaddress4 or IPaddress6). There are convenient macros named IP_ADDRESS4 and IP_ADDRESS6 provided for this purpose.
	IPaddress addr;

	// ....

	printf("%i\n", IP_ADDRESS4(&addr)->host);
In general, it is better to avoid dependency on a particular address type where possible. Instead, try to use DNS names.

SDLNet_PresentIP

In general, the new API tries to discourage dependencies on particular types of address (IPv4 or IPv6) and encourage use of DNS names instead. For this reason, the SDLNet_PresentIP function has been added. When presenting an IP address as a string, do not generate the string by hand, but use the SDLNet_PresentIP function instead to convert it. eg.
	IPaddress addr;

	// ....

	printf("New connection from %s!\n", SDLNet_PresentIP(&addr));

SDLNet_ResolveHost

SDLNet_ResolveHost has an extra parameter to allow specifying the type of address to resolve. eg.
	IPaddress addr;

	// resolve foo.bar.com:4378 as an IPv4 address

	SDLNet_ResolveHost(SDLNET_IPV4, &addr, "foo.bar.com", 4378);

	// resolve baz.qux.org:8539 as an IPv6 address

	SDLNet_ResolveHost(SDLNET_IPV6, &addr, "baz.qux.org", 8539);
Previously, one way to check if a resolve had failed was to check if addr.host == INADDR_NONE. Do not do this. Instead check the return value of SDLNet_ResolveHost.
	IPaddress addr;

	if (SDLNet_ResolveHost(SDLNET_IPV4, &addr, "shoenix.org", 8201) < 0) {
		printf("Resolve failed!\n");
	}

SDLNet_TCP_Open

Previously, the way to create a TCP socket was with SDLNet_TCP_Open. This was used both for creating server sockets and connecting to remote hosts. This function has now been removed: instead use SDLNet_TCP_OpenServer to create a server socket and SDLNet_TCP_Connect to connect to a remote machine.

To create a server:

	TCPsocket sock;

	// create a new IPv4 server on port 8592

	sock = SDLNet_TCP_OpenServer(SDLNET_IPV4, 8592);

To connect to a remote host, given a pointer to an IPaddress structure addr:
	TCPsocket sock;

	sock = SDLNet_TCP_Connect(addr);

SDLNet_UDP_Open

When creating a UDP socket, you must now specify the type of socket to create. For example:
	UDPsocket sock;

	// create a new IPv4 socket on port 8201

	sock = SDLNet_UDP_Open(SDLNET_IPV4, 8201);

	// create a new IPv6 socket on port 9182

	sock = SDLNet_UDP_Open(SDLNET_IPV6, 9182);

SDLNET_ANY

As well as the SDLNET_IPV4 and SDLNET_IPV6 address types, there is also a third, SDLNET_ANY. Some hostnames have both IPv4 and IPv6 addresses bound to them. Passing SDLNET_ANY to SDLNet_ResolveHost will attempt to resolve both types. If the name given resolves to an address of either type, it will be returned. If it resolves to both types, the IPaddress structure is filled in to contain both addresses, and given addr.type == SDLNET_ANY.

This IPaddress_any structure can then be passed to SDLNet_TCP_Connect, which will try to connect on both address types. For example:

	IPaddress addr;
	TCPsocket sock;

	if (SDLNet_ResolveHost(SDLNET_ANY, &addr, "shoe.bar.com", 9281) < 0) {
		printf("Resolve failed!\n");
		exit(-1);
	}

	sock = SDLNet_TCP_Connect(&addr);
It is then unneccesary when connecting to a host to try to resolve and connect to it as both IPv4 and IPv6 separately, as this is taken care of by the underlying library.

Note that in creating a server with SDLNet_TCP_OpenServer, or when using UDP, you must still explicitely specify the address type (ie. you cannot pass SDLNET_ANY as the socket type).


Simon Howard