[Haskell-cafe] Re: Review request for my baby steps towards a "platform independent interactive graphics" using VNC

C K Kashyap ckkashyap at gmail.com
Sat Nov 6 08:36:25 EDT 2010

I've progressed further - now the VNC client opens up a window with
the dimensions set in the code!


I've pasted the code here for quick reference - would really
appreciate some feedback.

module Main where

import Network.Server
import Network.Socket
import Control.Monad
import System.IO

import qualified Data.ByteString.Lazy as BS
import Data.Char
import Data.Binary.Get
import Data.Binary.Put
import Data.Word

main :: IO ()
main = do
	running <- serveOne (Just $ UserWithDefaultGroup "ckk") server
	putStrLn "server is accepting connections!!!"
	waitFor running

	where server = Server (SockAddrInet 5901 iNADDR_ANY) Stream doVNC

doVNC :: ServerRoutine
doVNC (h,n,p) = do startRFB h

startRFB :: Handle -> IO ()
startRFB h = do
		hPutStr h "RFB 003.003\n"
		hFlush h

		clientHeaderByteStream <- BS.hGet h 12
		putStrLn (show clientHeaderByteStream)
		let (m,n) = ( runGet readClientHeader clientHeaderByteStream)

		-- Send 1 to the client, meaning, no auth required
		BS.hPutStr h (BS.pack [0,0,0,1])
		hFlush h

		clientInitMessage <- BS.hGet h 1

		let sharedOrNot = runGet (do {x<-getWord8;return(x);}) clientInitMessage

		putStrLn (show sharedOrNot)

		BS.hPutStr h serverInitMessage
		hFlush h

serverInitMessage :: BS.ByteString
serverInitMessage = runPut $ do
				putWord16be (300::Word16) -- width
				putWord16be (300::Word16) -- height
				--pixel format
				putWord8 (32::Word8) -- bits per pixl
				putWord8 (24::Word8) -- depth
				putWord8 (1::Word8) -- big endian
				putWord8 (1::Word8) -- true color
				putWord16be (255::Word16) -- red max
				putWord16be (255::Word16) -- green max
				putWord16be (255::Word16) -- blue max
				putWord8 (24::Word8) -- red shift
				putWord8 (1::Word8)  -- green shift
				putWord8 (1::Word8)  -- blue shift
				putWord8 (0::Word8)
				putWord8 (0::Word8)
				putWord8 (0::Word8)
				--name length
				let name = "Haskell Framebuffer"
				putWord32be (((fromIntegral.length) name)::Word32)
				putLazyByteString (stringToByteString name)

byteString2Number :: BS.ByteString -> Int
byteString2Number bs = _byteString2Number 1 (digits bs)
		_byteString2Number _ [] = 0
		_byteString2Number n (x:xs) = (n*x) + (_byteString2Number (n*10) xs)
		digits bs = map ((+(-48)).fromIntegral) (BS.unpack(BS.reverse bs))

readClientHeader  = do
	getLazyByteString 4
	m <- getLazyByteString 3
	n <- getLazyByteString 3
	let majorVersionNumber = byteString2Number m
	let minorVersionNumber = byteString2Number n
	if (majorVersionNumber /= 3) then
		fail ("ERROR: Unsupported version " ++ (show majorVersionNumber))
		return (byteString2Number m,byteString2Number n)

word8ToByteString :: Word8 -> BS.ByteString
word8ToByteString n = runPut $ putWord8 n

word16ToByteString :: Word16 -> BS.ByteString
word16ToByteString n = runPut $ putWord16be n

word32ToByteString :: Word32 -> BS.ByteString
word32ToByteString n = runPut $ putWord32be n

stringToByteString :: String -> BS.ByteString
stringToByteString str = BS.pack (map (fromIntegral.ord) str)

On Thu, Nov 4, 2010 at 12:18 PM, C K Kashyap <ckkashyap at gmail.com> wrote:
> Hi,
> I started with the implementation of a VNC server library intended to
> be used as a library for rendering graphics and interacting with the
> user(mouse/keyboard). I'd appreciate it very much if I could  get some
> feedback on my approach to binary parsing and Haskellism.
> Also, any reference/suggestion on how I could go about using a state
> machine to deal with the RFB protocol.
> http://hpaste.org/41131/vnc_server
> It's really early - but just wanted to get some advice on the approach.
> --
> Regards,
> Kashyap


More information about the Haskell-Cafe mailing list