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


380
381
382
383
384
385
386
387
388
389
# File 'lib/netconfgen/netconfgen.rb', line 380

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



367
368
369
# File 'lib/netconfgen/netconfgen.rb', line 367

def address
  @address
end

#clientsHash

Current sessions



367
368
369
# File 'lib/netconfgen/netconfgen.rb', line 367

def clients
  @clients
end

#handlerHandler

Session handler



367
368
369
# File 'lib/netconfgen/netconfgen.rb', line 367

def handler
  @handler
end

#portInteger

Session dispatcher port



367
368
369
# File 'lib/netconfgen/netconfgen.rb', line 367

def port
  @port
end

Instance Method Details

#run!Object

Run the main server loop.

This is obviously blocking.



394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
# File 'lib/netconfgen/netconfgen.rb', line 394

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.



436
437
438
439
440
# File 'lib/netconfgen/netconfgen.rb', line 436

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