lib/em-whois.rb in em-whois-0.1.1 vs lib/em-whois.rb in em-whois-0.2.0
- old
+ new
@@ -2,51 +2,56 @@
require 'em-synchrony'
module Whois
class Server
module Adapters
+
class Base
+
private
- # This method handles the lowest connection
- # to the WHOIS server.
#
- # This is for internal use only!
+ # Overwrite Whois::Server::Adapters::Base#ask_the_socket to
+ # be EventMachine-aware, and send calls offs asynchronously
+ # if the EM reactor is running, otherwise fallback to the
+ # synchronous connection.
#
- # @api internal
alias :orig_ask_the_socket :ask_the_socket
def ask_the_socket(*args)
defined?(EM) && EM.reactor_running? ? em_ask_the_socket(*args) : orig_ask_the_socket(*args)
end # ask_the_socket
def em_ask_the_socket(query, *args)
- client = EventMachine::Synchrony::TCPSocket.new(*args)
- client.write("#{query}\r\n") # I could use put(foo) and forget the \n
- # but write/read is more symmetric than puts/read
- # and I really want to use read instead of gets.
+ fiber = Fiber.current
+ EM::connect args[0], args[1], AsyncClient, query, fiber
+ Fiber.yield
+ end # em_ask_the_socket
- response = ""
+ end # Base
- # Synchrony TCPSocket behaves a little differently, seems to require
- # polling until an IO exception is thrown.
- # TODO: There's gotta be a more elegant way to achieve this.
- while true do
- begin
- response += client.read
- rescue IOError => e
- break
- end
- end
+ class AsyncClient < EventMachine::Connection
- response
+ def initialize *args
+ @query, @fiber = args[0..1]
+ @data = ""
+ super
+ end
- ensure
- client.close if client # If != client something went wrong.
-
- end # em_ask_the_socket
+ def post_init
+ send_data "#{@query}\r\n"
+ end
- end
+ def receive_data(data)
+ @data << data
+ end
+
+ def unbind
+ @fiber.resume @data
+ end
+
+ end # AsyncClient
+
end
end
end