6 # wrapped TCPSocket for communication with the server.
7 # emulates a subset of TCPSocket functionality
9 # total number of lines sent to the irc server
10 attr_reader :lines_sent
12 # total number of lines received from the irc server
13 attr_reader :lines_received
15 # delay between lines sent
16 attr_reader :sendq_delay
19 attr_reader :sendq_burst
21 # server:: server to connect to
23 # host:: optional local host to bind to (ruby 1.7+ required)
24 # create a new IrcSocket
25 def initialize(server, port, host, sendq_delay=2, sendq_burst=4)
32 @sendq_delay = sendq_delay.to_f
36 @last_send = Time.new - @sendq_delay
39 @sendq_burst = sendq_burst.to_i
45 # open a TCP connection to the server
49 @sock=TCPSocket.new(@server, @port, @host)
50 rescue ArgumentError => e
51 $stderr.puts "Your version of ruby does not support binding to a "
52 $stderr.puts "specific local address, please upgrade if you wish "
53 $stderr.puts "to use HOST = foo"
54 $stderr.puts "(this option has been disabled in order to continue)"
55 @sock=TCPSocket.new(@server, @port)
58 @sock=TCPSocket.new(@server, @port)
64 @qthread = Thread.new { spooler }
68 def sendq_delay=(newfreq)
69 debug "changing sendq frequency to #{newfreq}"
70 @qmutex.synchronize do
71 @sendq_delay = newfreq
72 if newfreq == 0 && @qthread
76 elsif(newfreq != 0 && !@qthread)
77 @qthread = Thread.new { spooler }
82 def sendq_burst=(newburst)
83 @qmutex.synchronize do
84 @sendq_burst = newburst
88 # used to send lines to the remote IRCd
89 # message: IRC message to send
91 @qmutex.synchronize do
92 # debug "In puts - got mutex"
93 puts_critical(message)
97 # get the next line from the server (blocks)
104 debug "RECV: #{reply.inspect}"
110 @qmutex.synchronize do
111 # debug "QUEUEING: #{msg}"
115 # just send it if queueing is disabled
127 # pop a message off the queue, send it
131 if (now >= (@last_send + @sendq_delay))
132 # reset burst counter after @sendq_delay has passed
134 debug "in spool, resetting @burst"
135 elsif (@burst >= @sendq_burst)
136 # nope. can't send anything
139 @qmutex.synchronize do
140 debug "(can send #{@sendq_burst - @burst} lines, there are #{@sendq.length} to send)"
141 (@sendq_burst - @burst).times do
142 break if @sendq.empty?
143 puts_critical(@sendq.shift)
151 @qmutex.synchronize do
157 # flush the TCPSocket
162 # Wraps Kernel.select on the socket
164 Kernel.select([@sock], nil, nil, timeout)
167 # shutdown the connection to the server
174 # same as puts, but expects to be called with a mutex held on @qmutex
175 def puts_critical(message)
176 # debug "in puts_critical"
177 debug "SEND: #{message.inspect}"
178 @sock.send(message + "\n",0)
179 @last_send = Time.new