darcs patch: Implementation of aton and ntoa outside the IO monad

Sun Sep 24 10:06:48 JST 2006 Robert Marlow

Erk, I just realised this patch is completely wrong since the HostAddress will be totally different depending on the endianness of the platform. I'm looking into writing some utilities for handling endianness etc since it would be nice to be able to do I/O with raw bytes in haskell. In the meantime, please ignore this patch. On Sun, 2006-09-24 at 10:08 +0900, Robert Marlow wrote:
Sun Sep 24 10:06:48 JST 2006 Robert Marlow
* Implementation of aton and ntoa outside the IO monad inet_ntoa and inet_aton can be implemented purely to avoid the need for the IO monad. Additionally, inet_addr is currently incorrect due to using the inet_addr C function which is considered obsolete due to incorrectly failing while converting 255.255.255.255 as an address. _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries -- Robert Marlow

On Sun, Sep 24, 2006 at 05:07:23PM +0900, Robert Marlow wrote:
Erk, I just realised this patch is completely wrong since the HostAddress will be totally different depending on the endianness of the platform.
I was thinking about it before. As of now, Network libraries just put bits in network order into values of type HostAddress = Word32. But Word32 is interpreted in host order by Haskell, so the same IP address will be seen as a different number on little and big endian platforms. The best would be to have an endianness independent representation for IP4 addresses, by converting IP addresses to host order. This way things are simple - the most significant octet of IP address with be the most significant 8-bits of HostAddress, etc. Conversion to/from network order could be done around calls to various system calls. Yes, it adds an (small) additional cost (on little endian machines), but I think it's worth it. With current design you sometimes can't avoid impure and/or inelegant code. Best regards Tomasz

I think HostAddresses are probably good how they are now. It seems a bit too much work to convert a HostAddresses endianness everytime it's used. If the problem is how it appears (which along with PortAddress can be confusing) perhaps it just needs a different show implementation. I've attached some Byte utilities. I don't know if this would be considered useful to the Haskell libraries or not, but I find it useful for doing things like outputing raw binary and messing with endianness. It's poorly documented, but I can fix that if it's considered useful. On Sun, 2006-09-24 at 11:42 +0200, Tomasz Zielonka wrote:
I was thinking about it before. As of now, Network libraries just put bits in network order into values of type HostAddress = Word32. But Word32 is interpreted in host order by Haskell, so the same IP address will be seen as a different number on little and big endian platforms.
The best would be to have an endianness independent representation for IP4 addresses, by converting IP addresses to host order. This way things are simple - the most significant octet of IP address with be the most significant 8-bits of HostAddress, etc.
Conversion to/from network order could be done around calls to various system calls. Yes, it adds an (small) additional cost (on little endian machines), but I think it's worth it. With current design you sometimes can't avoid impure and/or inelegant code.
Best regards Tomasz
--
Robert Marlow

On Mon, Sep 25, 2006 at 05:09:13PM +0900, Robert Marlow wrote:
I think HostAddresses are probably good how they are now. It seems a bit too much work to convert a HostAddresses endianness everytime it's used.
Do you mean too much work for the programmer or for the computer? If the latter, then I propose to make HostAddresses an abstract newtype, which doesn't allow to observe the endianness of the platform. Internally it could still keep the address in network order, so no conversions would be neccessary. However, the easiest way to implement eg. comparisons for such a datatype would be to flip endianness before comparing. So you will have to pay the cost of conversion for some operations. I would prefer if this cost was associated with network operations (connect, sentto, recvfrom, ...), because they already have a relatively big cost and you don't call them so often.
If the problem is how it appears (which along with PortAddress can be confusing) perhaps it just needs a different show implementation.
The problem is everything that gives different results on platforms with different byte-orders. Show is one example, but there are also arithmetic operations, Ord, etc. Best regards Tomasz

