diff --git a/client.cc b/client.cc index 6a933c8..a80c0fb 100644 --- a/client.cc +++ b/client.cc @@ -63,6 +63,14 @@ void* new_tag(int num) { return new int(num); } +grpc_metadata_array* create_new_grpc_metadata_array_with_data(grpc_metadata* metadata, size_t count) { + grpc_metadata_array* arr = new grpc_metadata_array(); + grpc_metadata_array_init(arr); + arr->count = count; + if (count > 0) arr->metadata = metadata; + return arr; +} + grpc_metadata_array* create_new_grpc_metadata_array() { grpc_metadata_array* arr = new grpc_metadata_array(); grpc_metadata_array_init(arr); @@ -118,6 +126,19 @@ void grpc_ops_free(grpc_op* ops, int size) { free(ops); } +grpc_metadata* lisp_make_grpc_metadata(const char* key, + const char* value) { + grpc_slice slice_key = grpc_slice_from_copied_string(key); + grpc_slice slice_value = grpc_slice_from_copied_string(value); + + grpc_metadata* metadata = new grpc_metadata; + *metadata = grpc_metadata { + slice_key, + slice_value, + }; + return metadata; +} + // Takes in a preallocated grpc_op array. // Stores the given metadata, flags, and count for the // GRPC_OP_SEND_INITIAL_METADATA operation. diff --git a/client.lisp b/client.lisp index d81431e..b320805 100644 --- a/client.lisp +++ b/client.lisp @@ -155,7 +155,7 @@ RECEIVE_STATUS_ON_CLIENT op and RECEIVE-STATUS-ON-CLIENT-INDEX in the ops." (defconstant +num-ops-for-starting-call+ 3) -(defun start-grpc-call (channel service-method-name) +(defun start-grpc-call (channel service-method-name client-context) "Start a grpc call. Requires a pointer to a grpc CHANNEL object, and a SERVICE-METHOD-NAME string to direct the call to." (let* ((num-ops-for-sending-message +num-ops-for-starting-call+) @@ -171,9 +171,10 @@ string to direct the call to." (make-call :c-call c-call :c-tag tag :c-ops ops - :ops-plist ops-plist))) + :ops-plist ops-plist + :context client-context))) -(defun grpc-call (channel service-method-name bytes-to-send +(defun grpc-call (channel service-method-name bytes-to-send client-context server-stream client-stream) "Uses CHANNEL to call SERVICE-METHOD-NAME on the server with BYTES-TO-SEND as the arguement to the method and returns the response @@ -182,7 +183,7 @@ BYTES-TO-SEND should be a list of byte-vectors each containing a message to send in a single call to the server. In the case of a server or bidirectional call we return a list a list of byte vectors each being a response from the server, otherwise it's a single byte vector list containing a single response." - (let* ((call (start-grpc-call channel service-method-name))) + (let* ((call (start-grpc-call channel service-method-name client-context))) (unwind-protect (progn (if client-stream diff --git a/shared.lisp b/shared.lisp index 5cca9cd..fde0076 100644 --- a/shared.lisp +++ b/shared.lisp @@ -418,18 +418,39 @@ i of grpc_byte_buffer BUFFER." these operation guide the interaction between the client and server." (num-ops :int)) +(defun make-metadata (metadata) + "Sets OP[INDEX] to a Send Initial Metadata operation by adding metadata +METADATA, the count of metadata COUNT, and the flag FLAG." + (let* ((arr-size (length metadata)) + (metadata + (loop for (key value) in metadata + collect + (cffi:foreign-funcall "lisp_make_grpc_metadata" + :string key + :string value))) + (l-arr (make-array (list arr-size) + :initial-contents metadata))) + (cffi:with-foreign-array (arr l-arr (list :array :int64 arr-size)) + (cffi:foreign-funcall "create_new_grpc_metadata_array_with_data" + :pointer arr + :size arr-size)))) + (defun make-send-metadata-op (op metadata &key count flag - index) + index) "Sets OP[INDEX] to a Send Initial Metadata operation by adding metadata METADATA, the count of metadata COUNT, and the flag FLAG." - (cffi:foreign-funcall "lisp_grpc_make_send_metadata_op" - :pointer op - :int index - :pointer metadata - :int count - :int (convert-metadata-flag-to-integer flag) - :void)) + (let ((metadata-ptr (if metadata + (make-metadata metadata) + (cffi:null-pointer)))) + + (cffi:foreign-funcall "lisp_grpc_make_send_metadata_op" + :pointer op + :int index + :pointer metadata-ptr + :int count + :int (convert-metadata-flag-to-integer flag) + :void)) (defun make-send-message-op (op message &key index) "Sets OP[INDEX] to a 'Send Message' operation that sends MESSAGE @@ -509,7 +530,7 @@ want. Returns a plist containing keys being the op type and values being the ind (setf (getf ops-plist message-type) (incf cur-index)))) (when send-metadata - (make-send-metadata-op ops (cffi:null-pointer) + (make-send-metadata-op ops send-metadata :count 0 :flag 0 :index (next-marker :send-metadata))) (when send-message (make-send-message-op ops send-message :index (next-marker :send-message))) @@ -585,9 +606,12 @@ macros and only call once." (method-name "" :type string) ;; This is a plist where the key is a keyword for a type of op ;; and the value is the index of that op in an op-array. - (ops-plist nil :type list)) + (ops-plist nil :type list) + (context nil :type (or null client-context server-context))) -;; Shared call functions +(defstruct context + (deadline -1 :type integer) + (metadata nil :type list)) (defun receive-message (call) "Receive a message from the client for a CALL." @@ -628,7 +652,12 @@ macros and only call once." (ops (create-new-grpc-ops num-ops)) (grpc-slice (convert-bytes-to-grpc-byte-buffer bytes-to-send)) - (ops-plist (prepare-ops ops :send-message grpc-slice)) + (context (call-context call)) + (ops-plist (prepare-ops + ops + :send-message grpc-slice + :send-metadata (and context + (context-metadata context)))) (call-code (call-start-batch c-call ops num-ops tag))) (declare (ignore ops-plist)) (unless (eql call-code :grpc-call-ok) diff --git a/tests/integration-test.lisp b/tests/integration-test.lisp index 445931c..627e3c3 100644 --- a/tests/integration-test.lisp +++ b/tests/integration-test.lisp @@ -66,9 +66,13 @@ Parameters (grpc:with-insecure-channel (channel (concatenate 'string hostname ":" (write-to-string port-number))) - (let* ((message "Hello World") + (let* ((client-context + (grpc::make-context :metadata '(("my" "name") + ("is" "Lyra")))) + (message "Hello World") (response (grpc:grpc-call channel method-name (flexi-streams:string-to-octets message) + client-context nil nil)) (actual-client-response (flexi-streams:octets-to-string (car response))))