| 1 | |
|---|
| 2 | New patches: |
|---|
| 3 | |
|---|
| 4 | [Add IPv6 support. |
|---|
| 5 | Bryan O'Sullivan <bos@serpentine.com>**20070331183923 |
|---|
| 6 | |
|---|
| 7 | The only public API changes are to Network.Socket, which has the following |
|---|
| 8 | exported names added (no existing names have been removed): |
|---|
| 9 | |
|---|
| 10 | -- IPv6 address components |
|---|
| 11 | HostAddress6 |
|---|
| 12 | FlowInfo |
|---|
| 13 | ScopeID |
|---|
| 14 | |
|---|
| 15 | -- Name -> address lookup |
|---|
| 16 | getAddrInfo |
|---|
| 17 | AddrInfo |
|---|
| 18 | AddrInfoFlags |
|---|
| 19 | aI_PASSIVE |
|---|
| 20 | aI_CANONNAME |
|---|
| 21 | aI_NUMERICHOST |
|---|
| 22 | aI_ADDRCONFIG |
|---|
| 23 | defaultHints |
|---|
| 24 | |
|---|
| 25 | -- Address -> name lookup |
|---|
| 26 | getNameInfo |
|---|
| 27 | NameInfoFlags |
|---|
| 28 | nI_NOFQDN |
|---|
| 29 | nI_NUMERICHOST |
|---|
| 30 | nI_NAMEREQD |
|---|
| 31 | nI_NUMERICSERV |
|---|
| 32 | nI_DGRAM |
|---|
| 33 | |
|---|
| 34 | The SockAddr type acquires a new branch, SockAddr6. (This could cause |
|---|
| 35 | new "non-exhaustive matches" warnings when compiling pre-existing client |
|---|
| 36 | code that pattern-matches on SockAddr values. However, it will not |
|---|
| 37 | cause runtime pattern failure errors in clients using the pre-existing |
|---|
| 38 | IPv4 entry points, as they will never see IPv6 addresses.) |
|---|
| 39 | |
|---|
| 40 | This change moves a few type names from Network.BSD to Network.Socket: |
|---|
| 41 | |
|---|
| 42 | HostName |
|---|
| 43 | ServiceName |
|---|
| 44 | |
|---|
| 45 | These names are still re-exported from Network.BSD, so pre-existing code |
|---|
| 46 | should not be affected. |
|---|
| 47 | ] { |
|---|
| 48 | hunk ./Network/BSD.hsc 117 |
|---|
| 49 | -type HostName = String |
|---|
| 50 | hunk ./Network/BSD.hsc 118 |
|---|
| 51 | -type ServiceName = String |
|---|
| 52 | hunk ./Network/BSD.hsc 299 |
|---|
| 53 | --- | This is the default protocol for the given service. |
|---|
| 54 | -defaultProtocol :: ProtocolNumber |
|---|
| 55 | -defaultProtocol = 0 |
|---|
| 56 | - |
|---|
| 57 | hunk ./Network/Socket.hsc 54 |
|---|
| 58 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 59 | + HostAddress6, |
|---|
| 60 | + FlowInfo, |
|---|
| 61 | + ScopeID, |
|---|
| 62 | +#endif |
|---|
| 63 | hunk ./Network/Socket.hsc 65 |
|---|
| 64 | + -- * Address operations |
|---|
| 65 | + |
|---|
| 66 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 67 | + AddrInfo(..), |
|---|
| 68 | + |
|---|
| 69 | + AddrInfoFlags, |
|---|
| 70 | + aI_PASSIVE, |
|---|
| 71 | + aI_CANONNAME, |
|---|
| 72 | + aI_NUMERICHOST, |
|---|
| 73 | + aI_ADDRCONFIG, |
|---|
| 74 | + |
|---|
| 75 | + HostName, |
|---|
| 76 | + ServiceName, |
|---|
| 77 | + |
|---|
| 78 | + defaultHints, -- :: AddrInfo |
|---|
| 79 | + defaultProtocol, -- :: ProtocolNumber |
|---|
| 80 | + |
|---|
| 81 | + getAddrInfo, -- :: Maybe AddrInfo -> Maybe HostName -> Maybe ServiceName -> IO [AddrInfo] |
|---|
| 82 | + |
|---|
| 83 | + NameInfoFlags, |
|---|
| 84 | + nI_NOFQDN, |
|---|
| 85 | + nI_NUMERICHOST, |
|---|
| 86 | + nI_NAMEREQD, |
|---|
| 87 | + nI_NUMERICSERV, |
|---|
| 88 | + nI_DGRAM, |
|---|
| 89 | + |
|---|
| 90 | + getNameInfo, -- :: NameInfoFlags -> Bool -> Bool -> SockAddr -> IO (Maybe HostName, Maybe ServiceName) |
|---|
| 91 | +#endif |
|---|
| 92 | + |
|---|
| 93 | hunk ./Network/Socket.hsc 157 |
|---|
| 94 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 95 | + iN6ADDR_ANY, -- :: HostAddress6 |
|---|
| 96 | +#endif |
|---|
| 97 | hunk ./Network/Socket.hsc 204 |
|---|
| 98 | -import Foreign.Ptr ( Ptr, castPtr, plusPtr ) |
|---|
| 99 | +import Foreign.Ptr ( Ptr, castPtr, nullPtr, plusPtr ) |
|---|
| 100 | hunk ./Network/Socket.hsc 207 |
|---|
| 101 | -import Foreign.C.String ( withCString, peekCString, peekCStringLen, castCharToCChar ) |
|---|
| 102 | +import Foreign.C.String ( CString, withCString, peekCString, peekCStringLen, castCharToCChar ) |
|---|
| 103 | hunk ./Network/Socket.hsc 211 |
|---|
| 104 | -import Foreign.Marshal.Utils ( with ) |
|---|
| 105 | +import Foreign.Marshal.Utils ( maybeWith, with ) |
|---|
| 106 | hunk ./Network/Socket.hsc 234 |
|---|
| 107 | +type HostName = String |
|---|
| 108 | +type ServiceName = String |
|---|
| 109 | + |
|---|
| 110 | hunk ./Network/Socket.hsc 298 |
|---|
| 111 | +-- | This is the default protocol for a given service. |
|---|
| 112 | +defaultProtocol :: ProtocolNumber |
|---|
| 113 | +defaultProtocol = 0 |
|---|
| 114 | + |
|---|
| 115 | hunk ./Network/Socket.hsc 307 |
|---|
| 116 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 117 | +type HostAddress6 = (Word32, Word32, Word32, Word32) |
|---|
| 118 | +#endif |
|---|
| 119 | + |
|---|
| 120 | hunk ./Network/Socket.hsc 381 |
|---|
| 121 | --- families. Currently only Unix domain sockets and the Internet family |
|---|
| 122 | --- are supported. |
|---|
| 123 | +-- families. Currently only Unix domain sockets and the Internet |
|---|
| 124 | +-- families are supported. |
|---|
| 125 | + |
|---|
| 126 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 127 | +type FlowInfo = Word32 |
|---|
| 128 | +type ScopeID = Word32 |
|---|
| 129 | +#endif |
|---|
| 130 | hunk ./Network/Socket.hsc 393 |
|---|
| 131 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 132 | + | SockAddrInet6 |
|---|
| 133 | + PortNumber -- sin6_port (network byte order) |
|---|
| 134 | + FlowInfo -- sin6_flowinfo (ditto) |
|---|
| 135 | + HostAddress6 -- sin6_addr (ditto) |
|---|
| 136 | + ScopeID -- sin6_scope_id (ditto) |
|---|
| 137 | +#endif |
|---|
| 138 | hunk ./Network/Socket.hsc 424 |
|---|
| 139 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 140 | + showsPrec _ addr@(SockAddrInet6 port _ _ _) |
|---|
| 141 | + = showChar '[' |
|---|
| 142 | + . showString (unsafePerformIO $ |
|---|
| 143 | + fst `liftM` getNameInfo nI_NUMERICHOST True False addr >>= |
|---|
| 144 | + maybe (fail "showsPrec: impossible internal error") return) |
|---|
| 145 | + . showString "]:" |
|---|
| 146 | + . shows port |
|---|
| 147 | + |
|---|
| 148 | +instance Storable HostAddress6 where |
|---|
| 149 | + sizeOf _ = (#const sizeof(struct in6_addr)) |
|---|
| 150 | + alignment _ = alignment (undefined :: CInt) |
|---|
| 151 | + |
|---|
| 152 | + peek p = do |
|---|
| 153 | + a <- (#peek struct in6_addr, s6_addr32[0]) p |
|---|
| 154 | + b <- (#peek struct in6_addr, s6_addr32[1]) p |
|---|
| 155 | + c <- (#peek struct in6_addr, s6_addr32[2]) p |
|---|
| 156 | + d <- (#peek struct in6_addr, s6_addr32[3]) p |
|---|
| 157 | + return (a, b, c, d) |
|---|
| 158 | + |
|---|
| 159 | + poke p (a, b, c, d) = do |
|---|
| 160 | + (#poke struct in6_addr, s6_addr32[0]) p a |
|---|
| 161 | + (#poke struct in6_addr, s6_addr32[1]) p b |
|---|
| 162 | + (#poke struct in6_addr, s6_addr32[2]) p c |
|---|
| 163 | + (#poke struct in6_addr, s6_addr32[3]) p d |
|---|
| 164 | +#endif |
|---|
| 165 | hunk ./Network/Socket.hsc 471 |
|---|
| 166 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 167 | +pokeSockAddr p (SockAddrInet6 (PortNum port) flow addr scope) = do |
|---|
| 168 | +#if defined(darwin_TARGET_OS) |
|---|
| 169 | + zeroMemory p (#const sizeof(struct sockaddr_in6)) |
|---|
| 170 | +#endif |
|---|
| 171 | + (#poke struct sockaddr_in6, sin6_family) p ((#const AF_INET6) :: CSaFamily) |
|---|
| 172 | + (#poke struct sockaddr_in6, sin6_port) p port |
|---|
| 173 | + (#poke struct sockaddr_in6, sin6_flowinfo) p flow |
|---|
| 174 | + (#poke struct sockaddr_in6, sin6_addr) p addr |
|---|
| 175 | + (#poke struct sockaddr_in6, sin6_scope_id) p scope |
|---|
| 176 | +#endif |
|---|
| 177 | + |
|---|
| 178 | +peekSockAddr :: Ptr SockAddr -> IO SockAddr |
|---|
| 179 | hunk ./Network/Socket.hsc 497 |
|---|
| 180 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 181 | + (#const AF_INET6) -> do |
|---|
| 182 | + port <- (#peek struct sockaddr_in6, sin6_port) p |
|---|
| 183 | + flow <- (#peek struct sockaddr_in6, sin6_flowinfo) p |
|---|
| 184 | + addr <- (#peek struct sockaddr_in6, sin6_addr) p |
|---|
| 185 | + scope <- (#peek struct sockaddr_in6, sin6_scope_id) p |
|---|
| 186 | + return (SockAddrInet6 (PortNum port) flow addr scope) |
|---|
| 187 | +#endif |
|---|
| 188 | hunk ./Network/Socket.hsc 522 |
|---|
| 189 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 190 | +sizeOfSockAddr (SockAddrInet6 _ _ _ _) = #const sizeof(struct sockaddr_in6) |
|---|
| 191 | +#endif |
|---|
| 192 | hunk ./Network/Socket.hsc 908 |
|---|
| 193 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 194 | +socketPort sock@(MkSocket _ AF_INET6 _ _ _) = do |
|---|
| 195 | + (SockAddrInet6 port _ _ _) <- getSocketName sock |
|---|
| 196 | + return port |
|---|
| 197 | +#endif |
|---|
| 198 | hunk ./Network/Socket.hsc 1250 |
|---|
| 199 | +unpackSocketType:: CInt -> SocketType |
|---|
| 200 | hunk ./Network/Socket.hsc 1893 |
|---|
| 201 | +unpackSocketType t = case t of |
|---|
| 202 | + 0 -> NoSocketType |
|---|
| 203 | +#ifdef SOCK_STREAM |
|---|
| 204 | + (#const SOCK_STREAM) -> Stream |
|---|
| 205 | +#endif |
|---|
| 206 | +#ifdef SOCK_DGRAM |
|---|
| 207 | + (#const SOCK_DGRAM) -> Datagram |
|---|
| 208 | +#endif |
|---|
| 209 | +#ifdef SOCK_RAW |
|---|
| 210 | + (#const SOCK_RAW) -> Raw |
|---|
| 211 | +#endif |
|---|
| 212 | +#ifdef SOCK_RDM |
|---|
| 213 | + (#const SOCK_RDM) -> RDM |
|---|
| 214 | +#endif |
|---|
| 215 | +#ifdef SOCK_SEQPACKET |
|---|
| 216 | + (#const SOCK_SEQPACKET) -> SeqPacket |
|---|
| 217 | +#endif |
|---|
| 218 | + |
|---|
| 219 | hunk ./Network/Socket.hsc 1920 |
|---|
| 220 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 221 | +iN6ADDR_ANY :: HostAddress6 |
|---|
| 222 | +iN6ADDR_ANY = (0, 0, 0, 0) |
|---|
| 223 | +#endif |
|---|
| 224 | + |
|---|
| 225 | hunk ./Network/Socket.hsc 2050 |
|---|
| 226 | + |
|---|
| 227 | + |
|---|
| 228 | +----------------------------------------------------------------------------- |
|---|
| 229 | +-- Address and service lookups |
|---|
| 230 | + |
|---|
| 231 | +#if defined(IPV6_SOCKET_SUPPORT) |
|---|
| 232 | + |
|---|
| 233 | +-- | Flags that control the querying behaviour of 'getAddrInfo'. |
|---|
| 234 | +type AddrInfoFlags = CInt |
|---|
| 235 | + |
|---|
| 236 | +-- Portable flags. |
|---|
| 237 | + |
|---|
| 238 | +aI_PASSIVE :: AddrInfoFlags |
|---|
| 239 | +aI_PASSIVE = (#const AI_PASSIVE) |
|---|
| 240 | +aI_CANONNAME :: AddrInfoFlags |
|---|
| 241 | +aI_CANONNAME = (#const AI_CANONNAME) |
|---|
| 242 | +aI_NUMERICHOST :: AddrInfoFlags |
|---|
| 243 | +aI_NUMERICHOST = (#const AI_NUMERICHOST) |
|---|
| 244 | +aI_ADDRCONFIG :: AddrInfoFlags |
|---|
| 245 | +aI_ADDRCONFIG = (#const AI_ADDRCONFIG) |
|---|
| 246 | + |
|---|
| 247 | +data AddrInfo = |
|---|
| 248 | + AddrInfo { |
|---|
| 249 | + addrFlags :: AddrInfoFlags, |
|---|
| 250 | + addrFamily :: Family, |
|---|
| 251 | + addrSocketType :: SocketType, |
|---|
| 252 | + addrProtocol :: ProtocolNumber, |
|---|
| 253 | + addrAddress :: SockAddr, |
|---|
| 254 | + addrCanonName :: Maybe String |
|---|
| 255 | + } |
|---|
| 256 | + deriving (Show) |
|---|
| 257 | + |
|---|
| 258 | +INSTANCE_TYPEABLE0(AddrInfo,addrInfoTc,"AddrInfo") |
|---|
| 259 | + |
|---|
| 260 | +instance Storable AddrInfo where |
|---|
| 261 | + sizeOf _ = #const sizeof(struct addrinfo) |
|---|
| 262 | + alignment _ = alignment (undefined :: CInt) |
|---|
| 263 | + |
|---|
| 264 | + peek p = do |
|---|
| 265 | + ai_flags <- (#peek struct addrinfo, ai_flags) p |
|---|
| 266 | + ai_family <- (#peek struct addrinfo, ai_family) p |
|---|
| 267 | + ai_socktype <- (#peek struct addrinfo, ai_socktype) p |
|---|
| 268 | + ai_protocol <- (#peek struct addrinfo, ai_protocol) p |
|---|
| 269 | + ai_addr <- (#peek struct addrinfo, ai_addr) p >>= peekSockAddr |
|---|
| 270 | + ai_canonname_ptr <- (#peek struct addrinfo, ai_canonname) p |
|---|
| 271 | + |
|---|
| 272 | + ai_canonname <- if ai_canonname_ptr == nullPtr |
|---|
| 273 | + then return Nothing |
|---|
| 274 | + else liftM Just $ peekCString ai_canonname_ptr |
|---|
| 275 | + |
|---|
| 276 | + return (AddrInfo |
|---|
| 277 | + { |
|---|
| 278 | + addrFlags = ai_flags, |
|---|
| 279 | + addrFamily = unpackFamily ai_family, |
|---|
| 280 | + addrSocketType = unpackSocketType ai_socktype, |
|---|
| 281 | + addrProtocol = ai_protocol, |
|---|
| 282 | + addrAddress = ai_addr, |
|---|
| 283 | + addrCanonName = ai_canonname |
|---|
| 284 | + }) |
|---|
| 285 | + |
|---|
| 286 | + poke p (AddrInfo flags family socketType protocol _ _) = do |
|---|
| 287 | + (#poke struct addrinfo, ai_flags) p flags |
|---|
| 288 | + (#poke struct addrinfo, ai_family) p (packFamily family) |
|---|
| 289 | + (#poke struct addrinfo, ai_socktype) p (packSocketType socketType) |
|---|
| 290 | + (#poke struct addrinfo, ai_protocol) p protocol |
|---|
| 291 | + |
|---|
| 292 | + -- stuff below is probably not needed, but let's zero it for safety |
|---|
| 293 | + |
|---|
| 294 | + (#poke struct addrinfo, ai_addrlen) p (0::CSize) |
|---|
| 295 | + (#poke struct addrinfo, ai_addr) p nullPtr |
|---|
| 296 | + (#poke struct addrinfo, ai_canonname) p nullPtr |
|---|
| 297 | + (#poke struct addrinfo, ai_next) p nullPtr |
|---|
| 298 | + |
|---|
| 299 | +type NameInfoFlags = CInt |
|---|
| 300 | + |
|---|
| 301 | +nI_NOFQDN :: NameInfoFlags |
|---|
| 302 | +nI_NOFQDN = (#const NI_NOFQDN) |
|---|
| 303 | +nI_NUMERICHOST :: NameInfoFlags |
|---|
| 304 | +nI_NUMERICHOST = (#const NI_NUMERICHOST) |
|---|
| 305 | +nI_NAMEREQD :: NameInfoFlags |
|---|
| 306 | +nI_NAMEREQD = (#const NI_NAMEREQD) |
|---|
| 307 | +nI_NUMERICSERV :: NameInfoFlags |
|---|
| 308 | +nI_NUMERICSERV = (#const NI_NUMERICSERV) |
|---|
| 309 | +nI_DGRAM :: NameInfoFlags |
|---|
| 310 | +nI_DGRAM = (#const NI_DGRAM) |
|---|
| 311 | + |
|---|
| 312 | +-- | Default hints for address lookup with 'getAddrInfo'. The values |
|---|
| 313 | +-- of the 'addrAddress' and 'addrCanonName' fields are 'undefined', |
|---|
| 314 | +-- and are never inspected by 'getAddrInfo'. |
|---|
| 315 | + |
|---|
| 316 | +defaultHints :: AddrInfo |
|---|
| 317 | + |
|---|
| 318 | +defaultHints = AddrInfo { |
|---|
| 319 | + addrFlags = 0, |
|---|
| 320 | + addrFamily = AF_UNSPEC, |
|---|
| 321 | + addrSocketType = NoSocketType, |
|---|
| 322 | + addrProtocol = defaultProtocol, |
|---|
| 323 | + addrAddress = undefined, |
|---|
| 324 | + addrCanonName = undefined |
|---|
| 325 | + } |
|---|
| 326 | + |
|---|
| 327 | +-- | Resolve a host or service name query to one or more addresses. |
|---|
| 328 | +-- The 'AddrInfo' values that this function returns contain 'SockAddr' |
|---|
| 329 | +-- values that you can pass directly to 'connect' or |
|---|
| 330 | +-- 'bindSocket'. |
|---|
| 331 | +-- |
|---|
| 332 | +-- The 'AddrInfo' argument specifies the preferred query behaviour, |
|---|
| 333 | +-- socket options, or protocol. You can override these conveniently |
|---|
| 334 | +-- using Haskell's record update syntax on 'defaultHints', for example |
|---|
| 335 | +-- as follows: |
|---|
| 336 | +-- |
|---|
| 337 | +-- @ |
|---|
| 338 | +-- myHints = defaultHints { addrFlags = aI_ADDRCONFIG + aI_CANONNAME } |
|---|
| 339 | +-- @ |
|---|
| 340 | +-- |
|---|
| 341 | +-- Values for 'addrFlags' can be /or/ed together, and control query |
|---|
| 342 | +-- behaviour. The portable values are as follows: |
|---|
| 343 | +-- |
|---|
| 344 | +-- [@aI_PASSIVE@] If no 'HostName' value is provided, the network |
|---|
| 345 | +-- address in each 'SockAddr' |
|---|
| 346 | +-- will be left as a "wild card", i.e. as either 'iNADDR_ANY' |
|---|
| 347 | +-- or 'iN6ADDR_ANY'. This is useful for server applications that |
|---|
| 348 | +-- will accept connections from any client. |
|---|
| 349 | +-- |
|---|
| 350 | +-- [@aI_CANONNAME@] The 'addrCanonName' field of the first returned |
|---|
| 351 | +-- 'AddrInfo' will contain the "canonical name" of the host. |
|---|
| 352 | +-- |
|---|
| 353 | +-- [@aI_NUMERICHOST@] The 'HostName' argument /must/ be a numeric |
|---|
| 354 | +-- address in string form, and network name lookups will not be |
|---|
| 355 | +-- attempted. |
|---|
| 356 | +-- |
|---|
| 357 | +-- [@aI_ADDRCONFIG@] The list of returned 'AddrInfo' values will only |
|---|
| 358 | +-- contain IPv4 addresses if the local system has at least one |
|---|
| 359 | +-- IPv4 interface configured, and likewise for IPv6. |
|---|
| 360 | +-- |
|---|
| 361 | +-- A number of non-portable values for 'addrFlags' may also be |
|---|
| 362 | +-- available, depending on your platform. |
|---|
| 363 | +-- |
|---|
| 364 | +-- You must provide a real value for at least one of the 'HostName' or |
|---|
| 365 | +-- 'ServiceName' arguments. 'HostName' can be either a numeric |
|---|
| 366 | +-- network address (dotted quad for IPv4, hex for IPv6) or a hostname. |
|---|
| 367 | +-- In the latter case, its addresses will be looked up unless |
|---|
| 368 | +-- 'aI_NUMERICHOST' is specified as a hint. If you do not provide a |
|---|
| 369 | +-- 'HostName' value /and/ do not set 'aI_PASSIVE' as a hint, network |
|---|
| 370 | +-- addresses in the result will contain the address of the loopback |
|---|
| 371 | +-- interface. |
|---|
| 372 | +-- |
|---|
| 373 | +-- If the query fails, this function throws an IO exception instead of |
|---|
| 374 | +-- returning an empty list. Otherwise, it returns a non-empty list |
|---|
| 375 | +-- of 'AddrInfo' values. |
|---|
| 376 | +-- |
|---|
| 377 | +-- There are several reasons why a query might result in several |
|---|
| 378 | +-- values. For example, the queried-for host could be multihomed, or |
|---|
| 379 | +-- the service might be available via several protocols. |
|---|
| 380 | +-- |
|---|
| 381 | +-- Note: the order of arguments is slightly different to that defined |
|---|
| 382 | +-- for @getaddrinfo@ in RFC 2553. The 'AddrInfo' parameter comes first |
|---|
| 383 | +-- to make partial application easier. |
|---|
| 384 | +-- |
|---|
| 385 | +-- Example: |
|---|
| 386 | +-- @ |
|---|
| 387 | +-- let hints = defaultHints { addrFlags = aI_ADDRCONFIG + aI_CANONNAME } |
|---|
| 388 | +-- addrs <- getAddrInfo (Just hints) (Just "www.haskell.org") (Just "http") |
|---|
| 389 | +-- let addr = head addrs |
|---|
| 390 | +-- sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr) |
|---|
| 391 | +-- connect sock (addrAddress addr) |
|---|
| 392 | +-- @ |
|---|
| 393 | + |
|---|
| 394 | +getAddrInfo :: Maybe AddrInfo -- ^ preferred socket type or protocol |
|---|
| 395 | + -> Maybe HostName -- ^ host name to look up |
|---|
| 396 | + -> Maybe ServiceName -- ^ service name to look up |
|---|
| 397 | + -> IO [AddrInfo] -- ^ resolved addresses, with "best" first |
|---|
| 398 | + |
|---|
| 399 | +getAddrInfo hints node service = |
|---|
| 400 | + maybeWith withCString node $ \c_node -> |
|---|
| 401 | + maybeWith withCString service $ \c_service -> |
|---|
| 402 | + maybeWith with hints $ \c_hints -> |
|---|
| 403 | + alloca $ \ptr_ptr_addrs -> do |
|---|
| 404 | + ret <- c_getaddrinfo c_node c_service c_hints ptr_ptr_addrs |
|---|
| 405 | + case ret of |
|---|
| 406 | + 0 -> do ptr_addrs <- peek ptr_ptr_addrs |
|---|
| 407 | + ais <- followAddrInfo ptr_addrs |
|---|
| 408 | + c_freeaddrinfo ptr_addrs |
|---|
| 409 | + return ais |
|---|
| 410 | + _ -> do err <- gai_strerror ret |
|---|
| 411 | + ioError (IOError Nothing NoSuchThing "getAddrInfo" err |
|---|
| 412 | + Nothing) |
|---|
| 413 | + |
|---|
| 414 | +followAddrInfo :: Ptr AddrInfo -> IO [AddrInfo] |
|---|
| 415 | + |
|---|
| 416 | +followAddrInfo ptr_ai | ptr_ai == nullPtr = return [] |
|---|
| 417 | + | otherwise = do |
|---|
| 418 | + a <- peek ptr_ai |
|---|
| 419 | + as <- (#peek struct addrinfo, ai_next) ptr_ai >>= followAddrInfo |
|---|
| 420 | + return (a:as) |
|---|
| 421 | + |
|---|
| 422 | +foreign import ccall safe "getaddrinfo" |
|---|
| 423 | + c_getaddrinfo :: CString -> CString -> Ptr AddrInfo -> Ptr (Ptr AddrInfo) |
|---|
| 424 | + -> IO CInt |
|---|
| 425 | + |
|---|
| 426 | +foreign import ccall safe "freeaddrinfo" |
|---|
| 427 | + c_freeaddrinfo :: Ptr AddrInfo -> IO () |
|---|
| 428 | + |
|---|
| 429 | +gai_strerror :: CInt -> IO String |
|---|
| 430 | + |
|---|
| 431 | +gai_strerror n = c_gai_strerror n >>= peekCString |
|---|
| 432 | + |
|---|
| 433 | +foreign import ccall safe "gai_strerror" |
|---|
| 434 | + c_gai_strerror :: CInt -> IO CString |
|---|
| 435 | + |
|---|
| 436 | +withCStringIf :: Bool -> Int -> (CSize -> CString -> IO a) -> IO a |
|---|
| 437 | +withCStringIf False _ f = f 0 nullPtr |
|---|
| 438 | +withCStringIf True n f = allocaBytes n (f (fromIntegral n)) |
|---|
| 439 | + |
|---|
| 440 | +getNameInfo :: NameInfoFlags |
|---|
| 441 | + -> Bool |
|---|
| 442 | + -> Bool |
|---|
| 443 | + -> SockAddr |
|---|
| 444 | + -> IO (Maybe HostName, Maybe ServiceName) |
|---|
| 445 | + |
|---|
| 446 | +getNameInfo flags doHost doService addr = |
|---|
| 447 | + withCStringIf doHost (#const NI_MAXHOST) $ \c_hostlen c_host -> |
|---|
| 448 | + withCStringIf doService (#const NI_MAXSERV) $ \c_servlen c_serv -> do |
|---|
| 449 | + withSockAddr addr $ \ptr_addr sz -> do |
|---|
| 450 | + ret <- c_getnameinfo ptr_addr (fromIntegral sz) c_host c_hostlen |
|---|
| 451 | + c_serv c_servlen flags |
|---|
| 452 | + case ret of |
|---|
| 453 | + 0 -> do |
|---|
| 454 | + let peekIf doIf c_val = if doIf |
|---|
| 455 | + then liftM Just $ peekCString c_val |
|---|
| 456 | + else return Nothing |
|---|
| 457 | + host <- peekIf doHost c_host |
|---|
| 458 | + serv <- peekIf doService c_serv |
|---|
| 459 | + return (host, serv) |
|---|
| 460 | + _ -> do err <- gai_strerror ret |
|---|
| 461 | + ioError (IOError Nothing NoSuchThing "getNameInfo" err |
|---|
| 462 | + Nothing) |
|---|
| 463 | + |
|---|
| 464 | +foreign import ccall safe "getnameinfo" |
|---|
| 465 | + c_getnameinfo :: Ptr SockAddr -> CInt{-CSockLen???-} -> CString -> CSize -> CString |
|---|
| 466 | + -> CSize -> NameInfoFlags -> IO CInt |
|---|
| 467 | +#endif |
|---|
| 468 | hunk ./configure.ac 37 |
|---|
| 469 | +dnl -------------------------------------------------- |
|---|
| 470 | +dnl * test for in6_addr as proxy for IPv6 support |
|---|
| 471 | +dnl -------------------------------------------------- |
|---|
| 472 | +AC_MSG_CHECKING(for in6_addr in netinet/in.h) |
|---|
| 473 | +AC_EGREP_HEADER(in6_addr, netinet/in.h, |
|---|
| 474 | + [ AC_DEFINE([HAVE_IN6_ADDR], [1], [Define to 1 if in6_addr is available.]) AC_MSG_RESULT(yes) ], |
|---|
| 475 | + AC_MSG_RESULT(no)) |
|---|
| 476 | + |
|---|
| 477 | hunk ./include/HsNet.h 28 |
|---|
| 478 | + |
|---|
| 479 | +#ifdef HAVE_IN6_ADDR |
|---|
| 480 | +# define IPV6_SOCKET_SUPPORT 1 |
|---|
| 481 | +#else |
|---|
| 482 | +# undef IPV6_SOCKET_SUPPORT |
|---|
| 483 | +#endif |
|---|
| 484 | hunk ./network.cabal 2 |
|---|
| 485 | -version: 2.0 |
|---|
| 486 | +version: 2.0.1 |
|---|
| 487 | } |
|---|
| 488 | |
|---|
| 489 | Context: |
|---|
| 490 | |
|---|
| 491 | [apply changes from patch "make this test deterministic on a multiprocessor" in testsuite |
|---|
| 492 | Simon Marlow <simonmar@microsoft.com>**20070221142822] |
|---|
| 493 | [tests for use with GHC's test framework, moved from the testsuite |
|---|
| 494 | Simon Marlow <simonmar@microsoft.com>**20070221142258] |
|---|
| 495 | [README about building from darcs |
|---|
| 496 | Ross Paterson <ross@soi.city.ac.uk>**20070218110201] |
|---|
| 497 | [don't install Typeable.h, fixes #1106 |
|---|
| 498 | Simon Marlow <simonmar@microsoft.com>**20070201125821] |
|---|
| 499 | [network doesn't really need the html package |
|---|
| 500 | Ian Lynagh <igloo@earth.li>**20070111122348] |
|---|
| 501 | [includes -> install-includes |
|---|
| 502 | Ross Paterson <ross@soi.city.ac.uk>**20060829123744] |
|---|
| 503 | [change title to Haskell Hierarchical Libraries |
|---|
| 504 | Ross Paterson <ross@soi.city.ac.uk>**20060827131348] |
|---|
| 505 | [exclude Setup.hs from build |
|---|
| 506 | Ross Paterson <ross@soi.city.ac.uk>**20060824183533] |
|---|
| 507 | [add boilerplate Setup.hs |
|---|
| 508 | Ross Paterson <ross@soi.city.ac.uk>**20060824115019] |
|---|
| 509 | [Update Network.BSD header to not mention symlinks. |
|---|
| 510 | Ian Lynagh <igloo@earth.li>**20060823184314] |
|---|
| 511 | [Removed Network.CGI from the network package. A backwards-compatible new Network.CGI is available in the cgi package. |
|---|
| 512 | bringert@cs.chalmers.se**20060814095652] |
|---|
| 513 | [remove deprecated Network.BSD.{readlink,symlink} |
|---|
| 514 | Simon Marlow <simonmar@microsoft.com>**20060811153755] |
|---|
| 515 | [bump version to 2.0 |
|---|
| 516 | Simon Marlow <simonmar@microsoft.com>**20060811152554] |
|---|
| 517 | [depend on html (for the time being) |
|---|
| 518 | Simon Marlow <simonmar@microsoft.com>**20060810121424] |
|---|
| 519 | [initWinSock(): have defn match proto |
|---|
| 520 | sof@galois.com**20060613224903] |
|---|
| 521 | [only GHC has rtsSupportsBoundThreads |
|---|
| 522 | Ross Paterson <ross@soi.city.ac.uk>**20060531200123] |
|---|
| 523 | [add files used by configure |
|---|
| 524 | Ross Paterson <ross@soi.city.ac.uk>**20060518174356] |
|---|
| 525 | [Import unsafePerformIO |
|---|
| 526 | Sven Panne <sven.panne@aedion.de>**20060507171832] |
|---|
| 527 | [Import MVar type |
|---|
| 528 | Sven Panne <sven.panne@aedion.de>**20060507170308] |
|---|
| 529 | [Add various address families |
|---|
| 530 | Simon Marlow <simonmar@microsoft.com>**20060503081915] |
|---|
| 531 | [Fix for #265, build problem on AIX |
|---|
| 532 | Simon Marlow <simonmar@microsoft.com>**20060316143337 |
|---|
| 533 | Not the fix from the ticket, but this one at least doesn't require |
|---|
| 534 | modifying the configure script. |
|---|
| 535 | ] |
|---|
| 536 | [workaround for non-thread-safety of some functions in Network.BSD |
|---|
| 537 | Simon Marlow <simonmar@microsoft.com>**20060126153014 |
|---|
| 538 | Various functions in Network.BSD are non-thread-safe, |
|---|
| 539 | eg. getHostByName, because the underlying gethostbyname() provided by |
|---|
| 540 | the C library uses static storage. The workaround here is to use a |
|---|
| 541 | giant lock around these functions. |
|---|
| 542 | |
|---|
| 543 | In some cases, even the API we provide is itself unsafe, relying on |
|---|
| 544 | implicit state (eg. getHostEntry), but this commit makes no attempt to |
|---|
| 545 | fix that. We should deprecate this library in favour of a complete |
|---|
| 546 | replacement at some point (before 6.6 would be nice). |
|---|
| 547 | |
|---|
| 548 | Thanks to Einar Kartunnen for the patch. |
|---|
| 549 | ] |
|---|
| 550 | [Fix Ticket 647, Socket bug on Mac OS X |
|---|
| 551 | wolfgang.thaller@gmx.net**20060121050509 |
|---|
| 552 | Patch kindly provided by Greg Wright |
|---|
| 553 | ] |
|---|
| 554 | [TAG Initial conversion from CVS complete |
|---|
| 555 | John Goerzen <jgoerzen@complete.org>**20060112154134] |
|---|
| 556 | Patch bundle hash: |
|---|
| 557 | 673d24fc3164ee9f96aa2f3a25829d32fc731d28 |
|---|