summaryrefslogtreecommitdiff
path: root/server/src/GetHostByAddr.hs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/GetHostByAddr.hs')
-rw-r--r--server/src/GetHostByAddr.hs78
1 files changed, 78 insertions, 0 deletions
diff --git a/server/src/GetHostByAddr.hs b/server/src/GetHostByAddr.hs
new file mode 100644
index 00000000..068fc93d
--- /dev/null
+++ b/server/src/GetHostByAddr.hs
@@ -0,0 +1,78 @@
1{-# LANGUAGE ForeignFunctionInterface #-}
2{-# LANGUAGE NondecreasingIndentation #-}
3module GetHostByAddr where
4
5import Network.BSD
6import Foreign.Ptr
7import Foreign.C.Types
8import Foreign.Storable (Storable(..))
9import Foreign.Marshal.Utils (with)
10import Foreign.Marshal.Alloc
11import Control.Concurrent
12import System.IO.Unsafe
13import System.IO.Error (ioeSetErrorString, mkIOError)
14import Network.Socket
15import GHC.IO.Exception
16
17
18throwNoSuchThingIfNull :: String -> String -> IO (Ptr a) -> IO (Ptr a)
19throwNoSuchThingIfNull loc desc act = do
20 ptr <- act
21 if (ptr == nullPtr)
22 then ioError (ioeSetErrorString (mkIOError NoSuchThing loc Nothing Nothing) desc)
23 else return ptr
24
25{-# NOINLINE lock #-}
26lock :: MVar ()
27lock = unsafePerformIO $ newMVar ()
28
29withLock :: IO a -> IO a
30withLock act = withMVar lock (\_ -> act)
31
32trySysCall :: IO a -> IO a
33trySysCall act = act
34
35{-
36-- The locking of gethostbyaddr is similar to gethostbyname.
37-- | Get a 'HostEntry' corresponding to the given address and family.
38-- Note that only IPv4 is currently supported.
39getHostByAddr :: Family -> SockAddr -> IO HostEntry
40getHostByAddr family addr = do
41 withSockAddr addr $ \ ptr_addr len -> withLock $ do
42 throwNoSuchThingIfNull "getHostByAddr" "no such host entry"
43 $ trySysCall $ c_gethostbyaddr ptr_addr (fromIntegral len) (packFamily family)
44 >>= peek
45-}
46
47
48-- The locking of gethostbyaddr is similar to gethostbyname.
49-- | Get a 'HostEntry' corresponding to the given address and family.
50-- Note that only IPv4 is currently supported.
51-- getHostByAddr :: Family -> HostAddress -> IO HostEntry
52-- getHostByAddr family addr = do
53getHostByAddr :: SockAddr -> IO HostEntry
54getHostByAddr (SockAddrInet port addr ) = do
55 let family = AF_INET
56 with addr $ \ ptr_addr -> withLock $ do
57 throwNoSuchThingIfNull "getHostByAddr" "no such host entry"
58 $ trySysCall $ c_gethostbyaddr ptr_addr (fromIntegral (sizeOf addr)) (packFamily family)
59 >>= peek
60getHostByAddr (SockAddrInet6 port flow (a,b,c,d) scope) = do
61 let family = AF_INET6
62 allocaBytes 16 $ \ ptr_addr -> do
63 pokeElemOff ptr_addr 0 a
64 pokeElemOff ptr_addr 1 b
65 pokeElemOff ptr_addr 2 c
66 pokeElemOff ptr_addr 3 d
67 withLock $ do
68 throwNoSuchThingIfNull "getHostByAddr" "no such host entry"
69 $ trySysCall $ c_gethostbyaddr ptr_addr 16 (packFamily family)
70 >>= peek
71
72
73foreign import ccall safe "gethostbyaddr"
74 c_gethostbyaddr :: Ptr a -> CInt -> CInt -> IO (Ptr HostEntry)
75
76
77
78-- vim:ft=haskell: