Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ability to send metadata from the client #72

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down
9 changes: 5 additions & 4 deletions client.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -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+)
Expand All @@ -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<list of byte arrays>
Expand All @@ -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
Expand Down
53 changes: 41 additions & 12 deletions shared.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)))
Expand Down Expand Up @@ -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."
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 5 additions & 1 deletion tests/integration-test.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -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))))
Expand Down
Loading