class EventMachine::IRC::ConnectedClient

Attributes

channels[R]
nick[R]
realname[R]
state[R]
user[R]

Public Class Methods

new(server) click to toggle source
# File lib/eventmachine/irc/server.rb, line 54
def initialize(server)
  @server = server
  @channels = Array.new
  @nick = nil
  @user = nil
  @pass = nil
  @last_ping = Time.now
  @last_pong = Time.now
  @state = {}
  @welcomed = false
  @nick_tries = 0
end

Public Instance Methods

handle_abort() click to toggle source
# File lib/eventmachine/irc/server.rb, line 446
def handle_abort()
        handle_quit('aborted..')
end
handle_away(msg) click to toggle source
# File lib/eventmachine/irc/server.rb, line 356
def handle_away(msg)
        carp "handle away :#{msg}"
        if msg.nil? or msg =~ /^ *$/
                @state.delete(:away)
                repl_unaway
        else
                @state[:away] = msg
                repl_nowaway
        end
end
handle_connect() click to toggle source
# File lib/eventmachine/irc/server.rb, line 463
def handle_connect
        reply :raw, "NOTICE AUTH :#{Server.config['version']} initialized, welcome."
end
handle_eval(s) click to toggle source
# File lib/eventmachine/irc/server.rb, line 454
def handle_eval(s)
        reply :raw, eval(s)
end
handle_join(channel) click to toggle source
# File lib/eventmachine/irc/server.rb, line 81
def handle_join(channel)
  @channels << channel
end
handle_list(channel) click to toggle source
# File lib/eventmachine/irc/server.rb, line 367
def handle_list(channel)
        reply :numeric, LISTSTART
        case channel.strip
        when /^#/
                channel.split(/,/).each {|cname|
                        c = Server.channel_store[cname.strip]
                        reply :numeric, LIST, c.name, c.topic if c
                }
        else
                #older opera client sends LIST <1000
                #we wont obey the boolean after list, but allow the listing
                #nonetheless
                Server.channel_store.each_channel {|c|
                        reply :numeric, LIST, c.name, c.topic
                }
        end
        reply :numeric, LISTEND
end
handle_mode(target, rest) click to toggle source
# File lib/eventmachine/irc/server.rb, line 429
def handle_mode(target, rest)
        #TODO: dummy
        reply :mode, target, rest
end
handle_names(channels, server) click to toggle source
# File lib/eventmachine/irc/server.rb, line 403
def handle_names(channels, server)
        channels.split(/,/).each {|ch| send_nameslist(ch.strip) }
end
handle_newconnect(nick) click to toggle source
# File lib/eventmachine/irc/server.rb, line 137
def handle_newconnect(nick)
        @alive = true
        @nick = nick
        @host = Server.config['hostname']
        @ver = Server.config['version']
        @starttime = Server.config['starttime']
        send_welcome if !@user.nil?
end
handle_nick(nick) click to toggle source
# File lib/eventmachine/irc/server.rb, line 85
def handle_nick(nick)
          carp "nick => #{nick}"
          if Server.user_store[nick].nil?
                  userlist = {}
                  if @nick.nil?
                          handle_newconnect(nick)
                  else
                          userlist[nick] = self if self.nick != nick
                          Server.user_store.delete(@nick)
                          @nick = nick
                  end

                  Server.user_store << self

                  #send the info to the world
                  #get unique users.
                  @channels.each { |c|
                          Server.channel_store[c].each_user { |u|
                                  userlist[u.nick] = u
                          }
                  }
                  userlist.values.each {|user|
                          user.reply :nick, nick
                  }
                  @usermsg = ":#{@nick}!~#{@user}@#{@peername}"
          else
                  #check if we are just nicking ourselves.
                  unless Server.user_store[nick] == self
                          #verify the connectivity of earlier guy
                                  reply :numeric, ERR_NICKNAMEINUSE, "* #{nick} ", "Nickname is already in use."
                                  @nick_tries += 1
                                  if @nick_tries > Server.config['nick-tries']
                                          carp "kicking spurious user #{nick} after #{@nick_tries} tries"
                                          handle_abort
                                  end
                  end
          end
          @nick_tries = 0
