@@ -47,7 +47,6 @@ import Data.Domain
47
47
import qualified Data.Sequence as Seq
48
48
import qualified Data.Set as Set
49
49
import Data.Streaming.Network
50
- import qualified Data.Text as Text
51
50
import qualified Data.Text.Encoding as Text
52
51
import qualified Data.Text.Encoding.Error as Text
53
52
import qualified Data.Text.Lazy.Encoding as LText
@@ -59,9 +58,8 @@ import qualified Network.HTTP.Media as HTTP
59
58
import qualified Network.HTTP.Types as HTTP
60
59
import qualified Network.HTTP2.Client as HTTP2
61
60
import qualified Network.Socket as NS
61
+ import qualified Network.TLS as TLS
62
62
import qualified Network.Wai.Utilities.Error as Wai
63
- import OpenSSL.Session (SSL , SSLContext )
64
- import qualified OpenSSL.Session as SSL
65
63
import Servant.Client
66
64
import Servant.Client.Core
67
65
import Servant.Types.SourceT
@@ -124,7 +122,7 @@ connectSocket hostname port =
124
122
$ getSocketFamilyTCP hostname port NS. AF_UNSPEC
125
123
126
124
performHTTP2Request ::
127
- Maybe SSLContext ->
125
+ Maybe TLS. ClientParams ->
128
126
HTTP2. Request ->
129
127
ByteString ->
130
128
Int ->
@@ -140,42 +138,34 @@ performHTTP2Request mtlsConfig req hostname port = try $ do
140
138
pure $ resp $> foldMap byteString b
141
139
142
140
withHTTP2Request ::
143
- Maybe SSLContext ->
141
+ Maybe TLS. ClientParams ->
144
142
HTTP2. Request ->
145
143
ByteString ->
146
144
Int ->
147
145
(StreamingResponse -> IO a ) ->
148
146
IO a
149
- withHTTP2Request mSSLCtx req hostname port k = do
147
+ withHTTP2Request mtlsConfig req hostname port k = do
150
148
let clientConfig =
151
149
HTTP2. ClientConfig
152
- { HTTP2. scheme = " https" ,
153
- HTTP2. authority = hostname,
154
- HTTP2. cacheLimit = 20
155
- }
150
+ " https"
151
+ hostname
152
+ {- cacheLimit: -} 20
156
153
E. handle (E. throw . FederatorClientHTTP2Exception ) $
157
154
bracket (connectSocket hostname port) NS. close $ \ sock -> do
158
- let withHTTP2Config k' = case mSSLCtx of
155
+ let withHTTP2Config k' = case mtlsConfig of
159
156
Nothing -> bracket (HTTP2. allocSimpleConfig sock 4096 ) HTTP2. freeSimpleConfig k'
160
- Just sslCtx -> do
161
- ssl <- E. handle (E. throw . FederatorClientTLSException ) $ do
162
- ssl <- SSL. connection sslCtx sock
163
- -- We need to strip trailing dot because openssl doesn't ignore
164
- -- it. https://github.com/openssl/openssl/issues/11560
165
- let hostnameStr =
166
- Text. unpack $ case Text. decodeUtf8 hostname of
167
- (Text. stripSuffix " ." -> Just withoutTrailingDot) -> withoutTrailingDot
168
- noTrailingDot -> noTrailingDot
169
- SSL. setTlsextHostName ssl hostnameStr
170
- SSL. enableHostnameValidation ssl hostnameStr
171
- SSL. connect ssl
172
- pure ssl
173
- bracket (allocTLSConfig ssl 4096 ) freeTLSConfig k'
157
+ -- FUTUREWORK(federation): Use openssl
158
+ Just tlsConfig -> do
159
+ ctx <- E. handle (E. throw . FederatorClientTLSException ) $ do
160
+ ctx <- TLS. contextNew sock tlsConfig
161
+ TLS. handshake ctx
162
+ pure ctx
163
+ bracket (allocTLSConfig ctx 4096 ) freeTLSConfig k'
174
164
withHTTP2Config $ \ conf -> do
175
165
HTTP2. run clientConfig conf $ \ sendRequest ->
176
166
sendRequest req $ \ resp -> do
177
167
let headers = headersFromTable (HTTP2. responseHeaders resp)
178
- result = fromAction BS. null $ HTTP2. getResponseBodyChunk resp
168
+ result = fromAction BS. null ( HTTP2. getResponseBodyChunk resp)
179
169
case HTTP2. responseStatus resp of
180
170
Nothing -> E. throw FederatorClientNoStatusCode
181
171
Just status ->
@@ -361,23 +351,31 @@ versionNegotiation =
361
351
freeTLSConfig :: HTTP2. Config -> IO ()
362
352
freeTLSConfig cfg = free (HTTP2. confWriteBuffer cfg)
363
353
364
- allocTLSConfig :: SSL -> HTTP2. BufferSize -> IO HTTP2. Config
365
- allocTLSConfig ssl bufsize = do
354
+ allocTLSConfig :: TLS. Context -> HTTP2. BufferSize -> IO HTTP2. Config
355
+ allocTLSConfig ctx bufsize = do
366
356
buf <- mallocBytes bufsize
367
357
timmgr <- System.TimeManager. initialize $ 30 * 1000000
358
+ ref <- newIORef mempty
368
359
let readData :: Int -> IO ByteString
369
- -- Sometimes the frame header says that the payload length is 0. Reading 0
370
- -- bytes multiple times seems to be causing errors in openssl. I cannot
371
- -- figure out why. The previous implementation didn't try to read from the
372
- -- socket when trying to read 0 bytes, so special handling for 0 maintains
373
- -- that behaviour.
374
- readData 0 = pure " "
375
- readData n = SSL. read ssl n `catch` \ (_ :: SSL. ConnectionAbruptlyTerminated ) -> pure mempty
360
+ readData n = do
361
+ chunk <- readIORef ref
362
+ if BS. length chunk >= n
363
+ then case BS. splitAt n chunk of
364
+ (result, chunk') -> do
365
+ writeIORef ref chunk'
366
+ pure result
367
+ else do
368
+ chunk' <- TLS. recvData ctx
369
+ if BS. null chunk'
370
+ then pure chunk
371
+ else do
372
+ modifyIORef ref (<> chunk')
373
+ readData n
376
374
pure
377
375
HTTP2. Config
378
376
{ HTTP2. confWriteBuffer = buf,
379
377
HTTP2. confBufferSize = bufsize,
380
- HTTP2. confSendAll = SSL. write ssl ,
378
+ HTTP2. confSendAll = TLS. sendData ctx . LBS. fromStrict ,
381
379
HTTP2. confReadN = readData,
382
380
HTTP2. confPositionReadMaker = HTTP2. defaultPositionReadMaker,
383
381
HTTP2. confTimeoutManager = timmgr
0 commit comments