diff options
author | Giuseppe Bilotta <giuseppe.bilotta@gmail.com> | 2006-07-05 16:18:18 +0000 |
---|---|---|
committer | Giuseppe Bilotta <giuseppe.bilotta@gmail.com> | 2006-07-05 16:18:18 +0000 |
commit | 602da36df14da2cf1bab2b440e8f39018bba0b3f (patch) | |
tree | f175246393fbda21e4ec9f118d34f73f1e39a27c /lib/rbot | |
parent | 1f834f996fcf3e9ead0e1a4adcdebafc5b52c82e (diff) |
Improve debug output for multiline error messages. Improve exception handling for socket and connection problems. Stop sending pings when disconnected.
Diffstat (limited to 'lib/rbot')
-rw-r--r-- | lib/rbot/ircbot.rb | 81 | ||||
-rw-r--r-- | lib/rbot/ircsocket.rb | 35 |
2 files changed, 64 insertions, 52 deletions
diff --git a/lib/rbot/ircbot.rb b/lib/rbot/ircbot.rb index 8f0a2646..0cfc3f12 100644 --- a/lib/rbot/ircbot.rb +++ b/lib/rbot/ircbot.rb @@ -7,7 +7,9 @@ $debug = false unless $debug def debug(message=nil) if ($debug && message) stamp = Time.now.strftime("%Y/%m/%d %H:%M:%S") - print "D: [#{stamp}] #{message}\n" + message.to_s.each_line { |l| + $stdout.puts "D: [#{stamp}] #{l}" + } $stdout.flush end #yield @@ -38,20 +40,20 @@ module Irc class IrcBot # the bot's current nickname attr_reader :nick - + # the bot's IrcAuth data attr_reader :auth - + # the bot's BotConfig data attr_reader :config - + # the botclass for this bot (determines configdir among other things) attr_reader :botclass - + # used to perform actions periodically (saves configuration once per minute # by default) attr_reader :timer - + # bot's Language data attr_reader :lang @@ -79,7 +81,7 @@ class IrcBot :wizard => true) BotConfig.register BotConfigIntegerValue.new('server.port', :default => 6667, :type => :integer, :requires_restart => true, - :desc => "What port should the bot connect to?", + :desc => "What port should the bot connect to?", :validate => Proc.new {|v| v > 0}, :wizard => true) BotConfig.register BotConfigStringValue.new('server.password', :default => false, :requires_restart => true, @@ -124,7 +126,7 @@ class IrcBot puts "data directory '#{Config::datadir}' not found, did you setup.rb?" exit 2 end - + botclass = "#{Etc.getpwuid(Process::Sys.geteuid)[:dir]}/.rbot" unless botclass #botclass = "#{ENV['HOME']}/.rbot" unless botclass botclass = File.expand_path(botclass) @@ -138,7 +140,7 @@ class IrcBot end FileUtils.cp_r Config::datadir+'/templates', botclass end - + Dir.mkdir("#{botclass}/logs") unless File.exist?("#{botclass}/logs") Dir.mkdir("#{botclass}/registry") unless File.exist?("#{botclass}/registry") @@ -179,11 +181,11 @@ class IrcBot log "MOTD: #{line}", "server" } } - @client[:nicktaken] = proc { |data| + @client[:nicktaken] = proc { |data| nickchg "#{data[:nick]}_" @plugins.delegate "nicktaken", data[:nick] } - @client[:badnick] = proc {|data| + @client[:badnick] = proc {|data| puts "WARNING, bad nick (#{data[:nick]})" } @client[:ping] = proc {|data| @@ -265,7 +267,7 @@ class IrcBot onpart(m) } @client[:kick] = proc {|data| - m = KickMessage.new(self, data[:source], data[:target],data[:channel],data[:message]) + m = KickMessage.new(self, data[:source], data[:target],data[:channel],data[:message]) onkick(m) } @client[:invite] = proc {|data| @@ -325,7 +327,7 @@ class IrcBot begin @socket.connect rescue => e - raise "failed to connect to IRC server at #{@config['server.name']} #{@config['server.port']}: " + e + raise e.class, "failed to connect to IRC server at #{@config['server.name']} #{@config['server.port']}: " + e end @socket.puts "PASS " + @config['server.password'] if @config['server.password'] @socket.puts "NICK #{@nick}\nUSER #{@config['irc.user']} 4 #{@config['server.name']} :Ruby bot. (c) Tom Gilbert" @@ -338,7 +340,7 @@ class IrcBot begin connect @timer.start - + while @socket.connected? if @socket.select break unless reply = @socket.gets @@ -351,8 +353,9 @@ class IrcBot #rescue TimeoutError, SocketError => e rescue SystemExit exit 0 - rescue TimeoutError => e - puts e + rescue TimeoutError, SocketError => e + puts "#{e.class}: #{e}" + debug e.backtrace.join("\n") rescue Exception => e puts "network exception: #{e.inspect}" puts e.backtrace.join("\n") @@ -362,17 +365,18 @@ class IrcBot puts e.backtrace.join("\n") exit 2 end - + puts "disconnected" - @last_ping = nil + + stop_server_pings @channels.clear @socket.clearq - + puts "waiting to reconnect" sleep @config['server.reconnect_wait'] end end - + # type:: message type # where:: message target # message:: message text @@ -456,7 +460,7 @@ class IrcBot @logs[where].puts "[#{stamp}] #{message}" #debug "[#{stamp}] <#{where}> #{message}" end - + # set topic of channel +where+ to +topic+ def topic(where, topic) sendq "TOPIC #{where} :#{topic}" @@ -494,7 +498,7 @@ class IrcBot @socket.shutdown puts "rbot quit (#{message})" end - + # message:: optional IRC quit message # quit IRC, shutdown the bot def quit(message=nil) @@ -529,7 +533,7 @@ class IrcBot @plugins.rescan @keywords.rescan end - + # channel:: channel to join # key:: optional channel key if channel is +s # join a channel @@ -555,7 +559,7 @@ class IrcBot def mode(channel, mode, target) sendq "MODE #{channel} #{mode} #{target}" end - + # m:: message asking for help # topic:: optional topic help is requested for # respond to online help requests @@ -597,16 +601,7 @@ class IrcBot # we'll ping the server every 30 seconds or so, and expect a response # before the next one come around.. def start_server_pings - @last_ping = nil - # stop existing timers if running - unless @ping_timer.nil? - @timer.remove @ping_timer - @ping_timer = nil - end - unless @pong_timer.nil? - @timer.remove @pong_timer - @pong_timer = nil - end + stop_server_pings return unless @config['server.ping_timeout'] > 0 # we want to respond to a hung server within 30 secs or so @ping_timer = @timer.add(30) { @@ -622,15 +617,27 @@ class IrcBot @socket.shutdown rescue debug "couldn't shutdown connection (already shutdown?)" - ensure - raise TimeoutError, "no PONG from server in #{diff} seconds" end @last_ping = nil + raise TimeoutError, "no PONG from server in #{diff} seconds" end end } end + def stop_server_pings + @last_ping = nil + # stop existing timers if running + unless @ping_timer.nil? + @timer.remove @ping_timer + @ping_timer = nil + end + unless @pong_timer.nil? + @timer.remove @pong_timer + @pong_timer = nil + end + end + private # handle help requests for "core" topics @@ -849,7 +856,7 @@ class IrcBot # exit 2 end end - + # delegate to plugins @plugins.delegate("listen", m) @plugins.delegate("part", m) diff --git a/lib/rbot/ircsocket.rb b/lib/rbot/ircsocket.rb index 6ff93725..6a5f281a 100644 --- a/lib/rbot/ircsocket.rb +++ b/lib/rbot/ircsocket.rb @@ -9,16 +9,16 @@ module Irc class IrcSocket # total number of lines sent to the irc server attr_reader :lines_sent - + # total number of lines received from the irc server attr_reader :lines_received - + # delay between lines sent attr_reader :sendq_delay - + # max lines to burst attr_reader :sendq_burst - + # server:: server to connect to # port:: IRCd port # host:: optional local host to bind to (ruby 1.7+ required) @@ -48,7 +48,7 @@ module Irc @sendq_burst = 4 end end - + def connected? !@sock.nil? end @@ -56,7 +56,8 @@ module Irc # open a TCP connection to the server def connect if connected? - shutdown + debug "reconnecting socket while connected" + shutdown end if(@host) begin @@ -70,7 +71,7 @@ module Irc end else @sock=TCPSocket.new(@server, @port) - end + end @qthread = false @qmutex = Mutex.new @sendq = Array.new @@ -106,15 +107,19 @@ module Irc # get the next line from the server (blocks) def gets + if @sock.nil? + debug "socket get attempted while closed" + return nil + end begin - reply = @sock.gets - @lines_received += 1 - reply.strip! if reply - debug "RECV: #{reply.inspect}" - return reply + reply = @sock.gets + @lines_received += 1 + reply.strip! if reply + debug "RECV: #{reply.inspect}" + return reply rescue => e - debug "socket get failed: #{e}" - return nil + debug "socket get failed: #{e.inspect}" + return nil end end @@ -183,7 +188,7 @@ module Irc end private - + # same as puts, but expects to be called with a mutex held on @qmutex def puts_critical(message) # debug "in puts_critical" |