{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} module NLP.Concraft.Polish.Server ( -- * Server runConcraftServer -- * Client , submit ) where import Control.Applicative ((<$>)) import Control.Monad (forever, void) import Control.Concurrent (forkIO) import System.IO (Handle, hFlush) import qualified Network as N import qualified Data.Binary as B import qualified Data.ByteString.Lazy as BS import NLP.Concraft.Polish.Morphosyntax hiding (tag) import NLP.Concraft.Polish.Maca import qualified NLP.Concraft.Polish as C import qualified NLP.Concraft.Polish.Request as R ------------------------------------------------- -- Server ------------------------------------------------- -- | Run a Concraft server on a given port. runConcraftServer :: MacaPool -> C.Concraft -> N.PortID -> IO () runConcraftServer pool concraft port = N.withSocketsDo $ do sock <- N.listenOn port forever $ sockHandler pool concraft sock -- | Read and process short requests from the socket. sockHandler :: MacaPool -> C.Concraft -> N.Socket -> IO () sockHandler pool concraft sock = do (handle, _, _) <- N.accept sock -- putStrLn "Connection established" void $ forkIO $ do -- putStrLn "Waiting for input..." inp <- recvMsg handle -- putStr "> " >> T.putStrLn inp out <- R.short pool concraft inp -- putStr "No. of sentences: " >> print (length out) sendMsg handle out ------------------------------------------------- -- Client ------------------------------------------------- -- | Submit the given request. submit :: N.HostName -> N.PortID -> R.Request R.Short -> IO [Sent Tag] submit host port inp = do handle <- N.connectTo host port -- putStrLn "Connection established" -- putStr "Send request: " >> T.putStrLn inp sendMsg handle inp recvMsg handle ------------------------------------------------- -- Communication ------------------------------------------------- sendMsg :: B.Binary a => Handle -> a -> IO () sendMsg h msg = do let x = B.encode msg n = fromIntegral $ BS.length x sendInt h n BS.hPut h x hFlush h recvMsg :: B.Binary a => Handle -> IO a recvMsg h = do n <- recvInt h B.decode <$> BS.hGet h n sendInt :: Handle -> Int -> IO () sendInt h x = BS.hPut h (B.encode x) recvInt :: Handle -> IO Int recvInt h = B.decode <$> BS.hGet h 8 -- ------------------------------------------------- -- -- Stream binary encoding -- ------------------------------------------------- -- -- -- newtype Stream a = Stream { unstream :: [a] } -- -- -- instance B.Binary a => B.Binary (Stream a) where -- put (Stream []) = B.putWord8 0 -- put (Stream (x:xs)) = B.putWord8 1 >> B.put x >> B.put (Stream xs) -- get = error "use lazyDecodeStream insted" -- -- -- getMaybe :: B.Binary a => B.Get (Maybe a) -- getMaybe = do -- t <- B.getWord8 -- case t of -- 0 -> return Nothing -- _ -> fmap Just B.get -- -- -- step :: B.Binary a => (ByteString, Int64) -> Maybe (a, (ByteString, Int64)) -- step (xs, offset) = case B.runGetState getMaybe xs offset of -- (Just v, ys, newOffset) -> Just (v, (ys, newOffset)) -- _ -> Nothing -- -- -- lazyDecodeList :: B.Binary a => ByteString -> [a] -- lazyDecodeList xs = unfoldr step (xs, 0) -- -- -- lazyDecodeStream :: B.Binary a => ByteString -> Stream a -- lazyDecodeStream = Stream . lazyDecodeList