Class: ModSpox::Socket

Inherits:
Object
  • Object
show all
Defined in:
lib/mod_spox/Socket.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bot, server = nil, port = nil, delay = 2, burst_in = 2, burst = 4) ⇒ Socket

factory

MessageFactory to parse messages

server

Server to connect to

port

Port number to connect to

delay

Number of seconds to delay between bursts

burst_in

Number of seconds allowed to burst

burst

Number of lines allowed to be sent within the burst_in time limit

Create a new Socket



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/mod_spox/Socket.rb', line 30

def initialize(bot, server=nil, port=nil, delay=2, burst_in=2, burst=4)
    @pool = bot.pool
    @factory = bot.factory
    @pipeline = bot.pipeline
    @dcc = bot.dcc_sockets
    @server = server
    @port = port
    @sent = 0
    @received = 0
    @delay = delay.to_f > 0 ? delay.to_f : 2.0
    @burst = burst.to_i > 0 ? burst.to_i : 4
    @burst_in = 2
    @kill = false
    @time_check = nil
    @check_burst = 0
    @pause = false
    @sendq = PriorityQueue.new
    @lock = Mutex.new
    @ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
    @connected_at = nil
    @empty_lines = 0
    @max_empty = 5
    @servers = Array.new
    @connect_locker = Mutex.new
end

Instance Attribute Details

#burstObject

Returns the value of attribute burst.



15
16
17
# File 'lib/mod_spox/Socket.rb', line 15

def burst
  @burst
end

#burst_inObject

Returns the value of attribute burst_in.



16
17
18
# File 'lib/mod_spox/Socket.rb', line 16

def burst_in
  @burst_in
end

#connected_atObject (readonly)

Returns the value of attribute connected_at.



21
22
23
# File 'lib/mod_spox/Socket.rb', line 21

def connected_at
  @connected_at
end

#delayObject

Returns the value of attribute delay.



17
18
19
# File 'lib/mod_spox/Socket.rb', line 17

def delay
  @delay
end

#portObject (readonly)

Returns the value of attribute port.



19
20
21
# File 'lib/mod_spox/Socket.rb', line 19

def port
  @port
end

#receivedObject (readonly)

Returns the value of attribute received.



14
15
16
# File 'lib/mod_spox/Socket.rb', line 14

def received
  @received
end

#sentObject (readonly)

Returns the value of attribute sent.



13
14
15
# File 'lib/mod_spox/Socket.rb', line 13

def sent
  @sent
end

#serverObject (readonly)

Returns the value of attribute server.



18
19
20
# File 'lib/mod_spox/Socket.rb', line 18

def server
  @server
end

#socketObject (readonly)

Returns the value of attribute socket.



20
21
22
# File 'lib/mod_spox/Socket.rb', line 20

def socket
  @socket
end

Instance Method Details

#<<(message) ⇒ Object

message

String to be sent to server

Queues a message up to be sent to the IRC server



138
139
140
141
# File 'lib/mod_spox/Socket.rb', line 138

def <<(message)
    @sendq.direct_queue(message)
    @pool.process{ processor }
end

#connectObject

Connects to the IRC server



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/mod_spox/Socket.rb', line 57

def connect
    return unless @connect_locker.try_lock
    begin
        populate_servers if @servers.empty?
        s = @servers.pop
        @server = s.host
        @port = s.port.to_i
        Logger.info("Establishing connection to #{@server}:#{@port}")
        @socket = TCPSocket.new(@server, @port)
        @socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true)
        @empty_lines = 0
        s.connected = true
        s.save
        @connected_at = Time.now
        @pipeline << Messages::Internal::Connected.new(@server, @port)
    ensure
        @connect_locker.unlock
    end
end

#prioritize_message(target, message) ⇒ Object

target

Target for outgoing message

message

Message to send

This queues a message to be sent out of a prioritized queue. This allows for even message distribution rather than only on target at a time being flooded.



148
149
150
151
# File 'lib/mod_spox/Socket.rb', line 148

def prioritize_message(target, message)
    @sendq.priority_queue(target, message)
    @pool.process{ processor }
end

#process(string) ⇒ Object

string

string to be processed

Process a string



125
126
127
128
129
130
131
132
133
134
# File 'lib/mod_spox/Socket.rb', line 125

def process(string)
    string.strip!
    Logger.info(">> #{string}")
    if(string[0,5] == 'ERROR')
        @pipeline << Messages::Internal::Disconnected.new
        raise Exceptions::Disconnected.new
    end
    @received += 1
    @factory << string
end

#processorObject

Starts the thread for sending messages to the server



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/mod_spox/Socket.rb', line 154

def processor
    return unless @lock.try_lock
    did_write = false
    begin
        loop do
            write(@sendq.pop)
            did_write = true
            if((Time.now.to_i - @time_check) > @burst_in)
                @time_check = nil
                @check_burst = 0
            elsif((Time.now.to_i - @time_check) <= @burst_in && @check_burst >= @burst)
                Logger.warn("Burst limit hit. Output paused for: #{@delay} seconds")
                sleep(@delay)
                @time_check = nil
                @check_burst = 0
            end
        end
    rescue Exceptions::EmptyQueue => boom
        Logger.info('Socket reached an empty queue.')
    ensure
        @lock.unlock
        @pool.process{ processor } if did_write
    end
end

#puts(message) ⇒ Object

message

String to send to server

Sends a string to the IRC server



100
101
102
# File 'lib/mod_spox/Socket.rb', line 100

def puts(message)
    write(message)
end

#shutdown(restart = false) ⇒ Object

restart

Reconnect after closing connection

Closes connection to IRC server



181
182
183
184
185
186
187
188
189
# File 'lib/mod_spox/Socket.rb', line 181

def shutdown(restart=false)
    @socket.close unless @socket.nil? || @socket.closed?
    @kill = true
    server = Models::Server.find_or_create(:host => @server, :port => @port)
    server.connected = false
    server.save
    sleep(0.1)
    connect if restart
end

#write(message) ⇒ Object

message

String to send to server

Sends a string to the IRC server



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/mod_spox/Socket.rb', line 106

def write(message)
    return if message.nil?
    begin
        @socket.puts(message + "\n")
        @socket.flush
        Logger.info("<< #{message}")
        @last_send = Time.new
        @sent += 1
        @check_burst += 1
        @time_check = Time.now.to_i if @time_check.nil?
    rescue Object => boom
        Logger.warn("Failed to write message to server. #{boom}")
        @pipeline << Messages::Internal::Disconnected.new
        raise Exceptions::Disconnected.new
    end
end