Skip to content

Commit 9587cf5

Browse files
committed
Work-in-progress
1 parent 2edcdf0 commit 9587cf5

File tree

3 files changed

+161
-0
lines changed

3 files changed

+161
-0
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
cabal-version: 3.0
2+
Name: network-transport-quic
3+
Version: 0.1.0
4+
build-Type: Simple
5+
License: BSD-3-Clause
6+
License-file: LICENSE
7+
Copyright: Well-Typed LLP, Tweag I/O Limited
8+
Author: Duncan Coutts, Nicolas Wu, Edsko de Vries
9+
maintainer: The Distributed Haskell team
10+
Stability: experimental
11+
Homepage: http://haskell-distributed.github.com
12+
Bug-Reports: https://github.com/haskell-distributed/distributed-process/issues
13+
Synopsis: Networking layer for Cloud Haskell based on QUIC
14+
Description: Networking layer for Cloud Haskell based on QUIC
15+
tested-with: GHC==8.10.7 GHC==9.0.2 GHC==9.2.8 GHC==9.4.5 GHC==9.6.4 GHC==9.8.2 GHC==9.10.1 GHC==9.12.1
16+
Category: Network
17+
extra-doc-files: ChangeLog
18+
19+
source-repository head
20+
Type: git
21+
Location: https://github.com/haskell-distributed/distributed-process
22+
SubDir: packages/network-transport-quic
23+
24+
common warnings
25+
ghc-options: -Wall
26+
-Wcompat
27+
-Widentities
28+
-Wincomplete-uni-patterns
29+
-Wincomplete-record-updates
30+
-Wredundant-constraints
31+
-fhide-source-paths
32+
-Wpartial-fields
33+
-Wunused-packages
34+
35+
library
36+
import: warnings
37+
build-depends: async >= 2.2 && < 2.3,
38+
base >= 4.14 && < 5,
39+
binary,
40+
bytestring >= 0.10 && < 0.13,
41+
containers,
42+
network >= 3.1 && < 3.3,
43+
network-transport >= 0.5 && < 0.6,
44+
quic ^>=0.2,
45+
stm >=2.4 && <2.6
46+
exposed-modules: Network.Transport.QUIC
47+
other-modules: Network.Transport.QUIC.EndpointState
48+
default-language: Haskell2010
49+
default-extensions: ImportQualifiedPost
50+
-- The -threaded option is /required/ to use the quic library
51+
ghc-options: -threaded
52+
hs-source-dirs: src
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
module Network.Transport.QUIC (
2+
createTransport,
3+
QUICAddr (..),
4+
) where
5+
6+
import Control.Concurrent.STM (atomically)
7+
import Control.Concurrent.STM.TQueue (
8+
TQueue,
9+
newTQueueIO,
10+
readTQueue,
11+
writeTQueue,
12+
)
13+
import Data.ByteString qualified as BS
14+
import Data.ByteString.Char8 qualified as BS8
15+
import Network.QUIC qualified as QUIC
16+
import Network.QUIC.Server (defaultServerConfig)
17+
import Network.QUIC.Server qualified as QUIC.Server
18+
import Network.Transport (ConnectionId, EndPoint (..), EndPointAddress (EndPointAddress), Event (..), NewEndPointErrorCode, Transport (..), TransportError (..))
19+
20+
import Network.Socket (HostName, ServiceName)
21+
22+
{- | Create a new Transport.
23+
24+
Only a single transport should be created per Haskell process
25+
(threads can, and should, create their own endpoints though).
26+
-}
27+
createTransport :: QUICAddr -> IO Transport
28+
createTransport quicAddr = do
29+
pure $ Transport (newEndpoint quicAddr) closeQUICTransport
30+
31+
data QUICAddr = QUICAddr
32+
{ quicBindHost :: !HostName
33+
, quicBindPort :: !ServiceName
34+
}
35+
36+
newEndpoint :: QUICAddr -> IO (Either (TransportError NewEndPointErrorCode) EndPoint)
37+
newEndpoint quicAddr = do
38+
eventQueue <- newTQueueIO
39+
40+
QUIC.Server.run
41+
defaultServerConfig
42+
( \conn -> do
43+
-- TODO: create a bidirectional stream
44+
-- which can be re-used for sending
45+
quicStream <- QUIC.acceptStream conn
46+
-- TODO: how to ensure positivity of ConnectionId? QUIC StreamID should be a 62 bit integer,
47+
-- so there's room to make it a positive 64 bit integer (ConnectionId ~ Word64)
48+
let connId = fromIntegral (QUIC.streamId quicStream)
49+
receiveLoop connId quicStream eventQueue
50+
)
51+
52+
pure . Right $
53+
EndPoint
54+
(atomically (readTQueue eventQueue))
55+
(encodeQUICAddr quicAddr)
56+
_
57+
_
58+
_
59+
_
60+
where
61+
receiveLoop ::
62+
ConnectionId ->
63+
QUIC.Stream ->
64+
TQueue Event ->
65+
IO ()
66+
receiveLoop connId stream eventQueue = do
67+
incoming <- QUIC.recvStream stream 1024 -- TODO: variable length?
68+
-- TODO: check some state whether we should stop all connections
69+
if BS.null incoming
70+
then do
71+
atomically (writeTQueue eventQueue (ConnectionClosed connId))
72+
else do
73+
atomically (writeTQueue eventQueue (Received connId [incoming]))
74+
receiveLoop connId stream eventQueue
75+
76+
encodeQUICAddr :: QUICAddr -> EndPointAddress
77+
encodeQUICAddr (QUICAddr host port) = EndPointAddress (BS8.pack $ host <> ":" <> port)
78+
79+
closeQUICTransport :: IO ()
80+
closeQUICTransport = pure ()
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
module Network.Transport.QUIC.EndpointState (
2+
EndpointState,
3+
newConnection,
4+
) where
5+
6+
import Data.Map.Strict (Map)
7+
import Network.QUIC (Stream, StreamId)
8+
import Network.QUIC qualified as QUIC
9+
import Network.Transport (ConnectionId)
10+
11+
import Data.Map.Strict qualified as Map
12+
13+
newtype EndpointState = EndpointState
14+
{ streamIds :: Map StreamId ConnectionId
15+
, streams :: Map
16+
}
17+
18+
newConnection :: Stream -> EndpointState -> EndpointState
19+
newConnection stream (EndpointState sids) =
20+
EndpointState
21+
( Map.insert
22+
(QUIC.streamId stream)
23+
-- TODO: how to ensure positivity? QUIC StreamID should be a 62 bit integer,
24+
-- so there's room to make it a positive 64 bit integer (ConnectionId ~ Word64)
25+
(fromIntegral $ QUIC.streamId stream)
26+
sids
27+
)
28+
29+
lookupConnectionId :: EndpointState -> ConnectionId

0 commit comments

Comments
 (0)