Browse Source

Rework all slice-based accessors to return a copied string.

This is conservative and keeps the Swift-to-C interface
as simple as possible.
Tim Burks 8 years ago
parent
commit
f1023f7781

+ 6 - 4
Sources/CgRPC/include/CgRPC.h

@@ -109,6 +109,9 @@ void grpc_init();
 void grpc_shutdown();
 const char *grpc_version_string();
 
+// helper
+void cgrpc_free_copied_string(const char *string);
+
 // channel support
 cgrpc_channel *cgrpc_channel_create(const char *address);
 cgrpc_channel *cgrpc_channel_create_secure(const char *address,
@@ -147,8 +150,8 @@ cgrpc_completion_queue *cgrpc_handler_get_completion_queue(cgrpc_handler *h);
 grpc_call_error cgrpc_handler_request_call(cgrpc_handler *h,
                                            cgrpc_metadata_array *metadata,
                                            long tag);
-const char *cgrpc_handler_host(cgrpc_handler *h);
-const char *cgrpc_handler_method(cgrpc_handler *h);
+const char *cgrpc_handler_copy_host(cgrpc_handler *h);
+const char *cgrpc_handler_copy_method(cgrpc_handler *h);
 const char *cgrpc_handler_call_peer(cgrpc_handler *h);
 
 // call support
@@ -167,7 +170,6 @@ void cgrpc_metadata_array_destroy(cgrpc_metadata_array *array);
 size_t cgrpc_metadata_array_get_count(cgrpc_metadata_array *array);
 const char *cgrpc_metadata_array_copy_key_at_index(cgrpc_metadata_array *array, size_t index);
 const char *cgrpc_metadata_array_copy_value_at_index(cgrpc_metadata_array *array, size_t index);
-void cgrpc_metadata_free_copied_string(const char *string);
 void cgrpc_metadata_array_move_metadata(cgrpc_metadata_array *dest, cgrpc_metadata_array *src);
 void cgrpc_metadata_array_append_metadata(cgrpc_metadata_array *metadata, const char *key, const char *value);
 
@@ -234,7 +236,7 @@ cgrpc_metadata_array *cgrpc_observer_recv_status_on_client_get_metadata
 long cgrpc_observer_recv_status_on_client_get_status
 (cgrpc_observer_recv_status_on_client *observer);
 
-const char *cgrpc_observer_recv_status_on_client_get_status_details
+const char *cgrpc_observer_recv_status_on_client_copy_status_details
 (cgrpc_observer_recv_status_on_client *observer);
 
 // GRPC_OP_RECV_CLOSE_ON_SERVER

+ 6 - 4
Sources/CgRPC/shim/cgrpc.h

@@ -109,6 +109,9 @@ void grpc_init();
 void grpc_shutdown();
 const char *grpc_version_string();
 
+// helper
+void cgrpc_free_copied_string(const char *string);
+
 // channel support
 cgrpc_channel *cgrpc_channel_create(const char *address);
 cgrpc_channel *cgrpc_channel_create_secure(const char *address,
@@ -147,8 +150,8 @@ cgrpc_completion_queue *cgrpc_handler_get_completion_queue(cgrpc_handler *h);
 grpc_call_error cgrpc_handler_request_call(cgrpc_handler *h,
                                            cgrpc_metadata_array *metadata,
                                            long tag);
-const char *cgrpc_handler_host(cgrpc_handler *h);
-const char *cgrpc_handler_method(cgrpc_handler *h);
+const char *cgrpc_handler_copy_host(cgrpc_handler *h);
+const char *cgrpc_handler_copy_method(cgrpc_handler *h);
 const char *cgrpc_handler_call_peer(cgrpc_handler *h);
 
 // call support
@@ -167,7 +170,6 @@ void cgrpc_metadata_array_destroy(cgrpc_metadata_array *array);
 size_t cgrpc_metadata_array_get_count(cgrpc_metadata_array *array);
 const char *cgrpc_metadata_array_copy_key_at_index(cgrpc_metadata_array *array, size_t index);
 const char *cgrpc_metadata_array_copy_value_at_index(cgrpc_metadata_array *array, size_t index);
-void cgrpc_metadata_free_copied_string(const char *string);
 void cgrpc_metadata_array_move_metadata(cgrpc_metadata_array *dest, cgrpc_metadata_array *src);
 void cgrpc_metadata_array_append_metadata(cgrpc_metadata_array *metadata, const char *key, const char *value);
 
@@ -234,7 +236,7 @@ cgrpc_metadata_array *cgrpc_observer_recv_status_on_client_get_metadata
 long cgrpc_observer_recv_status_on_client_get_status
 (cgrpc_observer_recv_status_on_client *observer);
 
-const char *cgrpc_observer_recv_status_on_client_get_status_details
+const char *cgrpc_observer_recv_status_on_client_copy_status_details
 (cgrpc_observer_recv_status_on_client *observer);
 
 // GRPC_OP_RECV_CLOSE_ON_SERVER

+ 12 - 4
Sources/CgRPC/shim/handler.c

@@ -43,12 +43,20 @@ void cgrpc_handler_destroy(cgrpc_handler *h) {
   free(h);
 }
 
-const char *cgrpc_handler_host(cgrpc_handler *h) {
-  return (const char *) GRPC_SLICE_START_PTR(h->call_details.host);
+const char *cgrpc_handler_copy_host(cgrpc_handler *h) {
+  int length = GRPC_SLICE_LENGTH(h->call_details.host);
+  char *str = (char *) malloc(length + 1);
+  memcpy(str, GRPC_SLICE_START_PTR(h->call_details.host), length);
+  str[length] = 0;
+  return str;
 }
 
-const char *cgrpc_handler_method(cgrpc_handler *h) {
-  return (const char *) GRPC_SLICE_START_PTR(h->call_details.method);
+const char *cgrpc_handler_copy_method(cgrpc_handler *h) {
+  int length = GRPC_SLICE_LENGTH(h->call_details.method);
+  char *str = (char *) malloc(length + 1);
+  memcpy(str, GRPC_SLICE_START_PTR(h->call_details.method), length);
+  str[length] = 0;
+  return str;
 }
 
 const char *cgrpc_handler_call_peer(cgrpc_handler *h) {

+ 4 - 0
Sources/CgRPC/shim/internal.c

@@ -25,3 +25,7 @@ gpr_timespec cgrpc_deadline_in_seconds_from_now(float seconds) {
   return gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
                       gpr_time_from_millis((int64_t)(1e3 * seconds), GPR_TIMESPAN));
 }
+
+void cgrpc_free_copied_string(const char *string) {
+	free(string);
+}

+ 0 - 4
Sources/CgRPC/shim/metadata.c

@@ -49,10 +49,6 @@ const char *cgrpc_metadata_array_copy_value_at_index(cgrpc_metadata_array *array
   return str;
 }
 
-void cgrpc_metadata_free_copied_string(const char *string) {
-	free(string);
-}
-
 int cgrpc_metadata_array_get_value_length_at_index(cgrpc_metadata_array *array, size_t index) {
   return GRPC_SLICE_LENGTH(array->metadata[index].value);
   /*

+ 6 - 2
Sources/CgRPC/shim/observers.c

@@ -235,8 +235,12 @@ long cgrpc_observer_recv_status_on_client_get_status(cgrpc_observer_recv_status_
   return observer->server_status;
 }
 
-const char *cgrpc_observer_recv_status_on_client_get_status_details(cgrpc_observer_recv_status_on_client *observer) {
-  return (const char *) GRPC_SLICE_START_PTR(observer->server_details);
+const char *cgrpc_observer_recv_status_on_client_copy_status_details(cgrpc_observer_recv_status_on_client *observer) {
+  int length = GRPC_SLICE_LENGTH(observer->server_details);
+  char *str = (char *) malloc(length + 1);
+  memcpy(str, GRPC_SLICE_START_PTR(observer->server_details), length);
+  str[length] = 0;
+  return str;
 }
 
 int cgrpc_observer_recv_close_on_server_get_was_cancelled(cgrpc_observer_recv_close_on_server *observer) {

+ 16 - 4
Sources/gRPC/Handler.swift

@@ -38,14 +38,26 @@ public class Handler {
 
   /// The host name sent with the request
   public lazy var host: String = {
-    return String(cString:cgrpc_handler_host(self.underlyingHandler),
-                  encoding:.utf8)!;
+    if let string = cgrpc_handler_copy_host(self.underlyingHandler) {
+      defer {
+        cgrpc_free_copied_string(string);
+      }
+      return String(cString:string, encoding:.utf8)!;
+    } else {
+      return ""
+    }
   }()
 
   /// The method name sent with the request
   public lazy var method: String = {
-    return String(cString:cgrpc_handler_method(self.underlyingHandler),
-                  encoding:.utf8)!;
+    if let string = cgrpc_handler_copy_method(self.underlyingHandler) {
+      defer {
+        cgrpc_free_copied_string(string);
+      }
+      return String(cString:string, encoding:.utf8)!;
+    } else {
+      return ""
+    }
   }()
 
   /// The caller address associated with the request

+ 2 - 2
Sources/gRPC/Metadata.swift

@@ -73,7 +73,7 @@ public class Metadata : CustomStringConvertible, NSCopying {
   public func key(_ index: Int) -> (String) {
     if let string = cgrpc_metadata_array_copy_key_at_index(underlyingArray, index) {
       defer {
-        cgrpc_metadata_free_copied_string(string)
+        cgrpc_free_copied_string(string)
       }
       if let key = String(cString:string, encoding:String.Encoding.utf8) {
         return key
@@ -85,7 +85,7 @@ public class Metadata : CustomStringConvertible, NSCopying {
   public func value(_ index: Int) -> (String) {
     if let string = cgrpc_metadata_array_copy_value_at_index(underlyingArray, index) {
       defer {
-        cgrpc_metadata_free_copied_string(string)
+        cgrpc_free_copied_string(string)
       }
       if let value = String(cString:string, encoding:String.Encoding.utf8)  {
         return value

+ 8 - 2
Sources/gRPC/OperationGroup.swift

@@ -165,8 +165,14 @@ internal class OperationGroup {
     for (i, operation) in operations.enumerated() {
       switch (operation) {
       case .receiveStatusOnClient:
-        return String(cString:cgrpc_observer_recv_status_on_client_get_status_details(underlyingObservers[i]),
-                      encoding:String.Encoding.utf8)!
+        if let string = cgrpc_observer_recv_status_on_client_copy_status_details(underlyingObservers[i]) {
+          defer {
+            cgrpc_free_copied_string(string);
+          }
+          return String(cString:string, encoding:String.Encoding.utf8)!
+        } else {
+          return nil
+        }
       default:
         continue
       }

+ 2 - 2
Tests/gRPCTests/GRPCTests.swift

@@ -62,7 +62,7 @@
   }
  }
 
- let address = "localhost:8998"
+ let address = "localhost:8081"
  let host = "foo.test.google.fr"
  let clientText = "hello, server!"
  let serverText = "hello, client!"
@@ -78,7 +78,7 @@
   ["0": "zero",
    "1": "one",
    "2": "two"]
- let steps = 1
+ let steps = 10
  let hello = "/hello"
  let statusCode = 0
  let statusMessage = "OK"