1{-# LANGUAGE CPP, BangPatterns #-}
9 ( AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
10 , SocketType (Stream), SocketOption (ReuseAddr)
11 , accept, addrAddress, addrFlags, addrFamily, bindSocket, defaultProtocol
13 , getAddrInfo, listen, setSocketOption, socket, sClose, withSocketsDo )
14import System.Environment (getArgs, withArgs)
15import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
16import System.IO (withFile, IOMode(..), hPutStrLn, Handle, stderr)
17import Control.Concurrent (forkIO)
18import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
19import qualified Network.Socket as N
21import Data.ByteString (ByteString)
22import Data.ByteString.Char8 (pack, unpack)
23import qualified Data.ByteString as BS
24import qualified Network.Socket.ByteString as NBS
25import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
26import Data.ByteString.Internal as BSI
27import Foreign.Storable (pokeByteOff, peekByteOff)
28import Foreign.C (CInt(..))
29import Foreign.ForeignPtr (withForeignPtr)
30import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
32foreign import ccall unsafe "htonl" htonl :: CInt -> CInt
33foreign import ccall unsafe "ntohl" ntohl :: CInt -> CInt
38 serverReady <- newEmptyMVar
39 clientDone <- newEmptyMVar
43 putStrLn "server: creating TCP connection"
44 serverAddrs <- getAddrInfo
45 (Just (defaultHints { addrFlags = [AI_PASSIVE] } ))
48 let serverAddr = head serverAddrs
49 sock <- socket (addrFamily serverAddr) Stream defaultProtocol
50 setSocketOption sock ReuseAddr 1
51 bindSocket sock (addrAddress serverAddr)
53 putStrLn "server: awaiting client connection"
54 putMVar serverReady ()
56 (clientSock, clientAddr) <- accept sock
58 -- Set up channel that we will listen on and echo to the client
64 -- Read from the client and output on the channel
65 putStrLn "server: listening for pings"
71 let pings = read pingsStr
72 serverAddrs <- getAddrInfo
76 let serverAddr = head serverAddrs
77 sock <- socket (addrFamily serverAddr) Stream defaultProtocol
79 N.connect sock (addrAddress serverAddr)
84 -- Wait for the client to finish
87pingMessage :: ByteString
88pingMessage = pack "ping123"
90ping :: Socket -> Int -> IO ()
91ping sock pings = go pings
95 putStrLn $ "client did " ++ show pings ++ " pings"
97 before <- getCurrentTime
100 after <- getCurrentTime
101 -- putStrLn $ "client received " ++ unpack bs
102 let latency = (1e6 :: Double) * realToFrac (diffUTCTime after before)
103 hPutStrLn stderr $ show i ++ " " ++ show latency
106pong :: Socket -> Chan ByteString -> IO ()
109 -- putStrLn $ "server received " ++ unpack bs
110 when (BS.length bs > 0) $ do
114-- | Wrapper around NBS.recv (for profiling)
115recv :: Socket -> Int -> IO ByteString
117 header <- NBS.recv sock 4
118 length <- decodeLength header
119 NBS.recv sock (fromIntegral (length :: Int32))
121-- | Wrapper around NBS.send (for profiling)
122send :: Socket -> ByteString -> IO ()
124 length <- encodeLength (fromIntegral (BS.length bs))
125 NBS.sendMany sock [length, bs]
127-- | Encode length (manual for now)
128encodeLength :: Int32 -> IO ByteString
131 pokeByteOff p 0 (htonl (fromIntegral i32))
133-- | Decode length (manual for now)
134decodeLength :: ByteString -> IO Int32
136 let (fp, _, _) = BSI.toForeignPtr bs in
137 withForeignPtr fp $ \p -> do
138 w32 <- peekByteOff p 0
139 return (fromIntegral (ntohl w32))
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list