diff --git a/cbits/tlsinc.c b/cbits/tlsinc.c
--- a/cbits/tlsinc.c
+++ b/cbits/tlsinc.c
@@ -63,7 +63,10 @@
 void dispose_wired_session(wired_session_t* ws);
 static int thread_setup(void);
 
+// Preprocessor flag: when 1, we will trace ALPN info
+#define TRACE_ALPN_NEGOTIATION 0
 
+
 ////////////////////////////////////////////////////////////////////////
 
 
@@ -319,24 +322,32 @@
     connection_t* conn = (connection_t*) arg;
     static char output[64];
 
-    char* incursor = (char*) in;
 
-    while (incursor < (char*)in + inlen )
-    {
-        // Got a protocol.... can I satisfy it?
-        char sublen = *incursor;
-        //printf("offered prot %.*s \n", sublen, incursor+1);
+#if TRACE_ALPN_NEGOTIATION
+    printf("protocol check starts, offered %d bytes for protocols ^^^^^^^^^^^^^ \n", inlen);
+    int first_run = 1;
+#endif
+    char* stored_cursor = conn->protocol_list;
 
-        char* stored_cursor = conn->protocol_list;
+    while( stored_cursor < conn->protocol_list + conn->protocol_list_length)
+    {
+        char* incursor = (char*) in;
         int sto_protocol = 0;
+        char sublen2 = *stored_cursor;
 
-        while( stored_cursor < conn->protocol_list + conn->protocol_list_length)
+        while (incursor < (char*)in + inlen )
         {
-            char sublen2 = *stored_cursor;
+            // Got a protocol.... can I satisfy it?
+            char sublen = *incursor;
 
+#if TRACE_ALPN_NEGOTIATION
+            if (first_run)
+                printf("offered prot %.*s \n", sublen, incursor+1);
+#endif
+
             if (sublen != sublen2)
             {
-
+                // No match, just continue
             } else {
                 int cmpresult = strncmp( incursor + 1, stored_cursor + 1, sublen);
                 if (cmpresult == 0)
@@ -344,19 +355,29 @@
                     // They are equal, choose this one...
                     strncpy( output, stored_cursor+1, sublen);
                     *outlen = sublen;
-                    *out = output;
-
-
+                    *out = (unsigned char*)output;
+#if TRACE_ALPN_NEGOTIATION
+                    printf("protocol check ends by match vvvvvvvvvvv \n");
+#endif
                     return SSL_TLSEXT_ERR_OK;
                 }
             }
-            sto_protocol += 1;
-            stored_cursor += (1+sublen2);
+
+            incursor += (1+sublen);
         }
 
-        incursor += (1+sublen);
+#if TRACE_ALPN_NEGOTIATION
+        first_run = 0;
+#endif
+
+        sto_protocol += 1;
+        stored_cursor += (1+sublen2);
+
     }
 
+#if TRACE_ALPN_NEGOTIATION
+    printf("protocol check ends without match vvvvvvvvvvv \n");
+#endif
     // I think this is what should be returned
     return -1;
 }
@@ -487,7 +508,10 @@
         // Give the impression that we are using SNI
         SSL_CTX_set_tlsext_servername_callback(c->sslContext, ssl_servername_cb);
 
+        // Disable the session cache
+        SSL_CTX_set_session_cache_mode(c->sslContext, SSL_SESS_CACHE_OFF);
 
