@@ -10,7 +10,6 @@ module Network.Socket.Info where
10
10
11
11
import Foreign.Marshal.Alloc (alloca , allocaBytes )
12
12
import Foreign.Marshal.Utils (maybeWith , with )
13
- import GHC.IO (unsafePerformIO )
14
13
import GHC.IO.Exception (IOErrorType (NoSuchThing ))
15
14
import System.IO.Error (ioeSetErrorString , mkIOError )
16
15
@@ -441,16 +440,50 @@ instance Show SockAddr where
441
440
#else
442
441
showsPrec _ SockAddrUnix {} = error " showsPrec: not supported"
443
442
#endif
444
- showsPrec _ addr@ (SockAddrInet port _)
445
- = showString (unsafePerformIO $
446
- fst <$> getNameInfo [NI_NUMERICHOST ] True False addr >>=
447
- maybe (fail " showsPrec: impossible internal error" ) return )
443
+ showsPrec _ (SockAddrInet port ha)
444
+ = showHostAddress ha
448
445
. showString " :"
449
446
. shows port
450
- showsPrec _ addr @ (SockAddrInet6 port _ _ _)
447
+ showsPrec _ (SockAddrInet6 port _ ha6 _)
451
448
= showChar ' ['
452
- . showString (unsafePerformIO $
453
- fst <$> getNameInfo [NI_NUMERICHOST ] True False addr >>=
454
- maybe (fail " showsPrec: impossible internal error" ) return )
449
+ . showHostAddress6 ha6
455
450
. showString " ]:"
456
451
. shows port
452
+
453
+
454
+ -- Taken from on the implementation of showIPv4 in Data.IP.Addr
455
+ showHostAddress :: HostAddress -> ShowS
456
+ showHostAddress ip =
457
+ let (u3, u2, u1, u0) = hostAddressToTuple ip in
458
+ foldr1 (.) . intersperse (showChar ' .' ) $ map showInt [u3, u2, u1, u0]
459
+
460
+ -- Taken from showIPv6 in Data.IP.Addr.
461
+
462
+ -- | Show an IPv6 address in the most appropriate notation, based on recommended
463
+ -- representation proposed by <http://tools.ietf.org/html/rfc5952 RFC 5952>.
464
+ --
465
+ -- /The implementation is completely compatible with the current implementation
466
+ -- of the `inet_ntop` function in glibc./
467
+ showHostAddress6 :: HostAddress6 -> ShowS
468
+ showHostAddress6 ha6@ (a1, a2, a3, a4)
469
+ -- IPv4-Mapped IPv6 Address
470
+ | a1 == 0 && a2 == 0 && a3 == 0xffff =
471
+ showString " ::ffff:" . showHostAddress a4
472
+ -- IPv4-Compatible IPv6 Address (exclude IPRange ::/112)
473
+ | a1 == 0 && a2 == 0 && a3 == 0 && a4 >= 0x10000 =
474
+ showString " ::" . showHostAddress a4
475
+ -- length of longest run > 1, replace it with "::"
476
+ | end - begin > 1 =
477
+ showFields prefix . showString " ::" . showFields suffix
478
+ | otherwise =
479
+ showFields fields
480
+ where
481
+ fields =
482
+ let (u7, u6, u5, u4, u3, u2, u1, u0) = hostAddress6ToTuple ha6 in
483
+ [u7, u6, u5, u4, u3, u2, u1, u0]
484
+ showFields = foldr (.) id . intersperse (showChar ' :' ) . map showHex
485
+ prefix = take begin fields -- fields before "::"
486
+ suffix = drop end fields -- fields after "::"
487
+ begin = end + diff -- the longest run of zeros
488
+ (diff, end) = minimum $
489
+ scanl (\ c i -> if i == 0 then c - 1 else 0 ) 0 fields `zip` [0 .. ]
0 commit comments