Class: ModSpox::Sockets

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bot) ⇒ Sockets

Returns a new instance of Sockets.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/mod_spox/Sockets.rb', line 17

def initialize(bot)
    @bot = bot
    @irc_socket = nil
    @dcc_sockets = []
    @mapped_sockets = {}
    @spockets = Spockets::Spockets.new(:pool => bot.pool)
    @listening_dcc = []
    @dcc_ports = {:start => 49152, :end => 65535}
    @dcc_wait = 30
    @pipeline = bot.pipeline
    @factory = bot.factory
    @pipeline.hook(self, :check_dcc, :Incoming_Privmsg)
    @pipeline.hook(self, :return_socket, :Internal_DCCRequest)
    @pipeline.hook(self, :dcc_listener, :Internal_DCCListener)
    @pipeline.hook(self, :disconnect_irc, :Internal_Disconnected)
    @pipeline.hook(self, :queue_messages, :Internal_QueueSocket)
    @pipeline.hook(self, :unqueue_messages, :Internal_UnqueueSocket)
    @queues = {:irc => Queue.new, :dcc => Queue.new}
    @queue_messages = false
end

Instance Attribute Details

#irc_socketObject (readonly)

Returns the value of attribute irc_socket.



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

def irc_socket
  @irc_socket
end

Instance Method Details

#<<(message) ⇒ Object



63
64
65
66
67
68
69
70
71
72
# File 'lib/mod_spox/Sockets.rb', line 63

def <<(message)
    if(message =~ /::(\S+)::\s:(.+)$/)
        id = $1.to_i
        message = $2 + "\r\n"
        sock_info = @mapped_sockets[id]
        sock_info[:socket] << message
    else
        @irc_socket << message
    end
end

#check_dcc(message) ⇒ Object

message

ModSpox::Messages::Incoming::Privmsg

Checks if incoming message is a request to start a DCC chat session and builds the connection



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/mod_spox/Sockets.rb', line 81

def check_dcc(message)
    if(message.is_ctcp? && message.ctcp_type == 'DCC')
        if(message.message =~ /^CHAT chat (\S+) (\S+)/)
            if(message.source.in_group?('dcc') || message.source.in_group?('admin'))
                ip = IPAddr.new($1.to_i, Object::Socket::AF_INET).to_s
                port = $2.to_i
                build_connection(ip, port, message.source)
            else
                Logger.warn("Error: #{message.source.nick} is attempting to establish DCC connection without permission.")
            end
        end
    end
end

#dcc_listener(message) ⇒ Object

message

ModSpox::Messages::Internal::DCCListener

Sets up a new socket for a user to connect to. Helpful if the user wants a DCC chat session but is firewalled



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/mod_spox/Sockets.rb', line 110

def dcc_listener(message)
    Thread.new do
        me = Models::Nick.filter(:botnick => true).first
        return if me.nil?
        port = rand(@dcc_ports[:end] - @dcc_ports[:start]) + @dcc_ports[:start]
        socket = Object::Socket.new(Object::Socket::AF_INET, Object::Socket::SOCK_STREAM, 0)
        addr = Object::Socket.pack_sockaddr_in(port, me.address)
        socket.bind(addr)
        client = nil
        addrinfo = nil
        cport = nil
        cip = nil
        begin
            Timeout::timeout(@dcc_wait) do
                @pipeline << Messages::Outgoing::Privmsg.new(message.nick, "CHAT chat #{IPAddr.new(me.address).to_i} #{port}", false, true, 'DCC')
                socket.listen(5)
                client, addrinfo = socket.accept
                cport, cip = Object::Socket.unpack_sockaddr_in(addrinfo)
            end
            Logger.info("New DCC socket created for #{message.nick.nick} has connected from: #{cip}:#{cport}")
            @dcc_sockets << client
            @mapped_sockets[client.object_id] = {:socket => client, :nick => message.nick}
            @spockets.add(socket){|string| process_dcc_string(string, socket)}
        rescue Timeout::Error => boom
            Logger.warn("Timeout reached waiting for #{message.nick.nick} to connect to DCC socket. Closing.")
            client.close
        rescue Object => boom
            Logger.warn("Unknown error encountered while building DCC listener for: #{message.nick.nick}. Error: #{boom}")
            client.close
        ensure
            socket.close
        end
    end
end

#disconnect_irc(m = nil) ⇒ Object



154
155
156
# File 'lib/mod_spox/Sockets.rb', line 154

def disconnect_irc(m=nil)
    @spockets.remove(@irc_socket.socket) if @spockets.include?(@irc_socket.socket)
end

#irc_connect(server = nil, port = nil) ⇒ Object

server

IRC server string

port

IRC port

Connect to the given IRC server



41
42
43
44
45
46
47
48
49
50
# File 'lib/mod_spox/Sockets.rb', line 41

def irc_connect(server=nil, port=nil)
    if(@irc_socket.nil?)
        @irc_socket = Socket.new(@bot, server, port)
        @irc_socket.connect
        @spockets.add(@irc_socket.socket){|string| process_irc_string(string)}
        @spockets.on_close(@irc_socket.socket){ irc_reconnect }
    else
        irc_reconnect
    end
end

#irc_reconnectObject



52
53
54
55
56
57
58
59
60
61
# File 'lib/mod_spox/Sockets.rb', line 52

def irc_reconnect
    unless(@irc_socket.nil?)
        disconnect_irc
        @spockets.remove(@irc_socket.socket) if @spockets.include?(@irc_socket)
        @irc_socket.shutdown(true)
        @spockets.add(@irc_socket.socket){|string| process_irc_string(string)}
    else
        irc_connect
    end
end

#prioritize_message(target, message) ⇒ Object



74
75
76
# File 'lib/mod_spox/Sockets.rb', line 74

def prioritize_message(target, message)
    @irc_socket.prioritize_message(target, message)
end

#queue_messages(m) ⇒ Object



163
164
165
# File 'lib/mod_spox/Sockets.rb', line 163

def queue_messages(m)
    @queue_messages = true
end

#return_socket(message) ⇒ Object

message

ModSpox::Messages::Internal::DCCRequest

Returns the DCC Socket requested in a ModSpox::Messages::Internal::DCCSocket message.



98
99
100
101
102
103
104
105
# File 'lib/mod_spox/Sockets.rb', line 98

def return_socket(message)
    socket = nick = nil
    if(@mapped_socks.has_key?(message.socket_id))
        socket = @mapped_socks[message.socket_id][:socket]
        nick = @mapped_socks[message.socket_id][:nick]
    end
    @pipeline << Messages::Internal::DCCSocket.new(message.socket_id, nick, socket)
end

#shutdownObject

Shuts down all active sockets



146
147
148
149
150
151
152
# File 'lib/mod_spox/Sockets.rb', line 146

def shutdown
    @spockets.clear
    @irc_socket.shutdown
    @dcc_sockets.each do |sock|
        close_dcc(sock)
    end
end

#unqueue_messages(m) ⇒ Object



158
159
160
161
# File 'lib/mod_spox/Sockets.rb', line 158

def unqueue_messages(m)
    @queue_messages = false
    flush_queues
end