+
         // The only cipher supported by HTTP/2 ... sort of.
         result = SSL_CTX_set_cipher_list(c->sslContext,
             "ECDHE-RSA-AES128-GCM-SHA256" //  --  ibidem
@@ -811,16 +835,31 @@
 {
     if (ws == 0)
         return ;
+
     if ( ws-> sslHandle )
     {
-        SSL_shutdown( ws->sslHandle );
-        ws -> sslHandle = 0;
+        int rr = SSL_shutdown( ws->sslHandle );
+        // printf("rr=%d\n", rr);
+        int err = SSL_get_error(ws->sslHandle, rr);
+        if ( err < 0)
+        {
+            if ( err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE )
+            {
+                printf("error when closing socket / wait-for-data\n");
+            } else if (err != 0 ){
+                printf("cause openssl error code %d \n",err);
+            }
+        }
     }
+
+    SSL_free(ws->sslHandle);
+    ws -> sslHandle = 0;
     if (ws->socket)
     {
         close(ws->socket);
         ws -> socket = 0;
     }
+
     free(ws);
 }
 
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,9 +1,19 @@
+- 0.6.1.0 :
+    * Improved documentation.
+    * Improved ALPN negotiation handling.
+    * Messages with a body are now handled by the HTTP/1.1 speaking part of this
+      library.
+
 - 0.6.0.0 :
     * Changed the interface to provide more information to and from workers
     * Implemented HTTP/2 push
     * Upgraded dependencies to 1.0. for http2 package
     * Extended channel interface in such a way that latency is reduced, as a result,
       the test suite is completely broken. Please wait for 0.6.0.1 release.
+
+- 0.5.5.1 :
+    * Restricted HTTP2 package version.
+    * Fixes #2
 
 - 0.5.5.0 :
     * Made HeaderEditor a Monoid instance
diff --git a/hs-src/SecondTransfer.hs b/hs-src/SecondTransfer.hs
--- a/hs-src/SecondTransfer.hs
+++ b/hs-src/SecondTransfer.hs
@@ -6,6 +6,9 @@
 Stability   : experimental
 Portability : POSIX
 
+SecondTransfer is a HTTP/1.1 and HTTP/2 server session library, with an emphasis towards
+experimentation (so far).
+
 This library implements enough of the HTTP/2  to build
 compliant HTTP/2 servers. It also implements enough of
 HTTP/1.1 so you can actually use it to build polyglot web-servers.
@@ -15,9 +18,6 @@
 This library just takes care of making sense of sent and received
 frames.
 
-You can find more detailed information about this library at the page
-<https://www.httptwo.com/second-transfer/>.
-
 The library
 
   * Is concurrent, meaning that you can use amazing Haskell lightweight threads to
@@ -63,9 +63,11 @@
     -- if you wish.
     -- If you do multiple yields, no data will be left buffered between them,
     -- so that you can for example implement a chat client in a single HTTP/2 stream.
-    -- Pity browsers hardly support that.
+    -- Not that browsers support that. 
     yield "Hello world!"
-    -- No footers
+    -- The HTTP/2 protocol supports sending headers *after* stream data. So, you usually
+    -- return an empty list to signal that you don't want any of those headers. 
+    -- In these docs, the post headers are often called "footers".
     return []
 
 
@@ -107,7 +109,10 @@
 
 `AwareWorker` is the type of the basic callback function that you need to implement, but
 most times you can do with a simplified version called `CoherentWorker`. The function
-`coherentToAwareWorker` does the conversion.
+`coherentToAwareWorker` does the conversion. The difference between the two callbacks is 
+the level of information that you manage. With AwareWorker, you get a record on the request
+with all sort of details, things like the session id and the 
+
 The callback is used to handle all requests to the server on a given negotiated ALPN
 protocol. If you need routing functionality (and you most certainly will need it), you need
 to build that functionality inside the callback.
diff --git a/hs-src/SecondTransfer/Http1/Parse.hs b/hs-src/SecondTransfer/Http1/Parse.hs
--- a/hs-src/SecondTransfer/Http1/Parse.hs
+++ b/hs-src/SecondTransfer/Http1/Parse.hs
@@ -48,8 +48,6 @@
 import           SecondTransfer.MainLoop.CoherentWorker (Headers)
 import           SecondTransfer.Utils                   (subByteString)
 
-import           Prelude
-
 
 data IncrementalHttp1Parser = IncrementalHttp1Parser {
     _fullText :: Bu.Builder
diff --git a/hs-src/SecondTransfer/Http1/Session.hs b/hs-src/SecondTransfer/Http1/Session.hs
--- a/hs-src/SecondTransfer/Http1/Session.hs
+++ b/hs-src/SecondTransfer/Http1/Session.hs
@@ -8,6 +8,7 @@
 import           Control.Lens
 import           Control.Exception                       (catch)
 import           Control.Concurrent                      (forkIO)
+import           Control.Monad.IO.Class                  (liftIO)
 
 import qualified Data.ByteString                         as B
 -- import qualified Data.ByteString.Lazy                   as LB
@@ -15,10 +16,12 @@
 -- import qualified Data.ByteString.Builder                as Bu
 import           Data.Conduit
 import           Data.Conduit.List                       (consume)
+import           Data.IORef
 -- import           Data.Monoid                            (mconcat, mappend)
 
 import           SecondTransfer.MainLoop.CoherentWorker
 import           SecondTransfer.MainLoop.PushPullType
+import           SecondTransfer.MainLoop.Protocol
 import           SecondTransfer.Sessions.Internal        (SessionsContext, acquireNewSessionTag, sessionsConfig)
 
 -- Logging utilities
@@ -41,7 +44,7 @@
     =
     do
         new_session_tag <- acquireNewSessionTag sessions_context
-        infoM "Session.Session_HTTP11" $ "Starting new session with tag: " ++(show new_session_tag)
+        -- infoM "Session.Session_HTTP11" $ "Starting new session with tag: " ++(show new_session_tag)
         forkIO $ go new_session_tag (Just "") 1
         return ()
   where
@@ -52,13 +55,15 @@
 
     go :: Int -> Maybe B.ByteString -> Int -> IO ()
     go session_tag (Just leftovers) reuse_no = do
-        infoM "Session.Session_HTTP11" $ "(Re)Using session with tag: " ++ (show session_tag)
+        -- infoM "Session.Session_HTTP11" $ "(Re)Using session with tag: " ++ (show session_tag)
         maybe_leftovers <- add_data newIncrementalHttp1Parser leftovers session_tag reuse_no
         go session_tag maybe_leftovers (reuse_no + 1)
 
     go _ Nothing _  =
         return ()
 
+    -- This function will invoke itself as long as data is coming for the currently-being-parsed
+    -- request/response.
     add_data :: IncrementalHttp1Parser  -> B.ByteString -> Int -> Int -> IO (Maybe B.ByteString)
     add_data parser bytes session_tag reuse_no = do
         let
@@ -78,7 +83,7 @@
                     ( (\ _e -> do
                         -- This is a pretty harmless condition that happens
                         -- often when the remote peer closes the connection
-                        debugM "Session.HTTP1" "Could not receive data"
+                        -- debugM "Session.HTTP1" "Could not receive data"
                         close_action
                         return Nothing
                     ) :: IOProblem -> IO (Maybe B.ByteString) )
@@ -98,9 +103,11 @@
                         _headers_RQ = modified_headers,
                         _inputData_RQ = Nothing,
                         _perception_RQ = Perception {
-                          _startedTime_Pr = started_time,
-                          _streamId_Pr    = reuse_no,
-                          _sessionId_Pr   = session_tag
+                          _startedTime_Pr       = started_time,
+                          _streamId_Pr          = reuse_no,
+                          _sessionId_Pr         = session_tag,
+                          _protocol_Pr          = Http11_HPV,
+                          _anouncedProtocols_Pr = Nothing
                         }
                     }
                 let
@@ -117,18 +124,74 @@
                         return $ Just leftovers
                     )
                     ((\ _e -> do
-                        debugM "Session.HTTP1" "Session abandoned"
+                        -- debugM "Session.HTTP1" "Session abandoned"
                         close_action
                         return Nothing
                     ) :: IOProblem -> IO (Maybe B.ByteString) )
 
