Skip to content

Commit c02b8d9

Browse files
Add Unix socket support
1 parent 12b8f15 commit c02b8d9

File tree

2 files changed

+73
-17
lines changed

2 files changed

+73
-17
lines changed

grapesy/src/Network/GRPC/Client/Connection.hs

+29-10
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,9 @@ data Server =
257257

258258
-- | Make secure connection (with TLS) to the given server
259259
| ServerSecure ServerValidation SslKeyLog Address
260+
261+
-- | Make a local connection over a Unix domain socket
262+
| ServerUnix FilePath
260263
deriving stock (Show)
261264

262265
{-------------------------------------------------------------------------------
@@ -429,6 +432,8 @@ stayConnected connParams initialServer connStateVar connOutOfScope = do
429432
connectInsecure connParams attempt addr
430433
ServerSecure validation sslKeyLog addr ->
431434
connectSecure connParams attempt validation sslKeyLog addr
435+
ServerUnix path ->
436+
connectUnix connParams attempt path
432437

433438
thisReconnectPolicy <- atomically $ do
434439
putTMVar (attemptClosed attempt) $ either Just (\() -> Nothing) mRes
@@ -462,21 +467,21 @@ stayConnected connParams initialServer connStateVar connOutOfScope = do
462467
atomically $ writeTVar connStateVar $ ConnectionNotReady
463468
loop nextServer =<< f
464469

470+
-- | Unix domain socket connection
471+
connectUnix :: ConnParams -> Attempt -> FilePath -> IO ()
472+
connectUnix connParams attempt path = do
473+
client <- socket AF_UNIX Stream defaultProtocol
474+
connect client $ SockAddrUnix path
475+
connectSocket connParams attempt "localhost" client
476+
465477
-- | Insecure connection (no TLS)
466478
connectInsecure :: ConnParams -> Attempt -> Address -> IO ()
467479
connectInsecure connParams attempt addr = do
468480
Run.runTCPClientWithSettings
469481
runSettings
470482
(addressHost addr)
471-
(show $ addressPort addr) $ \sock ->
472-
bracket (HTTP2.Client.allocSimpleConfig sock writeBufferSize)
473-
HTTP2.Client.freeSimpleConfig $ \conf ->
474-
HTTP2.Client.run clientConfig conf $ \sendRequest _aux -> do
475-
let conn = Session.ConnectionToServer sendRequest
476-
atomically $
477-
writeTVar (attemptState attempt) $
478-
ConnectionReady (attemptClosed attempt) conn
479-
takeMVar $ attemptOutOfScope attempt
483+
(show $ addressPort addr)
484+
$ connectSocket connParams attempt (authority addr)
480485
where
481486
ConnParams{connHTTP2Settings} = connParams
482487

@@ -485,6 +490,20 @@ connectInsecure connParams attempt addr = do
485490
Run.settingsOpenClientSocket = openClientSocket connHTTP2Settings
486491
}
487492

