X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Network%2FHTTP%2FLucu%2FInteraction.hs;h=4c0735a3f54e3da532101c27c5e2b28bf0a10811;hb=83db536d11e8efb26848318ad4514b825f412460;hp=68c6c0e919d6431a4ccc8b8524c1bcefab0ee014;hpb=854f6d1709d468f7e1bf0db2dcd2d30de6bd5f5e;p=Lucu.git diff --git a/Network/HTTP/Lucu/Interaction.hs b/Network/HTTP/Lucu/Interaction.hs index 68c6c0e..4c0735a 100644 --- a/Network/HTTP/Lucu/Interaction.hs +++ b/Network/HTTP/Lucu/Interaction.hs @@ -2,61 +2,61 @@ module Network.HTTP.Lucu.Interaction ( Interaction(..) , InteractionState(..) , InteractionQueue - , newInteractionQueue -- IO InteractionQueue - , newInteraction -- Config -> HostName -> Maybe Request -> IO Interaction - - , writeItr -- Interaction -> (Interaction -> TVar a) -> a -> STM () - , readItr -- Interaction -> (Interaction -> TVar a) -> (a -> b) -> STM b - , readItrF -- (Functor f) => Interaction -> (Interaction -> TVar (f a)) -> (a -> b) -> STM (f b) - , updateItr -- Interaction -> (Interaction -> TVar a) -> (a -> a) -> STM () - , updateItrF -- (Functor f) => Interaction -> (Interaction -> TVar (f a)) -> (a -> a) -> STM () + , newInteractionQueue + , newInteraction + , defaultPageContentType + + , writeItr + , readItr + , readItrF + , updateItr + , updateItrF ) where import Control.Concurrent.STM -import qualified Data.ByteString.Lazy.Char8 as B -import Data.ByteString.Lazy.Char8 (ByteString) +import Data.ByteString.Base (ByteString, LazyByteString) +import Data.ByteString.Char8 as C8 +import qualified Data.ByteString.Lazy.Char8 as L8 import qualified Data.Sequence as S import Data.Sequence (Seq) -import Network +import Network.Socket import Network.HTTP.Lucu.Config +import Network.HTTP.Lucu.Headers +import Network.HTTP.Lucu.HttpVersion import Network.HTTP.Lucu.Request import Network.HTTP.Lucu.Response data Interaction = Interaction { - itrConfig :: Config - , itrRemoteHost :: HostName - , itrResourcePath :: Maybe [String] - , itrRequest :: Maybe Request - , itrResponse :: TVar (Maybe Response) - - -- FIXME: この三つは本來 TVar であるべきでないので、唯の Bool にす - -- るに越した事は無いが、それは重要でない。そんな golf で自分の貴重 - -- な時間を /dev/null に突っ込むのは、他にしたい事が何も無くなって - -- からにすべき。 - , itrRequestHasBody :: TVar Bool - , itrRequestIsChunked :: TVar Bool - , itrExpectedContinue :: TVar Bool - - , itrReqChunkLength :: TVar (Maybe Int) - , itrReqChunkRemaining :: TVar (Maybe Int) - , itrReqChunkIsOver :: TVar Bool - , itrReqBodyWanted :: TVar (Maybe Int) - , itrReqBodyWasteAll :: TVar Bool - , itrReceivedBody :: TVar ByteString -- Resource が受領した部分は削除される - - , itrWillReceiveBody :: TVar Bool - , itrWillChunkBody :: TVar Bool - , itrWillDiscardBody :: TVar Bool - , itrWillClose :: TVar Bool - - , itrBodyToSend :: TVar ByteString - , itrBodyIsNull :: TVar Bool - - , itrState :: TVar InteractionState - - , itrWroteContinue :: TVar Bool - , itrWroteHeader :: TVar Bool + itrConfig :: !Config + , itrRemoteAddr :: !SockAddr + , itrResourcePath :: !(Maybe [String]) + , itrRequest :: !(TVar (Maybe Request)) + , itrResponse :: !(TVar Response) + + , itrRequestHasBody :: !(TVar Bool) + , itrRequestIsChunked :: !(TVar Bool) + , itrExpectedContinue :: !(TVar Bool) + + , itrReqChunkLength :: !(TVar (Maybe Int)) + , itrReqChunkRemaining :: !(TVar (Maybe Int)) + , itrReqChunkIsOver :: !(TVar Bool) + , itrReqBodyWanted :: !(TVar (Maybe Int)) + , itrReqBodyWasteAll :: !(TVar Bool) + , itrReceivedBody :: !(TVar LazyByteString) -- Resource が受領した部分は削除される + + , itrWillReceiveBody :: !(TVar Bool) + , itrWillChunkBody :: !(TVar Bool) + , itrWillDiscardBody :: !(TVar Bool) + , itrWillClose :: !(TVar Bool) + + , itrBodyToSend :: !(TVar LazyByteString) + , itrBodyIsNull :: !(TVar Bool) + + , itrState :: !(TVar InteractionState) + + , itrWroteContinue :: !(TVar Bool) + , itrWroteHeader :: !(TVar Bool) } -- Resource の視點で見た時の状態。常に上から下へ行き、逆行しない。初期 @@ -75,9 +75,19 @@ newInteractionQueue :: IO InteractionQueue newInteractionQueue = newTVarIO S.empty -newInteraction :: Config -> HostName -> Maybe Request -> IO Interaction -newInteraction conf host req - = do responce <- newTVarIO Nothing +defaultPageContentType :: ByteString +defaultPageContentType = C8.pack "application/xhtml+xml" + + +newInteraction :: Config -> SockAddr -> Maybe Request -> IO Interaction +newInteraction conf addr req + = conf `seq` addr `seq` req `seq` + do request <- newTVarIO $ req + responce <- newTVarIO $ Response { + resVersion = HttpVersion 1 1 + , resStatus = Ok + , resHeaders = toHeaders [(C8.pack "Content-Type", defaultPageContentType)] + } requestHasBody <- newTVarIO False requestIsChunked <- newTVarIO False @@ -88,14 +98,14 @@ newInteraction conf host req reqChunkIsOver <- newTVarIO False -- 最後のチャンクを讀み終へた reqBodyWanted <- newTVarIO Nothing -- Resource が要求してゐるチャンク長 reqBodyWasteAll <- newTVarIO False -- 殘りの body を讀み捨てよと云ふ要求 - receivedBody <- newTVarIO B.empty + receivedBody <- newTVarIO L8.empty willReceiveBody <- newTVarIO False willChunkBody <- newTVarIO False willDiscardBody <- newTVarIO False willClose <- newTVarIO False - bodyToSend <- newTVarIO B.empty + bodyToSend <- newTVarIO L8.empty bodyIsNull <- newTVarIO True -- 一度でも bodyToSend が空でなくなったら False state <- newTVarIO ExaminingRequest @@ -105,13 +115,13 @@ newInteraction conf host req return $ Interaction { itrConfig = conf - , itrRemoteHost = host + , itrRemoteAddr = addr , itrResourcePath = Nothing - , itrRequest = req + , itrRequest = request , itrResponse = responce - , itrRequestHasBody = requestHasBody - , itrRequestIsChunked = requestIsChunked + , itrRequestHasBody = requestHasBody + , itrRequestIsChunked = requestIsChunked , itrExpectedContinue = expectedContinue , itrReqChunkLength = reqChunkLength @@ -138,25 +148,32 @@ newInteraction conf host req writeItr :: Interaction -> (Interaction -> TVar a) -> a -> STM () writeItr itr accessor value - = writeTVar (accessor itr) value + = itr `seq` accessor `seq` value `seq` + writeTVar (accessor itr) value readItr :: Interaction -> (Interaction -> TVar a) -> (a -> b) -> STM b readItr itr accessor reader - = readTVar (accessor itr) >>= return . reader + = itr `seq` accessor `seq` reader `seq` + readTVar (accessor itr) >>= return . reader -readItrF :: (Functor f) => Interaction -> (Interaction -> TVar (f a)) -> (a -> b) -> STM (f b) +readItrF :: Functor f => Interaction -> (Interaction -> TVar (f a)) -> (a -> b) -> STM (f b) readItrF itr accessor reader - = readItr itr accessor (fmap reader) + = itr `seq` accessor `seq` reader `seq` + readItr itr accessor (fmap reader) +{-# SPECIALIZE readItrF :: Interaction -> (Interaction -> TVar (Maybe a)) -> (a -> b) -> STM (Maybe b) #-} updateItr :: Interaction -> (Interaction -> TVar a) -> (a -> a) -> STM () updateItr itr accessor updator - = do old <- readItr itr accessor id + = itr `seq` accessor `seq` updator `seq` + do old <- readItr itr accessor id writeItr itr accessor (updator old) -updateItrF :: (Functor f) => Interaction -> (Interaction -> TVar (f a)) -> (a -> a) -> STM () +updateItrF :: Functor f => Interaction -> (Interaction -> TVar (f a)) -> (a -> a) -> STM () updateItrF itr accessor updator - = updateItr itr accessor (fmap updator) + = itr `seq` accessor `seq` updator `seq` + updateItr itr accessor (fmap updator) +{-# SPECIALIZE updateItrF :: Interaction -> (Interaction -> TVar (Maybe a)) -> (a -> a) -> STM () #-} \ No newline at end of file