lib/ionian/socket.rb in ionian-0.4.0 vs lib/ionian/socket.rb in ionian-0.4.1

- old
+ new

@@ -1,27 +1,28 @@ require 'ionian/extension/socket' module Ionian + + # A convenient wrapper for TCP, UDP, and Unix sockets. class Socket - ############ - # TODO NOTES - ############ - # Always lazily instiantiate @socket, even when persistent? - # May not work with forwarding method calls. - # Oh! Unless the forwarded methods check for @socket to exist. - # Will persistent methods have to check for the socket not to be - # closed as well? - - def initialize(**kvargs) + # Args: + # host: IP or hostname to connect to. + # port: Connection's port number. Default is 23. Unused by :unix protocol. + # protocol: Type of socket to create. :tcp, :udp, :unix. Default is :tcp. + # persistent: The socket remains open after data is sent if this is true. + # The socket closes after data is sent and a packet is received + # if this is false. Default is true. + # expression: Overrides the #read_match regular expression for received data. + def initialize(**kwargs) @socket = nil - @host = kvargs.fetch :host - @port = kvargs.fetch :port, 23 - @expression = kvargs.fetch :expression, nil - @protocol = kvargs.fetch :protocol, :tcp - @persistent = kvargs.fetch :persistent, true + @host = kwargs.fetch :host + @port = kwargs.fetch :port, 23 + @protocol = kwargs.fetch :protocol, :tcp + @persistent = kwargs.fetch :persistent, true + @expression = kwargs.fetch :expression, nil create_socket if @persistent end # Returns a symbol of the type of protocol this socket uses: @@ -33,19 +34,26 @@ # Returns true if the socket remains open after writing data. def persistent? @persistent == false || @persistent == nil ? false : true end - # Send a command (data) to the socket. Returns received matches. + # 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, **kvargs, &block) + # See Ionian::Extension::IO#read_match. + def cmd(string, **kwargs, &block) create_socket unless @persistent - @socket.write string + + if @protocol == :udp + @socket.send string, 0 + else + @socket.write string + end + @socket.flush - matches = @socket.read_match(kvargs) {|match| yield match if block_given?} + matches = @socket.read_match(kwargs) {|match| yield match if block_given?} @socket.close unless @persistent matches end @@ -54,13 +62,13 @@ # 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?(**kvargs) + def has_data?(**kwargs) return false unless @socket - @socket.has_data? kvargs + @socket.has_data? kwargs end # Returns true if the socket is closed. def closed? return true unless @socket @@ -81,12 +89,19 @@ # Writes the given string to the socket. Returns the number of # bytes written. def write(string) create_socket unless @persistent - num_bytes = @socket.write string + num_bytes = 0 + + if @protocol == :udp + num_bytes = @socket.send string, 0 + else + num_bytes = @socket.write string + end + unless @persistent # Read in data to prevent RST packets. has_data = ::IO.select [@socket], nil, nil, 0 @socket.readpartial 0xFFFF if has_data @@ -99,17 +114,19 @@ alias_method :<<, :write private + # Initialize or reinitialize @socket. def create_socket @socket.close if @socket and not @socket.closed? case @protocol when :tcp @socket = ::TCPSocket.new @host, @port when :udp @socket = ::UDPSocket.new + @socket.bind '', @port @socket.connect @host, @port when :unix @socket = ::UNIXSocket.new @host end \ No newline at end of file