end
handle_notice(target, msg) click to toggle source
# File lib/eventmachine/irc/server.rb, line 300
def handle_notice(target, msg)
        case target.strip
        when CHANNEL
                channel= Server.channel_store[target]
                if !channel.nil?
                        channel.notice(msg, self)
                else
                        send_nonick(target)
                end
        else
                user = Server.user_store[target]
                if !user.nil?
                        user.reply :notice, self.userprefix, user.nick, msg
                else
                        send_nonick(target)
                end
        end
end
handle_part(channel, msg) click to toggle source
# File lib/eventmachine/irc/server.rb, line 319
def handle_part(channel, msg)
        if Server.channel_store.channels.include? channel
                if Server.channel_store[channel].part(self, msg)
                        @channels.delete(channel)
                else
                        send_notonchannel channel
                end
        else
                send_nochannel channel
        end
end
handle_pass(pass) click to toggle source
# File lib/eventmachine/irc/server.rb, line 146
def handle_pass(pass)
  @pass = pass
end
handle_ping(pingmsg, rest) click to toggle source
# File lib/eventmachine/irc/server.rb, line 270
def handle_ping(pingmsg, rest)
        reply :pong, pingmsg
end
handle_pong(srv) click to toggle source
# File lib/eventmachine/irc/server.rb, line 274
def handle_pong(srv)
        carp "got pong: #{srv}"
end
handle_privmsg(target, msg) click to toggle source
# File lib/eventmachine/irc/server.rb, line 278
def handle_privmsg(target, msg)
        case target.strip
        when CHANNEL
                channel= Server.channel_store[target]
                if !channel.nil?
                        channel.privatemsg(msg, self)
                else
                        send_nonick(target)
                end
        else
                user = Server.user_store[target]
                if !user.nil?
                        if !user.state[:away].nil?
                                repl_away(user.nick,user.state[:away])
                        end
                        user.reply :privmsg, self.userprefix, user.nick, msg
                else
                        send_nonick(target)
                end
        end
end
handle_quit(msg) click to toggle source
# File lib/eventmachine/irc/server.rb, line 331
def handle_quit(msg)
        #do this to avoid double quit due to 2 threads.
        return if !@alive
        @alive = false
        @channels.each do |channel|
                Server.channel_store[channel].quit(self, msg)
        end
        Server.user_store.delete(self.nick)
        carp "#{self.nick} #{msg}"
@server.close_connection
end
handle_reload(password) click to toggle source
# File lib/eventmachine/irc/server.rb, line 443
def handle_reload(password)
end
handle_topic(channel, topic) click to toggle source
# File lib/eventmachine/irc/server.rb, line 343
def handle_topic(channel, topic)
        carp "handle topic for #{channel}:#{topic}"
        if topic.nil? or topic =~ /^ *$/
                send_topic(channel)
        else
                begin
                        Server.channel_store[channel].topic(topic,self)
                rescue Exception => e
                        carp e
                end
        end
end
handle_unknown(s) click to toggle source
# File lib/eventmachine/irc/server.rb, line 458
def handle_unknown(s)
        carp "unknown:>#{s}<"
        reply :numeric, ERR_UNKNOWNCOMMAND,s, "Unknown command"
end
handle_user(user, mode, unused, realname) click to toggle source
# File lib/eventmachine/irc/server.rb, line 125
def handle_user(user, mode, unused, realname)
  @user = user
  @mode = mode
  @realname = realname
  @usermsg = ":#{@nick}!~#{@user}@#{@peername}"
  send_welcome if !@nick.nil?
end
handle_userhost(nicks) click to toggle source
# File lib/eventmachine/irc/server.rb, line 434
def handle_userhost(nicks)
        info = []
        nicks.split(/,/).each {|nick|
                user = Server.user_store[nick]
                info << user.nick + '=-' + user.nick + '@' + user.peer
        }
        reply :numeric, USERHOST,"", info.join(' ')
end
handle_version() click to toggle source
# File lib/eventmachine/irc/server.rb, line 450
def handle_version()
        reply :numeric, VERSION,"#{Server.config['version']} Ruby IRCD", ""
