Binary read/write WAS [storing to a file]

I've been fiddling with binary read/write in Haskell. I put together a little example demonstrating my lack of understanding. It creates a connection requestion XAtom and spits it out over a socket. My real hangup occurs when I get a String back from the Socket and would like it nicely marshalled into the ConnectSuccess type. These techniques I would assume apply to binary read/write for files as well. Any criticism/suggestions are appreciated. import IO import Monad import GHC.IO import GHC.Storable import Network import Network.Socket import Data.Char import Data.Word import System.Environment import Parsec -- A Parser that looks for everything before the colon beforeColon :: Parser String beforeColon = many1 (satisfy $ \c -> c /= ':') -- Parse out the display name from the environment Variable DISPLAY parseDisplay :: String -> String parseDisplay s = if (name == "") then "localhost" else name where name = case (parse beforeColon "" s) of Left err -> "" Right x -> x -- repeat an IO action multiple times repeat' :: Int -> IO a -> IO () repeat' n f = foldr (>>) (return ()) (take n (repeat f)) -- Send the X11 Connection Request to a handle sendConnectReq :: Handle -> IO () sendConnectReq h = do -- O'Reilly claims this should be '\x66' -- Try it with this and it crashes like so -- *** Exception: user error -- Reason: Pattern match failure in do expression, open.hs:xx hPutChar h '\x6c' --platform dependent byte-ordering, MSB hPutChar h '\x00' --unused hPutChar h '\x0b' --protocol major 11 hPutChar h '\x00' --protocol minor 0 repeat' 8 (hPutChar h '\x00') -- pad it out to boundary hFlush h -- Totally clueless on this one -- What's the best for this? marshallSuccess :: String -> ConnectSuccess marshallSuccess s = let v = drop 39 s in ConnectSuccess 0 0 0 0 0 0 0 0 0 0 0 0 v -- Get the reply getConnectReply :: Handle -> IO (Either ConnectFail ConnectSuccess) getConnectReply h = do (r:rs) <- hGetContents h -- This is the line that crashes with an invalid request (reply ""?) if (r == '\x00') then return (Left (drop 7 rs)) else return (Right (marshallSuccess rs)) -- Error string, this probably should be an ioexception type type ConnectFail = String -- Connection success type to fill up with wonderful stuff data ConnectSuccess = ConnectSuccess { release :: Word32, id_base :: Word32, id_mask :: Word32, motion_buf :: Word32, max_req :: Word16, screens :: Word8, img_order :: Word8, bit_order :: Word8, bit_unit :: Word8, bit_pad :: Word8, min_keycode :: Word8, max_keycode :: Word8, vendor :: String } -- Main program to make an X11 connection request. main :: IO () main = withSocketsDo $ do hostname <- liftM parseDisplay (getEnv "DISPLAY") h <- connectTo hostname (Service "x11") sendConnectReq h reply <- getConnectReply h case reply of Left s -> putStr "Failure: " >> putStr s >> putChar '\n' Right s -> putStr "Success: " >> putStr (vendor s) >> putChar '\n'

I've been fiddling with binary read/write in Haskell. I put together a little example demonstrating my lack of understanding. It creates a connection requestion XAtom and spits it out over a socket. My real hangup occurs when I get a String back from the Socket and would like it nicely marshalled into the ConnectSuccess type. These techniques I would assume apply to binary read/write for files as well.
IIRC, the Fudgets library reads and writes X sockets so you could look here: http://www.cs.chalmers.se/ComputingScience/Research/Functional/Fudgets/ There is also the Xlib binding which works with both GHC and Hugs and is used in HGL: http://haskell.org/graphics/ -- Alastair Reid

On Thursday 14 November 2002 03:46 pm, you wrote:
I've been fiddling with binary read/write in Haskell. I put together a little example demonstrating my lack of understanding. It creates a connection requestion XAtom and spits it out over a socket. My real hangup occurs when I get a String back from the Socket and would like it nicely marshalled into the ConnectSuccess type. These techniques I would assume apply to binary read/write for files as well.
IIRC, the Fudgets library reads and writes X sockets so you could look here:
http://www.cs.chalmers.se/ComputingScience/Research/Functional/Fudgets/
Xlib sockets and binding wasn't the point of the question. The example was contrived to show the basic problem or reading / writing some arbitrary binary sequence. I looked at the solution in the Fudgets library, an interesting solution is ine there for typed sockets. http://www.cs.chalmers.se/~hallgren/Thesis/client_server.html. It allows for a typed return on a socket, with a nice tight set of code. This typed return I understand relies on the types being members of the Read class. The problem of the Xatom, is a bit more difficult. Embedded in the reply of the open connection request is a "string" for the vendor. The length of the string is at byte 24 in the reply, it's a 2 byte Word. The string of the vendor starts at byte 40. This is followed by a 4-byte padding. Once your past this oddness, it gets a lot funner with all kinds of other embedded information pointing all over the place in the packet. I don't think String is a member of the Read class. So my thinking was to read the reply in as a String and process it. Problem is I don't even know how to extract the first four bytes of a String as a raw Word32. That would be a start, but the general problem is a tad bit more difficult. I've been reading some about the "Binary" module and it's translation into GHC going on. Is that the purpose of it to help in such situations? Shawn
participants (2)
-
Alastair Reid
-
Shawn P. Garbett