import System.Environment import Control.Monad.State import Control.Monad.List type St = (Bool,Int,String) action (server,client) = get >>= \(isServer,_,_)->if isServer then server else client line s = action (liftIO $ putStrLn s,liftIO getLine >>= guard . (==s)) getChars 0 cs = return (reverse cs) getChars n cs = getChar >>= getChars (n-1) . (:cs) http = line "HTTP/1.1 200" len = action (get >>= \(_,_,b)->line ("Content-Length: "++(show (length b))) ,do l <- liftIO getLine let ("Content-Length:",_:b) = span (/=' ') l modify (\(s,_,t)->(s,read b,t)) ) typ = line "Content-Type: text/plain" empty = line "" body = action (get >>= \(_,_,b)->liftIO $ putStr b ,get >>= \(s,l,_)->liftIO (getChars l "") >>= \b->put (s,l,b) ) protocol = http >> len >> typ >> empty >> body server = runListT $ runStateT protocol (True,undefined,"this\nis\na\ntext\n") client = runListT $ runStateT protocol (False,undefined,"") main = do mode:_ <- getArgs case mode of "server" -> server >> return () "client" -> client >>= mapM_ (\(_,(_,_,text))->putStr text)