Class: BERTRPC::Action
- Inherits:
-
Object
- Object
- BERTRPC::Action
- Includes:
- Encodes
- Defined in:
- lib/bertrpc/action.rb
Instance Method Summary collapse
-
#connect_to(host, port, timeout = nil) ⇒ Object
Creates a socket object which does speedy, non-blocking reads and can perform reliable read timeouts.
- #execute ⇒ Object
-
#initialize(svc, req, mod, fun, args) ⇒ Action
constructor
A new instance of Action.
- #read(sock, len, timeout) ⇒ Object
- #transaction(bert_request) ⇒ Object
-
#write(sock, bert) ⇒ Object
private.
Methods included from Encodes
#decode_bert_response, #encode_ruby_request, #error
Constructor Details
#initialize(svc, req, mod, fun, args) ⇒ Action
Returns a new instance of Action.
5 6 7 8 9 10 11 |
# File 'lib/bertrpc/action.rb', line 5 def initialize(svc, req, mod, fun, args) @svc = svc @req = req @mod = mod @fun = fun @args = args end |
Instance Method Details
#connect_to(host, port, timeout = nil) ⇒ Object
Creates a socket object which does speedy, non-blocking reads and can perform reliable read timeouts.
Raises Timeout::Error on timeout.
+host+ String address of the target TCP server
+port+ Integer port of the target TCP server
+timeout+ Optional Integer (in seconds) of the read timeout
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/bertrpc/action.rb', line 75 def connect_to(host, port, timeout = nil) addr = Socket.getaddrinfo(host, nil, Socket::AF_INET) sock = Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0) sock.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 if timeout secs = Integer(timeout) usecs = Integer((timeout - secs) * 1_000_000) optval = [secs, usecs].pack("l_2") sock.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, optval sock.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval end sock.connect(Socket.pack_sockaddr_in(port, addr[0][3])) sock end |
#execute ⇒ Object
13 14 15 16 17 |
# File 'lib/bertrpc/action.rb', line 13 def execute bert_request = encode_ruby_request(t[@req.kind, @mod, @fun, @args]) bert_response = transaction(bert_request) decode_bert_response(bert_response) end |
#read(sock, len, timeout) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/bertrpc/action.rb', line 26 def read(sock, len, timeout) data, size = [], 0 while size < len r, w, e = IO.select([sock], [], [], timeout) raise Errno::EAGAIN if r.nil? msg, sender = sock.recvfrom(len - size) raise Errno::ECONNRESET if msg.size == 0 size += msg.size data << msg end data.join '' end |
#transaction(bert_request) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/bertrpc/action.rb', line 39 def transaction(bert_request) timeout = @svc.timeout && Float(@svc.timeout) sock = connect_to(@svc.host, @svc.port, timeout) if @req. if @req.[:cache] && @req.[:cache][0] == :validation token = @req.[:cache][1] info_bert = encode_ruby_request([:info, :cache, [:validation, token]]) write(sock, info_bert) end end write(sock, bert_request) lenheader = read(sock, 4, timeout) raise ProtocolError.new(ProtocolError::NO_HEADER) unless lenheader len = lenheader.unpack('N').first bert_response = read(sock, len, timeout) raise ProtocolError.new(ProtocolError::NO_DATA) unless bert_response sock.close bert_response rescue Errno::ECONNREFUSED raise ConnectionError.new(@svc.host, @svc.port) rescue Errno::EAGAIN raise ReadTimeoutError.new(@svc.host, @svc.port, @svc.timeout) rescue Errno::ECONNRESET raise ReadError.new(@svc.host, @svc.port) end |
#write(sock, bert) ⇒ Object
private
21 22 23 24 |
# File 'lib/bertrpc/action.rb', line 21 def write(sock, bert) sock.write([bert.bytesize].pack("N")) sock.write(bert) end |