-
Notifications
You must be signed in to change notification settings - Fork 0
/
client-ip-echo.hs
60 lines (50 loc) · 1.89 KB
/
client-ip-echo.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
--- nix-shell -p "haskellPackages.ghcWithPackages (pkgs: [pkgs.network])"
import System.Environment
import System.Exit
import Network.Socket hiding (send, sendTo, recv, recvFrom)
import Network.Socket.ByteString
import qualified Data.ByteString.Char8 as C
import Data.Bits
import Data.Word
main = do args <- getArgs
case args of
[] -> usage
(p:[]) -> echoPortStr p
(x:y:_) -> usage
usage = putStrLn "usage: client-ip-echo <port>"
echoPortStr portStr = do case (reads portStr) of
[] -> usage
[(p, _)] -> echoPort p
passiveAddress :: AddrInfo
passiveAddress = defaultHints { addrFlags = [AI_PASSIVE]
, addrFamily = AF_INET
, addrSocketType = Stream
}
echoPort :: Integer -> IO ()
echoPort p = do
addrInfos <- getAddrInfo (Just passiveAddress) Nothing (Just $ show p)
case addrInfos of
[addrInfo] -> do
ios <- socket AF_INET Stream defaultProtocol
bind ios $ addrAddress addrInfo
listen ios 1
echoPort1 ios
_ ->
exitWith $ ExitFailure 1
echoPort1 ios = do (s, addr) <- accept ios
let addrs = hostaddr addr
putStrLn ("accepted connection from " ++ addrs)
send s (C.pack addrs)
close s
echoPort1 ios
shiftmask :: Word32 -> Int -> Integer -> Integer
shiftmask x y z = (.&.) (shiftR (toInteger x) y) z
hostaddr :: SockAddr -> String
hostaddr (SockAddrInet _ hAddr) =
let
w1 = shiftmask hAddr 0 (2^8-1)
w2 = shiftmask hAddr 8 (2^8-1)
w3 = shiftmask hAddr 16 (2^8-1)
w4 = shiftmask hAddr 24 (2^8-1)
in (show w1) ++ "." ++ (show w2) ++ "." ++ (show w3) ++ "." ++ (show w4)
hostaddr _ = "unsupported address type"