Class: NetConfGen::Server::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/netconfgen/netconfgen.rb

Overview

Basic server utilizing threads for handling sessions.

It lacks a mutex around access to @clients, in case you’d want to stress test it for 10K or something.

Direct Known Subclasses

RWSimple

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(handler, opts = {}) ⇒ Base

Initialize the server.

Options:

- :address => address to listen to (default: '0.0.0.0')
- :port    => dispatcher port (default: 69)
- :logger  => logger instance

Parameters:

  • handler (Handler)

    Initialized session handler

  • opts (Hash) (defaults to: {})

    Options



463
464
465
466
467
468
469
470
471
472
# File 'lib/netconfgen/netconfgen.rb', line 463

def initialize(handler, opts = {})
  @handler = handler

  @address = opts[:address] || '0.0.0.0'
  @port    = opts[:port] || 69
  @logger  = opts[:logger]

  @clients = Hash.new
  @run = false
end

Instance Attribute Details

#addressString

Address to listen to

Returns:

  • (String)

    the current value of address



450
451
452
# File 'lib/netconfgen/netconfgen.rb', line 450

def address
  @address
end

#clientsHash

Current sessions

Returns:

  • (Hash)

    the current value of clients



450
451
452
# File 'lib/netconfgen/netconfgen.rb', line 450

def clients
  @clients
end

#handlerHandler

Session handler

Returns:

  • (Handler)

    the current value of handler



450
451
452
# File 'lib/netconfgen/netconfgen.rb', line 450

def handler
  @handler
end

#portInteger

Session dispatcher port

Returns:

  • (Integer)

    the current value of port



450
451
452
# File 'lib/netconfgen/netconfgen.rb', line 450

def port
  @port
end

Instance Method Details

#run!Object

Run the main server loop.

This is obviously blocking.



477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
# File 'lib/netconfgen/netconfgen.rb', line 477

def run!
  log :info, "UDP server loop at #{@address}:#{@port}"
  @run = true
  Socket.udp_server_loop(@address, @port) do |msg, src|
    break unless @run

    addr = src.remote_address
    tag = "[#{addr.ip_address}:#{addr.ip_port.to_s.ljust(5)}]"
    log :info, "#{tag} New initial packet received"

    begin
      pkt = Packet.parse(msg)
    rescue ParseError => e
      log :warn, "#{tag} Packet parse error: #{e.to_s}"
      next
    end

    log :debug, "#{tag} -> PKT: #{pkt.inspect}"
    tid = get_tid
    tag = "[#{addr.ip_address}:#{addr.ip_port.to_s.ljust(5)}:#{tid.to_s.ljust(5)}]"
    sock = addr.connect_from(@address, tid)
    @clients[tid] = tag

    unless pkt.is_a?(Packet::RRQ) || pkt.is_a?(Packet::WRQ)
      log :warn, "#{tag} Bad initial packet: #{pkt.class}"
      sock.send(Packet::ERROR.new(4, 'Illegal TFTP operation.').encode, 0)
      sock.close
      next
    end

    Thread.new do
      @handler.run!(tag, pkt, sock, src)
      @clients.delete(tid)
      log :info, "#{tag} Session ended"
    end
  end
  log :info, 'UDP server loop has stopped'
end

#stopObject

Stop the main server loop.

This will allow the currently pending sessions to finish.



519
520
521
522
523
# File 'lib/netconfgen/netconfgen.rb', line 519

def stop
  log :info, 'Stopping UDP server loop'
  @run = false
  UDPSocket.new.send('break', 0, @address, @port)
end