packages feed

scion-0.1: server/Scion/Server/Generic.hs

module Scion.Server.Generic 
  ( handle
  ) where

import Prelude hiding ( log )

import Scion
import Scion.Types (gets, SessionState(..))
import Scion.Server.ConnectionIO as CIO
import Scion.Server.Commands

import Text.JSON
import Text.JSON.Types
import qualified Data.ByteString.Lazy.Char8 as S
import qualified Data.ByteString.Lazy.UTF8 as S
import qualified System.Log.Logger as HL

log :: HL.Priority -> String -> IO ()
log = HL.logM "protocol.generic"
logDebug :: MonadIO m => String -> m ()
logDebug = liftIO . log HL.DEBUG

type StopServer = Bool

handle :: (ConnectionIO con) =>
          con
       -> Int
       -> ScionM StopServer
handle con 0 = do
   loop
  where
   loop = do
     -- TODO: don't require line-based input
     str <- liftIO $ CIO.getLine con
     logDebug $ "parsing command: " ++ show str
     let mb_req = decodeStrict (S.toString str)
     (resp, keep_going) 
         <- case mb_req of
              Error _ -> return (malformedRequest, True)
              Ok req -> handleRequest req
     c <- gets client
     let resp_str = encodeStrict (if (c == "vim") then vimHack resp else resp)
     logDebug $ show resp_str
     liftIO $ CIO.putLine con (S.fromString resp_str)
     --logDebug $ "sent response"
     if keep_going then loop else do 
       --logDebug "finished serving connection."
       return True

handle con unknownVersion = do
  -- handshake failure, don't accept this client version 
  liftIO $ CIO.putLine con $ 
    S.pack $ "failure: Don't know how to talk to client version "
      ++ (show unknownVersion)
  return False

-- vim doesn't know about true,false,null thus can't parse it. this functions
-- mapps those values to 1,0,""
vimHack :: JSValue -> JSValue
vimHack JSNull = JSString (toJSString "")
vimHack (JSBool True) = JSRational False 1
vimHack (JSBool False) = JSRational False 0
vimHack (JSArray l) = JSArray $ map vimHack l
vimHack (JSObject (JSONObject list)) = JSObject $ JSONObject $ map (\(x,y) -> (x, vimHack y)) list
vimHack e = e  -- JSRational, JSString