blob: 07385129ef45c57440ee9547452164676acfc7aa [file] [log] [blame]
Craig Tiller6169d5f2016-03-31 07:46:18 -07001# Copyright 2015, Google Inc.
Masood Malekghassemi743c10c2015-06-16 18:05:27 -07002# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met:
7#
8# * Redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer.
10# * Redistributions in binary form must reproduce the above
11# copyright notice, this list of conditions and the following disclaimer
12# in the documentation and/or other materials provided with the
13# distribution.
14# * Neither the name of Google Inc. nor the names of its
15# contributors may be used to endorse or promote products derived from
16# this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
Ken Payson58c0f962016-09-16 13:43:13 -070030from libc.stdint cimport intptr_t
Masood Malekghassemi743c10c2015-06-16 18:05:27 -070031
Masood Malekghassemiaed42a82015-12-07 16:35:40 -080032class ConnectivityState:
Masood Malekghassemi116982e2015-12-11 15:53:38 -080033 idle = GRPC_CHANNEL_IDLE
34 connecting = GRPC_CHANNEL_CONNECTING
35 ready = GRPC_CHANNEL_READY
36 transient_failure = GRPC_CHANNEL_TRANSIENT_FAILURE
Nathaniel Manista5444bed2016-06-16 23:37:12 +000037 shutdown = GRPC_CHANNEL_SHUTDOWN
Masood Malekghassemiaed42a82015-12-07 16:35:40 -080038
39
40class ChannelArgKey:
Masood Malekghassemi116982e2015-12-11 15:53:38 -080041 enable_census = GRPC_ARG_ENABLE_CENSUS
42 max_concurrent_streams = GRPC_ARG_MAX_CONCURRENT_STREAMS
Mark D. Roth9a51cad2016-09-22 08:21:32 -070043 max_receive_message_length = GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH
44 max_send_message_length = GRPC_ARG_MAX_SEND_MESSAGE_LENGTH
Masood Malekghassemi116982e2015-12-11 15:53:38 -080045 http2_initial_sequence_number = GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER
46 default_authority = GRPC_ARG_DEFAULT_AUTHORITY
47 primary_user_agent_string = GRPC_ARG_PRIMARY_USER_AGENT_STRING
48 secondary_user_agent_string = GRPC_ARG_SECONDARY_USER_AGENT_STRING
49 ssl_target_name_override = GRPC_SSL_TARGET_NAME_OVERRIDE_ARG
Masood Malekghassemiaed42a82015-12-07 16:35:40 -080050
51
52class WriteFlag:
Masood Malekghassemi116982e2015-12-11 15:53:38 -080053 buffer_hint = GRPC_WRITE_BUFFER_HINT
54 no_compress = GRPC_WRITE_NO_COMPRESS
Masood Malekghassemiaed42a82015-12-07 16:35:40 -080055
56
Masood Malekghassemi743c10c2015-06-16 18:05:27 -070057class StatusCode:
Masood Malekghassemi116982e2015-12-11 15:53:38 -080058 ok = GRPC_STATUS_OK
59 cancelled = GRPC_STATUS_CANCELLED
60 unknown = GRPC_STATUS_UNKNOWN
61 invalid_argument = GRPC_STATUS_INVALID_ARGUMENT
62 deadline_exceeded = GRPC_STATUS_DEADLINE_EXCEEDED
63 not_found = GRPC_STATUS_NOT_FOUND
64 already_exists = GRPC_STATUS_ALREADY_EXISTS
65 permission_denied = GRPC_STATUS_PERMISSION_DENIED
66 unauthenticated = GRPC_STATUS_UNAUTHENTICATED
67 resource_exhausted = GRPC_STATUS_RESOURCE_EXHAUSTED
68 failed_precondition = GRPC_STATUS_FAILED_PRECONDITION
69 aborted = GRPC_STATUS_ABORTED
70 out_of_range = GRPC_STATUS_OUT_OF_RANGE
71 unimplemented = GRPC_STATUS_UNIMPLEMENTED
72 internal = GRPC_STATUS_INTERNAL
73 unavailable = GRPC_STATUS_UNAVAILABLE
74 data_loss = GRPC_STATUS_DATA_LOSS
Masood Malekghassemi743c10c2015-06-16 18:05:27 -070075
76
77class CallError:
Masood Malekghassemi116982e2015-12-11 15:53:38 -080078 ok = GRPC_CALL_OK
79 error = GRPC_CALL_ERROR
80 not_on_server = GRPC_CALL_ERROR_NOT_ON_SERVER
81 not_on_client = GRPC_CALL_ERROR_NOT_ON_CLIENT
82 already_accepted = GRPC_CALL_ERROR_ALREADY_ACCEPTED
83 already_invoked = GRPC_CALL_ERROR_ALREADY_INVOKED
84 not_invoked = GRPC_CALL_ERROR_NOT_INVOKED
85 already_finished = GRPC_CALL_ERROR_ALREADY_FINISHED
86 too_many_operations = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS
87 invalid_flags = GRPC_CALL_ERROR_INVALID_FLAGS
88 invalid_metadata = GRPC_CALL_ERROR_INVALID_METADATA
Masood Malekghassemi743c10c2015-06-16 18:05:27 -070089
90
91class CompletionType:
Masood Malekghassemi116982e2015-12-11 15:53:38 -080092 queue_shutdown = GRPC_QUEUE_SHUTDOWN
93 queue_timeout = GRPC_QUEUE_TIMEOUT
94 operation_complete = GRPC_OP_COMPLETE
Masood Malekghassemi743c10c2015-06-16 18:05:27 -070095
96
97class OperationType:
Masood Malekghassemi116982e2015-12-11 15:53:38 -080098 send_initial_metadata = GRPC_OP_SEND_INITIAL_METADATA
99 send_message = GRPC_OP_SEND_MESSAGE
100 send_close_from_client = GRPC_OP_SEND_CLOSE_FROM_CLIENT
101 send_status_from_server = GRPC_OP_SEND_STATUS_FROM_SERVER
102 receive_initial_metadata = GRPC_OP_RECV_INITIAL_METADATA
103 receive_message = GRPC_OP_RECV_MESSAGE
104 receive_status_on_client = GRPC_OP_RECV_STATUS_ON_CLIENT
105 receive_close_on_server = GRPC_OP_RECV_CLOSE_ON_SERVER
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700106
107
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700108class CompressionAlgorithm:
109 none = GRPC_COMPRESS_NONE
110 deflate = GRPC_COMPRESS_DEFLATE
111 gzip = GRPC_COMPRESS_GZIP
112
113
114class CompressionLevel:
115 none = GRPC_COMPRESS_LEVEL_NONE
116 low = GRPC_COMPRESS_LEVEL_LOW
117 medium = GRPC_COMPRESS_LEVEL_MED
118 high = GRPC_COMPRESS_LEVEL_HIGH
119
120
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700121cdef class Timespec:
122
123 def __cinit__(self, time):
124 if time is None:
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700125 with nogil:
126 self.c_time = gpr_now(GPR_CLOCK_REALTIME)
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800127 return
128 if isinstance(time, int):
129 time = float(time)
130 if isinstance(time, float):
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700131 if time == float("+inf"):
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700132 with nogil:
133 self.c_time = gpr_inf_future(GPR_CLOCK_REALTIME)
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700134 elif time == float("-inf"):
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700135 with nogil:
136 self.c_time = gpr_inf_past(GPR_CLOCK_REALTIME)
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700137 else:
138 self.c_time.seconds = time
139 self.c_time.nanoseconds = (time - float(self.c_time.seconds)) * 1e9
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800140 self.c_time.clock_type = GPR_CLOCK_REALTIME
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800141 elif isinstance(time, Timespec):
142 self.c_time = (<Timespec>time).c_time
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700143 else:
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800144 raise TypeError("expected time to be float, int, or Timespec, not {}"
145 .format(type(time)))
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700146
147 @property
148 def seconds(self):
Masood Malekghassemi5a65bcd2015-09-25 11:27:10 -0700149 # TODO(atash) ensure that everywhere a Timespec is created that it's
150 # converted to GPR_CLOCK_REALTIME then and not every time someone wants to
151 # read values off in Python.
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700152 cdef gpr_timespec real_time
153 with nogil:
154 real_time = (
155 gpr_convert_clock_type(self.c_time, GPR_CLOCK_REALTIME))
Masood Malekghassemi5a65bcd2015-09-25 11:27:10 -0700156 return real_time.seconds
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700157
158 @property
159 def nanoseconds(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800160 cdef gpr_timespec real_time = (
161 gpr_convert_clock_type(self.c_time, GPR_CLOCK_REALTIME))
Masood Malekghassemi5a65bcd2015-09-25 11:27:10 -0700162 return real_time.nanoseconds
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700163
164 def __float__(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800165 cdef gpr_timespec real_time = (
166 gpr_convert_clock_type(self.c_time, GPR_CLOCK_REALTIME))
Masood Malekghassemi5a65bcd2015-09-25 11:27:10 -0700167 return <double>real_time.seconds + <double>real_time.nanoseconds / 1e9
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700168
Masood Malekghassemi10509a22016-02-03 13:32:22 -0800169 @staticmethod
170 def infinite_future():
171 return Timespec(float("+inf"))
172
173 @staticmethod
174 def infinite_past():
175 return Timespec(float("-inf"))
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700176
Masood Malekghassemia66dad52017-01-20 18:13:26 -0500177 def __richcmp__(Timespec self not None, Timespec other not None, int op):
178 cdef gpr_timespec self_c_time = self.c_time
179 cdef gpr_timespec other_c_time = other.c_time
180 cdef int result = gpr_time_cmp(self_c_time, other_c_time)
181 if op == 0: # <
182 return result < 0
183 elif op == 2: # ==
184 return result == 0
185 elif op == 4: # >
186 return result > 0
187 elif op == 1: # <=
188 return result <= 0
189 elif op == 3: # !=
190 return result != 0
191 elif op == 5: # >=
192 return result >= 0
193 else:
194 raise ValueError('__richcmp__ `op` contract violated')
195
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700196
197cdef class CallDetails:
198
199 def __cinit__(self):
siddharthshukla9eedb4f2016-07-12 14:02:12 +0200200 grpc_init()
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700201 with nogil:
202 grpc_call_details_init(&self.c_details)
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700203
204 def __dealloc__(self):
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700205 with nogil:
206 grpc_call_details_destroy(&self.c_details)
siddharthshukla9eedb4f2016-07-12 14:02:12 +0200207 grpc_shutdown()
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700208
209 @property
210 def method(self):
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800211 if self.c_details.method != NULL:
212 return <bytes>self.c_details.method
213 else:
214 return None
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700215
216 @property
217 def host(self):
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800218 if self.c_details.host != NULL:
219 return <bytes>self.c_details.host
220 else:
221 return None
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700222
223 @property
224 def deadline(self):
225 timespec = Timespec(float("-inf"))
226 timespec.c_time = self.c_details.deadline
227 return timespec
228
229
230cdef class OperationTag:
231
232 def __cinit__(self, user_tag):
233 self.user_tag = user_tag
234 self.references = []
235
236
237cdef class Event:
238
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800239 def __cinit__(self, grpc_completion_type type, bint success,
240 object tag, Call operation_call,
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700241 CallDetails request_call_details,
242 Metadata request_metadata,
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800243 bint is_new_request,
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700244 Operations batch_operations):
245 self.type = type
246 self.success = success
247 self.tag = tag
248 self.operation_call = operation_call
249 self.request_call_details = request_call_details
250 self.request_metadata = request_metadata
251 self.batch_operations = batch_operations
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800252 self.is_new_request = is_new_request
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700253
254
255cdef class ByteBuffer:
256
Ken Payson6a654dd2016-06-27 14:12:08 -0700257 def __cinit__(self, bytes data):
siddharthshukla9eedb4f2016-07-12 14:02:12 +0200258 grpc_init()
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700259 if data is None:
260 self.c_byte_buffer = NULL
261 return
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700262
263 cdef char *c_data = data
Craig Tillerd41a4a72016-10-26 16:16:06 -0700264 cdef grpc_slice data_slice
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700265 cdef size_t data_length = len(data)
266 with nogil:
Craig Tillerd41a4a72016-10-26 16:16:06 -0700267 data_slice = grpc_slice_from_copied_buffer(c_data, data_length)
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700268 with nogil:
269 self.c_byte_buffer = grpc_raw_byte_buffer_create(
270 &data_slice, 1)
271 with nogil:
Craig Tillerd41a4a72016-10-26 16:16:06 -0700272 grpc_slice_unref(data_slice)
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700273
274 def bytes(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800275 cdef grpc_byte_buffer_reader reader
Craig Tillerd41a4a72016-10-26 16:16:06 -0700276 cdef grpc_slice data_slice
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700277 cdef size_t data_slice_length
278 cdef void *data_slice_pointer
Masood Malekghassemie38b9172016-07-01 13:48:06 -0700279 cdef bint reader_status
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700280 if self.c_byte_buffer != NULL:
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700281 with nogil:
Masood Malekghassemie38b9172016-07-01 13:48:06 -0700282 reader_status = grpc_byte_buffer_reader_init(
283 &reader, self.c_byte_buffer)
284 if not reader_status:
285 return None
alexce379382016-03-22 17:49:56 +0000286 result = bytearray()
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700287 with nogil:
288 while grpc_byte_buffer_reader_next(&reader, &data_slice):
Craig Tillerd41a4a72016-10-26 16:16:06 -0700289 data_slice_pointer = grpc_slice_start_ptr(data_slice)
290 data_slice_length = grpc_slice_length(data_slice)
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700291 with gil:
292 result += (<char *>data_slice_pointer)[:data_slice_length]
Craig Tillerd41a4a72016-10-26 16:16:06 -0700293 grpc_slice_unref(data_slice)
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700294 with nogil:
295 grpc_byte_buffer_reader_destroy(&reader)
alexce379382016-03-22 17:49:56 +0000296 return bytes(result)
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700297 else:
298 return None
299
300 def __len__(self):
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700301 cdef size_t result
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700302 if self.c_byte_buffer != NULL:
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700303 with nogil:
304 result = grpc_byte_buffer_length(self.c_byte_buffer)
305 return result
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700306 else:
307 return 0
308
309 def __str__(self):
310 return self.bytes()
311
312 def __dealloc__(self):
313 if self.c_byte_buffer != NULL:
Ken Payson136ea362016-07-11 10:38:39 -0700314 grpc_byte_buffer_destroy(self.c_byte_buffer)
siddharthshukla9eedb4f2016-07-12 14:02:12 +0200315 grpc_shutdown()
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700316
317
318cdef class SslPemKeyCertPair:
319
Ken Payson6a654dd2016-06-27 14:12:08 -0700320 def __cinit__(self, bytes private_key, bytes certificate_chain):
321 self.private_key = private_key
322 self.certificate_chain = certificate_chain
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700323 self.c_pair.private_key = self.private_key
324 self.c_pair.certificate_chain = self.certificate_chain
325
326
Ken Payson58c0f962016-09-16 13:43:13 -0700327
328cdef void* copy_ptr(void* ptr):
329 return ptr
330
331
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800332cdef void destroy_ptr(void* ptr):
Ken Payson58c0f962016-09-16 13:43:13 -0700333 pass
334
335
336cdef int compare_ptr(void* ptr1, void* ptr2):
337 if ptr1 < ptr2:
338 return -1
339 elif ptr1 > ptr2:
340 return 1
341 else:
342 return 0
343
344
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700345cdef class ChannelArg:
346
Ken Payson6a654dd2016-06-27 14:12:08 -0700347 def __cinit__(self, bytes key, value):
348 self.key = key
Ken Payson58c0f962016-09-16 13:43:13 -0700349 self.value = value
Ken Payson1efb6012016-06-08 13:06:44 -0700350 self.c_arg.key = self.key
351 if isinstance(value, int):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800352 self.c_arg.type = GRPC_ARG_INTEGER
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700353 self.c_arg.value.integer = self.value
Ken Payson6a654dd2016-06-27 14:12:08 -0700354 elif isinstance(value, bytes):
Ken Payson1efb6012016-06-08 13:06:44 -0700355 self.c_arg.type = GRPC_ARG_STRING
356 self.c_arg.value.string = self.value
Ken Payson58c0f962016-09-16 13:43:13 -0700357 elif hasattr(value, '__int__'):
358 # Pointer objects must override __int__() to return
359 # the underlying C address (Python ints are word size). The
360 # lifecycle of the pointer is fixed to the lifecycle of the
361 # python object wrapping it.
362 self.ptr_vtable.copy = &copy_ptr
363 self.ptr_vtable.destroy = &destroy_ptr
364 self.ptr_vtable.cmp = &compare_ptr
365 self.c_arg.type = GRPC_ARG_POINTER
366 self.c_arg.value.pointer.vtable = &self.ptr_vtable
367 self.c_arg.value.pointer.address = <void*>(<intptr_t>int(self.value))
Ken Payson6a654dd2016-06-27 14:12:08 -0700368 else:
Ken Payson58c0f962016-09-16 13:43:13 -0700369 # TODO Add supported pointer types to this message
Ken Payson6a654dd2016-06-27 14:12:08 -0700370 raise TypeError('Expected int or bytes, got {}'.format(type(value)))
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700371
372
373cdef class ChannelArgs:
374
375 def __cinit__(self, args):
siddharthshukla9eedb4f2016-07-12 14:02:12 +0200376 grpc_init()
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700377 self.args = list(args)
378 for arg in self.args:
379 if not isinstance(arg, ChannelArg):
380 raise TypeError("expected list of ChannelArg")
381 self.c_args.arguments_length = len(self.args)
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700382 with nogil:
383 self.c_args.arguments = <grpc_arg *>gpr_malloc(
384 self.c_args.arguments_length*sizeof(grpc_arg))
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700385 for i in range(self.c_args.arguments_length):
386 self.c_args.arguments[i] = (<ChannelArg>self.args[i]).c_arg
387
388 def __dealloc__(self):
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700389 with nogil:
390 gpr_free(self.c_args.arguments)
siddharthshukla9eedb4f2016-07-12 14:02:12 +0200391 grpc_shutdown()
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700392
393 def __len__(self):
394 # self.args is never stale; it's only updated from this file
395 return len(self.args)
396
397 def __getitem__(self, size_t i):
398 # self.args is never stale; it's only updated from this file
399 return self.args[i]
400
401
402cdef class Metadatum:
403
Ken Payson6a654dd2016-06-27 14:12:08 -0700404 def __cinit__(self, bytes key, bytes value):
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800405 self._key = key
406 self._value = value
407 self.c_metadata.key = self._key
408 self.c_metadata.value = self._value
409 self.c_metadata.value_length = len(self._value)
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700410
411 @property
412 def key(self):
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800413 return <bytes>self.c_metadata.key
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700414
415 @property
416 def value(self):
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800417 return <bytes>self.c_metadata.value[:self.c_metadata.value_length]
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700418
419 def __len__(self):
420 return 2
421
422 def __getitem__(self, size_t i):
423 if i == 0:
424 return self.key
425 elif i == 1:
426 return self.value
427 else:
428 raise IndexError("index must be 0 (key) or 1 (value)")
429
430 def __iter__(self):
431 return iter((self.key, self.value))
432
433
434cdef class _MetadataIterator:
435
436 cdef size_t i
437 cdef Metadata metadata
438
439 def __cinit__(self, Metadata metadata not None):
440 self.i = 0
441 self.metadata = metadata
442
Masood Malekghassemi5a65bcd2015-09-25 11:27:10 -0700443 def __iter__(self):
444 return self
445
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700446 def __next__(self):
447 if self.i < len(self.metadata):
448 result = self.metadata[self.i]
449 self.i = self.i + 1
450 return result
451 else:
Masood Malekghassemi5a65bcd2015-09-25 11:27:10 -0700452 raise StopIteration
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700453
454
455cdef class Metadata:
456
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800457 def __cinit__(self, metadata):
458 grpc_init()
459 self.metadata = list(metadata)
Masood Malekghassemic4d10df2017-01-18 17:47:52 -0800460 for metadatum in metadata:
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700461 if not isinstance(metadatum, Metadatum):
462 raise TypeError("expected list of Metadatum")
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800463 with nogil:
464 grpc_metadata_array_init(&self.c_metadata_array)
465 self.c_metadata_array.count = len(self.metadata)
466 self.c_metadata_array.capacity = len(self.metadata)
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700467 with nogil:
468 self.c_metadata_array.metadata = <grpc_metadata *>gpr_malloc(
469 self.c_metadata_array.count*sizeof(grpc_metadata)
470 )
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700471 for i in range(self.c_metadata_array.count):
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800472 self.c_metadata_array.metadata[i] = (
473 (<Metadatum>self.metadata[i]).c_metadata)
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700474
475 def __dealloc__(self):
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800476 # this frees the allocated memory for the grpc_metadata_array (although
477 # it'd be nice if that were documented somewhere...)
478 # TODO(atash): document this in the C core
479 grpc_metadata_array_destroy(&self.c_metadata_array)
480 grpc_shutdown()
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700481
482 def __len__(self):
483 return self.c_metadata_array.count
484
485 def __getitem__(self, size_t i):
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800486 return Metadatum(
487 key=<bytes>self.c_metadata_array.metadata[i].key,
488 value=<bytes>self.c_metadata_array.metadata[i].value[
489 :self.c_metadata_array.metadata[i].value_length])
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700490
491 def __iter__(self):
492 return _MetadataIterator(self)
493
494
495cdef class Operation:
496
497 def __cinit__(self):
siddharthshukla9eedb4f2016-07-12 14:02:12 +0200498 grpc_init()
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700499 self.references = []
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800500 self._received_status_details = NULL
501 self._received_status_details_capacity = 0
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700502 self.is_valid = False
503
504 @property
505 def type(self):
506 return self.c_op.type
507
508 @property
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700509 def flags(self):
510 return self.c_op.flags
511
512 @property
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800513 def has_status(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800514 return self.c_op.type == GRPC_OP_RECV_STATUS_ON_CLIENT
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800515
516 @property
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700517 def received_message(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800518 if self.c_op.type != GRPC_OP_RECV_MESSAGE:
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700519 raise TypeError("self must be an operation receiving a message")
520 return self._received_message
521
522 @property
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800523 def received_message_or_none(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800524 if self.c_op.type != GRPC_OP_RECV_MESSAGE:
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800525 return None
526 return self._received_message
527
528 @property
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700529 def received_metadata(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800530 if (self.c_op.type != GRPC_OP_RECV_INITIAL_METADATA and
531 self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT):
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700532 raise TypeError("self must be an operation receiving metadata")
533 return self._received_metadata
534
535 @property
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800536 def received_metadata_or_none(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800537 if (self.c_op.type != GRPC_OP_RECV_INITIAL_METADATA and
538 self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT):
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800539 return None
540 return self._received_metadata
541
542 @property
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700543 def received_status_code(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800544 if self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT:
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700545 raise TypeError("self must be an operation receiving a status code")
546 return self._received_status_code
547
548 @property
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800549 def received_status_code_or_none(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800550 if self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT:
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800551 return None
552 return self._received_status_code
553
554 @property
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700555 def received_status_details(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800556 if self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT:
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700557 raise TypeError("self must be an operation receiving status details")
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800558 if self._received_status_details:
559 return self._received_status_details
560 else:
561 return None
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700562
563 @property
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800564 def received_status_details_or_none(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800565 if self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT:
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800566 return None
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800567 if self._received_status_details:
568 return self._received_status_details
569 else:
570 return None
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800571
572 @property
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700573 def received_cancelled(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800574 if self.c_op.type != GRPC_OP_RECV_CLOSE_ON_SERVER:
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700575 raise TypeError("self must be an operation receiving cancellation "
576 "information")
577 return False if self._received_cancelled == 0 else True
578
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800579 @property
580 def received_cancelled_or_none(self):
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800581 if self.c_op.type != GRPC_OP_RECV_CLOSE_ON_SERVER:
Masood Malekghassemiaed42a82015-12-07 16:35:40 -0800582 return None
583 return False if self._received_cancelled == 0 else True
584
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700585 def __dealloc__(self):
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800586 # We *almost* don't need to do anything; most of the objects are handled by
587 # Python. The remaining one(s) are primitive fields filled in by GRPC core.
588 # This means that we need to clean up after receive_status_on_client.
589 if self.c_op.type == GRPC_OP_RECV_STATUS_ON_CLIENT:
590 gpr_free(self._received_status_details)
siddharthshukla9eedb4f2016-07-12 14:02:12 +0200591 grpc_shutdown()
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700592
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700593def operation_send_initial_metadata(Metadata metadata, int flags):
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700594 cdef Operation op = Operation()
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800595 op.c_op.type = GRPC_OP_SEND_INITIAL_METADATA
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700596 op.c_op.flags = flags
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700597 op.c_op.data.send_initial_metadata.count = metadata.c_metadata_array.count
598 op.c_op.data.send_initial_metadata.metadata = (
599 metadata.c_metadata_array.metadata)
600 op.references.append(metadata)
601 op.is_valid = True
602 return op
603
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700604def operation_send_message(data, int flags):
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700605 cdef Operation op = Operation()
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800606 op.c_op.type = GRPC_OP_SEND_MESSAGE
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700607 op.c_op.flags = flags
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700608 byte_buffer = ByteBuffer(data)
Mark D. Rothe6dd7732017-01-25 10:44:30 -0800609 op.c_op.data.send_message.send_message = byte_buffer.c_byte_buffer
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700610 op.references.append(byte_buffer)
611 op.is_valid = True
612 return op
613
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700614def operation_send_close_from_client(int flags):
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700615 cdef Operation op = Operation()
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800616 op.c_op.type = GRPC_OP_SEND_CLOSE_FROM_CLIENT
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700617 op.c_op.flags = flags
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700618 op.is_valid = True
619 return op
620
621def operation_send_status_from_server(
Ken Payson6a654dd2016-06-27 14:12:08 -0700622 Metadata metadata, grpc_status_code code, bytes details, int flags):
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700623 cdef Operation op = Operation()
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800624 op.c_op.type = GRPC_OP_SEND_STATUS_FROM_SERVER
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700625 op.c_op.flags = flags
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700626 op.c_op.data.send_status_from_server.trailing_metadata_count = (
627 metadata.c_metadata_array.count)
628 op.c_op.data.send_status_from_server.trailing_metadata = (
629 metadata.c_metadata_array.metadata)
630 op.c_op.data.send_status_from_server.status = code
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800631 op.c_op.data.send_status_from_server.status_details = details
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700632 op.references.append(metadata)
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800633 op.references.append(details)
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700634 op.is_valid = True
635 return op
636
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700637def operation_receive_initial_metadata(int flags):
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700638 cdef Operation op = Operation()
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800639 op.c_op.type = GRPC_OP_RECV_INITIAL_METADATA
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700640 op.c_op.flags = flags
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700641 op._received_metadata = Metadata([])
Mark D. Roth203de0f2017-01-26 08:04:15 -0800642 op.c_op.data.receive_initial_metadata.receive_initial_metadata = (
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700643 &op._received_metadata.c_metadata_array)
644 op.is_valid = True
645 return op
646
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700647def operation_receive_message(int flags):
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700648 cdef Operation op = Operation()
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800649 op.c_op.type = GRPC_OP_RECV_MESSAGE
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700650 op.c_op.flags = flags
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700651 op._received_message = ByteBuffer(None)
652 # n.b. the c_op.data.receive_message field needs to be deleted by us,
653 # anyway, so we just let that be handled by the ByteBuffer() we allocated
654 # the line before.
Mark D. Roth203de0f2017-01-26 08:04:15 -0800655 op.c_op.data.receive_message.receive_message = (
Mark D. Roth26e973e2017-01-25 15:02:08 -0800656 &op._received_message.c_byte_buffer)
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700657 op.is_valid = True
658 return op
659
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700660def operation_receive_status_on_client(int flags):
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700661 cdef Operation op = Operation()
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800662 op.c_op.type = GRPC_OP_RECV_STATUS_ON_CLIENT
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700663 op.c_op.flags = flags
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700664 op._received_metadata = Metadata([])
665 op.c_op.data.receive_status_on_client.trailing_metadata = (
666 &op._received_metadata.c_metadata_array)
667 op.c_op.data.receive_status_on_client.status = (
668 &op._received_status_code)
669 op.c_op.data.receive_status_on_client.status_details = (
Craig Tiller5e01e2a2017-01-20 18:11:52 -0800670 &op._received_status_details)
671 op.c_op.data.receive_status_on_client.status_details_capacity = (
672 &op._received_status_details_capacity)
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700673 op.is_valid = True
674 return op
675
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700676def operation_receive_close_on_server(int flags):
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700677 cdef Operation op = Operation()
Masood Malekghassemi116982e2015-12-11 15:53:38 -0800678 op.c_op.type = GRPC_OP_RECV_CLOSE_ON_SERVER
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700679 op.c_op.flags = flags
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700680 op.c_op.data.receive_close_on_server.cancelled = &op._received_cancelled
681 op.is_valid = True
682 return op
683
684
685cdef class _OperationsIterator:
686
687 cdef size_t i
688 cdef Operations operations
689
690 def __cinit__(self, Operations operations not None):
691 self.i = 0
692 self.operations = operations
693
Masood Malekghassemi5a65bcd2015-09-25 11:27:10 -0700694 def __iter__(self):
695 return self
696
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700697 def __next__(self):
698 if self.i < len(self.operations):
699 result = self.operations[self.i]
700 self.i = self.i + 1
701 return result
702 else:
Masood Malekghassemi5a65bcd2015-09-25 11:27:10 -0700703 raise StopIteration
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700704
705
706cdef class Operations:
707
708 def __cinit__(self, operations):
siddharthshukla9eedb4f2016-07-12 14:02:12 +0200709 grpc_init()
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700710 self.operations = list(operations) # normalize iterable
711 self.c_ops = NULL
712 self.c_nops = 0
713 for operation in self.operations:
714 if not isinstance(operation, Operation):
715 raise TypeError("expected operations to be iterable of Operation")
716 self.c_nops = len(self.operations)
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700717 with nogil:
718 self.c_ops = <grpc_op *>gpr_malloc(sizeof(grpc_op)*self.c_nops)
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700719 for i in range(self.c_nops):
720 self.c_ops[i] = (<Operation>(self.operations[i])).c_op
721
722 def __len__(self):
723 return self.c_nops
724
725 def __getitem__(self, size_t i):
726 # self.operations is never stale; it's only updated from this file
727 return self.operations[i]
728
729 def __dealloc__(self):
Masood Malekghassemi3d2d5b92016-03-15 15:54:25 -0700730 with nogil:
731 gpr_free(self.c_ops)
siddharthshukla9eedb4f2016-07-12 14:02:12 +0200732 grpc_shutdown()
Masood Malekghassemi743c10c2015-06-16 18:05:27 -0700733
734 def __iter__(self):
735 return _OperationsIterator(self)
736
Masood Malekghassemi93cc06a2016-05-13 14:25:35 -0700737
738cdef class CompressionOptions:
739
740 def __cinit__(self):
741 with nogil:
742 grpc_compression_options_init(&self.c_options)
743
744 def enable_algorithm(self, grpc_compression_algorithm algorithm):
745 with nogil:
746 grpc_compression_options_enable_algorithm(&self.c_options, algorithm)
747
748 def disable_algorithm(self, grpc_compression_algorithm algorithm):
749 with nogil:
750 grpc_compression_options_disable_algorithm(&self.c_options, algorithm)
751
752 def is_algorithm_enabled(self, grpc_compression_algorithm algorithm):
753 cdef int result
754 with nogil:
755 result = grpc_compression_options_is_algorithm_enabled(
756 &self.c_options, algorithm)
757 return result
758
759 def to_channel_arg(self):
760 return ChannelArg(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET,
761 self.c_options.enabled_algorithms_bitset)
762
763
764def compression_algorithm_name(grpc_compression_algorithm algorithm):
765 cdef char* name
766 with nogil:
767 grpc_compression_algorithm_name(algorithm, &name)
768 # Let Cython do the right thing with string casting
769 return name