-            HeadersAndBody_H1PC _headers _stopcondition _recv_leftovers -> do
-                -- print "HeadersAndBody_H1PC"
-                -- Let's see if I can go through the basic movements first, then through
-                -- more complicated things.
-                -- TODO: Implement posts and other requests with bodies....
-                close_action
-                error "NotImplemented requests with bodies"
+            HeadersAndBody_H1PC headers stopcondition recv_leftovers -> do
+                let
+                    modified_headers = addExtraHeaders sessions_context headers
+                started_time <- getTime Monotonic
+                set_leftovers <- newIORef ""
+
+                principal_stream <- coherent_worker Request {
+                        _headers_RQ = modified_headers,
+                        _inputData_RQ = Just $ counting_read recv_leftovers stopcondition set_leftovers,
+                        _perception_RQ = Perception {
+                          _startedTime_Pr       = started_time,
+                          _streamId_Pr          = reuse_no,
+                          _sessionId_Pr         = session_tag,
+                          _protocol_Pr          = Http11_HPV,
+                          _anouncedProtocols_Pr = Nothing
+                        }
+                    }
+                let
+                    data_and_conclusion = principal_stream ^. dataAndConclusion_PS
+                    response_headers    = principal_stream ^. headers_PS
+                (_, fragments) <- runConduit $ fuseBoth data_and_conclusion consume
+                channel_leftovers <- readIORef set_leftovers
+                let
+                    response_text =
+                        serializeHTTPResponse response_headers fragments
+
+                catch
+                    (do
+                        push_action response_text
+                        return $ Just channel_leftovers
+                    )
+                    ((\ _e -> do
+                        -- debugM "Session.HTTP1" "Session abandoned"
+                        close_action
+                        return Nothing
+                    ) :: IOProblem -> IO (Maybe B.ByteString) )
+
+    counting_read :: B.ByteString -> BodyStopCondition -> IORef B.ByteString -> Source IO B.ByteString
+    counting_read leftovers un@(UseBodyLength_BSC n) set_leftovers = do
+        -- Can I continue?
+        if n == 0 then
+          do
+            liftIO $ writeIORef set_leftovers leftovers
+            return ()
+        else
+          do
+            let
+                lngh_leftovers = B.length leftovers
+            if lngh_leftovers > 0 then
+                if lngh_leftovers <= n then
+                  do
+                    yield leftovers
+                    counting_read "" (UseBodyLength_BSC (n - lngh_leftovers )) set_leftovers
+                else
+                  do
+                    let
+                      (pass, new_leftovers) = B.splitAt n leftovers
+                    yield pass
+                    counting_read new_leftovers (UseBodyLength_BSC 0) set_leftovers
+            else
+              do
+                more_text <- liftIO $ best_effort_pull_action True
+                counting_read more_text un set_leftovers
 
 
 addExtraHeaders :: SessionsContext -> Headers -> Headers
