Class: Flexo::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/flexo/server.rb

Overview

The class that does all the socket-works. Using Sender, it sends commands to the server, and, using Dispatcher, gets the responses sent back into Flexo for further processing.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeServer

Returns a new instance of Server.



15
16
17
18
19
20
# File 'lib/flexo/server.rb', line 15

def initialize
  @manager  = Flexo::Manager.instance
  @socket   = nil
  @server   = nil
  @welcomed = false
end

Instance Attribute Details

#nicknameObject (readonly)

Returns the value of attribute nickname.



12
13
14
# File 'lib/flexo/server.rb', line 12

def nickname
  @nickname
end

#serverObject (readonly)

Returns the value of attribute server.



11
12
13
# File 'lib/flexo/server.rb', line 11

def server
  @server
end

#threadObject (readonly)

Returns the value of attribute thread.



10
11
12
# File 'lib/flexo/server.rb', line 10

def thread
  @thread
end

#welcomedObject (readonly)

Returns the value of attribute welcomed.



13
14
15
# File 'lib/flexo/server.rb', line 13

def welcomed
  @welcomed
end

Instance Method Details

#connectObject

Does the connecting, looping through the defined servers, trying the next one if it fails.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/flexo/server.rb', line 60

def connect
  debug "Starting to connect!"
  host = @manager.config['core.hostname'].to_s
  @manager.config['core.server'].each do |server|
    debug "Connecting to #{server[:host]}:#{server[:port]}"
    debug "  using host #{host}" if host.length > 0
    debug "  using SSL" if server[:ssl]
    timeout(30) do
      err = 0
      begin
        if host.length > 0
          @socket = TCPSocket.new(server[:host], server[:port], host)
        else
          @socket = TCPSocket.new(server[:host], server[:port])
        end

        if(server[:ssl])
          begin
            require 'openssl'
          rescue LoadError
            @manager.logger.error "SSL library not available."
            continue
          end
          
          context = OpenSSL::SSL::SSLContext.new()
          # FIXME: Might want to change this one, or at least have it configurable
          context.verify_mode = OpenSSL::SSL::VERIFY_NONE
          @socket = OpenSSL::SSL::SSLSocket.new(@socket, context)
          @socket.sync_close = true
          @socket.connect
        end
      rescue Errno::ECONNREFUSED => h
        msg = "Connection to #{server[:host]} at port #{server[:port]} was refused"
        err = 1
      rescue Errno::EHOSTUNREACH => h
        msg = "#{server[:host]} is unreachable!"
        err = 1
      rescue Timeout::Error => h
        msg = "Connection to #{server[:host]} timed out"
        err = 1
      rescue Errno::EADDRNOTAVAIL => h
        msg = "Unable to assign requested address"
        err = 2
      rescue OpenSSL::SSL::SSLError => h
        msg = "Unable to connect using SSL (#{h.message})"
        err = 1
      end

      if(err != 0)
        @socket = nil
        @manager.logger.warn(msg)
        if err > 1 # Critical error!
          @manager.logger.error("Critical errors encountered!")
          exit 1
        end
      else
        @manager.logger.info("Connected to #{server[:host]}")
        @server = server[:host]
        
        return
      end
    end
  end
end

#debug(line) ⇒ Object

:nodoc:



41
42
43
# File 'lib/flexo/server.rb', line 41

def debug(line) # :nodoc:
  @manager.logger.debug(line)
end

#disconnectObject

Disconnects from the server



155
156
157
# File 'lib/flexo/server.rb', line 155

def disconnect
  @socket.close unless @socket.closed?
end

#loginObject

This function goes through the login-process



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/flexo/server.rb', line 126

def 
  config = @manager.config

  # First, we add a handler to fix things
  # if our nickname is taken
  nicktaken = @manager.dispatcher.subscribe(:ERR_NICKNAMEINUSE) do
    nick = config['core.nick'].shift
    quote "NICK #{nick}"
    @manager.logger.info("Nickname taken, trying #{nick}")
    @manager.nickname = nick
  end

  nick = config['core.nick'].shift
  @manager.sender.nick nick
  @manager.sender.user config['core.username'], 0, config['core.realname']

  @manager.thread do
    @manager.dispatcher.await(:RPL_WELCOME, :timeout => 30) do |reply|
      @manager.mutex do
        @manager.nickname = nick
        @manager.logger.debug "Welcomed!"
        @welcomed = true
      end
      @manager.dispatcher.unsubscribe(nicktaken)
    end
  end
end

#quote(data) ⇒ Object

Called by Sender.quote. This function just writes the prepared line to the socket.



47
48
49
50
51
52
53
54
55
56
# File 'lib/flexo/server.rb', line 47

def quote(data)
  begin
    @socket.print("#{data.chomp}\r\n")
    @socket.flush
  rescue IOError => e
    @manager.logger.error("Connection to #{@server} lost")
    disconnect
    exit 1
  end
end

#reconnect(s = 0) ⇒ Object

Reconnects



160
161
162
163
164
# File 'lib/flexo/server.rb', line 160

def reconnect(s = 0)
  disconnect
  sleep s
  connect
end

#setupObject



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/flexo/server.rb', line 22

def setup
  connect

  @thread = @manager.thread do
    begin
      while line = @socket.gets
        @manager.dispatcher.receive(line)
      end
      disconnect
    rescue Errno::ETIMEDOUT
      @manager.logger.error "Connection lost. Reconnecting"
      reconnect
    rescue Errno::ECONNRESET
      @manager.logger.error "Connection reset by peer. Reconnecting after five seconds"
      reconnect 5
    end
  end
end