class HrrRbNetconf::Server::Capability::Base_1_1::Receiver

Public Class Methods

new(io_r, logger: nil) click to toggle source
# File lib/hrr_rb_netconf/server/capability/base_1_1.rb, line 150
def initialize io_r, logger: nil
  self.logger = logger
  @io_r = io_r
end

Public Instance Methods

receive_message() click to toggle source
# File lib/hrr_rb_netconf/server/capability/base_1_1.rb, line 155
def receive_message
  chunk_size = StringIO.new
  chunked_msg = StringIO.new
  decoded_msg = StringIO.new
  read_len = 1
  state = :beginning_of_msg
  until state == :end_of_msg
    begin
      buf = @io_r.read(read_len)
    rescue => e
      log_info { "Receiver IO closed: #{e.class}: #{e.message}" }
      return nil
    end
    if buf.nil?
      log_info { "Receiver IO closed" }
      return nil
    end
    chunked_msg.write buf
    case state
    when :beginning_of_msg
      if buf == "\n"
        state = :before_chunk_size
      else
        info = "In beginning_of_msg: expected #{"\n".inspect}, but got #{buf.inspect}: #{chunked_msg.string.inspect}"
        log_info { info }
        raise Error['malformed-message'].new("rpc", "error", logger: logger)
      end
    when :before_chunk_size
      if buf == "#"
        state = :in_chunk_size
      else
        info = "In before_chunk_size: expected #{"#".inspect}, but got #{buf.inspect}: #{chunked_msg.string.inspect}"
        log_info { info }
        raise Error['malformed-message'].new("rpc", "error", logger: logger)
      end
    when :in_chunk_size
      if buf =~ /[0-9]/
        chunk_size.write buf
      elsif buf == "\n"
        read_len = chunk_size.string.to_i
        state = :in_chunk_data
      elsif buf == "#"
        state = :ending_msg
      else
        info = "In in_chunk_size: expected #{"/[0-9]/".inspect}, #{"\n".inspect}, or #{"#".inspect}, but got #{buf.inspect}: #{chunked_msg.string.inspect}"
        log_info { info }
        raise Error['malformed-message'].new("rpc", "error", logger: logger)
      end
    when :in_chunk_data
      chunk_size = StringIO.new
      decoded_msg.write buf
      read_len = 1
      state = :after_chunk_data
    when :after_chunk_data
      if buf == "\n"
        state = :before_chunk_size
      else
        info = "In after_chunk_data: expected #{"\n".inspect}, but got #{buf.inspect}: #{chunked_msg.string.inspect}"
        log_info { info }
        raise Error['malformed-message'].new("rpc", "error", logger: logger)
      end
    when :ending_msg
      if buf == "\n"
        state = :end_of_msg
      else
        info = "In ending_msg: expected #{"\n".inspect}, but got #{buf.inspect}: #{chunked_msg.string.inspect}"
        log_info { info }
        raise Error['malformed-message'].new("rpc", "error", logger: logger)
      end
    end
  end
  log_debug { "Received message: #{decoded_msg.string.inspect}" }
  begin
    received_msg = REXML::Document.new(decoded_msg.string, {:ignore_whitespace_nodes => :all}).root
    validate_received_msg received_msg
    received_msg
  rescue => e
    info = "Invalid received message: #{e.message.split("\n").first}: #{decoded_msg.string.inspect}"
    log_info { info }
    raise Error['malformed-message'].new("rpc", "error", logger: logger)
  end
end
validate_received_msg(received_msg) click to toggle source
# File lib/hrr_rb_netconf/server/capability/base_1_1.rb, line 238
def validate_received_msg received_msg
  unless received_msg
    raise "No valid root tag interpreted"
  end
  unless "rpc" == received_msg.name
    raise "Invalid message: expected #{"rpc".inspect}, but got #{received_msg.name.inspect}"
  end
  unless "urn:ietf:params:xml:ns:netconf:base:1.0" == received_msg.namespace
    raise "Invalid namespace: expected #{"urn:ietf:params:xml:ns:netconf:base:1.0".inspect}, but got #{received_msg.namespace.inspect}"
  end
end