<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">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.<br>
      <br>
      I had looked at Linux and Windows, and seen that they both used
      the same <tt>sockaddr_in?</tt> 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 <tt>EnetAddress</tt>
      not depend on system types and instead "coincidently" mimic them).<br>
      <br>
      As to port-endianness, I too figured that in the vast majority of
      cases <tt>EnetAddress</tt>es 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.<br>
      <br>
      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 <tt>sockaddr</tt>s to <tt>enetAddress</tt>es.
      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.<br>
      <br>
      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 <tt>EnetAddress</tt> 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.<br>
      <br>
      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 <tt>sockAddr</tt>s
      (though at at least ENet will always be consistent across
      platforms).<br>
      <br>
      If the point of this is making something that is both more
      consistent <i>and nicer</i> 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).<br>
      <br>
      <pre><tt>enum HostType {
    IPv4 = 0;
    IPv6 = -1;
}
struct EnetHostAddr6 {
    enet_uint32 flowInfo;
    enet_uint8  address[8];
    enet_uint32 scopeID;
}
struct ENetAddress
{
    enet_uint16 port;</tt>
<tt><tt>    </tt></tt><tt><tt><tt>enet_uint8</tt>  typeTag; // tag goes </tt>where padding did before
    union {
        enet_uint32 v4;
        EnetIP6     v6;
    }           host;
};
</tt></pre>
      <br>
      -John<br>
      <br>
      Where I looked for <tt>sockaddr_in6</tt> info:<br>
<a class="moz-txt-link-freetext" href="https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man4/inet6.4.html">https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man4/inet6.4.html</a><br>
      <a class="moz-txt-link-freetext" href="http://linux.die.net/man/7/ipv6">http://linux.die.net/man/7/ipv6</a><br>
      <a class="moz-txt-link-freetext" href="http://msdn.microsoft.com/en-us/library/aa915715.aspx">http://msdn.microsoft.com/en-us/library/aa915715.aspx</a><br>
      <br>
      On 07/13/2013 06:08 AM, Lee Salzman wrote:<br>
    </div>
    <blockquote cite="mid:51E12711.7030902@gmail.com" type="cite">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.
      <br>
      <br>
      So you end up with something like:
      <br>
      <br>
      struct ENetAddress
      <br>
      {
      <br>
          enet_uint32 host;
      <br>
          enet_uint16 port, reserved;
      <br>
          enet_uint32 flowInfo;
      <br>
          enet_uint8 address[16];
      <br>
          enet_uint32 scopeId;
      <br>
      };
      <br>
      <br>
      Then have:
      <br>
      <br>
      ENET_HOST_IPV6 = 0xAC1111AC
      <br>
      <br>
      ... where the above is some hex palindrome (reads same in both big
      and little endian) is otherwise not a public ipv4 host.
      <br>
      <br>
      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.
      <br>
      <br>
      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.
      <br>
      <br>
      On 07/07/2013 09:23 PM, James Bellinger wrote:
      <br>
      <blockquote type="cite">On 7/7/2013 12:10 PM, John Cotton Ericson
        wrote:
        <br>
        <blockquote type="cite">I recently submitted a patch "sketching"
          IPv6 support for ENet:
          <a class="moz-txt-link-freetext" href="https://github.com/lsalzman/enet/pull/21">https://github.com/lsalzman/enet/pull/21</a> . 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.
          <br>
          <br>
          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:
          <br>
          <br>
          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.
          <br>
          <br>
        </blockquote>
        It doesn't have to break anything. Here's one possible route...
        <br>
        <br>
        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.
        <br>
        Have it initialized with accessor functions, and give it a
        structure like
        <br>
        <br>
        struct ENetAddress2
        <br>
        {
        <br>
        uint8_t magicIPv6Marker[6];
        <br>
        real data like port, address, type, etc;
        <br>
        };
        <br>
        <br>
        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.
        <br>
        <br>
        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.
        <br>
        <br>
        Something like that. Your thoughts?
        <br>
        <br>
        <blockquote type="cite">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.
          <br>
        </blockquote>
        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.
        <br>
        <br>
        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.
        <br>
        <br>
        James
        <br>
        _______________________________________________
        <br>
        ENet-discuss mailing list
        <br>
        <a class="moz-txt-link-abbreviated" href="mailto:ENet-discuss@cubik.org">ENet-discuss@cubik.org</a>
        <br>
        <a class="moz-txt-link-freetext" href="http://lists.cubik.org/mailman/listinfo/enet-discuss">http://lists.cubik.org/mailman/listinfo/enet-discuss</a>
        <br>
        <br>
      </blockquote>
      <br>
      _______________________________________________
      <br>
      ENet-discuss mailing list
      <br>
      <a class="moz-txt-link-abbreviated" href="mailto:ENet-discuss@cubik.org">ENet-discuss@cubik.org</a>
      <br>
      <a class="moz-txt-link-freetext" href="http://lists.cubik.org/mailman/listinfo/enet-discuss">http://lists.cubik.org/mailman/listinfo/enet-discuss</a>
      <br>
    </blockquote>
    <br>
  </body>
</html>