From b550607f60d4aeac3b6c8ecc316ff1147a81cf47 Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Fri, 14 Apr 2017 19:28:01 -0700 Subject: [PATCH] gRPC 1.2.0 compatibility (#12) * update for reorganized headers in gRPC v1.1: https://github.com/grpc/grpc/pull/7559 * update nix files * rename all gpr_slice to grpc_slice since we can't be backwards compatible anyway * use gRPC 1.1.4 * now compatible with gRPC 1.2.0 * use nixpkgs 17.03 to get protobuf3_2, newer proto3-* deps, fix some warnings * another warning --- cbits/grpc_haskell.c | 99 +++++++++++++------------ grpc-haskell.cabal | 12 +-- include/grpc_haskell.h | 34 +++++---- nix/grpc.nix | 6 +- nix/proto3-suite.nix | 4 +- nix/proto3-wire.nix | 4 +- nixpkgs.json | 6 +- release.nix | 19 +++-- src/Network/GRPC/LowLevel/Op.hs | 39 ++++------ src/Network/GRPC/Unsafe.chs | 9 ++- src/Network/GRPC/Unsafe/ByteBuffer.chs | 4 +- src/Network/GRPC/Unsafe/ChannelArgs.chs | 2 +- src/Network/GRPC/Unsafe/Metadata.chs | 16 ++-- src/Network/GRPC/Unsafe/Op.chs | 7 +- src/Network/GRPC/Unsafe/Slice.chs | 23 +++--- 15 files changed, 147 insertions(+), 137 deletions(-) diff --git a/cbits/grpc_haskell.c b/cbits/grpc_haskell.c index 29c4579..c6f0ad6 100644 --- a/cbits/grpc_haskell.c +++ b/cbits/grpc_haskell.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -38,32 +39,47 @@ grpc_call *grpc_channel_create_call_(grpc_channel *channel, grpc_completion_queue *completion_queue, const char *method, const char *host, gpr_timespec *deadline, void *reserved) { + grpc_slice method_slice = grpc_slice_from_copied_string(method); + grpc_slice host_slice = grpc_slice_from_copied_string(host); return grpc_channel_create_call(channel, parent_call, propagation_mask, - completion_queue, method, host, - *deadline, reserved); + completion_queue, method_slice, + &host_slice, *deadline, reserved); } -size_t gpr_slice_length_(gpr_slice *slice){ - return GPR_SLICE_LENGTH(*slice); -} - -uint8_t *gpr_slice_start_(gpr_slice *slice){ - return GPR_SLICE_START_PTR(*slice); -} - -gpr_slice* gpr_slice_from_copied_buffer_(const char *source, size_t len){ - gpr_slice* retval = malloc(sizeof(gpr_slice)); - //note: 'gpr_slice_from_copied_string' handles allocating space for 'source'. - *retval = gpr_slice_from_copied_buffer(source, len); +grpc_slice* grpc_slice_malloc_(size_t len){ + grpc_slice* retval = malloc(sizeof(grpc_slice)); + *retval = grpc_slice_malloc(len); return retval; } -void gpr_slice_unref_(gpr_slice* slice){ - gpr_slice_unref(*slice); +size_t grpc_slice_length_(grpc_slice *slice){ + return GRPC_SLICE_LENGTH(*slice); } -void free_slice(gpr_slice *slice){ - gpr_slice_unref(*slice); +uint8_t *grpc_slice_start_(grpc_slice *slice){ + return GRPC_SLICE_START_PTR(*slice); +} + + +grpc_slice* grpc_slice_from_copied_string_(const char* source){ + grpc_slice* retval = malloc(sizeof(grpc_slice)); + *retval = grpc_slice_from_copied_string(source); + return retval; +} + +grpc_slice* grpc_slice_from_copied_buffer_(const char *source, size_t len){ + grpc_slice* retval = malloc(sizeof(grpc_slice)); + //note: 'grpc_slice_from_copied_string' handles allocating space for 'source'. + *retval = grpc_slice_from_copied_buffer(source, len); + return retval; +} + +void grpc_slice_unref_(grpc_slice* slice){ + grpc_slice_unref(*slice); +} + +void free_slice(grpc_slice *slice){ + grpc_slice_unref(*slice); grpc_haskell_free("free_slice", slice); } @@ -89,8 +105,8 @@ void byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader){ grpc_haskell_free("byte_buffer_reader_destroy", reader); } -gpr_slice *grpc_byte_buffer_reader_readall_(grpc_byte_buffer_reader *reader){ - gpr_slice *retval = malloc(sizeof(gpr_slice)); +grpc_slice *grpc_byte_buffer_reader_readall_(grpc_byte_buffer_reader *reader){ + grpc_slice *retval = malloc(sizeof(grpc_slice)); *retval = grpc_byte_buffer_reader_readall(reader); return retval; } @@ -170,24 +186,18 @@ void metadata_free(grpc_metadata* m){ void set_metadata_key_val(char *key, char *val, size_t val_len, grpc_metadata *arr, size_t i){ grpc_metadata *p = arr + i; - p->key = key; - p->value = val; - p->value_length = val_len; + p->key = grpc_slice_from_copied_string(key); + p->value = grpc_slice_from_copied_buffer(val,val_len); } -const char* get_metadata_key(grpc_metadata *arr, size_t i){ +grpc_slice* get_metadata_key(grpc_metadata *arr, size_t i){ grpc_metadata *p = arr + i; - return p->key; + return &p->key; } -const char* get_metadata_val(grpc_metadata *arr, size_t i){ +grpc_slice* get_metadata_val(grpc_metadata *arr, size_t i){ grpc_metadata *p = arr + i; - return p->value; -} - -size_t get_metadata_val_len(grpc_metadata *arr, size_t i){ - grpc_metadata *p = arr + i; - return p->value_length; + return &(p->value); } grpc_op* op_array_create(size_t n){ @@ -207,7 +217,7 @@ void op_array_destroy(grpc_op* op_array, size_t n){ metadata_free(op->data.send_initial_metadata.metadata); break; case GRPC_OP_SEND_MESSAGE: - grpc_byte_buffer_destroy(op->data.send_message); + grpc_byte_buffer_destroy(op->data.send_message.send_message); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: break; @@ -256,7 +266,7 @@ void op_send_message(grpc_op *op_array, size_t i, grpc_byte_buffer *payload){ grpc_op *op = op_array + i; op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message = grpc_byte_buffer_copy(payload); + op->data.send_message.send_message = grpc_byte_buffer_copy(payload); op->flags = 0; op->reserved = NULL; } @@ -272,7 +282,7 @@ void op_recv_initial_metadata(grpc_op *op_array, size_t i, grpc_metadata_array** arr){ grpc_op *op = op_array + i; op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata = *arr; + op->data.recv_initial_metadata.recv_initial_metadata = *arr; op->flags = 0; op->reserved = NULL; } @@ -281,7 +291,7 @@ void op_recv_message(grpc_op *op_array, size_t i, grpc_byte_buffer **payload_recv){ grpc_op *op = op_array + i; op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message = payload_recv; + op->data.recv_message.recv_message = payload_recv; op->flags = 0; op->reserved = NULL; } @@ -289,13 +299,12 @@ void op_recv_message(grpc_op *op_array, size_t i, void op_recv_status_client(grpc_op *op_array, size_t i, grpc_metadata_array** arr, grpc_status_code* status, - char **details, size_t* details_capacity){ + grpc_slice* details){ grpc_op *op = op_array + i; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = *arr; op->data.recv_status_on_client.status = status; op->data.recv_status_on_client.status_details = details; - op->data.recv_status_on_client.status_details_capacity = details_capacity; op->flags = 0; op->reserved = NULL; } @@ -310,7 +319,7 @@ void op_recv_close_server(grpc_op *op_array, size_t i, int *was_cancelled){ void op_send_status_server(grpc_op *op_array, size_t i, size_t metadata_count, grpc_metadata* m, - grpc_status_code status, char *details){ + grpc_status_code status, grpc_slice *details){ grpc_op *op = op_array + i; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->data.send_status_from_server.trailing_metadata_count = metadata_count; @@ -319,9 +328,7 @@ void op_send_status_server(grpc_op *op_array, size_t i, memcpy(op->data.send_status_from_server.trailing_metadata, m, metadata_count*sizeof(grpc_metadata)); op->data.send_status_from_server.status = status; - op->data.send_status_from_server.status_details - = malloc(sizeof(char)*(strlen(details) + 1)); - strcpy((char*)(op->data.send_status_from_server.status_details), details); + op->data.send_status_from_server.status_details = details; op->flags = 0; op->reserved = NULL; } @@ -398,12 +405,12 @@ grpc_call* grpc_channel_create_registered_call_( *deadline, reserved); } -char* call_details_get_method(grpc_call_details* details){ - return details->method; +grpc_slice* call_details_get_method(grpc_call_details* details){ + return &details->method; } -char* call_details_get_host(grpc_call_details* details){ - return details->host; +grpc_slice* call_details_get_host(grpc_call_details* details){ + return &details->host; } gpr_timespec* call_details_get_deadline(grpc_call_details* details){ diff --git a/grpc-haskell.cabal b/grpc-haskell.cabal index 933f798..3b3033c 100644 --- a/grpc-haskell.cabal +++ b/grpc-haskell.cabal @@ -19,7 +19,7 @@ Flag Debug flag with-examples description: Also build example executables. manual: True - default: True + default: False library build-depends: @@ -29,7 +29,7 @@ library , stm == 2.4.* , containers ==0.5.* , managed >= 1.0.0 && < 1.1 - , pipes ==4.1.* + , pipes >=4.1 && <=4.4 , transformers , proto3-suite , proto3-wire @@ -79,8 +79,8 @@ library , grpc/status.h , grpc/support/time.h , grpc/impl/codegen/compression_types.h - , grpc/impl/codegen/slice_buffer.h - , grpc/impl/codegen/slice.h + , grpc/slice_buffer.h + , grpc/slice.h build-tools: c2hs default-language: Haskell2010 ghc-options: -Wall -fwarn-incomplete-patterns -fno-warn-unused-do-bind @@ -206,14 +206,14 @@ test-suite test , tasty-quickcheck ==0.8.* , containers ==0.5.* , managed >= 1.0.0 && < 1.1 - , pipes ==4.1.* + , pipes >=4.1 && <=4.4 , proto3-suite , transformers , safe , clock >=0.6.0 && <0.8.0 , turtle >= 1.2.0 , text - , QuickCheck ==2.8.* + , QuickCheck >=2.8 && <3.0 other-modules: LowLevelTests, LowLevelTests.Op, diff --git a/include/grpc_haskell.h b/include/grpc_haskell.h index 7093b1f..fa82397 100644 --- a/include/grpc_haskell.h +++ b/include/grpc_haskell.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include @@ -23,13 +23,17 @@ grpc_call *grpc_channel_create_call_(grpc_channel *channel, const char *method, const char *host, gpr_timespec *deadline, void *reserved); -size_t gpr_slice_length_(gpr_slice *slice); +grpc_slice* grpc_slice_malloc_(size_t len); -uint8_t *gpr_slice_start_(gpr_slice *slice); +size_t grpc_slice_length_(grpc_slice *slice); -gpr_slice* gpr_slice_from_copied_buffer_(const char *source, size_t len); +uint8_t *grpc_slice_start_(grpc_slice *slice); -void free_slice(gpr_slice *slice); +grpc_slice* grpc_slice_from_copied_string_(const char* source); + +grpc_slice* grpc_slice_from_copied_buffer_(const char *source, size_t len); + +void free_slice(grpc_slice *slice); grpc_byte_buffer **create_receiving_byte_buffer(); @@ -39,7 +43,7 @@ grpc_byte_buffer_reader *byte_buffer_reader_create(grpc_byte_buffer *buffer); void byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader); -gpr_slice* grpc_byte_buffer_reader_readall_(grpc_byte_buffer_reader *reader); +grpc_slice* grpc_byte_buffer_reader_readall_(grpc_byte_buffer_reader *reader); void timespec_destroy(gpr_timespec* t); @@ -68,11 +72,9 @@ void metadata_free(grpc_metadata* m); void set_metadata_key_val(char *key, char *val, size_t val_len, grpc_metadata *arr, size_t i); -const char* get_metadata_key(grpc_metadata *arr, size_t i); +grpc_slice* get_metadata_key(grpc_metadata *arr, size_t i); -const char* get_metadata_val(grpc_metadata *arr, size_t i); - -size_t get_metadata_val_len(grpc_metadata *arr, size_t i); +grpc_slice* get_metadata_val(grpc_metadata *arr, size_t i); grpc_op* op_array_create(size_t n); @@ -95,15 +97,15 @@ void op_recv_message(grpc_op *op_array, size_t i, grpc_byte_buffer **payload_recv); void op_recv_status_client(grpc_op *op_array, size_t i, - grpc_metadata_array** arr, - grpc_status_code* status, - char **details, size_t* details_capacity); + grpc_metadata_array** arr, + grpc_status_code* status, + grpc_slice* details); void op_recv_close_server(grpc_op *op_array, size_t i, int *was_cancelled); void op_send_status_server(grpc_op *op_array, size_t i, size_t metadata_count, grpc_metadata* m, - grpc_status_code status, char *details); + grpc_status_code status, grpc_slice *details); grpc_status_code* create_status_code_ptr(); @@ -135,9 +137,9 @@ grpc_call* grpc_channel_create_registered_call_( grpc_completion_queue *completion_queue, void *registered_call_handle, gpr_timespec *deadline, void *reserved); -char* call_details_get_method(grpc_call_details* details); +grpc_slice* call_details_get_method(grpc_call_details* details); -char* call_details_get_host(grpc_call_details* details); +grpc_slice* call_details_get_host(grpc_call_details* details); gpr_timespec* call_details_get_deadline(grpc_call_details* details); diff --git a/nix/grpc.nix b/nix/grpc.nix index 1581c5e..aa7f11f 100644 --- a/nix/grpc.nix +++ b/nix/grpc.nix @@ -3,12 +3,12 @@ stdenv.mkDerivation rec { name = "grpc-${version}"; - version = "1.0.1-${lib.strings.substring 0 7 rev}"; - rev = "6040b471bcd1d6bb05b25c126b6545180a1d3528"; + version = "1.2.0-${lib.strings.substring 0 7 rev}"; + rev = "e2cfe9df79c4eda4e376222df064c4c65e616352"; src = fetchgit { inherit rev; url = "https://github.com/grpc/grpc.git"; - sha256 = "1kx6jkx2dnnfnjfyc50ravfk7mfdszj988vndrlzs1zkd6627k4z"; + sha256 = "19ldbjlnbc287hkaylsigm8w9fai2bjdbfxk6315kl75cq54iprr"; }; preInstall = "export prefix"; buildInputs = diff --git a/nix/proto3-suite.nix b/nix/proto3-suite.nix index c8a1560..90052d6 100644 --- a/nix/proto3-suite.nix +++ b/nix/proto3-suite.nix @@ -8,8 +8,8 @@ mkDerivation { version = "0.1.0.0"; src = fetchgit { url = "https://github.com/awakenetworks/proto3-suite.git"; - sha256 = "1g6w4ddqybgwnj3143bkl7sp9f5ch6d8qpb242fi4m396585bpq9"; - rev = "8db2ceb8c48a3f8dc2cbdc492d1e8cbaf8b62a15"; + sha256 = "1w5qwwlivrxkd6943rxsw3znk9jjpf7ad11gm0zl4lzq6k3kdinp"; + rev = "46f40d38c4db8a6320bab010ae30e75c83fab6ee"; }; libraryHaskellDepends = [ base bytestring cereal containers deepseq filepath haskell-src mtl diff --git a/nix/proto3-wire.nix b/nix/proto3-wire.nix index 2b5f349..00b43d9 100644 --- a/nix/proto3-wire.nix +++ b/nix/proto3-wire.nix @@ -7,8 +7,8 @@ mkDerivation { version = "1.0.0"; src = fetchgit { url = "https://github.com/awakenetworks/proto3-wire.git"; - sha256 = "1v1jsgsdrhaz3ddbil09yqimnps3svgqbjvdk7hil4irpgqkfs98"; - rev = "1b88bf24aad15db1f59a00d201d609fa308157f7"; + sha256 = "10z1sirmiz29r2nx5dza1y1p3kp83wsq80pz4msxqmaykpyh5iaa"; + rev = "62b50ea460847dde5bc8e63d2f93360d9bfcae9d"; }; libraryHaskellDepends = [ base bytestring cereal containers deepseq QuickCheck safe text diff --git a/nixpkgs.json b/nixpkgs.json index 2656ecc..0c99a0c 100644 --- a/nixpkgs.json +++ b/nixpkgs.json @@ -1,6 +1,6 @@ { "url": "https://github.com/NixOS/nixpkgs.git", - "rev": "7ae9da426924537755ce9164fd5b5f81ce16a1c3", - "date": "2017-01-31T10:35:58-06:00", - "sha256": "1fcvc066c270dd2yfir8cpj0gcslsbvw7grnk2fayb06rkppjxrf" + "rev": "1849e695b00a54cda86cb75202240d949c10c7ce", + "date": "2017-03-30T18:32:09+02:00", + "sha256": "1fw9ryrz1qzbaxnjqqf91yxk1pb9hgci0z0pzw53f675almmv9q2" } diff --git a/release.nix b/release.nix index 4d6cce2..a9d0afe 100644 --- a/release.nix +++ b/release.nix @@ -62,7 +62,12 @@ let nixpkgs = import ./nixpkgs.nix; config = { packageOverrides = pkgs: rec { - cython = pkgs.buildPythonPackage rec { + protobuf3_2NoCheck = + pkgs.stdenv.lib.overrideDerivation + pkgs.pythonPackages.protobuf3_2 + (oldAttrs : {doCheck = false; doInstallCheck = false;}); + + cython = pkgs.pythonPackages.buildPythonPackage rec { name = "Cython-${version}"; version = "0.24.1"; @@ -106,8 +111,8 @@ let src = pkgs.fetchgit { url = "https://github.com/grpc/grpc.git"; - rev = "c204647295437b01337ad8e6c17c4296609c7a13"; - sha256 = "0ifg5acwcb0qyf5g5mrja8ab4x3f1fxdw80rkmhn3kyjkhjzm9ik"; + rev = "e2cfe9df79c4eda4e376222df064c4c65e616352"; + sha256 = "19ldbjlnbc287hkaylsigm8w9fai2bjdbfxk6315kl75cq54iprr"; }; preConfigure = '' @@ -127,7 +132,7 @@ let propagatedBuildInputs = [ cython pkgs.pythonPackages.futures - pkgs.pythonPackages.protobuf3_0 + protobuf3_2NoCheck pkgs.pythonPackages.enum34 ]; }; @@ -139,8 +144,8 @@ let src = pkgs.fetchgit { url = "https://github.com/grpc/grpc.git"; - rev = "c204647295437b01337ad8e6c17c4296609c7a13"; - sha256 = "0ifg5acwcb0qyf5g5mrja8ab4x3f1fxdw80rkmhn3kyjkhjzm9ik"; + rev = "e2cfe9df79c4eda4e376222df064c4c65e616352"; + sha256 = "19ldbjlnbc287hkaylsigm8w9fai2bjdbfxk6315kl75cq54iprr"; }; preConfigure = '' @@ -162,7 +167,7 @@ let propagatedBuildInputs = [ cython pkgs.pythonPackages.futures - pkgs.pythonPackages.protobuf3_0 + protobuf3_2NoCheck pkgs.pythonPackages.enum34 grpcio ]; diff --git a/src/Network/GRPC/LowLevel/Op.hs b/src/Network/GRPC/LowLevel/Op.hs index 9fae9a6..32244d0 100644 --- a/src/Network/GRPC/LowLevel/Op.hs +++ b/src/Network/GRPC/LowLevel/Op.hs @@ -12,19 +12,18 @@ import Control.Monad.Trans.Except import Data.ByteString (ByteString) import qualified Data.ByteString as B import Data.Maybe (catMaybes) -import Foreign.C.String (CString) import Foreign.C.Types (CInt) -import Foreign.Marshal.Alloc (free, malloc, - mallocBytes) +import Foreign.Marshal.Alloc (free, malloc) import Foreign.Ptr (Ptr, nullPtr) -import Foreign.Storable (peek, poke) +import Foreign.Storable (peek) import Network.GRPC.LowLevel.CompletionQueue import Network.GRPC.LowLevel.GRPC import qualified Network.GRPC.Unsafe as C (Call) import qualified Network.GRPC.Unsafe.ByteBuffer as C import qualified Network.GRPC.Unsafe.Metadata as C import qualified Network.GRPC.Unsafe.Op as C -import qualified Network.GRPC.Unsafe.Slice as C (Slice, freeSlice) +import qualified Network.GRPC.Unsafe.Slice as C +import Network.GRPC.Unsafe.Slice (Slice) -- | Sum describing all possible send and receive operations that can be batched -- and executed by gRPC. Usually these are processed in a handful of @@ -46,12 +45,10 @@ data OpContext = OpSendInitialMetadataContext C.MetadataKeyValPtr Int | OpSendMessageContext (C.ByteBuffer, C.Slice) | OpSendCloseFromClientContext - | OpSendStatusFromServerContext C.MetadataKeyValPtr Int C.StatusCode - B.ByteString + | OpSendStatusFromServerContext C.MetadataKeyValPtr Int C.StatusCode Slice | OpRecvInitialMetadataContext (Ptr C.MetadataArray) | OpRecvMessageContext (Ptr C.ByteBuffer) - | OpRecvStatusOnClientContext (Ptr C.MetadataArray) (Ptr C.StatusCode) - (Ptr CString) + | OpRecvStatusOnClientContext (Ptr C.MetadataArray) (Ptr C.StatusCode) Slice | OpRecvCloseOnServerContext (Ptr CInt) deriving Show @@ -72,7 +69,7 @@ createOpContext (OpSendStatusFromServer m code (StatusDetails str)) = uncurry OpSendStatusFromServerContext <$> C.createMetadata m <*> return code - <*> return str + <*> C.byteStringToSlice str createOpContext OpRecvInitialMetadata = fmap OpRecvInitialMetadataContext C.metadataArrayCreate createOpContext OpRecvMessage = @@ -80,10 +77,8 @@ createOpContext OpRecvMessage = createOpContext OpRecvStatusOnClient = do pmetadata <- C.metadataArrayCreate pstatus <- C.createStatusCodePtr - pstr <- malloc - cstring <- mallocBytes defaultStatusStringLen - poke pstr cstring - return $ OpRecvStatusOnClientContext pmetadata pstatus pstr + slice <- C.grpcSliceMalloc defaultStatusStringLen + return $ OpRecvStatusOnClientContext pmetadata pstatus slice createOpContext OpRecvCloseOnServer = fmap OpRecvCloseOnServerContext $ malloc @@ -97,14 +92,13 @@ setOpArray arr i (OpSendMessageContext (bb,_)) = setOpArray arr i OpSendCloseFromClientContext = C.opSendCloseClient arr i setOpArray arr i (OpSendStatusFromServerContext kvs l code details) = - B.useAsCString details $ \cstr -> - C.opSendStatusServer arr i l kvs code cstr + C.opSendStatusServer arr i l kvs code details setOpArray arr i (OpRecvInitialMetadataContext pmetadata) = C.opRecvInitialMetadata arr i pmetadata setOpArray arr i (OpRecvMessageContext pbb) = C.opRecvMessage arr i pbb -setOpArray arr i (OpRecvStatusOnClientContext pmetadata pstatus pstr) = do - C.opRecvStatusClient arr i pmetadata pstatus pstr defaultStatusStringLen +setOpArray arr i (OpRecvStatusOnClientContext pmetadata pstatus slice) = + C.opRecvStatusClient arr i pmetadata pstatus slice setOpArray arr i (OpRecvCloseOnServerContext pcancelled) = do C.opRecvCloseServer arr i pcancelled @@ -120,12 +114,10 @@ freeOpContext (OpRecvInitialMetadataContext metadata) = C.metadataArrayDestroy metadata freeOpContext (OpRecvMessageContext pbb) = C.destroyReceivingByteBuffer pbb -freeOpContext (OpRecvStatusOnClientContext metadata pcode pstr) = do +freeOpContext (OpRecvStatusOnClientContext metadata pcode slice) = do C.metadataArrayDestroy metadata C.destroyStatusCodePtr pcode - str <- peek pstr - free str - free pstr + C.freeSlice slice freeOpContext (OpRecvCloseOnServerContext pcancelled) = grpcDebug ("freeOpContext: freeing pcancelled: " ++ show pcancelled) >> free pcancelled @@ -176,8 +168,7 @@ resultFromOpContext (OpRecvStatusOnClientContext pmetadata pcode pstr) = do metadata <- peek pmetadata metadataMap <- C.getAllMetadataArray metadata code <- C.derefStatusCodePtr pcode - cstr <- peek pstr - statusInfo <- B.packCString cstr + statusInfo <- C.sliceToByteString pstr return $ Just $ OpRecvStatusOnClientResult metadataMap code statusInfo resultFromOpContext (OpRecvCloseOnServerContext pcancelled) = do grpcDebug "resultFromOpContext: OpRecvCloseOnServerContext" diff --git a/src/Network/GRPC/Unsafe.chs b/src/Network/GRPC/Unsafe.chs index 1ae4a5d..40280b2 100644 --- a/src/Network/GRPC/Unsafe.chs +++ b/src/Network/GRPC/Unsafe.chs @@ -6,7 +6,7 @@ module Network.GRPC.Unsafe where import Control.Exception (bracket) import Control.Monad -import Data.ByteString (ByteString, useAsCString, packCString) +import Data.ByteString (ByteString, useAsCString) import Foreign.C.String (CString, peekCString) import Foreign.Marshal.Alloc (free) @@ -20,10 +20,11 @@ import Network.GRPC.Unsafe.Constants {#import Network.GRPC.Unsafe.Op#} {#import Network.GRPC.Unsafe.Metadata#} {#import Network.GRPC.Unsafe.ChannelArgs#} +{#import Network.GRPC.Unsafe.Slice#} #include #include -#include +#include #include {#context prefix = "grpc" #} @@ -286,8 +287,8 @@ getPeerPeek cstr = do `CompletionQueue',unTag `Tag'} -> `CallError'#} -{#fun unsafe call_details_get_method as ^ {`CallDetails'} -> `ByteString' packCString* #} +{#fun unsafe call_details_get_method as ^ {`CallDetails'} -> `ByteString' sliceToByteString* #} -{#fun unsafe call_details_get_host as ^ {`CallDetails'} -> `ByteString' packCString* #} +{#fun unsafe call_details_get_host as ^ {`CallDetails'} -> `ByteString' sliceToByteString* #} {#fun call_details_get_deadline as ^ {`CallDetails'} -> `CTimeSpec' peek* #} diff --git a/src/Network/GRPC/Unsafe/ByteBuffer.chs b/src/Network/GRPC/Unsafe/ByteBuffer.chs index 28026ba..91b698f 100644 --- a/src/Network/GRPC/Unsafe/ByteBuffer.chs +++ b/src/Network/GRPC/Unsafe/ByteBuffer.chs @@ -3,9 +3,9 @@ module Network.GRPC.Unsafe.ByteBuffer where #include -#include +#include #include -#include +#include #include diff --git a/src/Network/GRPC/Unsafe/ChannelArgs.chs b/src/Network/GRPC/Unsafe/ChannelArgs.chs index d7b898d..f7cd1c2 100644 --- a/src/Network/GRPC/Unsafe/ChannelArgs.chs +++ b/src/Network/GRPC/Unsafe/ChannelArgs.chs @@ -9,7 +9,7 @@ import Foreign.Storable #include #include -#include +#include #include #include diff --git a/src/Network/GRPC/Unsafe/Metadata.chs b/src/Network/GRPC/Unsafe/Metadata.chs index 103faea..99276c3 100644 --- a/src/Network/GRPC/Unsafe/Metadata.chs +++ b/src/Network/GRPC/Unsafe/Metadata.chs @@ -4,11 +4,13 @@ module Network.GRPC.Unsafe.Metadata where +{#import Network.GRPC.Unsafe.Slice#} + import Control.Exception import Control.Monad import Data.Function (on) import Data.ByteString (ByteString, useAsCString, - useAsCStringLen, packCString, packCStringLen) + useAsCStringLen) import Data.List (sortBy, groupBy) import qualified Data.SortedList as SL import qualified Data.Map.Strict as M @@ -111,13 +113,10 @@ setMetadataKeyVal k v m i = useAsCStringLen v $ \(vStr, vLen) -> setMetadataKeyVal' k vStr vLen m i {#fun unsafe get_metadata_key as getMetadataKey' - {`MetadataKeyValPtr', `Int'} -> `CString'#} + {`MetadataKeyValPtr', `Int'} -> `Slice'#} {#fun unsafe get_metadata_val as getMetadataVal' - {`MetadataKeyValPtr', `Int'} -> `CString'#} - -{#fun unsafe get_metadata_val_len as getMetadataValLen - {`MetadataKeyValPtr', `Int'} -> `Int'#} + {`MetadataKeyValPtr', `Int'} -> `Slice'#} withMetadataArrayPtr :: (Ptr MetadataArray -> IO a) -> IO a withMetadataArrayPtr = bracket metadataArrayCreate metadataArrayDestroy @@ -126,12 +125,11 @@ withMetadataKeyValPtr :: Int -> (MetadataKeyValPtr -> IO a) -> IO a withMetadataKeyValPtr i f = bracket (metadataAlloc i) metadataFree f getMetadataKey :: MetadataKeyValPtr -> Int -> IO ByteString -getMetadataKey m = getMetadataKey' m >=> packCString +getMetadataKey m = getMetadataKey' m >=> sliceToByteString getMetadataVal :: MetadataKeyValPtr -> Int -> IO ByteString getMetadataVal m i = do vStr <- getMetadataVal' m i - vLen <- getMetadataValLen m i - packCStringLen (vStr, vLen) + sliceToByteString vStr createMetadata :: MetadataMap -> IO (MetadataKeyValPtr, Int) createMetadata m = do diff --git a/src/Network/GRPC/Unsafe/Op.chs b/src/Network/GRPC/Unsafe/Op.chs index 8724a4f..e7c82e2 100644 --- a/src/Network/GRPC/Unsafe/Op.chs +++ b/src/Network/GRPC/Unsafe/Op.chs @@ -2,8 +2,9 @@ module Network.GRPC.Unsafe.Op where +{#import Network.GRPC.Unsafe.Slice#} + import Control.Exception -import Foreign.C.String import Foreign.C.Types import Foreign.Ptr {#import Network.GRPC.Unsafe.ByteBuffer#} @@ -90,7 +91,7 @@ withOpArray n f = bracket (opArrayCreate n) (flip opArrayDestroy n) f -- this call. {#fun unsafe op_recv_status_client as ^ {`OpArray', `Int',id `Ptr MetadataArray', castPtr `Ptr StatusCode', - castPtr `Ptr CString', `Int'} + `Slice'} -> `()'#} -- | Creates an op of type GRPC_OP_RECV_CLOSE_ON_SERVER at the specified index @@ -104,5 +105,5 @@ withOpArray n f = bracket (opArrayCreate n) (flip opArrayDestroy n) f -- Metadata and string are copied when creating the op, and can be safely -- destroyed immediately after calling this function. {#fun unsafe op_send_status_server as ^ - {`OpArray', `Int', `Int', `MetadataKeyValPtr', `StatusCode', `CString'} + {`OpArray', `Int', `Int', `MetadataKeyValPtr', `StatusCode', `Slice'} -> `()'#} diff --git a/src/Network/GRPC/Unsafe/Slice.chs b/src/Network/GRPC/Unsafe/Slice.chs index e69744f..cb533a6 100644 --- a/src/Network/GRPC/Unsafe/Slice.chs +++ b/src/Network/GRPC/Unsafe/Slice.chs @@ -2,7 +2,7 @@ module Network.GRPC.Unsafe.Slice where -#include +#include #include import qualified Data.ByteString as B @@ -12,12 +12,12 @@ import Foreign.Ptr -- | A 'Slice' is gRPC's string type. We can easily convert these to and from -- ByteStrings. This type is a pointer to a C type. -{#pointer *gpr_slice as Slice newtype #} +{#pointer *grpc_slice as Slice newtype #} deriving instance Show Slice -- TODO: we could also represent this type as 'Ptr Slice', by doing this: --- newtype Slice = Slice {#type gpr_slice#} +-- newtype Slice = Slice {#type grpc_slice#} -- This would have no practical effect, but it would communicate intent more -- clearly by emphasizing that the type is indeed a pointer and that the data -- it is pointing to might change/be destroyed after running IO actions. To make @@ -27,13 +27,18 @@ deriving instance Show Slice -- maybe the established idiom is to do what c2hs does. -- | Get the length of a slice. -{#fun unsafe gpr_slice_length_ as ^ {`Slice'} -> `CULong'#} +{#fun unsafe grpc_slice_length_ as ^ {`Slice'} -> `CULong'#} + +-- | Slices allocated using this function must be freed by +-- 'freeSlice' +{#fun unsafe grpc_slice_malloc_ as ^ {`Int'} -> `Slice'#} -- | Returns a pointer to the start of the character array contained by the -- slice. -{#fun unsafe gpr_slice_start_ as ^ {`Slice'} -> `Ptr CChar' castPtr #} +{#fun unsafe grpc_slice_start_ as ^ {`Slice'} -> `Ptr CChar' castPtr #} -{#fun unsafe gpr_slice_from_copied_buffer_ as ^ {`CString', `Int'} -> `Slice'#} +-- | Slices must be freed using 'freeSlice'. +{#fun unsafe grpc_slice_from_copied_buffer_ as ^ {`CString', `Int'} -> `Slice'#} -- | Properly cleans up all memory used by a 'Slice'. Danger: the Slice should -- not be used after this function is called on it. @@ -46,10 +51,10 @@ deriving instance Show Slice -- getting and freeing the slice behind the scenes. sliceToByteString :: Slice -> IO B.ByteString sliceToByteString slice = do - len <- fmap fromIntegral $ gprSliceLength slice - str <- gprSliceStart slice + len <- fmap fromIntegral $ grpcSliceLength slice + str <- grpcSliceStart slice B.packCStringLen (str, len) -- | Copies a 'ByteString' to a 'Slice'. byteStringToSlice :: B.ByteString -> IO Slice -byteStringToSlice bs = B.useAsCStringLen bs $ uncurry gprSliceFromCopiedBuffer +byteStringToSlice bs = B.useAsCStringLen bs $ uncurry grpcSliceFromCopiedBuffer