diff --git a/hs-src/SecondTransfer/Http2/Framer.hs b/hs-src/SecondTransfer/Http2/Framer.hs
--- a/hs-src/SecondTransfer/Http2/Framer.hs
+++ b/hs-src/SecondTransfer/Http2/Framer.hs
@@ -135,7 +135,7 @@
     , _closeAction           :: CloseAction
 
     -- Global id of the session, used for e.g. error reporting.
-    , _sessionIdAtFramer     :: Int
+    , _sessionIdAtFramer     :: !Int
 
     -- Sessions context, used for thing like e.g. error reporting
     , _sessionsContext       :: SessionsContext
@@ -166,7 +166,7 @@
 
     new_session_id <- modifyMVarMasked
         session_id_mvar $
-        \ session_id -> return (session_id+1, session_id)
+        \ session_id -> return $ session_id `seq` (session_id + 1, session_id)
 
     (session_input, session_output) <- http2Session
                                         aware_worker
diff --git a/hs-src/SecondTransfer/Http2/Session.hs b/hs-src/SecondTransfer/Http2/Session.hs
--- a/hs-src/SecondTransfer/Http2/Session.hs
+++ b/hs-src/SecondTransfer/Http2/Session.hs
@@ -66,6 +66,7 @@
 -- Imports from other parts of the program
 import           SecondTransfer.MainLoop.CoherentWorker
 import           SecondTransfer.MainLoop.Tokens
