]> gitweb @ CieloNegro.org - Lucu.git/blobdiff - Network/HTTP/Lucu/Interaction.hs
staticDir
[Lucu.git] / Network / HTTP / Lucu / Interaction.hs
index 44f4243b6ebe2abb5b02cb0891d783bd60f60655..68c6c0e919d6431a4ccc8b8524c1bcefab0ee014 100644 (file)
@@ -3,7 +3,13 @@ module Network.HTTP.Lucu.Interaction
     , InteractionState(..)
     , InteractionQueue
     , newInteractionQueue -- IO InteractionQueue
-    , newInteraction      -- HostName -> Maybe Request -> IO Interaction
+    , 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 ()
     )
     where
 
@@ -13,25 +19,39 @@ import           Data.ByteString.Lazy.Char8 (ByteString)
 import qualified Data.Sequence as S
 import           Data.Sequence (Seq)
 import           Network
+import           Network.HTTP.Lucu.Config
 import           Network.HTTP.Lucu.Request
 import           Network.HTTP.Lucu.Response
 
 data Interaction = Interaction {
-      itrRemoteHost  :: HostName
-    , itrRequest     :: Maybe Request
-    , itrResponse    :: TVar (Maybe Response)
-
+      itrConfig       :: Config
+    , itrRemoteHost   :: HostName
+    , itrResourcePath :: Maybe [String]
+    , itrRequest      :: Maybe Request
+    , itrResponse     :: TVar (Maybe Response)
+
+    -- FIXME: この三つは本來 TVar であるべきでないので、唯の Bool にす
+    -- るに越した事は無いが、それは重要でない。そんな golf で自分の貴重
+    -- な時間を /dev/null に突っ込むのは、他にしたい事が何も無くなって
+    -- からにすべき。
     , itrRequestHasBody    :: TVar Bool
-    , itrRequestBodyLength :: TVar (Maybe Integer) -- chunked の場合は不明
     , itrRequestIsChunked  :: TVar Bool
-    , itrReceivedBody      :: TVar ByteString -- Resource が受領した部分は削除される
-    
     , itrExpectedContinue  :: TVar Bool
 
-    , itrWillChunkBody    :: TVar Bool
-    , itrWillDiscardBody  :: TVar Bool
-    , itrWillClose        :: TVar Bool
-    , itrBodyToSend       :: TVar ByteString
+    , 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
 
@@ -40,14 +60,13 @@ data Interaction = Interaction {
     }
 
 -- Resource の視點で見た時の状態。常に上から下へ行き、逆行しない。初期
--- 状態は ExaminingHeader (リクエストボディが有る時) または
--- DecidingHeader (無い時)。終了状態は常に Done
-data InteractionState = ExaminingHeader
+-- 状態は ExaminingRequest。
+data InteractionState = ExaminingRequest
                       | GettingBody
                       | DecidingHeader
                       | DecidingBody
                       | Done
-                        deriving (Show, Eq, Ord)
+                        deriving (Show, Eq, Ord, Enum)
 
 type InteractionQueue = TVar (Seq Interaction)
 
@@ -56,46 +75,88 @@ newInteractionQueue :: IO InteractionQueue
 newInteractionQueue = newTVarIO S.empty
 
 
-newInteraction :: HostName -> Maybe Request -> IO Interaction
-newInteraction host req
+newInteraction :: Config -> HostName -> Maybe Request -> IO Interaction
+newInteraction conf host req
     = do responce <- newTVarIO Nothing
 
-         requestHasBody    <- newTVarIO False
-         requestBodyLength <- newTVarIO Nothing
-         requestIsChunked  <- newTVarIO False
-         receivedBody      <- newTVarIO B.empty
+         requestHasBody     <- newTVarIO False
+         requestIsChunked   <- newTVarIO False
+         expectedContinue   <- newTVarIO False
+         
+         reqChunkLength     <- newTVarIO Nothing -- 現在のチャンク長
+         reqChunkRemaining  <- newTVarIO Nothing -- 現在のチャンクの殘り
+         reqChunkIsOver     <- newTVarIO False   -- 最後のチャンクを讀み終へた
+         reqBodyWanted      <- newTVarIO Nothing -- Resource が要求してゐるチャンク長
+         reqBodyWasteAll    <- newTVarIO False   -- 殘りの body を讀み捨てよと云ふ要求
+         receivedBody       <- newTVarIO B.empty
 
-         expectedContinue <- newTVarIO False
+         willReceiveBody   <- newTVarIO False
+         willChunkBody     <- newTVarIO False
+         willDiscardBody   <- newTVarIO False
+         willClose         <- newTVarIO False
 
-         willChunkBody   <- newTVarIO False
-         willDiscardBody <- newTVarIO False
-         willClose       <- newTVarIO False
-         bodyToSend      <- newTVarIO B.empty
+         bodyToSend <- newTVarIO B.empty
+         bodyIsNull <- newTVarIO True -- 一度でも bodyToSend が空でなくなったら False
 
-         state <- newTVarIO undefined
+         state <- newTVarIO ExaminingRequest
 
          wroteContinue <- newTVarIO False
          wroteHeader   <- newTVarIO False
 
          return $ Interaction {
-                      itrRemoteHost = host
-                    , itrRequest    = req
-                    , itrResponse   = responce
+                      itrConfig       = conf
+                    , itrRemoteHost   = host
+                    , itrResourcePath = Nothing
+                    , itrRequest      = req
+                    , itrResponse     = responce
 
                     , itrRequestHasBody    = requestHasBody
-                    , itrRequestBodyLength = requestBodyLength
                     , itrRequestIsChunked  = requestIsChunked
+                    , itrExpectedContinue = expectedContinue
+
+                    , itrReqChunkLength    = reqChunkLength
+                    , itrReqChunkRemaining = reqChunkRemaining
+                    , itrReqChunkIsOver    = reqChunkIsOver
+                    , itrReqBodyWanted     = reqBodyWanted
+                    , itrReqBodyWasteAll   = reqBodyWasteAll
                     , itrReceivedBody      = receivedBody
 
-                    , itrExpectedContinue = expectedContinue
+                    , itrWillReceiveBody   = willReceiveBody
+                    , itrWillChunkBody     = willChunkBody
+                    , itrWillDiscardBody   = willDiscardBody
+                    , itrWillClose         = willClose
 
-                    , itrWillChunkBody    = willChunkBody
-                    , itrWillDiscardBody  = willDiscardBody
-                    , itrWillClose        = willClose
-                    , itrBodyToSend       = bodyToSend
+                    , itrBodyToSend = bodyToSend
+                    , itrBodyIsNull = bodyIsNull
                     
                     , itrState = state
                     
                     , itrWroteContinue = wroteContinue
                     , itrWroteHeader   = wroteHeader
                     }
+
+
+writeItr :: Interaction -> (Interaction -> TVar a) -> a -> STM ()
+writeItr itr accessor value
+    = writeTVar (accessor itr) value
+
+
+readItr :: Interaction -> (Interaction -> TVar a) -> (a -> b) -> STM b
+readItr itr accessor reader
+    = readTVar (accessor itr) >>= return . reader
+
+
+readItrF :: (Functor f) => Interaction -> (Interaction -> TVar (f a)) -> (a -> b) -> STM (f b)
+readItrF itr accessor reader
+    = readItr itr accessor (fmap reader)
+
+
+updateItr :: Interaction -> (Interaction -> TVar a) -> (a -> a) -> STM ()
+updateItr itr accessor updator
+    = do old <- readItr itr accessor id
+         writeItr itr accessor (updator old)
+
+
+updateItrF :: (Functor f) => Interaction -> (Interaction -> TVar (f a)) -> (a -> a) -> STM ()
+updateItrF itr accessor updator
+    = updateItr itr accessor (fmap updator)