-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | HTTP/2 library
--   
--   HTTP/2 library including frames, priority queues, HPACK, client and
--   server.
@package http2
@version 5.0.1

module Network.HPACK.Token

-- | Internal representation for header keys.
data Token
Token :: Int -> Bool -> Bool -> CI ByteString -> Token

-- | Index for value table
[tokenIx] :: Token -> Int

-- | should be indexed in HPACK
[shouldBeIndexed] :: Token -> Bool

-- | is this a pseudo header key?
[isPseudo] :: Token -> Bool

-- | Case insensitive header key
[tokenKey] :: Token -> CI ByteString

-- | Extracting a case insensitive header key from a token.
tokenCIKey :: Token -> ByteString

-- | Extracting a folded header key from a token.
tokenFoldedKey :: Token -> ByteString

-- | Making a token from a header key.
--   
--   <pre>
--   &gt;&gt;&gt; toToken ":authority" == tokenAuthority
--   True
--   
--   &gt;&gt;&gt; toToken "foo"
--   Token {tokenIx = 73, shouldBeIndexed = True, isPseudo = False, tokenKey = "foo"}
--   
--   &gt;&gt;&gt; toToken ":bar"
--   Token {tokenIx = 73, shouldBeIndexed = True, isPseudo = True, tokenKey = ":bar"}
--   </pre>
toToken :: ByteString -> Token

-- | Minimum token index.
minTokenIx :: Int

-- | Maximun token index defined in the static table.
maxStaticTokenIx :: Int

-- | Maximum token index.
maxTokenIx :: Int

-- | Token index for <a>tokenCookie</a>.
cookieTokenIx :: Int

-- | Is this token ix to be held in the place holder?
isMaxTokenIx :: Int -> Bool

-- | Is this token ix for Cookie?
isCookieTokenIx :: Int -> Bool

-- | Is this token ix for a header not defined in the static table?
isStaticTokenIx :: Int -> Bool

-- | Is this token for a header not defined in the static table?
isStaticToken :: Token -> Bool
tokenAuthority :: Token
tokenMethod :: Token
tokenPath :: Token
tokenScheme :: Token
tokenStatus :: Token
tokenAcceptCharset :: Token
tokenAcceptEncoding :: Token
tokenAcceptLanguage :: Token
tokenAcceptRanges :: Token
tokenAccept :: Token
tokenAccessControlAllowOrigin :: Token
tokenAge :: Token
tokenAllow :: Token
tokenAuthorization :: Token
tokenCacheControl :: Token
tokenContentDisposition :: Token
tokenContentEncoding :: Token
tokenContentLanguage :: Token
tokenContentLength :: Token
tokenContentLocation :: Token
tokenContentRange :: Token
tokenContentType :: Token
tokenCookie :: Token
tokenDate :: Token
tokenEtag :: Token
tokenExpect :: Token
tokenExpires :: Token
tokenFrom :: Token
tokenHost :: Token
tokenIfMatch :: Token
tokenIfModifiedSince :: Token
tokenIfNoneMatch :: Token
tokenIfRange :: Token
tokenIfUnmodifiedSince :: Token
tokenLastModified :: Token
tokenLink :: Token
tokenLocation :: Token
tokenMaxForwards :: Token
tokenProxyAuthenticate :: Token
tokenProxyAuthorization :: Token
tokenRange :: Token
tokenReferer :: Token
tokenRefresh :: Token
tokenRetryAfter :: Token
tokenServer :: Token
tokenSetCookie :: Token
tokenStrictTransportSecurity :: Token
tokenTransferEncoding :: Token
tokenUserAgent :: Token
tokenVary :: Token
tokenVia :: Token
tokenWwwAuthenticate :: Token

-- | A place holder to hold header keys not defined in the static table. |
--   For Warp
tokenConnection :: Token
tokenTE :: Token
tokenMax :: Token

-- | For QPACK
tokenAccessControlAllowCredentials :: Token
tokenAccessControlAllowHeaders :: Token
tokenAccessControlAllowMethods :: Token
tokenAccessControlExposeHeaders :: Token
tokenAccessControlRequestHeaders :: Token
tokenAccessControlRequestMethod :: Token
tokenAltSvc :: Token
tokenContentSecurityPolicy :: Token
tokenEarlyData :: Token
tokenExpectCt :: Token
tokenForwarded :: Token
tokenOrigin :: Token
tokenPurpose :: Token
tokenTimingAllowOrigin :: Token
tokenUpgradeInsecureRequests :: Token
tokenXContentTypeOptions :: Token
tokenXForwardedFor :: Token
tokenXFrameOptions :: Token
tokenXXssProtection :: Token
instance GHC.Show.Show Network.HPACK.Token.Token
instance GHC.Classes.Eq Network.HPACK.Token.Token

module Network.HPACK.Internal

-- | Integer encoding with a write buffer.
encodeI :: WriteBuffer -> (Word8 -> Word8) -> Int -> Int -> IO ()

-- | Encoding integer with a temporary buffer whose size is 4096. No prefix
--   is set.
--   
--   <pre>
--   &gt;&gt;&gt; BS.unpack &lt;$&gt; encodeInteger 5 10
--   [10]
--   
--   &gt;&gt;&gt; BS.unpack &lt;$&gt; encodeInteger 5 1337
--   [31,154,10]
--   
--   &gt;&gt;&gt; BS.unpack &lt;$&gt; encodeInteger 8 42
--   [42]
--   </pre>
encodeInteger :: Int -> Int -> IO ByteString

-- | Integer decoding with a read buffer. The first argument is N of
--   prefix.
decodeI :: Int -> Word8 -> ReadBuffer -> IO Int

-- | Integer decoding. The first argument is N of prefix.
--   
--   <pre>
--   &gt;&gt;&gt; decodeInteger 5 10 $ BS.empty
--   10
--   
--   &gt;&gt;&gt; decodeInteger 5 31 $ BS.pack [154,10]
--   1337
--   
--   &gt;&gt;&gt; decodeInteger 8 42 $ BS.empty
--   42
--   </pre>
decodeInteger :: Int -> Word8 -> ByteString -> IO Int

-- | String encoding. The algorithm based on copy avoidance and selection
--   of better result of huffman or raw.
encodeS :: WriteBuffer -> Bool -> (Word8 -> Word8) -> (Word8 -> Word8) -> Int -> ByteString -> IO ()

-- | String encoding (7+) with a temporary buffer whose size is 4096.
encodeString :: Bool -> ByteString -> IO ByteString

-- | String decoding with Huffman decoder.
decodeS :: (Word8 -> Word8) -> (Word8 -> Bool) -> Int -> HuffmanDecoder -> ReadBuffer -> IO ByteString

-- | Converting to <a>HeaderList</a>.
--   
--   <ul>
--   <li>Headers are decoded as is.</li>
--   <li><a>DecodeError</a> would be thrown if the HPACK format is
--   broken.</li>
--   <li><a>BufferOverrun</a> will be thrown if the temporary buffer for
--   Huffman decoding is too small.</li>
--   </ul>
decodeSimple :: (Word8 -> ReadBuffer -> IO TokenHeader) -> ReadBuffer -> IO HeaderList

-- | Converting to <a>TokenHeaderList</a> and <a>ValueTable</a>.
--   
--   <ul>
--   <li>Multiple values of Cookie: are concatenated.</li>
--   <li>If a pseudo header appears multiple times,
--   <a>IllegalHeaderName</a> is thrown.</li>
--   <li>If unknown pseudo headers appear, <a>IllegalHeaderName</a> is
--   thrown.</li>
--   <li>If pseudo headers are found after normal headers,
--   <a>IllegalHeaderName</a> is thrown.</li>
--   <li>If a header key contains capital letters, <a>IllegalHeaderName</a>
--   is thrown.</li>
--   <li>If the number of header fields is too large, <a>TooLargeHeader</a>
--   is thrown</li>
--   <li><a>DecodeError</a> would be thrown if the HPACK format is
--   broken.</li>
--   <li><a>BufferOverrun</a> will be thrown if the temporary buffer for
--   Huffman decoding is too small.</li>
--   </ul>
decodeSophisticated :: (Word8 -> ReadBuffer -> IO TokenHeader) -> ReadBuffer -> IO HeaderTable

