[ENet-discuss] IPv6 Support

John Cotton Ericson Ericson2314 at yahoo.com
Sun Jul 14 15:28:15 PDT 2013


First of all, sorry I did not respond to your email earlier, James. I 
think you responded before mailman finished processing my email address, 
as I never received your response.

I had looked at Linux and Windows, and seen that they both used the same 
sockaddr_in? structures (with network byte order for both the IP address 
and socket). I assumed then that all sufficiently modern Unix variants 
would also use it, but just in case cloned it's ABI for ENet, so in most 
cases conversion would be a no-op, and users could rely on it being the 
same even on esoteric systems were something different was native. (I 
hadn't actually implemented the fall-back code though, just made 
EnetAddress not depend on system types and instead "coincidently" mimic 
them).

As to port-endianness, I too figured that in the vast majority of cases 
EnetAddresses and port numbers would be passed around read-only so the 
endianness of the port wouldn't be much of nuisance. For the rarer case 
where somebody did need accesses functions could be provided. But yes, 
as C has no way to really implement abstract data types, there is no way 
to to ensure that users do indeed use the accessors, making this idea worse.

Of course, there is the other argument that it's best to have something 
different from all platforms so no one gets in the habit of just casting 
native sockaddrs to enetAddresses. I just checked, and found out that 
Mac/BSD does uses something different, contrary to my expectations, and 
Mac has enough market share that conversion would come up a lot on 
practice too. Naturally, if a new structure is being used, it might as 
well have port in native byte order.

So yes, I now whole-heartedly agree its best to disregard 
system-specific types and just do something that's easiest for the ENet 
user. However, I am not so sure about the "magic ipv4 address" idea. 
First of all, anybody relying on the current size of EnetAddress will 
still have compatibility broken. If they are relying on field offset, I 
imagine they probably are doing likewise with structure size too, and 
giving them a false notion of compatibility is more harmful than helpful.

Secondly, I feel like this is fundamentally holding backwards 
compatibility above cleanliness of the interface. Having users grab 
fields by offset is hardly friendlier than having them deal with 
endianness themselves. It's also no more convenient than the casting and 
offsetting that needs to be done with sockAddrs (though at at least ENet 
will always be consistent across platforms).