493+
-- | Insecure connection over the given socket
494+
connectSocket :: ConnParams -> Attempt -> String -> Socket -> IO ()
495+
connectSocket connParams attempt connAuthority sock = do
496+
bracket (HTTP2.Client.allocSimpleConfig sock writeBufferSize)
497+
HTTP2.Client.freeSimpleConfig $ \conf ->
498+
HTTP2.Client.run clientConfig conf $ \sendRequest _aux -> do
499+
let conn = Session.ConnectionToServer sendRequest
500+
atomically $
501+
writeTVar (attemptState attempt) $
502+
ConnectionReady (attemptClosed attempt) conn
503+
takeMVar $ attemptOutOfScope attempt
504+
where
505+
ConnParams{connHTTP2Settings} = connParams
506+
488507
settings :: HTTP2.Client.Settings
489508
settings = HTTP2.Client.defaultSettings {
490509
HTTP2.Client.maxConcurrentStreams =
@@ -498,7 +517,7 @@ connectInsecure connParams attempt addr = do
498517
clientConfig :: HTTP2.Client.ClientConfig
499518
clientConfig = overrideRateLimits connParams $
500519
HTTP2.Client.defaultClientConfig {
501-
HTTP2.Client.authority = authority addr
520+
HTTP2.Client.authority = connAuthority
502521
, HTTP2.Client.settings = settings
503522
, HTTP2.Client.connectionWindowSize =
504523
fromIntegral $

grapesy/src/Network/GRPC/Server/Run.hs

+44-7
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ data ServerConfig = ServerConfig {
6666
deriving stock (Show, Generic)
6767

6868
-- | Offer insecure connection (no TLS)
69-
data InsecureConfig = InsecureConfig {
69+
data InsecureConfig =
70+
-- | Insecure TCP connection
71+
InsecureConfig {
7072
-- | Hostname
7173
insecureHost :: Maybe HostName
7274

@@ -77,6 +79,11 @@ data InsecureConfig = InsecureConfig {
7779
-- 'getInsecureSocket' for a way to figure out what this port actually is.
7880
, insecurePort :: PortNumber
7981
}
82+
-- | Insecure (but local) Unix domain socket connection
83+
| InsecureUnix {
84+
-- | Path to the socket
85+
insecurePath :: FilePath
86+
}
8087
deriving stock (Show, Generic)
8188

8289
-- | Offer secure connection (over TLS)
@@ -297,14 +304,10 @@ runInsecure ::
297304
-> HTTP2.Server
298305
-> IO ()
299306
runInsecure http2 cfg socketTMVar server = do
300-
withServerSocket
301-
http2
302-
socketTMVar
303-
(insecureHost cfg)
304-
(insecurePort cfg) $ \listenSock ->
307+
openSock cfg $ \listenSock ->
305308
withTimeManager $ \mgr ->
306309
Run.runTCPServerWithSocket listenSock $ \clientSock -> do
307-
when (http2TcpNoDelay http2) $ do
310+
when (http2TcpNoDelay http2 && not isUnixSocket) $ do
308311
-- See description of 'withServerSocket'
309312
setSocketOption clientSock NoDelay 1
310313
when (http2TcpAbortiveClose http2) $ do
@@ -316,6 +319,22 @@ runInsecure http2 cfg socketTMVar server = do
316319
serverConfig :: HTTP2.ServerConfig
317320
serverConfig = mkServerConfig http2
318321

322+
openSock :: InsecureConfig -> (Socket -> IO a) -> IO a
323+
openSock InsecureConfig{insecureHost, insecurePort} = do
324+
withServerSocket
325+
http2
326+
socketTMVar
327+
insecureHost
328+
insecurePort
329+
openSock InsecureUnix{insecurePath} = do
330+
withUnixSocket
331+
insecurePath
332+
socketTMVar
333+
334+
isUnixSocket = case cfg of
335+
InsecureConfig{} -> False
336+
InsecureUnix{} -> True
337+
319338
{-------------------------------------------------------------------------------
320339
Secure (over TLS)
321340
-------------------------------------------------------------------------------}
@@ -420,3 +439,21 @@ withServerSocket http2Settings socketTMVar host port k = do
420439
]
421440
]
422441

442+
-- | Create a Unix domain socket
443+
--
444+
-- Note that @TCP_NODELAY@ should not be set on unix domain sockets,
445+
-- otherwise clients would get their connection closed immediately.
446+
withUnixSocket :: FilePath -> TMVar Socket -> (Socket -> IO a) -> IO a
447+
withUnixSocket path socketTMVar k = do
448+
bracket openServerSocket close $ \sock -> do
449+
atomically $ putTMVar socketTMVar sock
450+
k sock
451+
where
452+
openServerSocket :: IO Socket
453+
openServerSocket = do
454+
sock <- socket AF_UNIX Stream 0
455+
setSocketOption sock ReuseAddr 1
456+
withFdSocket sock setCloseOnExecIfNeeded
457+
bind sock $ SockAddrUnix path
458+
listen sock 1024
459+
return sock

0 commit comments

Comments
 (0)