def decode_response(self, response, data): data_len = len(data) # decode the header length if we have enough if data_len < len_struct_size: return None, None header_len = unpack_length(data)[0] if data_len < header_len + len_struct_size: return None, None # decode the payload length and see if we have enough body_len = unpack_length(data, header_len)[0] if data_len < header_len + body_len: return None, header_len + body_len - data_len # we have enough data, decode it all try: offset, response.header = bson.codec.decode_document(data, 0) offset, response.reply = bson.codec.decode_document(data, offset) # unpack primitive values # FIXME(msolomon) remove this hack response.reply = response.reply.get(WRAPPED_FIELD, response.reply) # Return header_len + body_len instead of the offsets returned # by the library, should be the same. return header_len + body_len, None except Exception as e: raise gorpc.GoRpcError('decode error', e)
def decode_response(self, response, data): data_len = len(data) # decode the header length if we have enough if data_len < len_struct_size: return None, None header_len = unpack_length(data)[0] if data_len < header_len + len_struct_size: return None, None # decode the payload length and see if we have enough body_len = unpack_length(data, header_len)[0] if data_len < header_len + body_len: return None, header_len + body_len - data_len # we have enough data, decode it all try: offset, response.header = decode_document(data, 0) offset, response.reply = decode_document(data, offset) # unpack primitive values # FIXME(msolomon) remove this hack response.reply = response.reply.get(WRAPPED_FIELD, response.reply) # the pure-python bson library returns the offset in the buffer # the cbson library returns -1 if everything was read # so we cannot use the 'offset' variable. Instead use # header_len + body_len for the complete length read return header_len + body_len, None except Exception as e: raise gorpc.GoRpcError('decode error', e)
def encode_request(self, req): try: if not isinstance(req.body, dict): # hack to handle simple values body = {WRAPPED_FIELD: req.body} else: body = req.body return bson.dumps(req.header) + bson.dumps(body) except Exception as e: raise gorpc.GoRpcError('encode error', e)
def __drain_conn_after_streaming_app_error(self): """Drains the connection of all incoming streaming packets (ignoring them). This is necessary for streaming calls which return application errors inside the RPC response (instead of through the usual GoRPC error return). This is because GoRPC always expects the last packet to be an error; either the usual GoRPC application error return, or a special "end-of-stream" error. If an application error is returned with the RPC response, there will still be at least one more packet coming, as GoRPC has not seen anything that it considers to be an error. If the connection is not drained of this last packet, future reads from the wire will be off by one and will return errors. """ next_result = self.client.stream_next() if next_result is not None: self.client.close() raise gorpc.GoRpcError( "Connection should only have one packet remaining" " after streaming app error in RPC response.")