From 5ceeae74cc802f9d6e58a3a4110bc2c0d1b29c2b Mon Sep 17 00:00:00 2001 From: Moritz Kiefer Date: Thu, 22 Aug 2019 18:12:21 +0200 Subject: [PATCH] Upgrade to gRPC 1.22 (#85) --- core/cbits/grpc_haskell.c | 16 +++-- core/grpc-haskell-core.cabal | 3 +- core/src/Network/GRPC/LowLevel/Call.hs | 8 +-- .../GRPC/LowLevel/Call/Unregistered.hs | 2 +- .../Network/GRPC/LowLevel/CompletionQueue.hs | 11 +-- .../GRPC/LowLevel/CompletionQueue/Internal.hs | 2 +- core/src/Network/GRPC/Unsafe.chs | 18 ++++- core/tests/LowLevelTests.hs | 2 +- core/tests/UnsafeTests.hs | 2 +- nix/grpc.nix | 67 ++++++++++--------- 10 files changed, 73 insertions(+), 58 deletions(-) diff --git a/core/cbits/grpc_haskell.c b/core/cbits/grpc_haskell.c index f098938..51c21a0 100644 --- a/core/cbits/grpc_haskell.c +++ b/core/cbits/grpc_haskell.c @@ -500,10 +500,10 @@ grpc_channel_credentials* grpc_ssl_credentials_create_internal( grpc_channel_credentials* creds; if(pem_key && pem_cert){ grpc_ssl_pem_key_cert_pair pair = {pem_key, pem_cert}; - creds = grpc_ssl_credentials_create(pem_root_certs, &pair, NULL); + creds = grpc_ssl_credentials_create(pem_root_certs, &pair, NULL, NULL); } else{ - creds = grpc_ssl_credentials_create(pem_root_certs, NULL, NULL); + creds = grpc_ssl_credentials_create(pem_root_certs, NULL, NULL, NULL); } return creds; } @@ -537,10 +537,16 @@ grpc_call_credentials* grpc_metadata_credentials_create_from_plugin_( //This callback is registered as the get_metadata callback for the call, and its //only job is to cast the void* state pointer to the correct function pointer //type and call the Haskell function with it. -void metadata_dispatcher(void *state, grpc_auth_metadata_context context, - grpc_credentials_plugin_metadata_cb cb, void *user_data){ - +int metadata_dispatcher(void *state, + grpc_auth_metadata_context context, + grpc_credentials_plugin_metadata_cb cb, + void *user_data, + grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX], + size_t *num_creds_md, + grpc_status_code *status, + const char ** error_details) { ((haskell_get_metadata*)state)(&context, cb, user_data); + return 0; } grpc_metadata_credentials_plugin* mk_metadata_client_plugin( diff --git a/core/grpc-haskell-core.cabal b/core/grpc-haskell-core.cabal index 61afb83..8c67ce9 100644 --- a/core/grpc-haskell-core.cabal +++ b/core/grpc-haskell-core.cabal @@ -53,7 +53,8 @@ library Network.GRPC.LowLevel.Call.Unregistered Network.GRPC.LowLevel.Client extra-libraries: - grpc + grpc + , gpr includes: include/grpc_haskell.h , grpc/grpc.h diff --git a/core/src/Network/GRPC/LowLevel/Call.hs b/core/src/Network/GRPC/LowLevel/Call.hs index 9349ac9..6c108d9 100644 --- a/core/src/Network/GRPC/LowLevel/Call.hs +++ b/core/src/Network/GRPC/LowLevel/Call.hs @@ -20,7 +20,6 @@ import Control.Exception (bracket) import Data.ByteString (ByteString) import Data.ByteString.Char8 (pack) import Data.List (intersperse) -import Data.Semigroup ((<>)) import Data.String (IsString) import Foreign.Marshal.Alloc (free, malloc) import Foreign.Ptr (Ptr, nullPtr) @@ -31,6 +30,7 @@ import Network.GRPC.LowLevel.GRPC (MetadataMap, import qualified Network.GRPC.Unsafe as C import qualified Network.GRPC.Unsafe.ByteBuffer as C import qualified Network.GRPC.Unsafe.Op as C +import qualified Network.GRPC.Unsafe.Time as C import System.Clock -- | Models the four types of RPC call supported by gRPC (and correspond to @@ -181,7 +181,7 @@ mgdPtr = managed (bracket malloc free) serverCallIsExpired :: ServerCall a -> IO Bool serverCallIsExpired sc = do - currTime <- getTime Monotonic + C.CTimeSpec currTime <- bracket (C.gprNow C.GprClockMonotonic) C.timespecDestroy peek return $ currTime > (callDeadline sc) debugClientCall :: ClientCall -> IO () @@ -209,11 +209,11 @@ debugServerCall = const $ return () destroyClientCall :: ClientCall -> IO () destroyClientCall cc = do grpcDebug "Destroying client-side call object." - C.grpcCallDestroy (unsafeCC cc) + C.grpcCallUnref (unsafeCC cc) destroyServerCall :: ServerCall a -> IO () destroyServerCall sc@ServerCall{ unsafeSC = c, .. } = do grpcDebug "destroyServerCall(R): entered." debugServerCall sc grpcDebug $ "Destroying server-side call object: " ++ show c - C.grpcCallDestroy c + C.grpcCallUnref c diff --git a/core/src/Network/GRPC/LowLevel/Call/Unregistered.hs b/core/src/Network/GRPC/LowLevel/Call/Unregistered.hs index f65a2e7..675ee2a 100644 --- a/core/src/Network/GRPC/LowLevel/Call/Unregistered.hs +++ b/core/src/Network/GRPC/LowLevel/Call/Unregistered.hs @@ -51,4 +51,4 @@ destroyServerCall call@ServerCall{..} = do grpcDebug "destroyServerCall(U): entered." debugServerCall call grpcDebug $ "Destroying server-side call object: " ++ show unsafeSC - C.grpcCallDestroy unsafeSC + C.grpcCallUnref unsafeSC diff --git a/core/src/Network/GRPC/LowLevel/CompletionQueue.hs b/core/src/Network/GRPC/LowLevel/CompletionQueue.hs index 5253f3a..ae7a9d7 100644 --- a/core/src/Network/GRPC/LowLevel/CompletionQueue.hs +++ b/core/src/Network/GRPC/LowLevel/CompletionQueue.hs @@ -52,9 +52,6 @@ import qualified Network.GRPC.Unsafe.Constants as C import qualified Network.GRPC.Unsafe.Metadata as C import qualified Network.GRPC.Unsafe.Op as C import qualified Network.GRPC.Unsafe.Time as C -import System.Clock (Clock (..), - getTime) -import System.Info (os) withCompletionQueue :: GRPC -> (CompletionQueue -> IO a) -> IO a withCompletionQueue grpc = bracket (createCompletionQueue grpc) @@ -62,7 +59,7 @@ withCompletionQueue grpc = bracket (createCompletionQueue grpc) createCompletionQueue :: GRPC -> IO CompletionQueue createCompletionQueue _ = do - unsafeCQ <- C.grpcCompletionQueueCreate C.reserved + unsafeCQ <- C.grpcCompletionQueueCreateForPluck C.reserved currentPluckers <- newTVarIO 0 currentPushers <- newTVarIO 0 shuttingDown <- newTVarIO False @@ -142,11 +139,7 @@ serverRequestCall rm s scq ccq = <*> mgdPayload (methodType rm) <*> managed C.withMetadataArrayPtr dbug = grpcDebug . ("serverRequestCall(R): " ++) - -- On OS X, gRPC gives us a deadline that is just a delta, so we convert - -- it to an actual deadline. - convertDeadline (fmap C.timeSpec . peek -> d) - | os == "darwin" = (+) <$> d <*> getTime Monotonic - | otherwise = d + convertDeadline timeSpecPtr = C.timeSpec <$> peek timeSpecPtr -- | Register the server's completion queue. Must be done before the server is -- started. diff --git a/core/src/Network/GRPC/LowLevel/CompletionQueue/Internal.hs b/core/src/Network/GRPC/LowLevel/CompletionQueue/Internal.hs index 464dddf..db63632 100644 --- a/core/src/Network/GRPC/LowLevel/CompletionQueue/Internal.hs +++ b/core/src/Network/GRPC/LowLevel/CompletionQueue/Internal.hs @@ -167,7 +167,7 @@ shutdownCompletionQueue CompletionQueue{..} = do drainLoop = do grpcDebug "drainLoop: before next() call" ev <- C.withDeadlineSeconds 1 $ \deadline -> - C.grpcCompletionQueueNext unsafeCQ deadline C.reserved + C.grpcCompletionQueuePluck unsafeCQ C.noTag deadline C.reserved grpcDebug $ "drainLoop: next() call got " ++ show ev case C.eventCompletionType ev of C.QueueShutdown -> return () diff --git a/core/src/Network/GRPC/Unsafe.chs b/core/src/Network/GRPC/Unsafe.chs index 3e3412b..d11f533 100644 --- a/core/src/Network/GRPC/Unsafe.chs +++ b/core/src/Network/GRPC/Unsafe.chs @@ -78,6 +78,9 @@ newtype Tag = Tag {unTag :: Ptr ()} deriving (Show, Eq) tag :: Int -> Tag tag = Tag . plusPtr nullPtr +noTag :: Tag +noTag = Tag nullPtr + instance Storable Tag where sizeOf (Tag p) = sizeOf p alignment (Tag p) = alignment p @@ -139,11 +142,18 @@ castPeek p = do {#fun grpc_shutdown as ^ {} -> `()'#} +{#fun grpc_shutdown_blocking as ^ {} -> `()'#} + {#fun grpc_version_string as ^ {} -> `String' #} --- | Create a new 'CompletionQueue'. See the docs for +-- | Create a new 'CompletionQueue' for GRPC_CQ_NEXT. See the docs for -- 'grpcCompletionQueueShutdown' for instructions on how to clean up afterwards. -{#fun grpc_completion_queue_create as ^ +{#fun grpc_completion_queue_create_for_next as ^ + {unReserved `Reserved'} -> `CompletionQueue'#} + +-- | Create a new 'CompletionQueue' for GRPC_CQ_PLUCK. See the docs for +-- 'grpcCompletionQueueShutdown' for instructions on how to clean up afterwards. +{#fun grpc_completion_queue_create_for_pluck as ^ {unReserved `Reserved'} -> `CompletionQueue'#} -- | Block until we get the next event off the given 'CompletionQueue', @@ -226,7 +236,9 @@ castPeek p = do {#fun grpc_call_cancel_with_status as ^ {`Call', `StatusCode', `String',unReserved `Reserved'} -> `()'#} -{#fun grpc_call_destroy as ^ {`Call'} -> `()'#} +{#fun grpc_call_ref as ^ {`Call'} -> `()'#} + +{#fun grpc_call_unref as ^ {`Call'} -> `()'#} -- | Gets the peer of the current call as a string. {#fun grpc_call_get_peer as ^ {`Call'} -> `String' getPeerPeek* #} diff --git a/core/tests/LowLevelTests.hs b/core/tests/LowLevelTests.hs index e3fa00b..75867ab 100644 --- a/core/tests/LowLevelTests.hs +++ b/core/tests/LowLevelTests.hs @@ -802,7 +802,7 @@ testClientMaxReceiveMessageLengthChannelArg = do -- Expect failure when the max recv payload size is set to 3 bytes, and we -- are sent 4. shouldFail = clientMax 3 $ \case - Left (GRPCIOBadStatusCode StatusInvalidArgument _) + Left (GRPCIOBadStatusCode StatusResourceExhausted _) -> pure () rsp -> clientFail ("Expected failure response, but got: " ++ show rsp) diff --git a/core/tests/UnsafeTests.hs b/core/tests/UnsafeTests.hs index eb8ba84..e335324 100644 --- a/core/tests/UnsafeTests.hs +++ b/core/tests/UnsafeTests.hs @@ -197,7 +197,7 @@ assertCqEventComplete e = do eventSuccess e HU.@?= True grpc :: IO a -> IO () -grpc = bracket_ grpcInit grpcShutdown . void +grpc = bracket_ grpcInit grpcShutdownBlocking . void _nowarnUnused :: a _nowarnUnused = assertCqEventComplete `undefined` threadDelaySecs diff --git a/nix/grpc.nix b/nix/grpc.nix index 71861ba..729e95b 100644 --- a/nix/grpc.nix +++ b/nix/grpc.nix @@ -1,42 +1,45 @@ -{ darwin, stdenv, lib, fetchgit, fixDarwinDylibNames, autoconf, automake, libtool, which, zlib -, openssl -}: +{ stdenv, fetchFromGitHub, cmake, zlib, c-ares, pkgconfig, openssl, protobuf, gflags }: stdenv.mkDerivation rec { - name = "grpc-${version}"; - version = "1.2.0-${lib.strings.substring 0 7 rev}"; - rev = "e2cfe9df79c4eda4e376222df064c4c65e616352"; - src = fetchgit { - inherit rev; - url = "https://github.com/grpc/grpc.git"; - sha256 = "19ldbjlnbc287hkaylsigm8w9fai2bjdbfxk6315kl75cq54iprr"; + version = "1.22.1"; + name = "grpc-${version}"; + src = fetchFromGitHub { + owner = "grpc"; + repo = "grpc"; + rev = "v${version}"; + sha256 = "1ci3v8xrr8iy65ixx2j0aw1i7cmmrm6pll1dnnbvndmjq573qiyk"; }; + nativeBuildInputs = [ cmake pkgconfig ]; + buildInputs = [ zlib c-ares c-ares.cmake-config openssl protobuf gflags ]; - NIX_CFLAGS_COMPILE = "-Wno-error"; + cmakeFlags = + [ "-DgRPC_ZLIB_PROVIDER=package" + "-DgRPC_CARES_PROVIDER=package" + "-DgRPC_SSL_PROVIDER=package" + "-DgRPC_PROTOBUF_PROVIDER=package" + "-DgRPC_GFLAGS_PROVIDER=package" + "-DBUILD_SHARED_LIBS=ON" + "-DCMAKE_SKIP_BUILD_RPATH=OFF" + ]; - # `grpc`'s `Makefile` does some magic to detect the correct `ld` and `strip` - # to use along with their flags, too. If Nix supplies `$LD` and `$STRIP` then - # this auto-detection fails and the build fails, which is why we unset the - # environment variables here and let the `Makefile` set them. - preBuild = '' - unset LD - unset STRIP + # CMake creates a build directory by default, this conflicts with the + # basel BUILD file on case-insensitive filesystems. + preConfigure = '' + rm -vf BUILD ''; - preInstall = "export prefix"; + preBuild = '' + export LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH + ''; - buildInputs = [ - autoconf - automake - libtool - which - zlib - openssl - ] ++ stdenv.lib.optional stdenv.isDarwin fixDarwinDylibNames; + NIX_CFLAGS_COMPILE = stdenv.lib.optionalString stdenv.cc.isClang "-Wno-error=unknown-warning-option"; - # Some versions of `ar` (such as the one provided by OS X) require an explicit - # `-r` flag, whereas other versions assume `-r` is the default if no mode is - # specified. For example, OS X requires the `-r` flag, so as a precaution we - # always specify the flag. - AROPTS = "-r"; + enableParallelBuilds = true; + + meta = with stdenv.lib; { + description = "The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)"; + license = licenses.asl20; + maintainers = [ maintainers.lnl7 ]; + homepage = https://grpc.io/; + }; }