{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE RankNTypes #-} module Network.HTTP2.Client.RawConnection ( RawHttp2Connection (..) , newRawHttp2Connection ) where import Data.ByteString (ByteString) import Network.Connection (connectTo, initConnectionContext, ConnectionParams(..), TLSSettings(..), connectionPut, connectionGetExact, connectionClose) import qualified Network.HTTP2 as HTTP2 import Network.Socket (HostName, PortNumber) import qualified Network.TLS as TLS -- TODO: catch connection errrors data RawHttp2Connection = RawHttp2Connection { _sendRaw :: ByteString -> IO () -- ^ Function to send raw data to the server. , _nextRaw :: Int -> IO ByteString -- ^ Function to block reading a datachunk of a given size from the server. , _close :: IO () } -- | Initiates a RawHttp2Connection with a server. -- -- The current code does not handle closing the connexion, yikes. newRawHttp2Connection :: HostName -- ^ Server's hostname. -> PortNumber -- ^ Server's port to connect to. -> TLS.ClientParams -- ^ TLS parameters. The 'TLS.onSuggestALPN' hook is -- overwritten to always return ["h2", "h2-17"]. -> IO RawHttp2Connection newRawHttp2Connection host port params = do -- Connects to SSL. ctx <- initConnectionContext conn <- connectTo ctx connParams -- Define raw byte-stream handlers. let putRaw dat = connectionPut conn dat let getRaw amount = connectionGetExact conn amount let doClose = connectionClose conn -- Initializes the HTTP2 stream. putRaw HTTP2.connectionPreface return $ RawHttp2Connection putRaw getRaw doClose where overwrittenALPNHook = (TLS.clientHooks params) { TLS.onSuggestALPN = return $ Just [ "h2", "h2-17" ] } modifiedParams = params { TLS.clientHooks = overwrittenALPNHook } connParams = ConnectionParams host port (Just . TLSSettings $ modifiedParams) Nothing