NineP-0.0.2.1: 9P2000 in pure Haskell

PortabilityOnly tested on GHC 6.12.1, uses TypeSynonymInstances
Stabilityexperimental
MaintainerDavid Leimbach <leimy2k@gmail.com>
Safe HaskellSafe-Inferred

Data.NineP

Contents

Description

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.

Synopsis

Bin - a little endian encode/decode class for Binary

class Bin a whereSource

Methods

get :: Get aSource

put :: a -> PutSource

Qid - Server side data type for path tracking (http://9p.cat-v.org for details)

data Qid Source

A Plan 9 Qid type. See http:9p.cat-v.org for more information

Constructors

Qid 

Instances

Stat - Namespace metadata (somewhat like a unix fstat)

data Stat Source

Provides information on a path entry at a 9P2000 server

Instances

Msg - envelope for 9P2000 messages

data Msg Source

The message envelope type for all 9P2000 messages

Constructors

Msg 

Instances

Tag - A message payload type

data Tag Source

A type that enumerates all the valid (and one invalid) message types in 9P2000

Instances

VarMsg - A data type encapsulating the various 9P messages

data VarMsg Source

A variable message type that encapsulates the valid kinds of messages in a 9P2000 payload

Instances

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