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)
31foreign import ccall unsafe "htonl" htonl :: CInt -> CInt
32foreign import ccall unsafe "ntohl" ntohl :: CInt -> CInt
37 serverReady <- newEmptyMVar
38 clientDone <- newEmptyMVar
42 putStrLn "server: creating TCP connection"
43 serverAddrs <- getAddrInfo
44 (Just (defaultHints { addrFlags = [AI_PASSIVE] } ))
47 let serverAddr = head serverAddrs
48 sock <- socket (addrFamily serverAddr) Stream defaultProtocol
49 setSocketOption sock ReuseAddr 1
50 bindSocket sock (addrAddress serverAddr)
52 putStrLn "server: awaiting client connection"
53 putMVar serverReady ()
55 (clientSock, clientAddr) <- accept sock
57 putStrLn "server: listening for pings"
63 let pings = read pingsStr
64 serverAddrs <- getAddrInfo
68 let serverAddr = head serverAddrs
69 sock <- socket (addrFamily serverAddr) Stream defaultProtocol
71 N.connect sock (addrAddress serverAddr)
76 -- Wait for the client to finish
79pingMessage :: ByteString
80pingMessage = pack "ping123"
82ping :: Socket -> Int -> IO ()
83ping sock pings = go pings
87 putStrLn $ "client did " ++ show pings ++ " pings"
89 before <- getCurrentTime
92 after <- getCurrentTime
93 -- putStrLn $ "client received " ++ unpack bs
94 let latency = (1e6 :: Double) * realToFrac (diffUTCTime after before)
95 hPutStrLn stderr $ show i ++ " " ++ show latency
98pong :: Socket -> IO ()
101 -- putStrLn $ "server received " ++ unpack bs
102 when (BS.length bs > 0) $ do
106-- | Wrapper around NBS.recv (for profiling)
107recv :: Socket -> Int -> IO ByteString
109 (header, payload) <- BS.splitAt 4 `fmap` NBS.recv sock (4 + i)
117-- | Wrapper around NBS.send (for profiling)
118send :: Socket -> ByteString -> IO ()
120 NBS.sendMany sock [header, bs]
122-- | Encode length (manual for now)
123encodeLength :: Int32 -> IO ByteString
126 pokeByteOff p 0 (htonl (fromIntegral i32))
128-- | Decode length (manual for now)
129decodeLength :: ByteString -> IO Int32
131 let (fp, _, _) = BSI.toForeignPtr bs in
132 withForeignPtr fp $ \p -> do
133 w32 <- peekByteOff p 0
134 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