If the point of this is making something that is both more consistent 
/and nicer/ than the POSIX sockets interface, I think a tagged union is 
the only way to go. Incidentally, The tag can be placed after the port, 
which preserves the current offsets (though for the reasons above, I 
don't think this is a good goal).

enum HostType {
     IPv4 = 0;
     IPv6 = -1;
}
struct EnetHostAddr6 {
     enet_uint32 flowInfo;
     enet_uint8  address[8];
     enet_uint32 scopeID;
}
struct ENetAddress
{
     enet_uint16 port;
     enet_uint8   typeTag; // tag goeswhere padding did before
     union {
         enet_uint32 v4;
         EnetIP6     v6;
     }           host;
};


-John

Where I looked for sockaddr_in6 info:
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man4/inet6.4.html
http://linux.die.net/man/7/ipv6
http://msdn.microsoft.com/en-us/library/aa915715.aspx

On 07/13/2013 06:08 AM, Lee Salzman wrote:
> What I was thinking a long time ago was to use a specific ipv4 host 
> address as the ipv6 marker, since the port is still necessary in any 
> case. And then underneath the port, reserve space for an actual ipv6 
> host address.
>
> So you end up with something like:
>
> struct ENetAddress
> {
>     enet_uint32 host;
>     enet_uint16 port, reserved;
>     enet_uint32 flowInfo;
>     enet_uint8 address[16];
>     enet_uint32 scopeId;
> };
>
> Then have:
>
> ENET_HOST_IPV6 = 0xAC1111AC
>
> ... where the above is some hex palindrome (reads same in both big and 
> little endian) is otherwise not a public ipv4 host.
>
> So you set the host to ENET_HOST_IPV6 and just fill in the rest of the 
> fields. Most use cases of ENetAddress blah = { host, port }; would 
> work as they always did. Certain stuff could possibly even be mirrored 
> between both ipv4 and ipv6 data when being passed back to the app.
>
> Only real danger is that ENET_HOST_IPV6's value needs to be chosen 
> well enough that it is "unlikely" for it to ever occur in practice by 
> accident or cause dangerous behavior if it does.
>
> On 07/07/2013 09:23 PM, James Bellinger wrote:
>> On 7/7/2013 12:10 PM, John Cotton Ericson wrote:
>>> I recently submitted a patch "sketching" IPv6 support for ENet: 
>>> https://github.com/lsalzman/enet/pull/21 . I say "sketching" as I 
>>> haven't tested it at all: once the issues below are resolved, I will 
>>> refine and test it, and then resubmit an actual patch.
>>>
>>> The biggest issue with this patch is it breaks the current interface 
>>> by redesigning the EnetAddress structure. One can read the comments 
>>> between Lee Salzman and I on the github page, but I will summarize 
>>> below:
>>>
>>> I think we both agreed the interface change with IPv6 support is 
>>> inevitable. I thought simply incrementing the version number, and 
>>> supporting two versions for a time would be sufficient. He supported 
>>> changing the namespace (function prefix and header names I assume) 
>>> in order to avoid clashes.
>>>
>> It doesn't have to break anything. Here's one possible route...
>>
>> The ENetAddress in most ENet structures is effectively read-only. Add 
>> an ENetAddress2 to ENetHost etc. and leave the others in as IPv4-only 
>> mirrors of the real data.
>> Have it initialized with accessor functions, and give it a structure 
>> like
>>
>> struct ENetAddress2
>> {
>> uint8_t magicIPv6Marker[6];
>> real data like port, address, type, etc;
>> };
>>
>> There are reserved IPv4 addresses that can't exist on the net, and 
>> you could use one of those for the magic. If the ENet address 
>> functions got one of these, and enet_initialize_with_callbacks was 
>> passed a sufficiently high version (so that the caller's structures 
>> have room for the extra data), the structure could be assumed 
>> ENetAddress2. Otherwise, it's an IPv4 address.
>>
>> If one wanted to transparently add IPv6, the old struct ENetAddress 
>> could become ENetCompatibleAddress, ENetHost's address could become 
>> addressIPv4, a new ENetAddress 'address' could be added at the end. 
>> For new projects compiling with new headers wanting compatibility 
>> with old ENet versions, an "IPv4-only" define could be added.
>>
>> Something like that. Your thoughts?
>>
>>> I also questioned storing the port number in host byte order, when 
>>> as far as I know Windows and Unix consistently store it in network 
>>> byte order. I brought this up because in my implementation, I 
>>> defined EnetAddress as a union of the existing sockaddr_in and 
>>> sockaddr_in6 structures, with the sole exception of keeping the 
>>> portnumber in host byte order as ENet currently does. Salzman 
>>> responded that the ease of working with port numbers in host byte 
>>> order outweighed the extra marshaling in the socket_* functions such 
>>> a design decision entailed.
>> Network byte order is an implementation detail of sockets. ENet's 
>> socket code is an abstraction layer above that so folks don't have to 
>> be exposed to it.
>>
>> sockaddr_in and sockaddr_in6 are going to be inconsistent between 
>> platforms. If you went this way, you would *have* to add accessor 
>> functions even for port, or nobody can support cross-platform 
>> wrappers that rely on the binary format (something that *mostly* has 
>> been possible with ENet to date). I can't see a compelling reason to 
>> use the platform-specific socket structs. Please do not do this.
>>
>> James
>> _______________________________________________
>> ENet-discuss mailing list
>> ENet-discuss at cubik.org
>> http://lists.cubik.org/mailman/listinfo/enet-discuss
>>
>
> _______________________________________________
> ENet-discuss mailing list
> ENet-discuss at cubik.org
> http://lists.cubik.org/mailman/listinfo/enet-discuss

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cubik.org/pipermail/enet-discuss/attachments/20130714/c9dc1a39/attachment.html>


More information about the ENet-discuss mailing list