krpc 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/krpc.gemspec +24 -0
- data/lib/krpc.rb +1 -0
- data/lib/krpc/KRPC.pb.rb +125 -0
- data/lib/krpc/attributes.rb +81 -0
- data/lib/krpc/client.rb +130 -0
- data/lib/krpc/connection.rb +108 -0
- data/lib/krpc/core_extensions.rb +28 -0
- data/lib/krpc/decoder.rb +54 -0
- data/lib/krpc/doc.rb +124 -0
- data/lib/krpc/encoder.rb +60 -0
- data/lib/krpc/error.rb +33 -0
- data/lib/krpc/gen.rb +117 -0
- data/lib/krpc/protobuf_utils.rb +134 -0
- data/lib/krpc/repl_tools.rb +12 -0
- data/lib/krpc/service.rb +96 -0
- data/lib/krpc/types.rb +237 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dd2789a9c287acf5c0102288bf37d79551d85bf1
|
4
|
+
data.tar.gz: c4135dc71e1b1e11ee8b75978ebeaf0d014e779d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 45bab162e5b7402b9553fc2e4fef9a1bbb8a048c40985e14b9fb53f1fe69580ae84da35813709b1cd8424100bdb67b1e2a5d2a304fda27efab38c5ef66110bb7
|
7
|
+
data.tar.gz: c2c5c2cf56506d4cb0df4940ed87945a464f64610aed0d47443dd0d3a1b74669f832f77e84256a2e33fb3fec5e6a6f8478e436d714bd4ddd75099d6a724ac81a
|
data/Gemfile
ADDED
data/krpc.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "krpc"
|
8
|
+
s.version = "0.1.0"
|
9
|
+
s.authors = ["Tomasz Więch"]
|
10
|
+
s.email = ["tewu.dev@gmail.com"]
|
11
|
+
|
12
|
+
s.summary = "Client library for kRPC"
|
13
|
+
s.homepage = "https://github.com/TeWu/krpc-rb"
|
14
|
+
s.license = "GPL-3.0"
|
15
|
+
|
16
|
+
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_runtime_dependency "ruby_protobuf", "~> 0.4"
|
20
|
+
s.add_runtime_dependency "colorize", "~> 0.7"
|
21
|
+
|
22
|
+
s.add_development_dependency "bundler", "~> 1.10"
|
23
|
+
end
|
24
|
+
|
data/lib/krpc.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'krpc/client'
|
data/lib/krpc/KRPC.pb.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
|
2
|
+
### Generated by rprotoc. DO NOT EDIT!
|
3
|
+
|
4
|
+
require 'protobuf/message/message'
|
5
|
+
require 'protobuf/message/enum'
|
6
|
+
require 'protobuf/message/service'
|
7
|
+
require 'protobuf/message/extend'
|
8
|
+
|
9
|
+
module KRPC
|
10
|
+
module PB
|
11
|
+
class Request < ::Protobuf::Message
|
12
|
+
defined_in __FILE__
|
13
|
+
required :string, :service, 1
|
14
|
+
required :string, :procedure, 2
|
15
|
+
repeated :Argument, :arguments, 3
|
16
|
+
end
|
17
|
+
class Argument < ::Protobuf::Message
|
18
|
+
defined_in __FILE__
|
19
|
+
required :uint32, :position, 1
|
20
|
+
required :bytes, :value, 2
|
21
|
+
end
|
22
|
+
class Response < ::Protobuf::Message
|
23
|
+
defined_in __FILE__
|
24
|
+
required :double, :time, 1
|
25
|
+
optional :string, :error, 2
|
26
|
+
optional :bytes, :return_value, 3
|
27
|
+
end
|
28
|
+
class StreamMessage < ::Protobuf::Message
|
29
|
+
defined_in __FILE__
|
30
|
+
repeated :StreamResponse, :responses, 1
|
31
|
+
end
|
32
|
+
class StreamResponse < ::Protobuf::Message
|
33
|
+
defined_in __FILE__
|
34
|
+
required :uint32, :id, 1
|
35
|
+
required :Response, :response, 2
|
36
|
+
end
|
37
|
+
class Services < ::Protobuf::Message
|
38
|
+
defined_in __FILE__
|
39
|
+
repeated :Service, :services, 1
|
40
|
+
end
|
41
|
+
class Service < ::Protobuf::Message
|
42
|
+
defined_in __FILE__
|
43
|
+
required :string, :name, 1
|
44
|
+
repeated :Procedure, :procedures, 2
|
45
|
+
repeated :Class, :classes, 3
|
46
|
+
repeated :Enumeration, :enumerations, 4
|
47
|
+
optional :string, :documentation, 5
|
48
|
+
end
|
49
|
+
class Procedure < ::Protobuf::Message
|
50
|
+
defined_in __FILE__
|
51
|
+
required :string, :name, 1
|
52
|
+
repeated :Parameter, :parameters, 2
|
53
|
+
optional :string, :return_type, 3
|
54
|
+
repeated :string, :attributes, 4
|
55
|
+
optional :string, :documentation, 5
|
56
|
+
end
|
57
|
+
class Parameter < ::Protobuf::Message
|
58
|
+
defined_in __FILE__
|
59
|
+
required :string, :name, 1
|
60
|
+
required :string, :type, 2
|
61
|
+
optional :bytes, :default_argument, 3
|
62
|
+
end
|
63
|
+
class Class < ::Protobuf::Message
|
64
|
+
defined_in __FILE__
|
65
|
+
required :string, :name, 1
|
66
|
+
optional :string, :documentation, 2
|
67
|
+
end
|
68
|
+
class Enumeration < ::Protobuf::Message
|
69
|
+
defined_in __FILE__
|
70
|
+
required :string, :name, 1
|
71
|
+
repeated :EnumerationValue, :values, 2
|
72
|
+
optional :string, :documentation, 3
|
73
|
+
end
|
74
|
+
class EnumerationValue < ::Protobuf::Message
|
75
|
+
defined_in __FILE__
|
76
|
+
required :string, :name, 1
|
77
|
+
required :int32, :value, 2
|
78
|
+
optional :string, :documentation, 3
|
79
|
+
end
|
80
|
+
class List < ::Protobuf::Message
|
81
|
+
defined_in __FILE__
|
82
|
+
repeated :bytes, :items, 1
|
83
|
+
end
|
84
|
+
class Dictionary < ::Protobuf::Message
|
85
|
+
defined_in __FILE__
|
86
|
+
repeated :DictionaryEntry, :entries, 1
|
87
|
+
end
|
88
|
+
class DictionaryEntry < ::Protobuf::Message
|
89
|
+
defined_in __FILE__
|
90
|
+
required :bytes, :key, 1
|
91
|
+
required :bytes, :value, 2
|
92
|
+
end
|
93
|
+
class Set < ::Protobuf::Message
|
94
|
+
defined_in __FILE__
|
95
|
+
repeated :bytes, :items, 1
|
96
|
+
end
|
97
|
+
class Tuple < ::Protobuf::Message
|
98
|
+
defined_in __FILE__
|
99
|
+
repeated :bytes, :items, 1
|
100
|
+
end
|
101
|
+
class Status < ::Protobuf::Message
|
102
|
+
defined_in __FILE__
|
103
|
+
required :string, :version, 1
|
104
|
+
required :uint64, :bytes_read, 2
|
105
|
+
required :uint64, :bytes_written, 3
|
106
|
+
required :float, :bytes_read_rate, 4
|
107
|
+
required :float, :bytes_written_rate, 5
|
108
|
+
required :uint64, :rpcs_executed, 6
|
109
|
+
required :float, :rpc_rate, 7
|
110
|
+
required :bool, :one_rpc_per_update, 8
|
111
|
+
required :uint32, :max_time_per_update, 9
|
112
|
+
required :bool, :adaptive_rate_control, 10
|
113
|
+
required :bool, :blocking_recv, 11
|
114
|
+
required :uint32, :recv_timeout, 12
|
115
|
+
required :float, :time_per_rpc_update, 13
|
116
|
+
required :float, :poll_time_per_rpc_update, 14
|
117
|
+
required :float, :exec_time_per_rpc_update, 15
|
118
|
+
required :uint32, :stream_rpcs, 16
|
119
|
+
required :uint64, :stream_rpcs_executed, 17
|
120
|
+
required :float, :stream_rpc_rate, 18
|
121
|
+
required :float, :time_per_stream_update, 19
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'krpc/error'
|
2
|
+
|
3
|
+
module KRPC
|
4
|
+
module Attributes
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def is_any_start_with?(attrs, prefix)
|
8
|
+
attrs.any?{|a| a.start_with? prefix }
|
9
|
+
end
|
10
|
+
alias_method :asw?, :is_any_start_with?
|
11
|
+
|
12
|
+
def is_a_property_accessor(attrs) asw?(attrs,"Property.") end
|
13
|
+
def is_a_property_getter(attrs) asw?(attrs,"Property.Get(") end
|
14
|
+
def is_a_property_setter(attrs) asw?(attrs,"Property.Set(") end
|
15
|
+
def is_a_class_method_or_property_accessor(attrs) asw?(attrs,"Class.") end
|
16
|
+
def is_a_class_method(attrs) asw?(attrs,"Class.Method(") end
|
17
|
+
def is_a_class_static_method(attrs) asw?(attrs,"Class.StaticMethod(") end
|
18
|
+
def is_a_class_property_accessor(attrs) asw?(attrs,"Class.Property.") end
|
19
|
+
def is_a_class_property_getter(attrs) asw?(attrs,"Class.Property.Get(") end
|
20
|
+
def is_a_class_property_setter(attrs) asw?(attrs,"Class.Property.Set(") end
|
21
|
+
|
22
|
+
def get_service_name(attrs)
|
23
|
+
if is_a_class_method(attrs) || is_a_class_static_method(attrs)
|
24
|
+
attrs.each do |a|
|
25
|
+
return $1 if /^Class\.(?:Static)?Method\(([^,\.]+)\.[^,]+,[^,]+\)$/ =~ a
|
26
|
+
end
|
27
|
+
elsif is_a_class_property_accessor(attrs)
|
28
|
+
attrs.each do |a|
|
29
|
+
return $1 if /^Class\.Property.(?:Get|Set)\(([^,\.]+)\.[^,]+,[^,]+\)$/ =~ a
|
30
|
+
end
|
31
|
+
end
|
32
|
+
raise(ValueError, "Procedure attributes are not a class method or property accessor")
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_class_name(attrs)
|
36
|
+
if is_a_class_method(attrs) || is_a_class_static_method(attrs)
|
37
|
+
attrs.each do |a|
|
38
|
+
return $1 if /^Class\.(?:Static)?Method\([^,\.]+\.([^,\.]+),[^,]+\)$/ =~ a
|
39
|
+
end
|
40
|
+
elsif is_a_class_property_accessor(attrs)
|
41
|
+
attrs.each do |a|
|
42
|
+
return $1 if /^Class\.Property.(?:Get|Set)\([^,\.]+\.([^,]+),[^,]+\)$/ =~ a
|
43
|
+
end
|
44
|
+
end
|
45
|
+
raise(ValueError, "Procedure attributes are not a class method or property accessor")
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_property_name(attrs)
|
49
|
+
if is_a_property_accessor(attrs)
|
50
|
+
attrs.each do |a|
|
51
|
+
return $1 if /^Property\.(?:Get|Set)\((.+)\)$/ =~ a
|
52
|
+
end
|
53
|
+
end
|
54
|
+
raise(ValueError, "Procedure attributes are not a property accessor")
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_class_method_or_property_name(attrs)
|
58
|
+
if is_a_class_method(attrs) || is_a_class_static_method(attrs) || is_a_class_property_accessor(attrs)
|
59
|
+
attrs.each do |a|
|
60
|
+
return $1 if /^Class\.(?:(?:Static)?Method|Property\.(?:Get|Set))\([^,]+,([^,]+)\)$/ =~ a
|
61
|
+
end
|
62
|
+
end
|
63
|
+
raise(ValueError, "Procedure attributes are not a class method or class property accessor")
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_parameter_type_attrs(pos, attrs)
|
67
|
+
attrs.map do |a|
|
68
|
+
(/^ParameterType\(#{pos}\).(.+)$/ =~ a) ? $1 : nil
|
69
|
+
end.compact
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_return_type_attrs(attrs)
|
73
|
+
attrs.map do |a|
|
74
|
+
(/^ReturnType.(.+)$/ =~ a) ? $1 : nil
|
75
|
+
end.compact
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
data/lib/krpc/client.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'krpc/connection'
|
2
|
+
require 'krpc/service'
|
3
|
+
require 'krpc/types'
|
4
|
+
require 'krpc/encoder'
|
5
|
+
require 'krpc/decoder'
|
6
|
+
require 'krpc/error'
|
7
|
+
require 'krpc/core_extensions'
|
8
|
+
require 'krpc/KRPC.pb'
|
9
|
+
|
10
|
+
module KRPC
|
11
|
+
class Client
|
12
|
+
DEFAULT_NAME = ""
|
13
|
+
|
14
|
+
include Doc::SuffixMethods
|
15
|
+
|
16
|
+
attr_reader :name, :rpc_connection, :stream_connection, :type_store, :krpc
|
17
|
+
|
18
|
+
def initialize(name = DEFAULT_NAME, host = Connection::DEFAULT_SERVER_HOST, rpc_port = Connection::DEFAULT_SERVER_RPC_PORT, stream_port = Connection::DEFAULT_SERVER_STREAM_PORT)
|
19
|
+
@name = name
|
20
|
+
@rpc_connection = RPCConncetion.new(name, host, rpc_port)
|
21
|
+
@stream_connection = StreamConncetion.new(rpc_connection, host, stream_port)
|
22
|
+
@type_store = Types::TypeStore.new
|
23
|
+
@krpc = Services::KRPC.new(self)
|
24
|
+
Doc.add_docstring_info(false, self.class, "krpc", return_type: @krpc.class)
|
25
|
+
end
|
26
|
+
|
27
|
+
def connect
|
28
|
+
rpc_connection.connect
|
29
|
+
stream_connection.connect
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def connect!
|
34
|
+
connect
|
35
|
+
generate_services_api!
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def close
|
40
|
+
stream_connection.close
|
41
|
+
rpc_connection.close
|
42
|
+
end
|
43
|
+
|
44
|
+
def connected?
|
45
|
+
rpc_connection.connected?
|
46
|
+
end
|
47
|
+
|
48
|
+
def generate_services_api!
|
49
|
+
return self if services_api_generated?
|
50
|
+
raise(Exception, "Can't generate services API while not connected to server -- call Client#connect! to connect to server and generate services API in one call") if not connected?
|
51
|
+
|
52
|
+
resp = krpc.get_services
|
53
|
+
resp.services.each do |service_msg|
|
54
|
+
next if service_msg.name == "KRPC"
|
55
|
+
service = Services.create_service(service_msg, self)
|
56
|
+
method_name = service.class.class_name.underscore
|
57
|
+
self.class.instance_eval do
|
58
|
+
define_method method_name do service end
|
59
|
+
end
|
60
|
+
Doc.add_docstring_info(false, self.class, method_name, return_type: service.class)
|
61
|
+
end
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def services_api_generated?
|
66
|
+
respond_to? :space_center
|
67
|
+
end
|
68
|
+
|
69
|
+
def rpc(service, procedure, args=[], kwargs={}, param_names=[], param_types=[], required_params_count=0, param_default=[], return_type: nil)
|
70
|
+
# Send request
|
71
|
+
req = build_request(service, procedure, args, kwargs, param_names, param_types, required_params_count, param_default)
|
72
|
+
rpc_connection.send Encoder.encode_request(req)
|
73
|
+
# Receive response
|
74
|
+
resp_length = rpc_connection.recv_varint
|
75
|
+
resp_data = rpc_connection.recv resp_length
|
76
|
+
resp = PB::Response.new
|
77
|
+
resp.parse_from_string resp_data
|
78
|
+
# Check for an error response
|
79
|
+
raise(RPCError, resp.error) if resp.has_field? "error"
|
80
|
+
# Optionally decode and return the response' return value
|
81
|
+
if return_type == nil
|
82
|
+
nil
|
83
|
+
else
|
84
|
+
Decoder.decode(resp.return_value, return_type, type_store)
|
85
|
+
end
|
86
|
+
rescue IOError => e
|
87
|
+
raise(Exception, "RPC call attempt while not connected to server -- call Client#connect first") if not connected?
|
88
|
+
raise e
|
89
|
+
end
|
90
|
+
|
91
|
+
protected #----------------------------------
|
92
|
+
|
93
|
+
def build_request(service, procedure, args=[], kwargs={}, param_names=[], param_types=[], required_params_count=0, param_default=[])
|
94
|
+
begin
|
95
|
+
raise(ArgumentError, "param_names and param_types should be equal length\n\tparam_names = #{param_names}\n\tparam_types = #{param_types}") unless param_names.size == param_types.size
|
96
|
+
raise ArgumentsNumberErrorSig.new(args.count, required_params_count..param_names.count) unless args.count <= param_names.count
|
97
|
+
kwargs_remaining = kwargs.count
|
98
|
+
|
99
|
+
param_names_symbols = param_names.map(&:to_sym)
|
100
|
+
req_args = param_names_symbols.map.with_index do |name,i|
|
101
|
+
is_kwarg = kwargs.has_key? name
|
102
|
+
raise ArgumentErrorSig.new("there are both positional and keyword arguments for parameter \"#{name}\"") if is_kwarg && i < args.count
|
103
|
+
kwargs_remaining -= 1 if is_kwarg
|
104
|
+
unless i >= required_params_count &&
|
105
|
+
(!is_kwarg && i >= args.count ||
|
106
|
+
!is_kwarg && args[i] == param_default[i] ||
|
107
|
+
is_kwarg && kwargs[name] == param_default[i])
|
108
|
+
arg = if is_kwarg then kwargs[name]
|
109
|
+
elsif i < args.count then args[i]
|
110
|
+
else raise ArgumentErrorSig.new("missing argument for parameter \"#{name}\"")
|
111
|
+
end
|
112
|
+
begin
|
113
|
+
arg = type_store.coerce_to(arg, param_types[i])
|
114
|
+
rescue ValueError
|
115
|
+
raise ArgumentErrorSig.new("argument for parameter \"#{name}\" must be a #{param_types[i].ruby_type} -- got #{args[i]} of type #{args[i].class}")
|
116
|
+
end
|
117
|
+
v = Encoder.encode(arg, param_types[i], type_store)
|
118
|
+
PB::Argument.new(position: i, value: v)
|
119
|
+
end
|
120
|
+
end.compact
|
121
|
+
raise ArgumentErrorSig.new("keyword arguments for non existing parameters: #{(kwargs.keys - param_names_symbols).join(", ")}") unless kwargs_remaining == 0
|
122
|
+
rescue ArgumentErrorSig => err
|
123
|
+
raise err.with_signature(Doc.docstring_for_procedure(service, procedure))
|
124
|
+
end
|
125
|
+
PB::Request.new(service: service, procedure: procedure, arguments: req_args)
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'krpc/encoder'
|
2
|
+
require 'krpc/decoder'
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
module KRPC
|
6
|
+
|
7
|
+
class Connection
|
8
|
+
DEFAULT_SERVER_HOST = "127.0.0.1"
|
9
|
+
DEFAULT_SERVER_RPC_PORT = 50000
|
10
|
+
DEFAULT_SERVER_STREAM_PORT = 50001
|
11
|
+
|
12
|
+
attr_reader :host, :port, :socket
|
13
|
+
|
14
|
+
def initialize(host, port)
|
15
|
+
@host, @port = host, port
|
16
|
+
end
|
17
|
+
|
18
|
+
def connect
|
19
|
+
if connected? then raise(ConnectionError, "Already connected")
|
20
|
+
else
|
21
|
+
@socket = TCPSocket.open(host, port)
|
22
|
+
begin
|
23
|
+
handshake
|
24
|
+
rescue Exception => e
|
25
|
+
close
|
26
|
+
raise e
|
27
|
+
end
|
28
|
+
end
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def close
|
33
|
+
if connected?
|
34
|
+
socket.close
|
35
|
+
cleanup
|
36
|
+
true
|
37
|
+
else false end
|
38
|
+
end
|
39
|
+
|
40
|
+
def connected?
|
41
|
+
!socket.nil? && !socket.closed?
|
42
|
+
end
|
43
|
+
|
44
|
+
def handshake; end
|
45
|
+
def cleanup; end
|
46
|
+
|
47
|
+
def send(msg) @socket.send(msg,0) end
|
48
|
+
def recv(maxlen = 1) @socket.recv(maxlen) end
|
49
|
+
|
50
|
+
def recv_varint
|
51
|
+
int_val = 0
|
52
|
+
shift = 0
|
53
|
+
loop do
|
54
|
+
byte = recv.ord
|
55
|
+
int_val |= (byte & 0b0111_1111) << shift
|
56
|
+
return int_val if (byte & 0b1000_0000) == 0
|
57
|
+
shift += 7
|
58
|
+
raise(RuntimeError, "too many bytes when decoding varint") if shift >= 64
|
59
|
+
sleep 0.1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
protected #----------------------------------
|
64
|
+
|
65
|
+
def trim_fill(str, len, fill_char = "\x00")
|
66
|
+
str = str.encode("UTF-8")[0,len]
|
67
|
+
str + fill_char*(len-str.length)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class RPCConncetion < Connection
|
72
|
+
attr_reader :name, :client_id
|
73
|
+
|
74
|
+
def initialize(name, host = DEFAULT_SERVER_HOST, port = DEFAULT_SERVER_RPC_PORT)
|
75
|
+
super host, port
|
76
|
+
@name = name
|
77
|
+
end
|
78
|
+
|
79
|
+
def handshake
|
80
|
+
send Encoder::RPC_HELLO_MESSAGE
|
81
|
+
send trim_fill(name, Encoder::NAME_LENGTH)
|
82
|
+
@client_id = recv Decoder::GUID_LENGTH
|
83
|
+
end
|
84
|
+
|
85
|
+
def cleanup
|
86
|
+
@client_id = nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class StreamConncetion < Connection
|
91
|
+
attr_reader :rpc_connection
|
92
|
+
|
93
|
+
def initialize(rpc_connection, host = DEFAULT_SERVER_HOST, port = DEFAULT_SERVER_STREAM_PORT)
|
94
|
+
super host, port
|
95
|
+
@rpc_connection = rpc_connection
|
96
|
+
end
|
97
|
+
|
98
|
+
def handshake
|
99
|
+
raise(ConnectionError, "RPC connection must optain client_id before stream connection can perform valid handshake - closing stream connection") if rpc_connection.client_id.nil?
|
100
|
+
send Encoder::STREAM_HELLO_MESSAGE
|
101
|
+
send rpc_connection.client_id
|
102
|
+
resp = recv Decoder::OK_LENGTH
|
103
|
+
raise ConnectionError unless resp == Decoder::OK_MESSAGE
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|