lib/ionian/socket.rb in ionian-0.6.4 vs lib/ionian/socket.rb in ionian-0.6.5

- old
+ new

@@ -3,10 +3,19 @@ module Ionian # A convenient wrapper for TCP, UDP, and Unix client sockets. class Socket + # IP address or URL of server. + attr_reader :host + + # Remote port number. + attr_reader :port + + # Local port number. + attr_reader :bind_port + # Creates a new socket or wraps an existing socket. # # Args: # host: IP or hostname to connect to. # port: Connection's port number. Default is 23. Unused by :unix protocol. @@ -20,11 +29,11 @@ # reuse_addr: Set true to enable the SO_REUSEADDR flag. Allows local address reuse. # no_delay: Set true to enable the TCP_NODELAY flag. Disables Nagle algorithm. # cork: Set true to enable the TCP_CORK flag. Buffers multiple writes # into one segment. # expression: Overrides the #read_match regular expression for received data. - def initialize(existing_socket = nil, **kwargs) + def initialize existing_socket = nil, **kwargs @socket = existing_socket @ionian_listeners = [] @expression = kwargs.fetch :expression, nil @@ -53,20 +62,21 @@ @persistent = true # Existing sockets are always persistent. @socket.expression = @expression if @expression initialize_socket_methods + else # Initialize new socket. - # TODO: Should be able to parse the port out of host. - # :port should override this parsed value. + # Parse host out of "host:port" if specified. + host_port_ary = kwargs.fetch(:host).to_s.split ':' - @host = kwargs.fetch :host - @port = kwargs.fetch :port, 23 + @host = host_port_ary[0] + @port = kwargs.fetch :port, host_port_ary[1].to_i || 23 @bind_port = kwargs.fetch :bind_port, @port - + # Automatically select UDP for the multicast range. Otherwise default to TCP. default_protocol = :tcp default_protocol = :udp if Ionian::Extension::Socket.multicast? @host default_protocol = :unix if @host.start_with? '/' @@ -92,11 +102,11 @@ def expression @expression || @socket.expression end # Set the regular expression used to match incoming data. - def expression=(exp) + def expression= exp @expression = exp @socket.expression = exp if @socket end # Returns true if the socket remains open after writing data. @@ -106,22 +116,22 @@ # Send a command (data) to the socket. # Returns an array of received matches. # Block yields received match. # See Ionian::Extension::IO#read_match. - def cmd(string, **kwargs, &block) + def cmd string, **kwargs, &block create_socket unless @persistent if @protocol == :udp @socket.send string, 0 else @socket.write string end @socket.flush - matches = @socket.read_match(kwargs) {|match| yield match if block_given?} + matches = @socket.read_match(kwargs) { |match| yield match if block_given? } @socket.close unless @persistent matches end @@ -136,23 +146,23 @@ end alias_method :on_match, :register_observer # Unregister a block from being called when matched data is received. - def unregister_observer(&block) - @ionian_listeners.delete_if {|o| o == block} + def unregister_observer &block + @ionian_listeners.delete_if { |o| o == block } @socket.unregister_observer &block if @socket block end ### Methods Forwarded To @socket ### # Returns true if there is data in the receive buffer. # Args: # Timeout: Number of seconds to wait for data until # giving up. Set to nil for blocking. - def has_data?(**kwargs) + def has_data? **kwargs return false unless @socket @socket.has_data? kwargs end # Returns true if the socket is closed. @@ -167,17 +177,17 @@ @socket.flush if @persistent end # Writes the given string(s) to the socket and appends a # newline character to any string not already ending with one. - def puts(*string) - self.write string.map{|s| s.chomp}.join("\n") + "\n" + def puts *string + self.write string.map{ |s| s.chomp }.join("\n") + "\n" end # Writes the given string to the socket. Returns the number of # bytes written. - def write(string) + def write string create_socket unless @persistent num_bytes = 0 if @protocol == :udp @@ -253,11 +263,11 @@ # Forward undefined methods to @socket. # This was chosen over method_missing to avoid traversing the object # hierarchy on every method call, like transmitting data. @socket.methods - .select {|m| @socket.respond_to? m} - .select {|m| not self.respond_to? m} + .select { |m| @socket.respond_to? m } + .select { |m| not self.respond_to? m } .each do |m| self.singleton_class.send :define_method, m do |*args, &block| @socket.__send__ m, *args, &block end end \ No newline at end of file