Module: CamperVan::Server

Includes:
Logger, EM::Protocols::LineText2
Defined in:
lib/camper_van/server.rb

Overview

The core EventMachine server instance that listens for IRC connections and maps them to IRCD instances.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logger

#logger

Instance Attribute Details

#ircdObject (readonly)

Public: returns the instance of the ircd for this connection



93
94
95
# File 'lib/camper_van/server.rb', line 93

def ircd
  @ircd
end

#optionsObject (readonly)

Public: returns connection options



96
97
98
# File 'lib/camper_van/server.rb', line 96

def options
  @options
end

Class Method Details

.daemonize(logger, pid) ⇒ Object

Turns the current process into a daemon.

logger - The logger to use pid - The path to the PID file



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/camper_van/server.rb', line 44

def self.daemonize(logger, pid)
  if !File.writable?(File.dirname(pid))
    logger.error "The PID file #{pid} is not writable"
    abort
  end

  logger.info "Daemonizing camper_van using PID #{pid}"

  Process.daemon

  File.open(pid, 'w') do |handle|
    handle.write(Process.pid.to_s)
  end

  Logging.reopen
end

.initialize_logging(opts = {}) ⇒ Object

Initialize the logging system

opts - Hash of logging options

- :log_level (default :info)
- :log_to - where to log to (default STDOUT), can be IO or
            String for log filename


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/camper_van/server.rb', line 67

def self.initialize_logging(opts={})
  Logging.consolidate("CamperVan")

  Logging.logger.root.level = opts[:log_level] || :info

  appender = case opts[:log_to]
  when String
    Logging.appenders.file(opts[:log_to])
  when IO
    Logging.appenders.io(opts[:log_to])
  when nil
    Logging.appenders.stdout
  end

  # YYYY-MM-DDTHH:MM:SS 12345 LEVEL LoggerName : The Log message
  appender.layout = Logging::Layouts::Pattern.new(:pattern => "%d %5p %5l %c : %m\n")

  Logging.logger.root.add_appenders appender
end

.run(bind_address = "localhost", port = 6667, options = {}) ⇒ Object

Public: start the server

bind_address - what address to bind to port - what port to listen on options - an optional hash of additional configuration

:log_level - defaults to 'info'
:log_to - log to filename (string), IO. defaults to STDOUT
:ssl - use ssl for client connections, defaults to false
:ssl_private_key - if using ssl, private key file to use, defaults to self-signed
:ssl_cert - if using ssl, cert file to use, defaults to self-signed
:ssl_verify_peer - if using ssl, verify client certificates, defaults to false
:daemon - if camper_van should daemonize itself
:pid - the path of the PID file to use.


19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/camper_van/server.rb', line 19

def self.run(bind_address="localhost", port=6667, options={})

  initialize_logging options

  EM.run do
    logger = Logging.logger[self.name]
    logger.info "starting server on #{bind_address}:#{port}"
    EM.start_server bind_address, port, self, options

    if options[:daemon]
      daemonize(logger, options[:pid])
    end

    trap("INT") do
      logger.info "SIGINT, shutting down"
      EM.stop
    end
  end
end

Instance Method Details

#initialize(options = {}) ⇒ Object



98
99
100
# File 'lib/camper_van/server.rb', line 98

def initialize(options={})
  @options = options
end

#post_init(*args) ⇒ Object

Public callback once a server connection is established.

Initializes an IRCD instance for this connection.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/camper_van/server.rb', line 105

def post_init(*args)
  logger.info "got connection from #{remote_ip}"

  # initialize the line-based protocol: IRC is \r\n
  @lt2_delimiter = "\r\n"

  # start up the IRCD for this connection
  @ircd = IRCD.new(self, options)

  if options[:ssl]
    logger.info "starting TLS for #{remote_ip}"
    start_tls(:cert_chain_file => options[:ssl_cert], :private_key_file => options[:ssl_private_key], :verify_peer => options[:ssl_verify_peer])
  end
end

#receive_line(line) ⇒ Object

Public: callback for when a line of the protocol has been received. Delegates the received line to the ircd instance.

line - the line received



124
125
126
127
# File 'lib/camper_van/server.rb', line 124

def receive_line(line)
  logger.debug "irc -> #{line.strip}"
  ircd.receive_line(line)
end

#remote_ipObject

Public: return the remote ip address of the connected client

Returns an IP address string



145
146
147
# File 'lib/camper_van/server.rb', line 145

def remote_ip
  @remote_ip ||= get_peername[4,4].unpack("C4").map { |q| q.to_s }.join(".")
end

#send_line(line) ⇒ Object

Public: send a line to the connected client.

line - the line to send, sans rn delimiter.



132
133
134
135
# File 'lib/camper_van/server.rb', line 132

def send_line(line)
  logger.debug "irc <- #{line}"
  send_data line + "\r\n"
end

#unbindObject

Public: callback when a client disconnects



138
139
140
# File 'lib/camper_van/server.rb', line 138

def unbind
  logger.info "closed connection from #{remote_ip}"
end