@@ -39,6 +39,9 @@ import Text.Printf
40import Safe
40import Safe
41import System.IO (stderr, hPutStrLn)
41import System.IO (stderr, hPutStrLn)
42+import Foreign.Storable (pokeByteOff, peekByteOff)
43+import Foreign.C (CInt(..))
44+import Foreign.ForeignPtr (withForeignPtr)
43#ifndef LAZY
46#ifndef LAZY
44import Data.ByteString.Char8 (ByteString)
47import Data.ByteString.Char8 (ByteString)
@@ -60,6 +63,9 @@ decode = Ser.decodeLazy
60encode :: Ser.Serialize a => a -> ByteString
63encode :: Ser.Serialize a => a -> ByteString
61decode :: Ser.Serialize a => ByteString -> Either String a
64decode :: Ser.Serialize a => ByteString -> Either String a
66+foreign import ccall unsafe "htonl" htonl :: CInt -> CInt
67+foreign import ccall unsafe "ntohl" ntohl :: CInt -> CInt
63type ChanId = Int
69type ChanId = Int
64type Chans = MVar (ChanId, IntMap (Chan [ByteString], [(ThreadId, Socket)]))
70type Chans = MVar (ChanId, IntMap (Chan [ByteString], [(ThreadId, Socket)]))
@@ -134,11 +140,12 @@ mkSourceEnd host service chanId = withSocketsDo $ do
134 N.connect sock (addrAddress serverAddr)
140 N.connect sock (addrAddress serverAddr)
135 NBS.sendAll sock $ encode (fromIntegral chanId :: Int32)
141 NBS.sendAll sock $ encode (fromIntegral chanId :: Int32)
136 return SourceEnd
142 return SourceEnd
137− { send = {-# SCC "send" #-} \bss -> do
143+ { send = {-# SCC "send" #-} \bss ->
138− let size = fromIntegral (sum . map BS.length $ bss) :: Int32
144+ let size = fromIntegral (sum . map BS.length $ bss) :: Int32 in
139− sizeStr | size < 255 = BS.singleton (toEnum $ fromEnum size)
146+ then sendNBS sock (BS.singleton (toEnum $ fromEnum size) : bss)
147+ else do size' <- encodeLength size
140− | otherwise = BS.cons (toEnum 255) (encode size)
148+ sendNBS sock (BS.singleton (toEnum 255) : size' : bss)
141− sendNBS sock (sizeStr:bss)
142 , closeSourceEnd = {-# SCC "closeSourceEnd" #-} sClose sock
149 , closeSourceEnd = {-# SCC "closeSourceEnd" #-} sClose sock
@@ -193,15 +200,15 @@ procMessages chans chanId chan sock = do
193 esizeBS <- recvExact sock 1
200 esizeBS <- recvExact sock 1
194 case esizeBS of
201 case esizeBS of
195 Left _ -> closeSocket
202 Left _ -> closeSocket
196− Right sizeBS -> do
203+ Right sizeBS ->
197− case decode sizeBS :: Either String Word8 of
204+ let size = toEnum . fromEnum $ BS.index sizeBS 0 in
198− Right 255 -> do
205+ if size < 255
206+ then procMessage size
199− esizeBS' <- recvExact sock (fromIntegral $ sizeOf (0 :: Int32))
207+ else do esizeBS' <- recvExact sock (fromIntegral $ sizeOf (0 :: Int32))
200− case esizeBS' of
208+ case esizeBS' of
201− Left _ -> closeSocket
209+ Left _ -> closeSocket
202− Right sizeBS' -> procMessage $ decode sizeBS'
210+ Right sizeBS' -> do sizeDec <- decodeLength sizeBS'
203− esize@(Right _) -> procMessage (fromIntegral <$> esize)
211+ procMessage sizeDec
204− Left msg -> error msg
206 err m = error $ printf "procMessages: %s" m
213 err m = error $ printf "procMessages: %s" m
207 closeSocket :: IO ()
214 closeSocket :: IO ()
@@ -216,9 +223,8 @@ procMessages chans chanId chan sock = do
216 let chanMap' = IntMap.insert chanId (chan, socks') chanMap
223 let chanMap' = IntMap.insert chanId (chan, socks') chanMap
217 putMVar chans (chanId', chanMap')
224 putMVar chans (chanId', chanMap')
218 sClose sock
225 sClose sock
219− procMessage :: Either String Int32 -> IO ()
226+ procMessage :: Int32 -> IO ()
220− procMessage (Left msg) = err msg
227+ procMessage size = do
221− procMessage (Right size) = do
222 ebs <- recvExact sock size
228 ebs <- recvExact sock size
223 case ebs of
229 case ebs of
224 Left _ -> closeSocket
230 Left _ -> closeSocket
@@ -289,3 +295,16 @@ forkWithExceptions forkit descr action = do
289 throwTo parent (e::SomeException)
295 throwTo parent (e::SomeException)
298+-- | Encode length (manual for now)
299+encodeLength :: Int32 -> IO ByteString
301+ BSI.create 4 $ \p ->
302+ pokeByteOff p 0 (htonl (fromIntegral i32))
304+-- | Decode length (manual for now)
305+decodeLength :: ByteString -> IO Int32
307+ let (fp, _, _) = BSI.toForeignPtr bs in
308+ withForeignPtr fp $ \p -> do
309+ w32 <- peekByteOff p 0
310+ return (fromIntegral (ntohl w32))