+import           SecondTransfer.MainLoop.Protocol
 import           SecondTransfer.Sessions.Config
 import           SecondTransfer.Sessions.Internal       (sessionExceptionHandler,
                                                          SessionsContext,
@@ -356,8 +357,6 @@
 --- more robust.
 sessionInputThread :: ReaderT SessionData IO ()
 sessionInputThread  = do
-    INSTRUMENTATION( debugM "HTTP2.Session" "Entering sessionInputThread" )
-
     -- This is an introductory and declarative block... all of this is tail-executed
     -- every time that  a packet needs to be processed. It may be a good idea to abstract
     -- these values in a closure...
@@ -518,7 +517,9 @@
                   perception = Perception {
                       _startedTime_Pr = headers_arrived_time,
                       _streamId_Pr = stream_id,
-                      _sessionId_Pr = current_session_id
+                      _sessionId_Pr = current_session_id,
+                      _protocol_Pr = Http2_HPV,
+                      _anouncedProtocols_Pr = Nothing
                       }
                   request = Request {
                       _headers_RQ = header_list_after,
@@ -571,9 +572,10 @@
                 maybe_thread_id <- H.lookup stream2workerthread stream_id
                 case maybe_thread_id  of
                     Nothing ->
-                        -- This is actually more like an internal error, when this
-                        -- happens, cancel the session
-                        error "InterruptingUnexistentStream"
+                        -- This is can actually happen in some implementations: we are asked to
+                        -- cancel an stream we know nothing about. Log which stream it is
+                        logit $  "InterruptingUnexistentStream " `mappend` (pack . show $ stream_id)
+                        -- and don't get too crazy about it.
 
                     Just thread_id -> do
                         -- INSTRUMENTATION( infoM "HTTP2.Session" $ "Stream successfully interrupted" )
diff --git a/hs-src/SecondTransfer/MainLoop/CoherentWorker.hs b/hs-src/SecondTransfer/MainLoop/CoherentWorker.hs
--- a/hs-src/SecondTransfer/MainLoop/CoherentWorker.hs
+++ b/hs-src/SecondTransfer/MainLoop/CoherentWorker.hs
@@ -27,6 +27,7 @@
     , CoherentWorker
     , InputDataStream
     , TupledPrincipalStream
+    , TupledRequest
     , FragmentDeliveryCallback
 
     , headers_RQ
@@ -42,6 +43,8 @@
     , startedTime_Pr
     , streamId_Pr
     , sessionId_Pr
+    , anouncedProtocols_Pr
+    , protocol_Pr
     , fragmentDeliveryCallback_Ef
     , priorityEffect_Ef
 
@@ -54,12 +57,14 @@
 
 
 import           Control.Lens
-import qualified Data.ByteString   as B
+import qualified Data.ByteString                       as B
 import           Data.Conduit
-import           Data.Foldable     (find)
-import           System.Clock      (TimeSpec)
+import           Data.Foldable                         (find)
+import           System.Clock                          (TimeSpec)
 
+import           SecondTransfer.MainLoop.Protocol      (HttpProtocolVersion)
 
+
 -- | The name part of a header
 type HeaderName = B.ByteString
 
@@ -84,15 +89,19 @@
 
 -- | Data related to the request
 data Perception = Perception {
-  -- Monotonic time close to when the request was first seen in
-  -- the processing pipeline.
-  _startedTime_Pr :: TimeSpec,
-  -- The HTTP/2 stream id. Or the serial number of the request in an
-  -- HTTP/1.1 session.
-  _streamId_Pr :: Int,
-  -- You know better than to use this for normal web request
-  -- processing. But otherwise a number uniquely identifying the session. 
-  _sessionId_Pr :: Int
+    -- | The HTTP/2 stream id. Or the serial number of the request in an
+    -- HTTP/1.1 session.
+    _streamId_Pr :: Int,
+    -- | A number uniquely identifying the session. This number is unique and
+    --   the same for each TPC connection that a client opens using a given protocol.
+    _sessionId_Pr :: Int,
+    -- | Monotonic time close to when the request was first seen in
+    -- the processing pipeline.
+    _startedTime_Pr       :: TimeSpec,
+    -- | Which protocol is serving the request
+    _protocol_Pr          :: HttpProtocolVersion,
+    -- | For new connections, probably a list of anounced protocols
+    _anouncedProtocols_Pr :: Maybe [B.ByteString]
   }
 
 makeLenses ''Perception
@@ -197,15 +206,22 @@
 --   cancels the stream
 type AwareWorker = Request -> IO PrincipalStream
 
--- | A CoherentWorker is a less fuzzy worker, but less aware.
-type CoherentWorker =  (Headers, Maybe InputDataStream) -> IO (Headers, PushedStreams, DataAndConclusion)
+-- | A CoherentWorker is a simplified callback that you can implement to handle requests.
+--  Then you can convert it to an AwareWorker with `tupledPrincipalStreamToPrincipalStream`.
+type CoherentWorker =  TupledRequest -> IO TupledPrincipalStream
 
--- | Not exactly equivalent of the prinicipal stream
+-- | A tuple representing the data alone that you usually need to give as a response, that
+--   is, the headers in the response (including the HTTP/2 :status), any pushed streams,
+--   a stream with the response data and the footers.
 type TupledPrincipalStream = (Headers, PushedStreams, DataAndConclusion)
 
+-- | A tuple representing the data alone usually needed to create a response. That is,
+--   the headers (including HTTP/2 :path, :authority, etc) and maybe an input data stream
+--   for requests that include it, that is, POST and PUT.
 type TupledRequest = (Headers, Maybe InputDataStream)
 
 
+-- | Convert between the two types of callback.
 tupledPrincipalStreamToPrincipalStream :: TupledPrincipalStream -> PrincipalStream
 tupledPrincipalStreamToPrincipalStream (headers, pushed_streams, data_and_conclusion) = PrincipalStream
       {
diff --git a/hs-src/SecondTransfer/MainLoop/OpenSSL_TLS.hs b/hs-src/SecondTransfer/MainLoop/OpenSSL_TLS.hs
--- a/hs-src/SecondTransfer/MainLoop/OpenSSL_TLS.hs
+++ b/hs-src/SecondTransfer/MainLoop/OpenSSL_TLS.hs
@@ -303,15 +303,13 @@
 -- provideActions :: Wired_Ptr -> IO (LB.ByteString -> IO (), Int -> IO B.ByteString, IO ())
 provideActions :: Wired_Ptr -> IO AttendantCallbacks
 provideActions wired_ptr = do
-    already_closed_mvar <- newMVar False
+    can_write_mvar <- newMVar True
+    can_read_mvar  <- newMVar True
     let
         pushAction :: LB.ByteString -> IO ()
-        pushAction datum = do
-            already_closed <- readMVar already_closed_mvar
-            if already_closed
+        pushAction datum = withMVar can_write_mvar  $ \ can_write ->
+            if can_write
               then
-                throwIO $ TLSLayerGenericProblem "Tried to send data on closed handle"
-              else
                 BU.unsafeUseAsCStringLen (LB.toStrict datum) $ \ (pchar, len) -> do
                     result <- sendData wired_ptr pchar (fromIntegral len)
                     case result of
@@ -319,14 +317,13 @@
                                 return ()
                           | r == badHappened     ->
                                 throwIO $ TLSLayerGenericProblem "Could not send data"
+            else
+              throwIO $ TLSLayerGenericProblem "CouldNotWriteData--SocketAlreadyClosed"
 
         pullAction :: Int -> IO B.ByteString
-        pullAction bytes_to_get =  do
-            already_closed <- readMVar already_closed_mvar
-            if already_closed
+        pullAction bytes_to_get =  withMVar can_read_mvar  $ \ can_read ->
+            if can_read
               then
-                throwIO $ TLSLayerGenericProblem "Tried to receive on closed handle"
-              else
                 allocaBytes bytes_to_get $ \ pcharbuffer ->
                     alloca $ \ data_recvd_ptr -> do
                         result <- recvData wired_ptr pcharbuffer (fromIntegral bytes_to_get) data_recvd_ptr
@@ -336,14 +333,13 @@
                                     throwIO $ TLSLayerGenericProblem "Could not receive data"
 
                         B.packCStringLen (pcharbuffer, fromIntegral recvd_bytes)
+              else
+                throwIO $ TLSLayerGenericProblem "CouldNotReadData--SocketAlreadyClosed"
 
         bestEffortPullAction :: Bool -> IO B.ByteString
-        bestEffortPullAction can_wait =  do
-            already_closed <- readMVar already_closed_mvar
-            if already_closed
+        bestEffortPullAction can_wait = withMVar can_read_mvar  $ \ can_read ->
+            if can_read
               then
-                throwIO $ TLSLayerGenericProblem "Tried to receive on closed handle"
-              else
                 allocaBytes useBufferSize $ \ pcharbuffer ->
                     alloca $ \ data_recvd_ptr -> do
                         result <- recvDataBestEffort
@@ -358,14 +354,22 @@
                                     throwIO $ TLSLayerGenericProblem "Could not receive data"
 
                         B.packCStringLen (pcharbuffer, fromIntegral recvd_bytes)
+              else
+                throwIO $ TLSLayerGenericProblem "CouldNotReadData--SocketAlreadyClosed"
 
+
         closeAction :: IO ()
         -- Ensure that the socket and the struct are only closed once
-        closeAction = do
-            b <- readMVar already_closed_mvar
-            unless b $  do
-                modifyMVar_ already_closed_mvar (\ _ -> return True)
-                disposeWiredSession wired_ptr
+        closeAction =
+            modifyMVar_ can_write_mvar $ \ can_write ->
+                modifyMVar can_read_mvar $ \ can_read ->
+                    if can_write && can_read
+                      then do
+                          disposeWiredSession wired_ptr
+                          return (False,False)
+                      else
+                          return (False,False)
+
     return  AttendantCallbacks {
         _pushAction_AtC = pushAction,
         _pullAction_AtC = pullAction,
diff --git a/hs-src/SecondTransfer/MainLoop/Protocol.hs b/hs-src/SecondTransfer/MainLoop/Protocol.hs
new file mode 100644
--- /dev/null
+++ b/hs-src/SecondTransfer/MainLoop/Protocol.hs
@@ -0,0 +1,11 @@
+module SecondTransfer.MainLoop.Protocol (
+    HttpProtocolVersion(..)
+                                        ) where
+
+
+-- | The protocol version used. Here we distinguish only between
+--   HTTP/1.1 and  HTTP/2
+data HttpProtocolVersion =
+     Http11_HPV
+    |Http2_HPV
+
diff --git a/hs-src/SecondTransfer/MainLoop/PushPullType.hs b/hs-src/SecondTransfer/MainLoop/PushPullType.hs
--- a/hs-src/SecondTransfer/MainLoop/PushPullType.hs
+++ b/hs-src/SecondTransfer/MainLoop/PushPullType.hs
@@ -47,20 +47,29 @@
 --   is severed suddenly.
 type CloseAction = IO ()
 
-
+-- | A set of functions describing how to do I/O in a session.
+--   As usual, we provide lenses accessors.
 data AttendantCallbacks = AttendantCallbacks {
+    -- | put some data in the channel
     _pushAction_AtC               :: PushAction,
+    -- | get exactly this much data from the channel. This function can
+    --   be used by HTTP/2 since lengths are pretty well built inside the
+    --   protocoll itself.
     _pullAction_AtC               :: PullAction,
+    -- | pull data from the channel, as much as the TCP stack wants to provide.
+    --   we have no option but use this one when talking HTTP/1.1, where the best
+    --   way to know the length is to scan until a Content-Length is found.
     _bestEffortPullAction_AtC     :: BestEffortPullAction,
+    -- | this is called when we wish to close the channel.
     _closeAction_AtC              :: CloseAction
     }
 
 makeLenses ''AttendantCallbacks
 
--- | A function which takes three arguments: the first one says
---   how to send data (on a socket or similar transport), and the second one how
---   to receive data on the transport. The third argument encapsulates
---   the sequence of steps needed for a clean shutdown.
+-- | This is an intermediate type. It represents what you obtain
+--   by combining something that speaks the protocol and an AwareWorker.
+--   In turn, you need to feed a bundle of callbacks implementing I/O
+--   to finally start a server.
 --
 --   You can implement one of these to let somebody else  supply the
 --   push, pull and close callbacks. For example, 'tlsServeWithALPN' will
diff --git a/hs-src/SecondTransfer/Types.hs b/hs-src/SecondTransfer/Types.hs
--- a/hs-src/SecondTransfer/Types.hs
+++ b/hs-src/SecondTransfer/Types.hs
@@ -1,7 +1,9 @@
 module SecondTransfer.Types(
     module SecondTransfer.MainLoop.PushPullType
     ,module SecondTransfer.MainLoop.CoherentWorker
+    ,module SecondTransfer.MainLoop.Protocol
     ) where
 
 import SecondTransfer.MainLoop.PushPullType
 import SecondTransfer.MainLoop.CoherentWorker
+import SecondTransfer.MainLoop.Protocol
diff --git a/second-transfer.cabal b/second-transfer.cabal
--- a/second-transfer.cabal
+++ b/second-transfer.cabal
@@ -7,7 +7,7 @@
 -- PVP       summary:      +-+------- breaking API changes
 --                         | | +----- non-breaking API additions
 --                         | | | +--- code changes with no API change
-version     :              0.6.0.0
+version     :              0.6.1.0
 
 synopsis    :              Second Transfer HTTP/2 web server
 
@@ -53,7 +53,7 @@
 source-repository this
   type:     git
   location: git@github.com:alcidesv/second-transfer.git
-  tag:      0.6.0.0
+  tag:      0.6.1.0
 
 library
 
@@ -75,6 +75,7 @@
 
   other-modules:  SecondTransfer.MainLoop.CoherentWorker
                 , SecondTransfer.MainLoop.PushPullType
+                , SecondTransfer.MainLoop.Protocol
                 , SecondTransfer.MainLoop.Tokens
                 , SecondTransfer.MainLoop.Framer
                 , SecondTransfer.MainLoop.Logging