-- | String decoding (7+) with a temporal Huffman decoder whose buffer is
--   4096.
decodeString :: ReadBuffer -> IO ByteString

-- | Huffman encoding.
encodeH :: WriteBuffer -> ByteString -> IO Int

-- | Huffman encoding with a temporary buffer whose size is 4096.
encodeHuffman :: ByteString -> IO ByteString

-- | Huffman decoding.
decodeH :: GCBuffer -> BufferSize -> ReadBuffer -> Int -> IO ByteString

-- | Huffman decoding with a temporary buffer whose size is 4096.
decodeHuffman :: ByteString -> IO ByteString

-- | Huffman decoding.
type HuffmanDecoder = ReadBuffer -> Int -> IO ByteString

-- | Low devel Huffman decoding in a write buffer.
decH :: WriteBuffer -> ReadBuffer -> Int -> IO ()
type GCBuffer = ForeignPtr Word8

-- | Size in bytes.
type Size = Int

-- | Type for table entry. Size includes the 32 bytes magic number.
data Entry
Entry :: Size -> Token -> HeaderValue -> Entry

-- | Header.
type Header = (HeaderName, HeaderValue)

-- | Header name.
type HeaderName = ByteString

-- | Header value.
type HeaderValue = ByteString

-- | Index for table.
type Index = Int

-- | From <a>Header</a> to <a>Entry</a>.
toEntry :: Header -> Entry
toEntryToken :: Token -> HeaderValue -> Entry

-- | Getting the size of <a>Entry</a>.
entrySize :: Entry -> Size

-- | Getting <a>TokenHeader</a>.
entryTokenHeader :: Entry -> TokenHeader

-- | Getting <a>Token</a>.
entryToken :: Entry -> Token

-- | Getting <a>HeaderName</a>.
entryHeaderName :: Entry -> HeaderName

-- | Getting <a>HeaderValue</a>.
entryHeaderValue :: Entry -> HeaderValue

-- | Dummy <a>Entry</a> to initialize a dynamic table.
dummyEntry :: Entry

-- | How many entries can be stored in a dynamic table?
maxNumbers :: Size -> Int