On 9/25/06, Tomasz Zielonka
On Mon, Sep 25, 2006 at 05:09:13PM +0900, Robert Marlow wrote:
I think HostAddresses are probably good how they are now. It seems a bit too much work to convert a HostAddresses endianness everytime it's used.
Do you mean too much work for the programmer or for the computer?
If the latter, then I propose to make HostAddresses an abstract newtype, which doesn't allow to observe the endianness of the platform.
I'm surprised it isn't one already... I believe port numbers are.
Internally it could still keep the address in network order, so no conversions would be neccessary. However, the easiest way to implement eg. comparisons for such a datatype would be to flip endianness before comparing. So you will have to pay the cost of conversion for some operations. I would prefer if this cost was associated with network operations (connect, sentto, recvfrom, ...), because they already have a relatively big cost and you don't call them so often.
How often do you need to do comparisons on addresses for anything but equality (which doesn't require flipping to test)?
If the problem is how it appears (which along with PortAddress can be confusing) perhaps it just needs a different show implementation.
The problem is everything that gives different results on platforms with different byte-orders. Show is one example, but there are also arithmetic operations, Ord, etc.
... How often do you need to do arithmatic? Oh, btw, there are ntoh*/hton* functions for converting between host and network byte orders regardless of how crazy the host byte-order is...

On Tue, Sep 26, 2006 at 09:00:33AM -0400, Samuel Bronson wrote:
How often do you need to do comparisons on addresses for anything but equality (which doesn't require flipping to test)?
I may want to see if a HostAddresses is in a certain range of addresses - for example, a range assigned by an one of internet registries. Here it's actually important what ordering relation we use. The current one is useless. I may want to use (Map HostAddress something) or (Set HostAddress). I may want to sort HostAddresses to remove duplicates.
The problem is everything that gives different results on platforms with different byte-orders. Show is one example, but there are also arithmetic operations, Ord, etc.
... How often do you need to do arithmatic?
Additions, multiplications... rather not. But Data.Bits operations can be useful to manipulate netmasks and network addresses.
Oh, btw, there are ntoh*/hton* functions for converting between host and network byte orders regardless of how crazy the host byte-order is...
Why not do it better? Network byte order is meant to be used over the *network*. It is unfortunate that BSD sockets don't hide that detail from the programmer. I think Haskell should be a bit above the level of IP frames. Do you have any good reasons to keep the current status besides: - "we don't want additional conversions" - "that's how it's done in C" - "you don't need it" ? Best regards Tomasz

Hello Robert, Monday, September 25, 2006, 12:09:13 PM, you wrote:
data ByteOrder = BigEndian | LittleEndian deriving ( Eq, Show, Read )
jfyi: there are (very rare) computers that are not LE nor BE. afaik, VAX was one - it has smth like 1032 byte order, mixing BE in 2-byte words and LE of 2-byte words in 4-byte word (or vice versa, i'm not sure)
flipEndian :: Integral a => a -> a flipEndian = wordConcat . reverse . toWord8s
a bit faster: flipEndian n = let w1 = (n ) .&. 0xff w2 = (n >># 8) .&. 0xff w3 = (n >># 16) .&. 0xff w4 = (n >># 24) in (w1 <<# 24) .|. (w2 <<# 16) .|. (w3 <<# 8) .|. w4 #ifdef __GLASGOW_HASKELL__ (I# a) <<# (I# b) = (I# (a `iShiftL#` b)) (I# a) >># (I# b) = (I# (a `uncheckedIShiftRL#` b)) #else /* ! __GLASGOW_HASKELL__ */ a <<# b = a `shiftL` b a >># b = a `shiftR` b #endif /* ! __GLASGOW_HASKELL__ */ -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

On Mon, 2006-09-25 at 12:47 +0400, Bulat Ziganshin wrote:
Hello Robert,
jfyi: there are (very rare) computers that are not LE nor BE. afaik, VAX was one - it has smth like 1032 byte order, mixing BE in 2-byte words and LE of 2-byte words in 4-byte word (or vice versa, i'm not sure)
Yeah, I had a look for how people check such things in C and I didn't come accross any solutions for "middle-endianness" like that so I figured it was rare enough to ignore. Ultimately, it's not going to matter unless there are haskell compilers for these crazy platforms :) Is there any haskell compilers running on middle-endian platforms?
flipEndian :: Integral a => a -> a flipEndian = wordConcat . reverse . toWord8s
Heh, yeah I guess that was pretty lazy of me :)
a bit faster:
flipEndian n = let w1 = (n ) .&. 0xff w2 = (n >># 8) .&. 0xff w3 = (n >># 16) .&. 0xff w4 = (n >># 24) in (w1 <<# 24) .|. (w2 <<# 16) .|. (w3 <<# 8) .|. w4
#ifdef __GLASGOW_HASKELL__
(I# a) <<# (I# b) = (I# (a `iShiftL#` b)) (I# a) >># (I# b) = (I# (a `uncheckedIShiftRL#` b))
#else /* ! __GLASGOW_HASKELL__ */
a <<# b = a `shiftL` b a >># b = a `shiftR` b
#endif /* ! __GLASGOW_HASKELL__ */
Thanks
--
Robert Marlow

The VAX is little endian for 32 bit numbers. It's only 64 bit double that are stored with the longwords reversed. The PDP-11 on the other hand did swap the (16 bit) words when storing a (32 bit) long, compared to little endian. -- Lennart On Sep 25, 2006, at 04:47 , Bulat Ziganshin wrote:
Hello Robert,
Monday, September 25, 2006, 12:09:13 PM, you wrote:
data ByteOrder = BigEndian | LittleEndian deriving ( Eq, Show, Read )
jfyi: there are (very rare) computers that are not LE nor BE. afaik, VAX was one - it has smth like 1032 byte order, mixing BE in 2-byte words and LE of 2-byte words in 4-byte word (or vice versa, i'm not sure)
flipEndian :: Integral a => a -> a flipEndian = wordConcat . reverse . toWord8s
a bit faster:
flipEndian n = let w1 = (n ) .&. 0xff w2 = (n >># 8) .&. 0xff w3 = (n >># 16) .&. 0xff w4 = (n >># 24) in (w1 <<# 24) .|. (w2 <<# 16) .|. (w3 <<# 8) .|. w4
#ifdef __GLASGOW_HASKELL__
(I# a) <<# (I# b) = (I# (a `iShiftL#` b)) (I# a) >># (I# b) = (I# (a `uncheckedIShiftRL#` b))
#else /* ! __GLASGOW_HASKELL__ */
a <<# b = a `shiftL` b a >># b = a `shiftR` b
#endif /* ! __GLASGOW_HASKELL__ */
-- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
participants (5)
-
Bulat Ziganshin
-
Lennart Augustsson
-
Robert Marlow
-
Samuel Bronson
-
Tomasz Zielonka