@@ -5,8 +5,6 @@ module Main where
5import Control.Monad
5import Control.Monad
7import Data.Int
7import Data.Int
8−import qualified Data.Serialize as Ser
9−import Data.Word (Word8)
10import Network.Socket
8import Network.Socket
11 ( AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
9 ( AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
12 , SocketType (Stream), SocketOption (ReuseAddr)
10 , SocketType (Stream), SocketOption (ReuseAddr)
@@ -25,6 +23,13 @@ import Data.ByteString.Char8 (pack, unpack)
25import qualified Data.ByteString as BS
23import qualified Data.ByteString as BS
26import qualified Network.Socket.ByteString as NBS
24import qualified Network.Socket.ByteString as NBS
27import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
25import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime)
26+import Data.ByteString.Internal as BSI
27+import Foreign.Storable (pokeByteOff, peekByteOff)
28+import Foreign.C (CInt(..))
29+import Foreign.ForeignPtr (withForeignPtr)
31+foreign import ccall unsafe "htonl" htonl :: CInt -> CInt
32+foreign import ccall unsafe "ntohl" ntohl :: CInt -> CInt
29main :: IO ()
34main :: IO ()
@@ -102,13 +107,25 @@ pong sock = do
102recv :: Socket -> Int -> IO ByteString
107recv :: Socket -> Int -> IO ByteString
103recv sock i = do
108recv sock i = do
104 (header, payload) <- BS.splitAt 4 `fmap` NBS.recv sock (4 + i)
109 (header, payload) <- BS.splitAt 4 `fmap` NBS.recv sock (4 + i)
105− case Ser.decode header :: Either String Int32 of
110+ length <- decodeLength header -- Ignored
106− Left _ -> error "Could not decode header"
107− Right _ -> return payload
111+ return payload
109-- | Wrapper around NBS.send (for profiling)
113-- | Wrapper around NBS.send (for profiling)
110send :: Socket -> ByteString -> IO ()
114send :: Socket -> ByteString -> IO ()
111send sock bs = do
115send sock bs = do
113− length = fromIntegral $ BS.length bs
116+ length <- encodeLength (fromIntegral (BS.length bs))
114− NBS.sendMany sock [Ser.encode length, bs]
117+ NBS.sendMany sock [length, bs]
119+-- | Encode length (manual for now)
120+encodeLength :: Int32 -> IO ByteString
122+ BSI.create 4 $ \p ->
123+ pokeByteOff p 0 (htonl (fromIntegral i32))
125+-- | Decode length (manual for now)
126+decodeLength :: ByteString -> IO Int32
128+ let (fp, _, _) = BSI.toForeignPtr bs in
129+ withForeignPtr fp $ \p -> do
130+ w32 <- peekByteOff p 0
131+ return (fromIntegral (ntohl w32))