end
handle_who(mask, rest) click to toggle source
# File lib/eventmachine/irc/server.rb, line 407
def handle_who(mask, rest)
        channel = Server.channel_store[mask]
        hopcount = 0
        if channel.nil?
                #match against all users
                Server.user_store.each_user {|user|
                        reply :numeric, WHOREPLY ,
                        "#{user.channels[0]} #{user.userprefix} #{user.host} #{Server.config['hostname']} #{user.nick} H" , 
                        "#{hopcount} #{user.realname}" if File.fnmatch?(mask, "#{user.host}.#{user.realname}.#{user.nick}")
                }
                reply :numeric, ENDOFWHO, mask, "End of /WHO list."
        else
                #get all users in the channel
                channel.each_user {|user|
                        reply :numeric, WHOREPLY ,
                        "#{mask} #{user.userprefix} #{user.host} #{Server.config['hostname']} #{user.nick} H" , 
                        "#{hopcount} #{user.realname}"
                }
                reply :numeric, ENDOFWHO, mask, "End of /WHO list."
        end
end
handle_whois(target,nicks) click to toggle source
# File lib/eventmachine/irc/server.rb, line 386
def handle_whois(target,nicks)
        #ignore target for now.
        return reply(:numeric, NONICKNAMEGIVEN, "", "No nickname given") if nicks.strip.length == 0
        nicks.split(/,/).each {|nick|
                nick.strip!
                user = Server.user_store[nick]
                if user
                        reply :numeric, WHOISUSER, "#{user.nick} #{user.user} #{user.host} *", "#{user.realname}"
                        reply :numeric, WHOISCHANNELS, user.nick, "#{user.channels.join(' ')}"
                        repl_away user.nick, user.state[:away] if !user.state[:away].nil?
                        reply :numeric, ENDOFWHOIS, user.nick, "End of /WHOIS list"
                else
                        return send_nonick(nick) 
                end
        }
end
host() click to toggle source
# File lib/eventmachine/irc/server.rb, line 67
def host
  # TODO: figure out how to do this with event machine
  return @peername
end
mode() click to toggle source
# File lib/eventmachine/irc/server.rb, line 133
def mode
  return @mode
end
names(channel) click to toggle source
# File lib/eventmachine/irc/server.rb, line 229
def names(channel)
        return Server.channel_store[channel].nicks
end
raw(arg, abrt=false) click to toggle source
# File lib/eventmachine/irc/server.rb, line 513
def raw(arg, abrt=false)
        begin
                carp "--> #{arg}"
                @server.send_data(arg.chomp + "\n") if !arg.nil?
        rescue Exception => e
                carp "<#{self.userprefix}>#{e.message}"
                #carp e.backtrace.join("\n")
                handle_abort()
                raise e if abrt
        end
end
ready() click to toggle source
# File lib/eventmachine/irc/server.rb, line 77
def ready
  return (!@pass.nil? && !@nick.nil?)
