7 # wrapped TCPSocket for communication with the server.
8 # emulates a subset of TCPSocket functionality
10 # total number of lines sent to the irc server
11 attr_reader :lines_sent
13 # total number of lines received from the irc server
14 attr_reader :lines_received
16 # delay between lines sent
17 attr_reader :sendq_delay
20 attr_reader :sendq_burst
22 # server:: server to connect to
24 # host:: optional local host to bind to (ruby 1.7+ required)
25 # create a new IrcSocket
26 def initialize(server, port, host, sendq_delay=2, sendq_burst=4)
27 @timer = Timer::Timer.new
39 @sendq_delay = sendq_delay.to_f
43 @last_send = Time.new - @sendq_delay
46 @sendq_burst = sendq_burst.to_i
56 # open a TCP connection to the server
59 debug "reconnecting socket while connected"
64 @sock=TCPSocket.new(@server, @port, @host)
65 rescue ArgumentError => e
66 $stderr.puts "Your version of ruby does not support binding to a "
67 $stderr.puts "specific local address, please upgrade if you wish "
68 $stderr.puts "to use HOST = foo"
69 $stderr.puts "(this option has been disabled in order to continue)"
70 @sock=TCPSocket.new(@server, @port)
73 @sock=TCPSocket.new(@server, @port)
80 def sendq_delay=(newfreq)
81 debug "changing sendq frequency to #{newfreq}"
82 @qmutex.synchronize do
83 @sendq_delay = newfreq
93 def sendq_burst=(newburst)
94 @qmutex.synchronize do
95 @sendq_burst = newburst
99 # used to send lines to the remote IRCd
100 # message: IRC message to send
102 @qmutex.synchronize do
103 # debug "In puts - got mutex"
104 puts_critical(message)
108 # get the next line from the server (blocks)
111 debug "socket get attempted while closed"
117 reply.strip! if reply
118 debug "RECV: #{reply.inspect}"
121 debug "socket get failed: #{e.inspect}"
128 @qmutex.synchronize do
133 # just send it if queueing is disabled
138 # pop a message off the queue, send it
145 if (now >= (@last_send + @sendq_delay))
146 # reset burst counter after @sendq_delay has passed
148 debug "in spool, resetting @burst"
149 elsif (@burst >= @sendq_burst)
150 # nope. can't send anything, come back to us next tick...
154 @qmutex.synchronize do
155 debug "(can send #{@sendq_burst - @burst} lines, there are #{@sendq.length} to send)"
156 (@sendq_burst - @burst).times do
157 break if @sendq.empty?
158 puts_critical(@sendq.shift)
169 @qmutex.synchronize do
176 # flush the TCPSocket
181 # Wraps Kernel.select on the socket
182 def select(timeout=nil)
183 Kernel.select([@sock], nil, nil, timeout)
186 # shutdown the connection to the server
188 @sock.shutdown(how) unless @sock.nil?
194 # same as puts, but expects to be called with a mutex held on @qmutex
195 def puts_critical(message)
196 # debug "in puts_critical"
197 debug "SEND: #{message.inspect}"
198 @sock.send(message + "\n",0)
199 @last_send = Time.new