-- | HPACK(<a>https://tools.ietf.org/html/rfc7541</a>) encoding and
--   decoding a header list.
module Network.HPACK

-- | Converting <a>HeaderList</a> to the HPACK format. This function has
--   overhead of allocating/freeing a temporary buffer.
--   <a>BufferOverrun</a> will be thrown if the temporary buffer is too
--   small.
encodeHeader :: EncodeStrategy -> Size -> DynamicTable -> HeaderList -> IO ByteString

-- | Converting the HPACK format to <a>HeaderList</a>.
--   
--   <ul>
--   <li>Headers are decoded as is.</li>
--   <li><a>DecodeError</a> would be thrown if the HPACK format is
--   broken.</li>
--   <li><a>BufferOverrun</a> will be thrown if the temporary buffer for
--   Huffman decoding is too small.</li>
--   </ul>
decodeHeader :: DynamicTable -> ByteString -> IO HeaderList

-- | Converting <a>TokenHeaderList</a> to the HPACK format directly in the
--   buffer.
--   
--   When calling this function for a new <a>TokenHeaderList</a>, 4th
--   argument must be <a>True</a>.
--   
--   The return value is a pair of leftover <a>TokenHeaderList</a> and how
--   many bytes are filled in the buffer. If the leftover is empty, the
--   encoding is finished. Otherwise, this function should be called with
--   it again. 4th argument must be <a>False</a>.
--   
--   4th argument is relating to dynamic table size update. If <a>True</a>
--   and the limit is set by <a>setLimitForEncoding</a>, dynamic table size
--   update is generated at the beginning of the HPACK format.
encodeTokenHeader :: Buffer -> BufferSize -> EncodeStrategy -> Bool -> DynamicTable -> TokenHeaderList -> IO (TokenHeaderList, Int)

-- | Converting the HPACK format to <a>TokenHeaderList</a> and
--   <a>ValueTable</a>.
--   
--   <ul>
--   <li>Multiple values of Cookie: are concatenated.</li>
--   <li>If a pseudo header appears multiple times,
--   <a>IllegalHeaderName</a> is thrown.</li>
--   <li>If unknown pseudo headers appear, <a>IllegalHeaderName</a> is
--   thrown.</li>
--   <li>If pseudo headers are found after normal headers,
--   <a>IllegalHeaderName</a> is thrown.</li>
--   <li>If a header key contains capital letters, <a>IllegalHeaderName</a>
--   is thrown.</li>
--   <li><a>DecodeError</a> would be thrown if the HPACK format is
--   broken.</li>
--   <li><a>BufferOverrun</a> will be thrown if the temporary buffer for
--   Huffman decoding is too small.</li>
--   </ul>
decodeTokenHeader :: DynamicTable -> ByteString -> IO HeaderTable

-- | Type for dynamic table.
data DynamicTable

-- | Default dynamic table size. The value is 4,096 bytes: an array has 128
--   entries.
--   
--   <pre>
--   &gt;&gt;&gt; defaultDynamicTableSize
--   4096
--   </pre>
defaultDynamicTableSize :: Int

-- | Creating <a>DynamicTable</a> for encoding.
newDynamicTableForEncoding :: Size -> IO DynamicTable

-- | Creating <a>DynamicTable</a> for decoding.
newDynamicTableForDecoding :: Size -> Size -> IO DynamicTable

-- | Creating <a>DynamicTable</a> for encoding, performing the action and
--   clearing the <a>DynamicTable</a>.
withDynamicTableForEncoding :: Size -> (DynamicTable -> IO a) -> IO a

-- | Creating <a>DynamicTable</a> for decoding, performing the action and
--   clearing the <a>DynamicTable</a>.
withDynamicTableForDecoding :: Size -> Size -> (DynamicTable -> IO a) -> IO a

-- | When SETTINGS_HEADER_TABLE_SIZE is received from a peer, its value
--   should be set by this function.
setLimitForEncoding :: Size -> DynamicTable -> IO ()

-- | Compression algorithms for HPACK encoding.
data CompressionAlgo

-- | No compression
Naive :: CompressionAlgo

-- | Using indices in the static table only
Static :: CompressionAlgo

-- | Using indices
Linear :: CompressionAlgo

-- | Strategy for HPACK encoding.
data EncodeStrategy
EncodeStrategy :: CompressionAlgo -> Bool -> EncodeStrategy

-- | Which compression algorithm is used.
[compressionAlgo] :: EncodeStrategy -> CompressionAlgo

-- | Whether or not to use Huffman encoding for strings.
[useHuffman] :: EncodeStrategy -> Bool

-- | Default <a>EncodeStrategy</a>.
--   
--   <pre>
--   &gt;&gt;&gt; defaultEncodeStrategy
--   EncodeStrategy {compressionAlgo = Linear, useHuffman = False}
--   </pre>
defaultEncodeStrategy :: EncodeStrategy

-- | Errors for decoder.
data DecodeError

-- | Index is out of range
IndexOverrun :: Index -> DecodeError

-- | Eos appears in the middle of huffman string
EosInTheMiddle :: DecodeError

-- | Non-eos appears in the end of huffman string
IllegalEos :: DecodeError

-- | Eos of huffman string is more than 7 bits
TooLongEos :: DecodeError

-- | A peer set the dynamic table size less than 32
TooSmallTableSize :: DecodeError

-- | A peer tried to change the dynamic table size over the limit
TooLargeTableSize :: DecodeError

-- | Table size update at the non-beginning
IllegalTableSizeUpdate :: DecodeError
HeaderBlockTruncated :: DecodeError
IllegalHeaderName :: DecodeError
TooLargeHeader :: DecodeError

-- | Buffer overrun exception.
data () => BufferOverrun

-- | The buffer size is not enough
BufferOverrun :: BufferOverrun

-- | Header list.
type HeaderList = [Header]

-- | Header.
type Header = (HeaderName, HeaderValue)

-- | Header name.
type HeaderName = ByteString

-- | Header value.
type HeaderValue = ByteString

-- | TokenBased header list.
type TokenHeaderList = [TokenHeader]

-- | TokenBased header.
type TokenHeader = (Token, HeaderValue)

-- | An array to get <a>HeaderValue</a> quickly. <a>getHeaderValue</a>
--   should be used. Internally, the key is <a>tokenIx</a>.
type ValueTable = Array Int (Maybe HeaderValue)

-- | A pair of token list and value table.
type HeaderTable = (TokenHeaderList, ValueTable)

-- | Accessing <a>HeaderValue</a> with <a>Token</a>.
getHeaderValue :: Token -> ValueTable -> Maybe HeaderValue

-- | Converting a header list of the http-types style to
--   <a>TokenHeaderList</a> and <a>ValueTable</a>.
toHeaderTable :: [(CI HeaderName, HeaderValue)] -> IO HeaderTable

-- | Size in bytes.
type Size = Int

-- | Index for table.
type Index = Int

-- | A pointer to <a>Word8</a>.
type Buffer = Ptr Word8

-- | Size of a buffer.
type BufferSize = Int

-- | Retrieve the original string-like value.
original :: CI s -> s

-- | Retrieve the case folded string-like value. (Also see
--   <a>foldCase</a>).
foldedCase :: CI s -> s

-- | Make the given string-like value case insensitive.
mk :: FoldCase s => s -> CI s


-- | Framing in HTTP/2(<a>https://www.rfc-editor.org/rfc/rfc9113</a>).
module Network.HTTP2.Frame

-- | The data type for HTTP/2 frames.
data Frame
Frame :: FrameHeader -> FramePayload -> Frame
[frameHeader] :: Frame -> FrameHeader
[framePayload] :: Frame -> FramePayload

-- | The data type for HTTP/2 frame headers.
data FrameHeader
FrameHeader :: Int -> FrameFlags -> StreamId -> FrameHeader
[payloadLength] :: FrameHeader -> Int
[flags] :: FrameHeader -> FrameFlags
[streamId] :: FrameHeader -> StreamId

-- | The data type for HTTP/2 frame payloads.
data FramePayload
DataFrame :: ByteString -> FramePayload
HeadersFrame :: Maybe Priority -> HeaderBlockFragment -> FramePayload
PriorityFrame :: Priority -> FramePayload
RSTStreamFrame :: ErrorCode -> FramePayload
SettingsFrame :: SettingsList -> FramePayload
PushPromiseFrame :: StreamId -> HeaderBlockFragment -> FramePayload
PingFrame :: ByteString -> FramePayload
GoAwayFrame :: StreamId -> ErrorCode -> ByteString -> FramePayload
WindowUpdateFrame :: WindowSize -> FramePayload
ContinuationFrame :: HeaderBlockFragment -> FramePayload
UnknownFrame :: FrameType -> ByteString -> FramePayload

-- | The type for fragments of a header encoded with HPACK.
type HeaderBlockFragment = ByteString

-- | The type for padding in payloads.
type Padding = ByteString

-- | Checking if padding is defined in this frame type.
--   
--   <pre>
--   &gt;&gt;&gt; isPaddingDefined $ DataFrame ""
--   True
--   
--   &gt;&gt;&gt; isPaddingDefined $ PingFrame ""
--   False
--   </pre>
isPaddingDefined :: FramePayload -> Bool

-- | Encoding an HTTP/2 frame to <a>ByteString</a>. This function is not
--   efficient enough for high performace program because of the
--   concatenation of <a>ByteString</a>.
--   
--   <pre>
--   &gt;&gt;&gt; encodeFrame (encodeInfo id 1) (DataFrame "body")
--   "\NUL\NUL\EOT\NUL\NUL\NUL\NUL\NUL\SOHbody"
--   </pre>
encodeFrame :: EncodeInfo -> FramePayload -> ByteString

-- | Encoding an HTTP/2 frame to [<a>ByteString</a>]. This is suitable for
--   sendMany.
encodeFrameChunks :: EncodeInfo -> FramePayload -> [ByteString]

-- | Encoding an HTTP/2 frame header. The frame header must be completed.
encodeFrameHeader :: FrameType -> FrameHeader -> ByteString

-- | Writing an encoded HTTP/2 frame header to the buffer. The length of
--   the buffer must be larger than or equal to 9 bytes.
encodeFrameHeaderBuf :: FrameType -> FrameHeader -> Ptr Word8 -> IO ()

-- | Encoding an HTTP/2 frame payload. This returns a complete frame header
--   and chunks of payload.
encodeFramePayload :: EncodeInfo -> FramePayload -> (FrameHeader, [ByteString])

-- | Auxiliary information for frame encoding.
data EncodeInfo
EncodeInfo :: FrameFlags -> StreamId -> Maybe Padding -> EncodeInfo

-- | Flags to be set in a frame header
[encodeFlags] :: EncodeInfo -> FrameFlags

-- | Stream id to be set in a frame header
[encodeStreamId] :: EncodeInfo -> StreamId

-- | Padding if any. In the case where this value is set but the priority
--   flag is not set, this value gets preference over the priority flag.
--   So, if this value is set, the priority flag is also set.
[encodePadding] :: EncodeInfo -> Maybe Padding

-- | A smart builder of <a>EncodeInfo</a>.
--   
--   <pre>
--   &gt;&gt;&gt; encodeInfo setAck 0
--   EncodeInfo {encodeFlags = 1, encodeStreamId = 0, encodePadding = Nothing}
--   </pre>
encodeInfo :: (FrameFlags -> FrameFlags) -> Int -> EncodeInfo

-- | Decoding an HTTP/2 frame to <a>ByteString</a>. The second argument
--   must be include the entire of frame. So, this function is not useful
--   for real applications but useful for testing.
decodeFrame :: ByteString -> Either FrameDecodeError Frame

-- | Decoding an HTTP/2 frame header. Must supply 9 bytes.
decodeFrameHeader :: ByteString -> (FrameType, FrameHeader)

-- | Checking a frame header and reporting an error if any.
--   
--   <pre>
--   &gt;&gt;&gt; checkFrameHeader (FrameData,(FrameHeader 100 0 0))
--   Left (FrameDecodeError ProtocolError 0 "cannot used in control stream")
--   </pre>
checkFrameHeader :: (FrameType, FrameHeader) -> Either FrameDecodeError (FrameType, FrameHeader)
data FrameDecodeError
FrameDecodeError :: ErrorCode -> StreamId -> ShortByteString -> FrameDecodeError

-- | Decoding an HTTP/2 frame payload. This function is considered to
--   return a frame payload decoder according to a frame type.
decodeFramePayload :: FrameType -> FramePayloadDecoder

-- | The type for frame payload decoder.
type FramePayloadDecoder = FrameHeader -> ByteString -> Either FrameDecodeError FramePayload

-- | Frame payload decoder for DATA frame.
decodeDataFrame :: FramePayloadDecoder

-- | Frame payload decoder for HEADERS frame.
decodeHeadersFrame :: FramePayloadDecoder

-- | Frame payload decoder for PRIORITY frame.
decodePriorityFrame :: FramePayloadDecoder

-- | Frame payload decoder for RST_STREAM frame.
decodeRSTStreamFrame :: FramePayloadDecoder

-- | Frame payload decoder for SETTINGS frame.
decodeSettingsFrame :: FramePayloadDecoder

-- | Frame payload decoder for PUSH_PROMISE frame.
decodePushPromiseFrame :: FramePayloadDecoder

-- | Frame payload decoder for PING frame.
decodePingFrame :: FramePayloadDecoder

-- | Frame payload decoder for GOAWAY frame.
decodeGoAwayFrame :: FramePayloadDecoder

-- | Frame payload decoder for WINDOW_UPDATE frame.
decodeWindowUpdateFrame :: FramePayloadDecoder

-- | Frame payload decoder for CONTINUATION frame.
decodeContinuationFrame :: FramePayloadDecoder

-- | The type for raw frame type.
newtype FrameType
FrameType :: Word8 -> FrameType
pattern FrameData :: FrameType
pattern FrameHeaders :: FrameType
pattern FramePriority :: FrameType
pattern FrameRSTStream :: FrameType
pattern FrameSettings :: FrameType
pattern FramePushPromise :: FrameType
pattern FramePing :: FrameType
pattern FrameGoAway :: FrameType
pattern FrameWindowUpdate :: FrameType
pattern FrameContinuation :: FrameType

-- | Converting <a>FrameType</a> to <a>Word8</a>.
--   
--   <pre>
--   &gt;&gt;&gt; fromFrameType FrameData
--   0
--   
--   &gt;&gt;&gt; fromFrameType FrameContinuation
--   9
--   </pre>
fromFrameType :: FrameType -> Word8
toFrameType :: Word8 -> FrameType
minFrameType :: FrameType
maxFrameType :: FrameType

-- | Getting <a>FrameType</a> from <a>FramePayload</a>.
--   
--   <pre>
--   &gt;&gt;&gt; framePayloadToFrameType (DataFrame "body")
--   FrameData
--   </pre>
framePayloadToFrameType :: FramePayload -> FrameType

-- | Type for stream priority. Deprecated in RFC 9113 but provided for
--   <a>FrameHeaders</a>.
data Priority
Priority :: Bool -> StreamId -> Weight -> Priority
[exclusive] :: Priority -> Bool
[streamDependency] :: Priority -> StreamId
[weight] :: Priority -> Weight

-- | The type for weight in priority. Its values are from 1 to 256.
--   Deprecated in RFC 9113.
type Weight = Int

-- | The type for stream identifier
type StreamId = Int

-- | Checking if the stream identifier for control.
--   
--   <pre>
--   &gt;&gt;&gt; isControl 0
--   True
--   
--   &gt;&gt;&gt; isControl 1
--   False
--   </pre>
isControl :: StreamId -> Bool

-- | Checking if the stream identifier is from a client.
--   
--   <pre>
--   &gt;&gt;&gt; isClientInitiated 0
--   False
--   
--   &gt;&gt;&gt; isClientInitiated 1
--   True
--   </pre>
isClientInitiated :: StreamId -> Bool

-- | Checking if the stream identifier is from a server.
--   
--   <pre>
--   &gt;&gt;&gt; isServerInitiated 0
--   False
--   
--   &gt;&gt;&gt; isServerInitiated 2
--   True
--   </pre>
isServerInitiated :: StreamId -> Bool

-- | Checking if the exclusive flag is set.
testExclusive :: StreamId -> Bool

-- | Setting the exclusive flag.
setExclusive :: StreamId -> StreamId

-- | Clearing the exclusive flag.
clearExclusive :: StreamId -> StreamId

-- | The type for flags.
type FrameFlags = Word8

-- | The initial value of flags. No flags are set.
--   
--   <pre>
--   &gt;&gt;&gt; defaultFlags
--   0
--   </pre>
defaultFlags :: FrameFlags

-- | Checking if the END_STREAM flag is set. &gt;&gt;&gt; testEndStream 0x1
--   True
testEndStream :: FrameFlags -> Bool

-- | Checking if the ACK flag is set. &gt;&gt;&gt; testAck 0x1 True
testAck :: FrameFlags -> Bool

-- | Checking if the END_HEADERS flag is set.
--   
--   <pre>
--   &gt;&gt;&gt; testEndHeader 0x4
--   True
--   </pre>
testEndHeader :: FrameFlags -> Bool

-- | Checking if the PADDED flag is set.
--   
--   <pre>
--   &gt;&gt;&gt; testPadded 0x8
--   True
--   </pre>
testPadded :: FrameFlags -> Bool

-- | Checking if the PRIORITY flag is set.
--   
--   <pre>
--   &gt;&gt;&gt; testPriority 0x20
--   True
--   </pre>
testPriority :: FrameFlags -> Bool

-- | Setting the END_STREAM flag.
--   
--   <pre>
--   &gt;&gt;&gt; setEndStream 0
--   1
--   </pre>
setEndStream :: FrameFlags -> FrameFlags

-- | Setting the ACK flag.
--   
--   <pre>
--   &gt;&gt;&gt; setAck 0
--   1
--   </pre>
setAck :: FrameFlags -> FrameFlags

-- | Setting the END_HEADERS flag.
--   
--   <pre>
--   &gt;&gt;&gt; setEndHeader 0
--   4
--   </pre>
setEndHeader :: FrameFlags -> FrameFlags

-- | Setting the PADDED flag.
--   
--   <pre>
--   &gt;&gt;&gt; setPadded 0
--   8
--   </pre>
setPadded :: FrameFlags -> FrameFlags

-- | Setting the PRIORITY flag.
--   
--   <pre>
--   &gt;&gt;&gt; setPriority 0
--   32
--   </pre>
setPriority :: FrameFlags -> FrameFlags

-- | Association list of SETTINGS.
type SettingsList = [(SettingsKey, SettingsValue)]

-- | The type for SETTINGS key.
newtype SettingsKey
SettingsKey :: Word16 -> SettingsKey
pattern SettingsHeaderTableSize :: SettingsKey
pattern SettingsEnablePush :: SettingsKey
pattern SettingsMaxConcurrentStreams :: SettingsKey
pattern SettingsInitialWindowSize :: SettingsKey
pattern SettingsMaxFrameSize :: SettingsKey
pattern SettingsMaxHeaderListSize :: SettingsKey

-- | The type for raw SETTINGS value.
type SettingsValue = Int
fromSettingsKey :: SettingsKey -> Word16
toSettingsKey :: Word16 -> SettingsKey

-- | The default payload length of HTTP/2 payload.
--   
--   <pre>
--   &gt;&gt;&gt; defaultPayloadLength
--   16384
--   </pre>
defaultPayloadLength :: Int

-- | The maximum payload length of HTTP/2 payload.
--   
--   <pre>
--   &gt;&gt;&gt; maxPayloadLength
--   16777215
--   </pre>
maxPayloadLength :: Int

-- | Window size.
type WindowSize = Int

-- | The default initial window size.
--   
--   <pre>
--   &gt;&gt;&gt; defaultWindowSize
--   65535
--   </pre>
defaultWindowSize :: WindowSize

-- | The maximum window size.
--   
--   <pre>
--   &gt;&gt;&gt; maxWindowSize
--   2147483647
--   </pre>
maxWindowSize :: WindowSize

-- | Checking if a window size exceeds the maximum window size.
--   
--   <pre>
--   &gt;&gt;&gt; isWindowOverflow 10
--   False
--   
--   &gt;&gt;&gt; isWindowOverflow maxWindowSize
--   False
--   
--   &gt;&gt;&gt; isWindowOverflow (maxWindowSize + 1)
--   True
--   </pre>
isWindowOverflow :: WindowSize -> Bool

-- | The type for raw error code.
newtype ErrorCode
ErrorCode :: Word32 -> ErrorCode

-- | The type for error code. See
--   <a>https://www.rfc-editor.org/rfc/rfc9113#ErrorCodes</a>.
pattern NoError :: ErrorCode
pattern ProtocolError :: ErrorCode
pattern InternalError :: ErrorCode
pattern FlowControlError :: ErrorCode
pattern SettingsTimeout :: ErrorCode
pattern StreamClosed :: ErrorCode
pattern FrameSizeError :: ErrorCode
pattern RefusedStream :: ErrorCode
pattern Cancel :: ErrorCode
pattern CompressionError :: ErrorCode
pattern ConnectError :: ErrorCode
pattern EnhanceYourCalm :: ErrorCode
pattern InadequateSecurity :: ErrorCode
pattern HTTP11Required :: ErrorCode
fromErrorCode :: ErrorCode -> Word32
toErrorCode :: Word32 -> ErrorCode

-- | The preface of HTTP/2.
--   
--   <pre>
--   &gt;&gt;&gt; connectionPreface
--   "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
--   </pre>
connectionPreface :: ByteString

-- | Length of the preface.
--   
--   <pre>
--   &gt;&gt;&gt; connectionPrefaceLength
--   24
--   </pre>
connectionPrefaceLength :: Int

-- | The length of HTTP/2 frame header.
--   
--   <pre>
--   &gt;&gt;&gt; frameHeaderLength
--   9
--   </pre>
frameHeaderLength :: Int

-- | Default concurrency.
--   
--   <pre>
--   &gt;&gt;&gt; recommendedConcurrency
--   100
--   </pre>
recommendedConcurrency :: Int
type ErrorCodeId = ErrorCode
type SettingsKeyId = SettingsKey
type FrameTypeId = FrameType

module Network.HTTP2.Client.Internal

-- | Request from client.
newtype Request
Request :: OutObj -> Request

-- | Response from server.
newtype Response
Response :: InpObj -> Response

-- | Client configuration
data ClientConfig
ClientConfig :: Scheme -> Authority -> Int -> WindowSize -> Settings -> ClientConfig

-- | https or http
[scheme] :: ClientConfig -> Scheme

-- | Server name
[authority] :: ClientConfig -> Authority

-- | The maximum number of incoming streams on the net
[cacheLimit] :: ClientConfig -> Int

-- | The window size of connection.
[connectionWindowSize] :: ClientConfig -> WindowSize

-- | Settings
[settings] :: ClientConfig -> Settings

-- | HTTP/2 settings. See
--   <a>https://datatracker.ietf.org/doc/html/rfc9113#name-defined-settings</a>.
data Settings
Settings :: Int -> Bool -> Maybe Int -> WindowSize -> Int -> Maybe Int -> Settings

-- | SETTINGS_HEADER_TABLE_SIZE
[headerTableSize] :: Settings -> Int

-- | SETTINGS_ENABLE_PUSH
[enablePush] :: Settings -> Bool

-- | SETTINGS_MAX_CONCURRENT_STREAMS
[maxConcurrentStreams] :: Settings -> Maybe Int

-- | SETTINGS_INITIAL_WINDOW_SIZE
[initialWindowSize] :: Settings -> WindowSize

-- | SETTINGS_MAX_FRAME_SIZE
[maxFrameSize] :: Settings -> Int

-- | SETTINGS_MAX_HEADER_LIST_SIZE
[maxHeaderListSize] :: Settings -> Maybe Int

-- | Additional information.
data Aux
Aux :: IO Int -> Aux

-- | How many streams can be created without blocking.
[auxPossibleClientStreams] :: Aux -> IO Int
data Stream
data ClientIO
ClientIO :: SockAddr -> SockAddr -> (Request -> IO (StreamId, Stream)) -> (Stream -> IO Response) -> (ByteString -> IO ()) -> IO (StreamId, Stream) -> ClientIO
[cioMySockAddr] :: ClientIO -> SockAddr
[cioPeerSockAddr] :: ClientIO -> SockAddr
[cioWriteRequest] :: ClientIO -> Request -> IO (StreamId, Stream)
[cioReadResponse] :: ClientIO -> Stream -> IO Response
[cioWriteBytes] :: ClientIO -> ByteString -> IO ()
[cioCreateStream] :: ClientIO -> IO (StreamId, Stream)

-- | Launching a receiver and a sender.
runIO :: ClientConfig -> Config -> (ClientIO -> IO (IO a)) -> IO a


-- | HTTP/2 client library.
--   
--   Example:
--   
--   <pre>
--   {-# LANGUAGE OverloadedStrings #-}
--   {-# LANGUAGE RankNTypes #-}
--   
--   module Main where
--   
--   import Control.Concurrent.Async
--   import qualified Control.Exception as E
--   import qualified Data.ByteString.Char8 as C8
--   import Network.HTTP.Types
--   import Network.Run.TCP (runTCPClient) -- network-run
--   
--   import Network.HTTP2.Client
--   
--   serverName :: String
--   serverName = "127.0.0.1"
--   
--   main :: IO ()
--   main = runTCPClient serverName "80" $ runHTTP2Client serverName
--     where
--       cliconf host = defaultClientConfig { authority = C8.pack host }
--       runHTTP2Client host s = E.bracket (allocSimpleConfig s 4096)
--                                         freeSimpleConfig
--                                         (\conf -&gt; run (cliconf host) conf client)
--       client :: Client ()
--       client sendRequest _aux = do
--           let req0 = requestNoBody methodGet "/" []
--               client0 = sendRequest req0 $ \rsp -&gt; do
--                   print rsp
--                   getResponseBodyChunk rsp &gt;&gt;= C8.putStrLn
--               req1 = requestNoBody methodGet "/foo" []
--               client1 = sendRequest req1 $ \rsp -&gt; do
--                   print rsp
--                   getResponseBodyChunk rsp &gt;&gt;= C8.putStrLn
--           ex &lt;- E.try $ concurrently_ client0 client1
--           case ex of
--             Left  e  -&gt; print (e :: HTTP2Error)
--             Right () -&gt; putStrLn "OK"
--   </pre>
module Network.HTTP2.Client

-- | Running HTTP/2 client.
run :: ClientConfig -> Config -> Client a -> IO a

-- | "http" or "https".
type Scheme = ByteString

-- | Authority.
type Authority = ByteString

-- | Client configuration
data ClientConfig

-- | The default client config.
--   
--   The <tt>authority</tt> field will be used to set the HTTP2
--   <tt>:authority</tt> pseudo-header. In most cases you will want to
--   override it to be equal to <tt>host</tt>.
--   
--   Further background on <tt>authority</tt>: <a>RFC 3986</a> also allows
--   <tt>host:port</tt>, and most servers will accept this too. However,
--   when using TLS, many servers will expect the TLS SNI server name and
--   the <tt>:authority</tt> pseudo-header to be equal, and for TLS SNI the
--   server name should not include the port. Note that HTTP2 explicitly
--   <i>disallows</i> using <tt>userinfo@</tt> as part of the authority.
--   
--   <pre>
--   &gt;&gt;&gt; defaultClientConfig
--   ClientConfig {scheme = "http", authority = "localhost", cacheLimit = 64, connectionWindowSize = 1048576, settings = Settings {headerTableSize = 4096, enablePush = True, maxConcurrentStreams = Just 64, initialWindowSize = 262144, maxFrameSize = 16384, maxHeaderListSize = Nothing}}
--   </pre>
defaultClientConfig :: ClientConfig

-- | https or http
scheme :: ClientConfig -> Scheme

-- | Server name
authority :: ClientConfig -> Authority

-- | The maximum number of incoming streams on the net
cacheLimit :: ClientConfig -> Int

-- | The window size of connection.
connectionWindowSize :: ClientConfig -> WindowSize

-- | Settings
settings :: ClientConfig -> Settings

-- | HTTP/2 settings. See
--   <a>https://datatracker.ietf.org/doc/html/rfc9113#name-defined-settings</a>.
data Settings

-- | The default settings.
--   
--   <pre>
--   &gt;&gt;&gt; defaultSettings
--   Settings {headerTableSize = 4096, enablePush = True, maxConcurrentStreams = Just 64, initialWindowSize = 262144, maxFrameSize = 16384, maxHeaderListSize = Nothing}
--   </pre>
defaultSettings :: Settings

-- | SETTINGS_HEADER_TABLE_SIZE
headerTableSize :: Settings -> Int

-- | SETTINGS_ENABLE_PUSH
enablePush :: Settings -> Bool

-- | SETTINGS_MAX_CONCURRENT_STREAMS
maxConcurrentStreams :: Settings -> Maybe Int

-- | SETTINGS_INITIAL_WINDOW_SIZE
initialWindowSize :: Settings -> WindowSize

-- | SETTINGS_MAX_FRAME_SIZE
maxFrameSize :: Settings -> Int

-- | SETTINGS_MAX_HEADER_LIST_SIZE
maxHeaderListSize :: Settings -> Maybe Int

-- | HTTP/2 configuration.
data Config
Config :: Buffer -> BufferSize -> (ByteString -> IO ()) -> (Int -> IO ByteString) -> PositionReadMaker -> Manager -> SockAddr -> SockAddr -> Config

-- | This is used only by frameSender. This MUST be freed after frameSender
--   is terminated.
[confWriteBuffer] :: Config -> Buffer

-- | The size of the write buffer. We assume that the read buffer is the
--   same size. So, this value is announced via SETTINGS_MAX_FRAME_SIZE to
--   the peer.
[confBufferSize] :: Config -> BufferSize
[confSendAll] :: Config -> ByteString -> IO ()
[confReadN] :: Config -> Int -> IO ByteString
[confPositionReadMaker] :: Config -> PositionReadMaker
[confTimeoutManager] :: Config -> Manager

-- | This is copied into <tt>Aux</tt>, if exist, on server.
[confMySockAddr] :: Config -> SockAddr

-- | This is copied into <tt>Aux</tt>, if exist, on server.
[confPeerSockAddr] :: Config -> SockAddr

-- | Making simple configuration whose IO is not efficient. A write buffer
--   is allocated internally.
allocSimpleConfig :: Socket -> BufferSize -> IO Config

-- | Deallocating the resource of the simple configuration.
freeSimpleConfig :: Config -> IO ()

-- | Client type.
type Client a = (forall b. Request -> (Response -> IO b) -> IO b) -> Aux -> IO a

-- | Request from client.
data Request

-- | Creating request without body.
requestNoBody :: Method -> Path -> RequestHeaders -> Request

-- | Creating request with file.
requestFile :: Method -> Path -> RequestHeaders -> FileSpec -> Request

-- | Creating request with streaming.
requestStreaming :: Method -> Path -> RequestHeaders -> ((Builder -> IO ()) -> IO () -> IO ()) -> Request

-- | Like <a>requestStreaming</a>, but run the action with exceptions
--   masked
requestStreamingUnmask :: Method -> Path -> RequestHeaders -> ((forall x. IO x -> IO x) -> (Builder -> IO ()) -> IO () -> IO ()) -> Request

-- | Creating request with builder.
requestBuilder :: Method -> Path -> RequestHeaders -> Builder -> Request

-- | Trailers maker. A chunks of the response body is passed with
--   <a>Just</a>. The maker should update internal state with the
--   <a>ByteString</a> and return the next trailers maker. When response
--   body reaches its end, <a>Nothing</a> is passed and the maker should
--   generate trailers. An example:
--   
--   <pre>
--   {-# LANGUAGE BangPatterns #-}
--   import Data.ByteString (ByteString)
--   import qualified Data.ByteString.Char8 as C8
--   import Crypto.Hash (Context, SHA1) -- cryptonite
--   import qualified Crypto.Hash as CH
--   
--   -- Strictness is important for Context.
--   trailersMaker :: Context SHA1 -&gt; Maybe ByteString -&gt; IO NextTrailersMaker
--   trailersMaker ctx Nothing = return $ Trailers [("X-SHA1", sha1)]
--     where
--       !sha1 = C8.pack $ show $ CH.hashFinalize ctx
--   trailersMaker ctx (Just bs) = return $ NextTrailersMaker $ trailersMaker ctx'
--     where
--       !ctx' = CH.hashUpdate ctx bs
--   </pre>
--   
--   Usage example:
--   
--   <pre>
--   let h2rsp = responseFile ...
--       maker = trailersMaker (CH.hashInit :: Context SHA1)
--       h2rsp' = setResponseTrailersMaker h2rsp maker
--   </pre>
type TrailersMaker = Maybe ByteString -> IO NextTrailersMaker

-- | Either the next trailers maker or final trailers.
data NextTrailersMaker
NextTrailersMaker :: TrailersMaker -> NextTrailersMaker
Trailers :: [Header] -> NextTrailersMaker

-- | TrailersMake to create no trailers.
defaultTrailersMaker :: TrailersMaker

-- | Setting <a>TrailersMaker</a> to <a>Response</a>.
setRequestTrailersMaker :: Request -> TrailersMaker -> Request

-- | Response from server.
data Response

-- | Getting the status of a response.
responseStatus :: Response -> Maybe Status

-- | Getting the headers from a response.
responseHeaders :: Response -> HeaderTable

-- | Getting the body size from a response.
responseBodySize :: Response -> Maybe Int

-- | Reading a chunk of the response body. An empty <a>ByteString</a>
--   returned when finished.
getResponseBodyChunk :: Response -> IO ByteString

-- | Reading response trailers. This function must be called after
--   <a>getResponseBodyChunk</a> returns an empty.
getResponseTrailers :: Response -> IO (Maybe HeaderTable)

-- | Additional information.
data Aux

-- | How many streams can be created without blocking.
auxPossibleClientStreams :: Aux -> IO Int

-- | HTTP method (flat <tt>ByteString</tt> type).
type Method = ByteString

-- | Path.
type Path = ByteString

-- | File specification.
data FileSpec
FileSpec :: FilePath -> FileOffset -> ByteCount -> FileSpec

-- | Offset for file.
type FileOffset = Int64

-- | How many bytes to read
type ByteCount = Int64

-- | The connection error or the stream error. Stream errors are treated as
--   connection errors since there are no good recovery ways.
--   <a>ErrorCode</a> in connection errors should be the highest stream
--   identifier but in this implementation it identifies the stream that
--   caused this error.
data HTTP2Error
ConnectionIsClosed :: HTTP2Error
ConnectionIsTimeout :: HTTP2Error
ConnectionErrorIsReceived :: ErrorCode -> StreamId -> ReasonPhrase -> HTTP2Error
ConnectionErrorIsSent :: ErrorCode -> StreamId -> ReasonPhrase -> HTTP2Error
StreamErrorIsReceived :: ErrorCode -> StreamId -> HTTP2Error
StreamErrorIsSent :: ErrorCode -> StreamId -> ReasonPhrase -> HTTP2Error
BadThingHappen :: SomeException -> HTTP2Error
GoAwayIsSent :: HTTP2Error
type ReasonPhrase = ShortByteString

-- | The type for raw error code.
newtype ErrorCode
ErrorCode :: Word32 -> ErrorCode

-- | The type for error code. See
--   <a>https://www.rfc-editor.org/rfc/rfc9113#ErrorCodes</a>.
pattern NoError :: ErrorCode
pattern ProtocolError :: ErrorCode
pattern InternalError :: ErrorCode
pattern FlowControlError :: ErrorCode
pattern SettingsTimeout :: ErrorCode
pattern StreamClosed :: ErrorCode
pattern FrameSizeError :: ErrorCode
pattern RefusedStream :: ErrorCode
pattern Cancel :: ErrorCode
pattern CompressionError :: ErrorCode
pattern ConnectError :: ErrorCode
pattern EnhanceYourCalm :: ErrorCode
pattern InadequateSecurity :: ErrorCode
pattern HTTP11Required :: ErrorCode

-- | Naive implementation for readN.
defaultReadN :: Socket -> IORef (Maybe ByteString) -> Int -> IO ByteString

-- | Making a position read and its closer.
type PositionReadMaker = FilePath -> IO (PositionRead, Sentinel)

-- | Position read for files.
type PositionRead = FileOffset -> ByteCount -> Buffer -> IO ByteCount

-- | Manipulating a file resource.
data Sentinel

-- | Closing a file resource. Its refresher is automatiaclly generated by
--   the internal timer.
Closer :: IO () -> Sentinel

-- | Refreshing a file resource while reading. Closing the file must be
--   done by its own timer or something.
Refresher :: IO () -> Sentinel

-- | Position read based on <a>Handle</a>.
defaultPositionReadMaker :: PositionReadMaker

module Network.HTTP2.Internal

-- | Offset for file.
type FileOffset = Int64

-- | How many bytes to read
type ByteCount = Int64

-- | Position read for files.
type PositionRead = FileOffset -> ByteCount -> Buffer -> IO ByteCount

-- | Manipulating a file resource.
data Sentinel

-- | Closing a file resource. Its refresher is automatiaclly generated by
--   the internal timer.
Closer :: IO () -> Sentinel

-- | Refreshing a file resource while reading. Closing the file must be
--   done by its own timer or something.
Refresher :: IO () -> Sentinel

-- | Making a position read and its closer.
type PositionReadMaker = FilePath -> IO (PositionRead, Sentinel)

-- | Position read based on <a>Handle</a>.
defaultPositionReadMaker :: PositionReadMaker

-- | "http" or "https".
type Scheme = ByteString

-- | Authority.
type Authority = ByteString

-- | Path.
type Path = ByteString

-- | Input object
data InpObj
InpObj :: HeaderTable -> Maybe Int -> InpBody -> IORef (Maybe HeaderTable) -> InpObj

-- | Accessor for headers.
[inpObjHeaders] :: InpObj -> HeaderTable

-- | Accessor for body length specified in content-length:.
[inpObjBodySize] :: InpObj -> Maybe Int

-- | Accessor for body.
[inpObjBody] :: InpObj -> InpBody

-- | Accessor for trailers.
[inpObjTrailers] :: InpObj -> IORef (Maybe HeaderTable)
type InpBody = IO ByteString

-- | Output object
data OutObj
OutObj :: [Header] -> OutBody -> TrailersMaker -> OutObj

-- | Accessor for header.
[outObjHeaders] :: OutObj -> [Header]

-- | Accessor for outObj body.
[outObjBody] :: OutObj -> OutBody

-- | Accessor for trailers maker.
[outObjTrailers] :: OutObj -> TrailersMaker
data OutBody
OutBodyNone :: OutBody

-- | Streaming body takes a write action and a flush action.
OutBodyStreaming :: ((Builder -> IO ()) -> IO () -> IO ()) -> OutBody

-- | Like <a>OutBodyStreaming</a>, but with a callback to unmask expections
--   
--   This is used in the client: we spawn the new thread for the request
--   body with exceptions masked, and provide the body of
--   <a>OutBodyStreamingUnmask</a> with a callback to unmask them again
--   (typically after installing an exception handler).
--   
--   We do <i>NOT</i> support this in the server, as here the scope of the
--   thread that is spawned for the server is the entire handler, not just
--   the response streaming body.
--   
--   TODO: The analogous change for the server-side would be to provide a
--   similar <tt>unmask</tt> callback as the first argument in the
--   <tt>Server</tt> type alias.
OutBodyStreamingUnmask :: ((forall x. IO x -> IO x) -> (Builder -> IO ()) -> IO () -> IO ()) -> OutBody
OutBodyBuilder :: Builder -> OutBody
OutBodyFile :: FileSpec -> OutBody

-- | File specification.
data FileSpec
FileSpec :: FilePath -> FileOffset -> ByteCount -> FileSpec
data Next
Next :: BytesFilled -> Bool -> Maybe DynaNext -> Next
type BytesFilled = Int
type DynaNext = Buffer -> BufferSize -> WindowSize -> IO Next
data StreamingChunk
StreamingFinished :: IO () -> StreamingChunk
StreamingFlush :: StreamingChunk
StreamingBuilder :: Builder -> StreamingChunk
fillBuilderBodyGetNext :: Builder -> DynaNext
fillFileBodyGetNext :: PositionRead -> FileOffset -> ByteCount -> IO () -> DynaNext
fillStreamBodyGetNext :: IO (Maybe StreamingChunk) -> DynaNext

-- | Trailers maker. A chunks of the response body is passed with
--   <a>Just</a>. The maker should update internal state with the
--   <a>ByteString</a> and return the next trailers maker. When response
--   body reaches its end, <a>Nothing</a> is passed and the maker should
--   generate trailers. An example:
--   
--   <pre>
--   {-# LANGUAGE BangPatterns #-}
--   import Data.ByteString (ByteString)
--   import qualified Data.ByteString.Char8 as C8
--   import Crypto.Hash (Context, SHA1) -- cryptonite
--   import qualified Crypto.Hash as CH
--   
--   -- Strictness is important for Context.
--   trailersMaker :: Context SHA1 -&gt; Maybe ByteString -&gt; IO NextTrailersMaker
--   trailersMaker ctx Nothing = return $ Trailers [("X-SHA1", sha1)]
--     where
--       !sha1 = C8.pack $ show $ CH.hashFinalize ctx
--   trailersMaker ctx (Just bs) = return $ NextTrailersMaker $ trailersMaker ctx'
--     where
--       !ctx' = CH.hashUpdate ctx bs
--   </pre>
--   
--   Usage example:
--   
--   <pre>
--   let h2rsp = responseFile ...
--       maker = trailersMaker (CH.hashInit :: Context SHA1)
--       h2rsp' = setResponseTrailersMaker h2rsp maker
--   </pre>
type TrailersMaker = Maybe ByteString -> IO NextTrailersMaker

-- | TrailersMake to create no trailers.
defaultTrailersMaker :: TrailersMaker

-- | Either the next trailers maker or final trailers.
data NextTrailersMaker
NextTrailersMaker :: TrailersMaker -> NextTrailersMaker
Trailers :: [Header] -> NextTrailersMaker

-- | Running trailers-maker.
--   
--   <pre>
--   bufferIO buf siz $ \bs -&gt; tlrmkr (Just bs)
--   </pre>
runTrailersMaker :: TrailersMaker -> Buffer -> Int -> IO NextTrailersMaker

-- | Manager to manage the thread and the timer.
data Manager

-- | Action to be spawned by the manager.
type Action = IO ()

-- | Starting a thread manager. Its action is initially set to 'return ()'
--   and should be set by <a>setAction</a>. This allows that the action can
--   include the manager itself.
start :: Manager -> IO Manager

-- | Setting the action to be spawned.
setAction :: Manager -> Action -> IO ()

-- | Stopping the manager.
stopAfter :: Manager -> IO a -> (Either SomeException a -> IO b) -> IO b

-- | Spawning the action.
spawnAction :: Manager -> IO ()

-- | Fork managed thread
--   
--   This guarantees that the thread ID is added to the manager's queue
--   before the thread starts, and is removed again when the thread
--   terminates (normally or abnormally).
forkManaged :: Manager -> IO () -> IO ()

-- | Like <a>forkManaged</a>, but run action with exceptions masked
forkManagedUnmask :: Manager -> ((forall x. IO x -> IO x) -> IO ()) -> IO ()

-- | Killing the IO action of the second argument on timeout.
timeoutKillThread :: Manager -> (Handle -> IO a) -> IO a

-- | Registering closer for a resource and returning a timer refresher.
timeoutClose :: Manager -> IO () -> IO (IO ())
data KilledByHttp2ThreadManager
KilledByHttp2ThreadManager :: Maybe SomeException -> KilledByHttp2ThreadManager
incCounter :: Manager -> IO ()
decCounter :: Manager -> IO ()
waitCounter0 :: Manager -> IO ()

module Network.HTTP2.Server.Internal

-- | Request from client.
newtype Request
Request :: InpObj -> Request

-- | Response from server.
newtype Response
Response :: OutObj -> Response

-- | Additional information.
data Aux
Aux :: Handle -> SockAddr -> SockAddr -> Aux

-- | Time handle for the worker processing this request and response.
[auxTimeHandle] :: Aux -> Handle

-- | Local socket address copied from <a>Config</a>.
[auxMySockAddr] :: Aux -> SockAddr

-- | Remove socket address copied from <a>Config</a>.
[auxPeerSockAddr] :: Aux -> SockAddr
data Stream
data ServerIO
ServerIO :: SockAddr -> SockAddr -> IO (StreamId, Stream, Request) -> (Stream -> Response -> IO ()) -> (ByteString -> IO ()) -> ServerIO
[sioMySockAddr] :: ServerIO -> SockAddr
[sioPeerSockAddr] :: ServerIO -> SockAddr
[sioReadRequest] :: ServerIO -> IO (StreamId, Stream, Request)
[sioWriteResponse] :: ServerIO -> Stream -> Response -> IO ()
[sioWriteBytes] :: ServerIO -> ByteString -> IO ()

-- | Launching a receiver and a sender without workers. Any frames can be
--   sent with <a>sioWriteBytes</a>.
runIO :: ServerConfig -> Config -> (ServerIO -> IO (IO ())) -> IO ()


-- | HTTP/2 server library.
--   
--   Example:
--   
--   <pre>
--   {-# LANGUAGE OverloadedStrings #-}
--   module Main (main) where
--   
--   import qualified Control.Exception as E
--   import Data.ByteString.Builder (byteString)
--   import Network.HTTP.Types (ok200)
--   import Network.Run.TCP (runTCPServer) -- network-run
--   
--   import Network.HTTP2.Server
--   
--   main :: IO ()
--   main = runTCPServer Nothing "80" runHTTP2Server
--     where
--       runHTTP2Server s = E.bracket (allocSimpleConfig s 4096)
--                                    freeSimpleConfig
--                                    (\config -&gt; run defaultServerConfig config server)
--       server _req _aux sendResponse = sendResponse response []
--         where
--           response = responseBuilder ok200 header body
--           header = [("Content-Type", "text/plain")]
--           body = byteString "Hello, world!\n"
--   </pre>
module Network.HTTP2.Server

-- | Running HTTP/2 server.
run :: ServerConfig -> Config -> Server -> IO ()

-- | Server configuration
data ServerConfig

-- | The default server config.
--   
--   <pre>
--   &gt;&gt;&gt; defaultServerConfig
--   ServerConfig {numberOfWorkers = 8, connectionWindowSize = 1048576, settings = Settings {headerTableSize = 4096, enablePush = True, maxConcurrentStreams = Just 64, initialWindowSize = 262144, maxFrameSize = 16384, maxHeaderListSize = Nothing}}
--   </pre>
defaultServerConfig :: ServerConfig

-- | The number of workers
numberOfWorkers :: ServerConfig -> Int

-- | The window size of incoming streams
connectionWindowSize :: ServerConfig -> WindowSize

-- | Settings
settings :: ServerConfig -> Settings

-- | HTTP/2 settings. See
--   <a>https://datatracker.ietf.org/doc/html/rfc9113#name-defined-settings</a>.
data Settings

-- | The default settings.
--   
--   <pre>
--   &gt;&gt;&gt; defaultSettings
--   Settings {headerTableSize = 4096, enablePush = True, maxConcurrentStreams = Just 64, initialWindowSize = 262144, maxFrameSize = 16384, maxHeaderListSize = Nothing}
--   </pre>
defaultSettings :: Settings

-- | SETTINGS_HEADER_TABLE_SIZE
headerTableSize :: Settings -> Int

-- | SETTINGS_ENABLE_PUSH
enablePush :: Settings -> Bool

-- | SETTINGS_MAX_CONCURRENT_STREAMS
maxConcurrentStreams :: Settings -> Maybe Int

-- | SETTINGS_INITIAL_WINDOW_SIZE
initialWindowSize :: Settings -> WindowSize

-- | SETTINGS_MAX_FRAME_SIZE
maxFrameSize :: Settings -> Int

-- | SETTINGS_MAX_HEADER_LIST_SIZE
maxHeaderListSize :: Settings -> Maybe Int

-- | HTTP/2 configuration.
data Config
Config :: Buffer -> BufferSize -> (ByteString -> IO ()) -> (Int -> IO ByteString) -> PositionReadMaker -> Manager -> SockAddr -> SockAddr -> Config

-- | This is used only by frameSender. This MUST be freed after frameSender
--   is terminated.
[confWriteBuffer] :: Config -> Buffer

-- | The size of the write buffer. We assume that the read buffer is the
--   same size. So, this value is announced via SETTINGS_MAX_FRAME_SIZE to
--   the peer.
[confBufferSize] :: Config -> BufferSize
[confSendAll] :: Config -> ByteString -> IO ()
[confReadN] :: Config -> Int -> IO ByteString
[confPositionReadMaker] :: Config -> PositionReadMaker
[confTimeoutManager] :: Config -> Manager

-- | This is copied into <tt>Aux</tt>, if exist, on server.
[confMySockAddr] :: Config -> SockAddr

-- | This is copied into <tt>Aux</tt>, if exist, on server.
[confPeerSockAddr] :: Config -> SockAddr

-- | Making simple configuration whose IO is not efficient. A write buffer
--   is allocated internally.
allocSimpleConfig :: Socket -> BufferSize -> IO Config

-- | Deallocating the resource of the simple configuration.
freeSimpleConfig :: Config -> IO ()

-- | Server type. Server takes a HTTP request, should generate a HTTP
--   response and push promises, then should give them to the sending
--   function. The sending function would throw exceptions so that they can
--   be logged.
type Server = Request -> Aux -> (Response -> [PushPromise] -> IO ()) -> IO ()

-- | Request from client.
data Request

-- | Getting the method from a request.
requestMethod :: Request -> Maybe Method

-- | Getting the path from a request.
requestPath :: Request -> Maybe Path

-- | Getting the authority from a request.
requestAuthority :: Request -> Maybe Authority

-- | Getting the scheme from a request.
requestScheme :: Request -> Maybe Scheme

-- | Getting the headers from a request.
requestHeaders :: Request -> HeaderTable

-- | Getting the body size from a request.
requestBodySize :: Request -> Maybe Int

-- | Reading a chunk of the request body. An empty <a>ByteString</a>
--   returned when finished.
getRequestBodyChunk :: Request -> IO ByteString

-- | Reading request trailers. This function must be called after
--   <a>getRequestBodyChunk</a> returns an empty.
getRequestTrailers :: Request -> IO (Maybe HeaderTable)

-- | Additional information.
data Aux

-- | Time handle for the worker processing this request and response.
auxTimeHandle :: Aux -> Handle

-- | Local socket address copied from <a>Config</a>.
auxMySockAddr :: Aux -> SockAddr

-- | Remove socket address copied from <a>Config</a>.
auxPeerSockAddr :: Aux -> SockAddr

-- | Response from server.
data Response

-- | Creating response without body.
responseNoBody :: Status -> ResponseHeaders -> Response

-- | Creating response with file.
responseFile :: Status -> ResponseHeaders -> FileSpec -> Response

-- | Creating response with streaming.
responseStreaming :: Status -> ResponseHeaders -> ((Builder -> IO ()) -> IO () -> IO ()) -> Response

-- | Creating response with builder.
responseBuilder :: Status -> ResponseHeaders -> Builder -> Response

-- | Getter for response body size. This value is available for file body.
responseBodySize :: Response -> Maybe Int

-- | Trailers maker. A chunks of the response body is passed with
--   <a>Just</a>. The maker should update internal state with the
--   <a>ByteString</a> and return the next trailers maker. When response
--   body reaches its end, <a>Nothing</a> is passed and the maker should
--   generate trailers. An example:
--   
--   <pre>
--   {-# LANGUAGE BangPatterns #-}
--   import Data.ByteString (ByteString)
--   import qualified Data.ByteString.Char8 as C8
--   import Crypto.Hash (Context, SHA1) -- cryptonite
--   import qualified Crypto.Hash as CH
--   
--   -- Strictness is important for Context.
--   trailersMaker :: Context SHA1 -&gt; Maybe ByteString -&gt; IO NextTrailersMaker
--   trailersMaker ctx Nothing = return $ Trailers [("X-SHA1", sha1)]
--     where
--       !sha1 = C8.pack $ show $ CH.hashFinalize ctx
--   trailersMaker ctx (Just bs) = return $ NextTrailersMaker $ trailersMaker ctx'
--     where
--       !ctx' = CH.hashUpdate ctx bs
--   </pre>
--   
--   Usage example:
--   
--   <pre>
--   let h2rsp = responseFile ...
--       maker = trailersMaker (CH.hashInit :: Context SHA1)
--       h2rsp' = setResponseTrailersMaker h2rsp maker
--   </pre>
type TrailersMaker = Maybe ByteString -> IO NextTrailersMaker

-- | Either the next trailers maker or final trailers.
data NextTrailersMaker
NextTrailersMaker :: TrailersMaker -> NextTrailersMaker
Trailers :: [Header] -> NextTrailersMaker

-- | TrailersMake to create no trailers.
defaultTrailersMaker :: TrailersMaker

-- | Setting <a>TrailersMaker</a> to <a>Response</a>.
setResponseTrailersMaker :: Response -> TrailersMaker -> Response

-- | HTTP/2 push promise or sever push. Pseudo REQUEST headers in push
--   promise is automatically generated. Then, a server push is sent
--   according to <a>promiseResponse</a>.
data PushPromise

-- | Creating push promise. The third argument is traditional, not used.
pushPromise :: ByteString -> Response -> Weight -> PushPromise

-- | Accessor for a URL path in a push promise (a virtual request from a
--   server). E.g. "/style/default.css".
promiseRequestPath :: PushPromise -> ByteString

-- | Accessor for response actually pushed from a server.
promiseResponse :: PushPromise -> Response

-- | Path.
type Path = ByteString

-- | Authority.
type Authority = ByteString

-- | "http" or "https".
type Scheme = ByteString

-- | File specification.
data FileSpec
FileSpec :: FilePath -> FileOffset -> ByteCount -> FileSpec

-- | Offset for file.
type FileOffset = Int64

-- | How many bytes to read
type ByteCount = Int64

-- | Naive implementation for readN.
defaultReadN :: Socket -> IORef (Maybe ByteString) -> Int -> IO ByteString

-- | Making a position read and its closer.
type PositionReadMaker = FilePath -> IO (PositionRead, Sentinel)

-- | Position read for files.
type PositionRead = FileOffset -> ByteCount -> Buffer -> IO ByteCount

-- | Manipulating a file resource.
data Sentinel

-- | Closing a file resource. Its refresher is automatiaclly generated by
--   the internal timer.
Closer :: IO () -> Sentinel

-- | Refreshing a file resource while reading. Closing the file must be
--   done by its own timer or something.
Refresher :: IO () -> Sentinel

-- | Position read based on <a>Handle</a>.
defaultPositionReadMaker :: PositionReadMaker
