
I am uncertain about all the issues here, but.... Why do you need to convert Socket to Handle? I have no clue if this code I pasted below works but it does compile:
import Network.Socket import Data.ByteString.Base as Base
-- 'recvBSFrom' gets a strict ByteString from a socket. -- createAndTrim' was not quite documented, so I looked at -- http://darcs.haskell.org/packages/base/Data/ByteString/Base.hs recvBSFrom :: Socket -> Int -> IO (ByteString,SockAddr) recvBSFrom sock nbytes = Base.createAndTrim' nbytes $ \ptr -> do (len,sockaddr) <- recvBufFrom sock ptr nbytes -- maybe check if len is (-1) ? return (0,len,sockaddr)
I was not sure how recvBufFrom handles errors, so if recvBufFrom might return a len of (-1) then the above will need to detect this. (This looks like it might happen for non-blocking sockets). The above was modeled after recvfrom, reproduced below from source at http://darcs.haskell.org/packages/network/Network/Socket.hsc
recvFrom :: Socket -> Int -> IO (String, Int, SockAddr) recvFrom sock nbytes = allocaBytes nbytes $ \ptr -> do (len, sockaddr) <- recvBufFrom sock ptr nbytes str <- peekCStringLen (ptr, len) return (str, len, sockaddr)
If you can figure out how to defer the calls to recvBSFrom properly then you can make Lazy ByteStrings as well. One would need to understand how to set the socket to non-blocking (?) and mimic the hGetContentsN code from http://darcs.haskell.org/packages/base/Data/ByteString/Lazy.hs If this hypothetical 'socketGetContentsAsLazyByteString' also creating a newEmptyMVar then it could return a (tryPutMVar m ()) action to allow the consumer of the lazy string to signal to the deferred reading process (which periodically calls (isEmptyMVar m)) that it should close the socket or at least stop trying to read from it. That way there is no _need_ to 'seq' your way to the end of the lazy bytestring to cause it to close. -- Chris