end
receive_data(data) click to toggle source
# File lib/eventmachine/irc/server.rb, line 525
def receive_data(data)
          carp "<-- '#{data.strip}'"
          s = if data =~ PREFIX
                  $1
          else
                  data
          end
          case s
          when /^[ ]*$/
                  return
          when /^PASS +(.+)$/i
                  handle_pass($1.strip)
          when /^NICK +(.+)$/i
                  handle_nick($1.strip) #done
          when /^USER +([^ ]+) +([0-9]+) +([^ ]+) +:(.*)$/i
                  handle_user($1, $2, $3, $4) #done
          when /^USER +([^ ]+) +([0-9]+) +([^ ]+) +:*(.*)$/i
                  #opera does this.
                  handle_user($1, $2, $3, $4) #done
          when /^USER ([^ ]+) +[^:]*:(.*)/i
                  #chatzilla does this.
                  handle_user($1, '', '', $3) #done
          when /^JOIN +(.+)$/i
                  handle_join($1) #done
          when /^PING +([^ ]+) *(.*)$/i
                  handle_ping($1, $2) #done
          when /^PONG +:(.+)$/i , /^PONG +(.+)$/i
                  handle_pong($1)
          when /^PRIVMSG +([^ ]+) +:(.*)$/i
                  handle_privmsg($1, $2) #done
          when /^NOTICE +([^ ]+) +(.*)$/i
                  handle_notice($1, $2) #done
          when /^PART :+([^ ]+) *(.*)$/i  
                  #some clients require this.
                  handle_part($1, $2) #done
          when /^PART +([^ ]+) *(.*)$/i
                  handle_part($1, $2) #done
          when /^QUIT :(.*)$/i
                  handle_quit($1) #done
          when /^QUIT *(.*)$/i
                  handle_quit($1) #done
          when /^TOPIC +([^ ]+) *:*(.*)$/i
                  handle_topic($1, $2) #done
          when /^AWAY +:(.*)$/i
                  handle_away($1)
          when /^AWAY +(.*)$/i #for opera
                  handle_away($1)
          when /^:*([^ ])* *AWAY *$/i
                  handle_away(nil)
  when /^AWAY\s*$/i
    handle_away(nil)
          when /^LIST *(.*)$/i
                  handle_list($1)
          when /^WHOIS +([^ ]+) +(.+)$/i
                  handle_whois($1,$2)
          when /^WHOIS +([^ ]+)$/i
                  handle_whois(nil,$1)
          when /^WHO +([^ ]+) *(.*)$/i
                  handle_who($1, $2)
          when /^NAMES +([^ ]+) *(.*)$/i
                  handle_names($1, $2)
          when /^MODE +([^ ]+) *(.*)$/i
                  handle_mode($1, $2)
          when /^USERHOST +:(.+)$/i
                  #besirc does this (not accourding to RFC 2812)
                  handle_userhost($1)
          when /^USERHOST +(.+)$/i
                  handle_userhost($1)
          when /^RELOAD +(.+)$/i
                  handle_reload($1)
          when /^VERSION *$/i
                  handle_version()
          when /^EVAL (.*)$/i
                  #strictly for debug
                  handle_eval($1)
          else
                  handle_unknown(s)
          end
end
repl_away(nick, msg) click to toggle source
# File lib/eventmachine/irc/server.rb, line 188
def repl_away(nick, msg)
        reply :numeric, AWAY, nick, msg
end
repl_bounce(sever, port) click to toggle source
# File lib/eventmachine/irc/server.rb, line 179
def repl_bounce(sever, port)
        reply :numeric, BOUNCE ,"Try server #{server}, port #{port}"
end
repl_created() click to toggle source
# File lib/eventmachine/irc/server.rb, line 171
def repl_created
        reply :numeric, CREATED, @nick, "This server was created #{@starttime}"
end
repl_ison() click to toggle source
# File lib/eventmachine/irc/server.rb, line 183
def repl_ison()
        #XXX TODO
        reply :numeric, ISON,"notimpl"
end
repl_mode() click to toggle source
# File lib/eventmachine/irc/server.rb, line 206
def repl_mode()
end
repl_motd() click to toggle source
# File lib/eventmachine/irc/server.rb, line 200
def repl_motd()
        reply :numeric, MOTDSTART,'', "- Message of the Day"
        reply :numeric, MOTD,'',      "- Do the dance see the source"
        reply :numeric, ENDOFMOTD,'', "- End of /MOTD command."
end
repl_myinfo() click to toggle source
# File lib/eventmachine/irc/server.rb, line 175
def repl_myinfo
        reply :numeric, MYINFO, @nick, "#{@host} #{@ver} #{@server.usermodes} #{@server.channelmodes}"
end
repl_nowaway() click to toggle source
# File lib/eventmachine/irc/server.rb, line 196
def repl_nowaway()
        reply :numeric, NOWAWAY, @nick,"You have been marked as being away"
end
repl_unaway() click to toggle source
# File lib/eventmachine/irc/server.rb, line 192
def repl_unaway()
        reply :numeric, UNAWAY, @nick,"You are no longer marked as being away"
