def connect(address=DEFAULT_ADDRESS, rpc_port=DEFAULT_RPC_PORT, stream_port=DEFAULT_STREAM_PORT, name=None): """ Connect to a kRPC server on the specified IP address and port numbers. If stream_port is None, does not connect to the stream server. Optionally give the kRPC server the supplied name to identify the client (up to 32 bytes of UTF-8 encoded text). """ assert rpc_port != stream_port # Connect to RPC server rpc_connection = Connection(address, rpc_port) rpc_connection.connect(retries=10, timeout=0.1) rpc_connection.send(Encoder.RPC_HELLO_MESSAGE) rpc_connection.send(Encoder.client_name(name)) client_identifier = rpc_connection.receive(Decoder.GUID_LENGTH) # Connect to Stream server if stream_port is not None: stream_connection = Connection(address, stream_port) stream_connection.connect(retries=10, timeout=0.1) stream_connection.send(Encoder.STREAM_HELLO_MESSAGE) stream_connection.send(client_identifier) ok_message = stream_connection.receive(Decoder.OK_LENGTH) assert ok_message == Decoder.OK_MESSAGE else: stream_connection = None return Client(rpc_connection, stream_connection)
def test_encode_message_delimited(self): request = krpc.schema.KRPC.Request() request.service = 'ServiceName' request.procedure = 'ProcedureName' data = Encoder.encode_delimited(request, self.types.as_type('KRPC.Request')) expected = '1c'+'0a0b536572766963654e616d65120d50726f6365647572654e616d65' self.assertEqual(expected, hexlify(data))
def test_encode_message(self): call = self.types.procedure_call_type.python_type() call.service = 'ServiceName' call.procedure = 'ProcedureName' data = Encoder.encode(call, self.types.procedure_call_type) expected = '0a0b536572766963654e616d65120d50726f6365647572654e616d65' self.assertEqual(expected, hexlify(data))
def test_encode_class(self): typ = self.types.as_type('Class(ServiceName.ClassName)') class_type = typ.python_type self.assertTrue(issubclass(class_type, ClassBase)) value = class_type(300) self.assertEqual(300, value._object_id) data = Encoder.encode(value, typ) self.assertEqual('ac02', hexlify(data))
def encode_argument(i, value): typ = param_types[i] if type(value) != typ.python_type: # Try coercing to the correct type try: value = self._types.coerce_to(value, typ) except ValueError: raise TypeError('%s.%s() argument %d must be a %s, got a %s' % \ (service, procedure, i, typ.python_type, type(value))) return Encoder.encode(value, typ)
def _build_request(self, service, procedure, args, param_names, param_types, return_type): #pylint: disable=unused-argument """ Build a KRPC.Request object """ request = krpc.schema.KRPC.Request(service=service, procedure=procedure) for i, (value, typ) in enumerate(itertools.izip(args, param_types)): if isinstance(value, DefaultArgument): continue if not isinstance(value, typ.python_type): try: value = self._types.coerce_to(value, typ) except ValueError: raise TypeError('%s.%s() argument %d must be a %s, got a %s' % \ (service, procedure, i, typ.python_type, type(value))) request.arguments.add(position=i, value=Encoder.encode(value, typ)) return request
def _build_call(self, service, procedure, args, param_names, param_types, return_type): # pylint: disable=unused-argument """ Build a KRPC.ProcedureCall object """ call = KRPC.ProcedureCall() call.service = service call.procedure = procedure for i, (value, typ) in enumerate(zip(args, param_types)): if isinstance(value, DefaultArgument): continue if not isinstance(value, typ.python_type): try: value = self._types.coerce_to(value, typ) except ValueError: raise TypeError( '%s.%s() argument %d must be a %s, got a %s' % (service, procedure, i, typ.python_type, type(value))) call.arguments.add(position=i, value=Encoder.encode(value, typ)) return call
def test_encode_value_delimited(self): data = Encoder.encode_delimited(300, self.types.as_type('int32')) self.assertEqual('02'+'ac02', hexlify(data))
def test_encode_value(self): data = Encoder.encode(300, self.types.uint32_type) self.assertEqual('ac02', hexlify(data))
def test_encode_unicode_string(self): data = Encoder.encode(b'\xe2\x84\xa2'.decode('utf-8'), self.types.as_type('string')) self.assertEqual('03e284a2', hexlify(data))
def test_long_client_name(self): message = Encoder.client_name('a'*33) self.assertEqual (32, len(message)) self.assertEqual ('61'*32, hexlify(message))
def _run_test_encode_value(self, typ, cases): for decoded, encoded in cases: data = Encoder.encode(decoded, self.types.as_type(typ)) self.assertEqual(encoded, hexlify(data))
def test_encode_class_none(self): typ = self.types.as_type('Class(ServiceName.ClassName)') value = None data = Encoder.encode(value, typ) self.assertEqual('00', hexlify(data))
def _send_request(self, request): """ Send a KRPC.Request object to the server """ data = Encoder.encode_delimited(request, self._request_type) self._rpc_connection.send(data)
def test_client_name(self): message = Encoder.client_name('foo') self.assertEqual (32, len(message)) self.assertEqual ('666f6f'+'00'*29, hexlify(message))
def test_empty_client_name(self): message = Encoder.client_name() self.assertEqual (32, len(message)) self.assertEqual ('00'*32, hexlify(message))
def send_message(self, message): """ Send a protobuf message """ self.send(Encoder.encode_message_with_size(message))