0

I'm trying to learn how to use conduits. I have a conduit that takes bytestrings and groups them into packets that represent actions being sent to a server. I then have a conduit that takes these packets, acts on them and yields a response packet. Finally I have a conduit that takes the response packets and turns them into a stream of bytestrings. The problem is that yield in the packet handling conduit always returns Nothing. My code looks like this

processingConduit :: ServerState -> Conduit BS.ByteString IO BS.ByteString
processingConduit state = getPacketConduit
    =$= processPacketConduit state
    =$= putPacketConduit

processPacketConduit :: ServerState -> Conduit ClientPacket IO ServerPacket
processPacketConduit state = awaitForever $ \packet -> do
    liftIO $ putStrLn "got something :)"
    let function = case packet of
            (LoginPacket _ _) -> login
            _                 -> ugh
    result <- liftIO $ function state packet
    yield result

getPacketConduit :: Conduit BS.ByteString IO ClientPacket
getPacketConduit = conduitGet (get :: Get ClientPacket)

putPacketConduit :: Conduit ServerPacket IO BS.ByteString
putPacketConduit = conduitPut (put :: ServerPacket -> Put)

I run the conduit using runTCPServer and it's able to accept connections and the getPacketConduit is able to convert the bytestring into valid packets, but awaitForever never calls its function. If I modify processPacketConduit to use await instead, I can see that it always returns Nothing.

duplode
  • 33,731
  • 7
  • 79
  • 150
user467526
  • 517
  • 5
  • 19
  • 1
    Can you provide a complete example? Coming up with the smallest possible example can really help in narrowing down the problem. – ErikR Jul 22 '15 at 08:56

1 Answers1

0

I figured out my error, I forgot that cereal serializes bytestring by sending length :: Int followed by the actual data. I was only sending a single byte for the length.

user467526
  • 517
  • 5
  • 19