end
repl_welcome() click to toggle source
# File lib/eventmachine/irc/server.rb, line 162
def repl_welcome
        client = "#{@nick}!#{@user}@#{@peername}"
        reply :numeric, WELCOME, @nick, "Welcome to this IRC server #{client}"
end
repl_yourhost() click to toggle source
# File lib/eventmachine/irc/server.rb, line 167
def repl_yourhost
        reply :numeric, YOURHOST, @nick, "Your host is #{@host}, running version #{@ver}"
end
reply(method, *args) click to toggle source
# File lib/eventmachine/irc/server.rb, line 467
def reply(method, *args)
        case method
        when :raw
                arg = *args
                raw arg
        when :ping
                host = *args
                raw "PING :#{host}"
        when :pong
                msg = *args
                # according to rfc 2812 the PONG must be of
                #PONG csd.bu.edu tolsun.oulu.fi
                # PONG message from csd.bu.edu to tolsun.oulu.fi
                # ie no host at the begining
                raw "PONG #{@host} #{@peername} :#{msg}"
        when :join
                user,channel = args
                raw "#{user} JOIN :#{channel}"
        when :part
                user,channel,msg = args
                raw "#{user} PART #{channel} :#{msg}"
        when :quit
                user,msg = args
                raw "#{user} QUIT :#{msg}"
        when :privmsg
                usermsg, channel, msg = args
                raw "#{usermsg} PRIVMSG #{channel} :#{msg}"
        when :notice
                usermsg, channel, msg = args
                raw "#{usermsg} NOTICE #{channel} :#{msg}"
        when :topic
                usermsg, channel, msg = args
                raw "#{usermsg} TOPIC #{channel} :#{msg}"
        when :nick
                nick = *args
                raw "#{@usermsg} NICK :#{nick}"
        when :mode
                nick, rest = args
                raw "#{@usermsg} MODE #{nick} :#{rest}"
        when :numeric
                numeric,msg,detail = args
                server = Server.config['hostname']
                raw ":#{server} #{'%03d'%numeric} #{@nick} #{msg} :#{detail}"
        end
end
send_nameslist(channel) click to toggle source
# File lib/eventmachine/irc/server.rb, line 233
def send_nameslist(channel)
        c =  Server.channel_store[channel]
        if c.nil?
                carp "names failed :#{c}"
                return 
        end
        names = []
        c.each_user {|user|
                names << c.mode(user) + user.nick if user.nick
        }
        reply :numeric, NAMREPLY,"= #{c.name}","#{names.join(' ')}"
        reply :numeric, ENDOFNAMES,"#{c.name} ","End of /NAMES list."
end
send_nochannel(channel) click to toggle source
# File lib/eventmachine/irc/server.rb, line 221
def send_nochannel(channel)
        reply :numeric, ERR_NOSUCHCHANNEL, channel, "That channel doesn't exist"
end
send_nonick(nick) click to toggle source
# File lib/eventmachine/irc/server.rb, line 217
def send_nonick(nick)
        reply :numeric, ERR_NOSUCHNICK, nick, "No such nick/channel"
end
send_notonchannel(channel) click to toggle source
# File lib/eventmachine/irc/server.rb, line 225
def send_notonchannel(channel)
        reply :numeric, ERR_NOTONCHANNEL, channel, "Not a member of that channel"
end
send_ping() click to toggle source
# File lib/eventmachine/irc/server.rb, line 247
def send_ping()
        reply :ping, "#{Server.config['hostname']}"
end
send_topic(channel) click to toggle source
# File lib/eventmachine/irc/server.rb, line 209
def send_topic(channel)
        if Server.channel_store[channel]
                reply :numeric, TOPIC,channel, "#{Server.channel_store[channel].topic}" 
        else
                send_notonchannel channel
        end
end
send_welcome() click to toggle source
# File lib/eventmachine/irc/server.rb, line 150
def send_welcome
        if !@welcomed
                repl_welcome
                repl_yourhost
                repl_created
                repl_myinfo
                repl_motd
                repl_mode
                @welcomed = true
        end
end
userprefix() click to toggle source
# File lib/eventmachine/irc/server.rb, line 72
def userprefix
  # Where is this defined?
  return @usermsg
end