Class: Erlang::NodeConnection

Inherits:
EM::Connection
  • Object
show all
Includes:
EM::Deferrable
Defined in:
lib/rinterface/node.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#argsObject

Returns the value of attribute args.



79
80
81
# File 'lib/rinterface/node.rb', line 79

def args
  @args
end

Returns the value of attribute cookie.



79
80
81
# File 'lib/rinterface/node.rb', line 79

def cookie
  @cookie
end

#destnodeObject

Returns the value of attribute destnode.



79
80
81
# File 'lib/rinterface/node.rb', line 79

def destnode
  @destnode
end

#funObject

Returns the value of attribute fun.



79
80
81
# File 'lib/rinterface/node.rb', line 79

def fun
  @fun
end

#hostObject

Returns the value of attribute host.



79
80
81
# File 'lib/rinterface/node.rb', line 79

def host
  @host
end

#modObject

Returns the value of attribute mod.



79
80
81
# File 'lib/rinterface/node.rb', line 79

def mod
  @mod
end

#mynameObject

Returns the value of attribute myname.



79
80
81
# File 'lib/rinterface/node.rb', line 79

def myname
  @myname
end

#portObject

Returns the value of attribute port.



79
80
81
# File 'lib/rinterface/node.rb', line 79

def port
  @port
end

Class Method Details

.build_nodenameObject

Build a nodename for us



108
109
110
111
112
# File 'lib/rinterface/node.rb', line 108

def self.build_nodename
  require 'socket'
  myhostname = Socket.gethostname.split(".")[0]
  "ruby_client@#{myhostname}"
end

Get the Cookie from the home directory



100
101
102
103
104
105
# File 'lib/rinterface/node.rb', line 100

def self.get_cookie
  # ... I did it all for the cookie, come on the cookie ...
  fp = File.expand_path("~#{ENV['USER']}/.erlang.cookie")
  fh = File.open(fp,'r')
  fh.readline.strip
end

.rpc_call(node, port, mod, fun, args) ⇒ Object

node = destination node port = the port of the Erlang node (from epmd) mod = the module to call fun = the function to call args = args to pass to fun



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/rinterface/node.rb', line 86

def self.rpc_call(node,port,mod,fun,args)
  EM.connect("127.0.0.1",port,self) do |c|
    c.destnode = node
    c.mod = mod
    c.fun = fun
    c.args = args
    c.port = port
    c.myname = build_nodename
    c.cookie = get_cookie
  end
end

Instance Method Details

#call_remoteObject



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/rinterface/node.rb', line 220

def call_remote
  myPid = Erlang::Terms::Pid.new(self.myname.intern,5,5,5)
  call_tuple = [:call,self.mod.intern,self.fun.intern,Erlang::Terms::List.new(self.args),:user]
  rpc_tuple  = [myPid,call_tuple]
  ctl_msg = [6,myPid,self.cookie.intern,:rex]

  encode_data = Encoder.new
  encode_data.term_to_binary(ctl_msg)
  encode_data.term_to_binary(rpc_tuple)
  data = encode_data.out.string

  f = Encoder.new
  f.write_4(data.length + 1)
  final_out = f.out.string + 'p' + data
  send_data final_out
end

#connection_completedObject



118
119
120
# File 'lib/rinterface/node.rb', line 118

def connection_completed
  send_data send_name
end

#determine_messageObject



163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/rinterface/node.rb', line 163

def determine_message
  decoder = Decode.read_bits(@resp)
  packet_size = decoder.read_2
  #puts "PacketSize: #{packet_size}"
  status_code = decoder.read_string(1)
  case status_code
  when 's' then receive_status(packet_size,decoder)
  when 'n' then receive_challenge(packet_size,decoder)
  when 'a' then receive_challenge_ack(packet_size,decoder)
  else "Got back a weird packet"
  end
end

#handle_any_responseObject



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/rinterface/node.rb', line 127

def handle_any_response
  result = ""
  decoder = Decode.read_bits(@resp)
  s = decoder.read_4
  #puts "Size: #{s}"
  code = decoder.read_string(1)
  if code == 'p'
    #puts "found the p"
    # read the control message and ignore
    decoder.read_any
    # read the message
    result = decoder.read_any
    #puts "Raw Response: #{result.inspect}"
    set_deferred_success result[1]
  else
    # This seems to never happen...always 'p'
    result = decoder.read_any
    set_deferred_failure result
  end
end

#make_challenge(her_challenge) ⇒ Object



200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/rinterface/node.rb', line 200

def make_challenge(her_challenge)
  incr_digest = Digest::MD5.new()
  incr_digest << @cookie
  incr_digest << her_challenge.to_s
  digest = incr_digest.digest
  our_challenge = rand(10000)
  encoder = Encoder.new
  encoder.write_2(21)
  encoder.write_string('r')
  encoder.write_4(our_challenge)
  encoder.write_string(digest)
  encoder.out.string
end

#post_initObject



114
115
116
# File 'lib/rinterface/node.rb', line 114

def post_init
  @responder = :determine_message
end

#receive_challenge(packet_size, decoder) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/rinterface/node.rb', line 187

def receive_challenge(packet_size,decoder)
  dist_code = decoder.read_2
  #puts "Code: #{dist_code}"
  flags = decoder.read_4
  #puts "Flags #{flags}"
  challenge = decoder.read_4
  his_name = decoder.read_string(decoder.in.size-13)
  #puts "His name: #{his_name}"
  #puts "Got the challenge #{challenge}"
  #out_challenge = make_challenge(challenge)
  send_data make_challenge(challenge)
end

#receive_challenge_ack(packet_size, decoder) ⇒ Object

Handshake complete…send the RPC



215
216
217
218
# File 'lib/rinterface/node.rb', line 215

def receive_challenge_ack(packet_size,decoder)
  @responder = :handle_any_response
  call_remote
end

#receive_data(data) ⇒ Object



122
123
124
125
# File 'lib/rinterface/node.rb', line 122

def receive_data data
  @resp = data
  send @responder
end

#receive_status(packet_size, decoder) ⇒ Object



176
177
178
179
180
181
182
183
184
185
# File 'lib/rinterface/node.rb', line 176

def receive_status(packet_size,decoder)
  status = decoder.read_string(packet_size-1)
  if decoder.in.size > (packet_size + 2)
    # Hack when both receive packets are crammed together into 1
    next_packet_size = decoder.read_2 # read size
    status_code = decoder.read_string(1)
    receive_challenge(next_packet_size, decoder)
  end
  set_deferred_failure "Failed on Recv Status: #{status_code}" unless status == 'ok'
end

#send_nameObject



148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/rinterface/node.rb', line 148

def send_name
  full_host_name = self.myname
  encode = Encoder.new
  encode.write_2(full_host_name.length + 7)
  # node type
  encode.write_1(110)
  # distChoose
  encode.write_2(5)
  # flags
  encode.write_4(4|256|1024|2048)
  # node name
  encode.write_string(full_host_name)
  encode.out.string
end