@@ -5,8 +5,6 @@ module Main where
55import Control.Monad
66
77import Data.Int
8−import qualified Data.Serialize as Ser
9−import Data.Word (Word8)
108import Network.Socket
119 ( AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
1210 , SocketType (Stream), SocketOption (ReuseAddr)
@@ -25,6 +23,13 @@ import Data.ByteString.Char8 (pack, unpack)
2523import qualified Data.ByteString as BS
2624import qualified Network.Socket.ByteString as NBS
2725import 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)
30+
31+foreign import ccall unsafe "htonl" htonl :: CInt -> CInt
32+foreign import ccall unsafe "ntohl" ntohl :: CInt -> CInt
2833
2934main :: IO ()
3035main = do
@@ -102,13 +107,25 @@ pong sock = do
102107recv :: Socket -> Int -> IO ByteString
103108recv sock i = do
104109 (header, payload) <- BS.splitAt 4 `fmap` NBS.recv sock (4 + i)
105− case Ser.decode header :: Either String Int32 of
106− Left _ -> error "Could not decode header"
107− Right _ -> return payload
110+ length <- decodeLength header -- Ignored
111+ return payload
108112
109113-- | Wrapper around NBS.send (for profiling)
110114send :: Socket -> ByteString -> IO ()
111115send sock bs = do
112− let length :: Int32
113− length = fromIntegral $ BS.length bs
114− NBS.sendMany sock [Ser.encode length, bs]
116+ length <- encodeLength (fromIntegral (BS.length bs))
117+ NBS.sendMany sock [length, bs]
118+
119+-- | Encode length (manual for now)
120+encodeLength :: Int32 -> IO ByteString
121+encodeLength i32 =
122+ BSI.create 4 $ \p ->
123+ pokeByteOff p 0 (htonl (fromIntegral i32))
124+
125+-- | Decode length (manual for now)
126+decodeLength :: ByteString -> IO Int32
127+decodeLength bs =
128+ let (fp, _, _) = BSI.toForeignPtr bs in
129+ withForeignPtr fp $ \p -> do
130+ w32 <- peekByteOff p 0
131+ return (fromIntegral (ntohl w32))