Portability | Only tested on GHC 6.12.1, uses TypeSynonymInstances |
---|---|
Stability | experimental |
Maintainer | David Leimbach <leimy2k@gmail.com> |
Safe Haskell | Safe-Inferred |
Module providing Binary serialization of 9P messages to and from lazy ByteStrings.
This library does not currently provide any networking support or wrappers for easy to write clients or servers, though that may come with time as we decide the best way to implement these.
9P2000 messages are sent in little endian byte order rather than network byte order (big endian)
Lightly tested against an Inferno operating system share with no authentication successfully.
- class Bin a where
- data Qid = Qid {}
- data Stat = Stat {}
- data Msg = Msg {}
- data Tag
- data VarMsg
- = Tversion {
- tv_msize :: Word32
- tv_version :: String
- | Rversion {
- rv_msize :: Word32
- rv_version :: String
- | Tauth { }
- | Rauth { }
- | Rerror { }
- | Tflush { }
- | Rflush
- | Tattach { }
- | Rattach { }
- | Twalk { }
- | Rwalk { }
- | Topen { }
- | Ropen { }
- | Tcreate { }
- | Rcreate {
- rcr_qid :: Qid
- rcr_iounit :: Word32
- | Tread { }
- | Rread { }
- | Twrite {
- twr_fid :: Word32
- twr_offset :: Word64
- twr_dat :: ByteString
- | Rwrite { }
- | Tclunk { }
- | Rclunk
- | Tremove { }
- | Rremove
- | Tstat { }
- | Rstat { }
- | Twstat { }
- | Rwstat
- = Tversion {
- putVarMsg :: VarMsg -> Put
- getVarMsg :: Tag -> Get VarMsg
Bin - a little endian encode/decode class for Binary
Qid - Server side data type for path tracking (http://9p.cat-v.org for details)
A Plan 9 Qid type. See http:9p.cat-v.org for more information
Stat - Namespace metadata (somewhat like a unix fstat)
Provides information on a path entry at a 9P2000 server
Msg - envelope for 9P2000 messages
The message envelope type for all 9P2000 messages
Tag - A message payload type
A type that enumerates all the valid (and one invalid) message types in 9P2000
VarMsg - A data type encapsulating the various 9P messages
A variable message type that encapsulates the valid kinds of messages in a 9P2000 payload
putVarMsg - function that can encode all VarMsg types to a lazy ByteString
putVarMsg :: VarMsg -> PutSource
For every lower level VarMsg type, encodes a full wrapper around that type for use with 9P2000 streams
getVarMsg - function to decode all VarMsg types from a lazy ByteString
getVarMsg :: Tag -> Get VarMsgSource
For every messages type, runs a Get parser to decode that type of payload from the 9P2000 stream
Example
Exchanging initial version data with any 9P2000 server
module Main where
import Data.Maybe import Control.Monad import qualified Data.ByteString.Lazy.Char8 as C import Network.Socket hiding (send, recv) import Network.Socket.ByteString.Lazy import Data.Int import Data.Binary.Get import Data.Binary.Put import Debug.Trace import Data.NineP connector :: IO Socket connector = withSocketsDo $ do ainfo <- getAddrInfo Nothing (Just "127.0.0.1") (Just "6872") let a = head ainfo sock <- socket AF_INET Stream defaultProtocol
At this point we've just created our socket to a machine on 127.0.0.1:6872 where we'd expect to see a 9P2000 server.
putStrLn "Trying to connect" connect sock (addrAddress (traceShow a a)) putStrLn "connected!"
The socket is connected at this point, build up a TVersion message, asking to speak to the server with the 9P2000 protocol.
The 1024 tells the server the maximum message size we'd like to support.
let version = Msg TTversion (-1) $ Tversion 1024 "9P2000" putStrLn $ "About to send: " ++ show version
We now need to pack the message into a bytestring. This is handled by the Bin class instance Msg, and the serialization is handled by runPut. We send this data to the socket.
send sock $ runPut (put version) putStrLn "Getting response"
Now wait for a response from the server, evaluated runGet over it to de-serialize it, and show it.
msg <- recv sock 50 let response = runGet get msg ::Msg putStrLn $ show response return sock