@@ -1,4 +1,4 @@
1−{-# LANGUAGE DerivingVia, DeriveGeneric, RankNTypes, ScopedTypeVariables, MultiParamTypeClasses, OverloadedStrings, GeneralizedNewtypeDeriving, TypeApplications #-}
1+{-# LANGUAGE DerivingVia, DeriveGeneric, RankNTypes, ScopedTypeVariables, MultiParamTypeClasses, OverloadedStrings, GeneralizedNewtypeDeriving, TypeApplications, CPP #-}
22{- HLINT ignore "Use lambda-case" -}
33module Network.RPC.Curryer.Server where
44import Streamly
@@ -24,34 +24,31 @@ import qualified Streamly.Internal.Data.Stream.IsStream as S
2424import qualified Data.Binary as B
2525import qualified Data.UUID as UUIDBase
2626import qualified Data.UUID.V4 as UUIDBase
27−import qualified Streamly.Internal.Data.Array.Storable.Foreign.Types as SA
27+
2828import qualified Network.RPC.Curryer.StreamlyAdditions as SA
2929import Control.Monad
3030import Data.Hashable
3131import System.Timeout
3232import qualified Network.ByteOrder as BO
33+import Data.Proxy
3334
3435-- for toArrayS conversion
35−import qualified Data.ByteString.Internal as BSI
36+{-import qualified Data.ByteString.Internal as BSI
37+import qualified Streamly.Internal.Data.Array.Storable.Foreign.Types as SA
3638import Foreign.ForeignPtr (plusForeignPtr)
3739import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
3840import GHC.Ptr (plusPtr)
39−
40−--import Debug.Trace
41−
42−data ClientHelloMessage = ClientHelloMessage Int Int
43− deriving Generic
44− deriving Serialise via WineryVariant ClientHelloMessage
45−
46−data ServerHelloMessage = ServerHelloMessage { serverServices :: [String],
47− serverInfo :: String
48− }
49− deriving Generic
50− deriving Serialise via WineryRecord ServerHelloMessage
51−
52−--request-response token
53−--client-side timeout
54−--server-to-client and client-to-server async request (no response requested)
41+-}
42+#if CURRYER_SHOW_BYTES == 1
43+import Debug.Trace
44+#endif
45+
46+traceBytes :: Applicative f => String -> BS.ByteString -> f ()
47+#if CURRYER_SHOW_BYTES == 1
48+traceBytes msg bs = traceShowM (msg, BS.length bs, bs)
49+#else
50+traceBytes _ _ = pure ()
51+#endif
5552
5653type Timeout = Int
5754
@@ -104,30 +101,35 @@ localHostAddr = (127,0,0,1)
104101-- Each message is length-prefixed by a 32-bit unsigned length.
105102messageBoundaryP :: Parser IO Word8 BS.ByteString
106103messageBoundaryP = do
107− let x = FL.toList
108− w4x8 <- P.take 4 x
104+ let s = FL.toList
105+ w4x8 <- P.take 4 s
109106 --traceShowM ("w4x8"::String, w4x8)
110107 let c = fromIntegral (BO.word32 (BS.pack w4x8))
111108 --traceShowM ("c"::String, c)
112− vals <- P.take c x
109+ vals <- P.take c s
113110 let bytes = BS.pack vals
114111 --traceShowM ("parsedBytes"::String, c, BS.length bytes, bytes)
115112 pure bytes
116113
117114type NewConnectionHandler msg = IO (Maybe msg)
118115
119−type NewMessageHandler msg resp = msg -> IO (HandlerResponse resp)
116+type NewMessageHandler req resp = req -> IO (HandlerResponse resp)
120117
121−serve :: (Show msg, Serialise msg, Serialise resp) =>
118+serve :: forall req resp. (Show req, Serialise req, Serialise resp) =>
122119 NewConnectionHandler resp ->
123− NewMessageHandler msg resp ->
120+ NewMessageHandler req resp ->
124121 HostAddr ->
125122 PortNumber ->
126123 Maybe (MVar SockAddr) ->
127124 IO Bool
128125serve connhandler userMsgHandler hostaddr port mSockLock = do
129− let handleSock sock = do
130− putStrLn "handleSock"
126+ let
127+ decoder :: NewMessageHandler req resp -> Decoder (Message req)
128+ decoder _ =
129+ case getDecoder (schema (Proxy @(Message req))) of
130+ Left exc -> error (show exc)
131+ Right dec -> dec
132+ handleSock sock = do
131133 -- allow the server to send an async welcome message to the new client, if necessary
132134 mResp <- connhandler
133135 case mResp of
@@ -135,8 +137,8 @@ serve connhandler userMsgHandler hostaddr port mSockLock = do
135137 Just resp -> do
136138 requestID <- UUID <$> UUIDBase.nextRandom
137139 sendMessage (AsyncRequest requestID resp) sock
138− drainSocketMessages sock (serverMessageHandler sock userMsgHandler)
139− serially (S.unfold (SA.acceptOnAddrWith [(ReuseAddr,1)] mSockLock) (hostaddr, port)) & serially . S.mapM (handleWithM handleSock) & S.drain
140+ drainSocketMessages sock (decoder userMsgHandler) (serverMessageHandler sock userMsgHandler)
141+ serially (S.unfold (SA.acceptOnAddrWith [(ReuseAddr,1)] mSockLock) (hostaddr, port)) & parallely . S.mapM (handleWithM handleSock) & S.drain
140142 pure True
141143
142144serverMessageHandler :: forall req resp. (Show req,
@@ -147,7 +149,7 @@ serverMessageHandler :: forall req resp. (Show req,
147149 -> Message req
148150 -> IO ()
149151serverMessageHandler sock requestMessageHandler msg = do
150− putStrLn $ "GOT MSG " ++ show msg
152+ --putStrLn $ "GOT MSG " ++ show msg
151153 let --runTimeout :: IO (HandlerResponse resp) -> IO (Maybe (HandlerResponse resp))
152154 runTimeout mTimeout m = case mTimeout of
153155 Nothing -> Just <$> m
@@ -155,7 +157,6 @@ serverMessageHandler sock requestMessageHandler msg = do
155157 case msg of
156158 Response{} -> putStrLn "client sent response"
157159 ResponseExpectedRequest requestID mTimeout val -> do
158− putStrLn "server received ResponseExpectedRequest"
159160 resp <- runTimeout mTimeout (requestMessageHandler val)
160161 case resp of
161162 Just (HandlerResponse responseVal) -> sendMessage (Response requestID responseVal) sock
@@ -164,7 +165,6 @@ serverMessageHandler sock requestMessageHandler msg = do
164165 Nothing ->
165166 sendMessage (TimedOutResponse @(Message resp) requestID) sock
166167 AsyncRequest _ val -> do
167− putStrLn "AsyncReq"
168168 void $ requestMessageHandler val
169169 --no response necessary
170170 ExceptionResponse{} -> putStrLn "client sent exception response"
@@ -177,29 +177,26 @@ type AsyncMessageHandler a = a -> IO ()
177177
178178
179179
180−drainSocketMessages :: Serialise msg => Socket -> MessageHandler msg -> IO ()
181−drainSocketMessages sock msgHandler = do
180+drainSocketMessages :: Serialise msg => Socket -> Decoder (Message msg) -> MessageHandler msg -> IO ()
181+drainSocketMessages sock decoder msgHandler = do
182182 let sockStream = S.unfold readWithBufferOf (1024 * 4, sock)
183183 handler bs = do
184− case deserialise bs of
185− Left err ->
186− print err
187− Right val ->
188− msgHandler val --add response function
184+ let decoded = evalDecoder decoder bs
185+ msgHandler decoded
189186 S.drain $ serially $ S.parseMany messageBoundaryP sockStream & S.mapM handler
190187
191188--send length-tagged bytestring, perhaps should be in network byte order?
192189sendMessage :: Serialise a => Message a -> Socket -> IO ()
193190sendMessage msg socket' = do
194191 let
195− msgbytes = serialise msg
192+ msgbytes = serialiseOnly msg
196193 fullbytes = lenbytes <> msgbytes
197194 len = BS.length msgbytes
198195 lenbytes = BO.bytestring32 (fromIntegral len)
199196
200197 byteCount <- Socket.send socket' fullbytes
201198 when (byteCount /= BS.length fullbytes) (error "bytes sent mismatch")
202− --traceShowM ("sent bytes:" :: String, byteCount, fullbytes)
199+ traceBytes "sent bytes" fullbytes
203200
204201
205202
@@ -207,6 +204,7 @@ sendMessage msg socket' = do
207204-- | Convert a 'ByteString' to an array of 'Word8'. This function unwraps the
208205-- 'ByteString' and wraps it with 'Array' constructors and hence the operation
209206-- is performed in constant time.
207+{-
210208{-# INLINE toArrayS #-}
211209toArrayS :: BS.ByteString -> SA.Array Word8
212210--slow path
@@ -220,3 +218,4 @@ toArraySlow :: BS.ByteString -> SA.Array Word8
220218toArraySlow bs = arr
221219 where
222220 arr = SA.fromList (BS.unpack bs)
221+-}