class Syndi::IRC::Protocol

A class for parsing of data per the specifications of the IRC protocol, v3.1.

@see tools.ietf.org/html/rfc1459 @see ircv3.atheme.org/

@since 4.0.0

Public Class Methods

new(lib) click to toggle source

Construct a new IRC data parser.

@param [Syndi::IRC::Library] lib The IRC library instance.

# File lib/syndi/irc/protocol.rb, line 21
def initialize lib
  extend Syndi::IRC::Protocol::Numerics
  lib.events.on :receive, &method(:parse)
end

Public Instance Methods

on_authenticate(irc, raw, params) click to toggle source

AUTHENTICATE

@param [Syndi::IRC::Server] irc The IRC connection. @param [String] raw The data received. @param [Array<String>] params The data received divided by \s through

regexp.
# File lib/syndi/irc/protocol.rb, line 48
def on_authenticate irc, raw, params
  username = $m.conf['irc'][irc.s]['SASL']['username']
  password = $m.conf['irc'][irc.s]['SASL']['password']
  
  if irc.supp.sasl_method    == :dh_blowfish
    crypt = Syndi::IRC::SASL::Mech::DHBlowfish.encrypt(username, password, params.last)
  elsif irc.supp.sasl_method == :plain
    crypt = Syndi::IRC::SASL::Mech::Plain.encrypt(username, password, params.last)
  end

  while crypt.length >= 400
    irc.snd "AUTHENTICATE #{crypt.slice!(0, 400)}"
  end

  if crypt.length > 0
    irc.snd "AUTHENTICATE #{crypt}"
  else
    irc.snd('AUTHENTICATE +')
  end
  # And we're done!
end
on_cap(irc, raw, params) click to toggle source

CAP

@param [Syndi::IRC::Server] irc The IRC connection. @param [String] raw The data received. @param [Array<String>] params The data received divided by \s through

regexp.
# File lib/syndi/irc/protocol.rb, line 76
def on_cap irc, raw, params
  case params[3]

  when 'LS'
    params[4].gsub!(/^:/, '')
    cap_ls(irc, params[4..-1])
  when 'ACK'
    params[4].gsub!(/^:/, '')
    cap_ack(irc, params[4..-1])
  end
end
on_ping(irc, raw, params) click to toggle source

PING

Return a PONG.

@param [Syndi::IRC::Server] irc The IRC connection. @param [String] raw The data received. @param [Array<String>] params The data received divided by \s through

regexp.
# File lib/syndi/irc/protocol.rb, line 96
def on_ping irc, raw, params
  irc.snd("PONG #{params[1]}")
end
parse(irc, raw) click to toggle source

Parse IRC data.

@param [Syndi::IRC::Server] irc The IRC connection. @param [String] raw The data received.

# File lib/syndi/irc/protocol.rb, line 30
def parse irc, raw
    
  params  = raw.split(/\s+/)
  command = (raw =~ /^:/ ? params[1] : params[0]).dc

  # Check if we process this command.
  if respond_to? "on_#{command}"
    send("on_#{command}", irc, raw, params)
  end

end

Private Instance Methods

cap_ack(irc, list) click to toggle source

CAP ACK

We must save all capabilities into irc.supp.cap, and initiate SASL if possible.

@param [Syndi::IRC::Server] irc The IRC connection. @param [Array<String>] list List of capabilities.

# File lib/syndi/irc/protocol.rb, line 138
def cap_ack irc, list

  irc.supp.cap = list
    
  if list.include? 'sasl'
    irc.supp.sasl_id << $m.clock.spawn($m.conf['irc'][irc.s]['SASL']['timeout']||10, :once, irc) do |s|
      $m.error "SASL authentication on #{s} failed: authentication procedure timed out."
      s.snd('AUTHENTICATE *')
      s.cap_end
    end
    irc.authenticate :dh_blowfish
  else
    irc.snd('CAP END') # end capability negotiation and complete registration
  end

end
cap_ls(irc, list) click to toggle source

CAP LS

Currently, Syndi's capabilities include the multi-prefix, sasl, account-notify, away-notify, and extended-join extensions.

@param [Syndi::IRC::Server] irc The IRC connection. @param [Array<String>] list List of capabilities.

# File lib/syndi/irc/protocol.rb, line 111
def cap_ls irc, list

  req = []
    
  # Every extension possible will be used except SASL, which requires
  # special configuration.
  %w[multi-prefix account-notify away-notify extended-join].each do |ext|
    req.push ext if list.include? ext
  end

  if $m.conf['irc'][irc.s]['SASL'] and list.include? 'sasl'
    require 'syndi/irc/sasl/mech'
    req.push 'sasl'
  end

  # Send CAP REQ.
  irc.snd("CAP REQ :#{req.join(' ')}") unless req.empty?

end