class Citrus::Components::Connector

Connector

Public Class Methods

new(app, args={}) click to toggle source

Initialize the component

@param [Object] app @param [Hash] args

# File lib/citrus/components/connector.rb, line 22
def initialize app, args={}
  @app = app
  @connector = get_connector args

  @encode = args[:encode]
  @decode = args[:decode]

  @blacklist_cb = args[:black_list_cb]
  @black_lists = []

  @server = nil
  @session = nil
  @connection = nil
end

Public Instance Methods

after_start(&block) click to toggle source

Component lifecycle callback

# File lib/citrus/components/connector.rb, line 61
def after_start &block
  @connector.start &block
  @connector.on(:connection) { |socket| host_filter socket }
end
send(req_id, route, msg, recvs, args) { |exception 'failed to send message for encode result is empty'| ... } click to toggle source

Send message to the client

@param [Integer] req_id @param [String] route @param [Hash] msg @param [Array] recvs @param [Hash] args

# File lib/citrus/components/connector.rb, line 82
def send req_id, route, msg, recvs, args, &block
  if @encode
    # use customized encode
    msg = @encode.call self, req_id, route, msg
  elsif @connector.respond_to? :encode
    # use connector default encode
    msg = @connector.encode req_id, route, msg
  end

  if msg.empty?
    EM.next_tick {
      block_given? and yield Exception.new 'failed to send message for encode result is empty'
    }
    return
  end

  @app.components['push_scheduler'].schedule req_id, route, msg, recvs, args, &block
end
start() { |exception 'failed to start connector component for server component not loaded'| ... } click to toggle source

Start the component

# File lib/citrus/components/connector.rb, line 38
def start &block
  @server = @app.components['server']
  @session = @app.components['session']
  @connection = @app.components['connection']

  unless @server
    EM.next_tick {
      block_given? and yield Exception.new 'failed to start connector component for server component not loaded'
    }
    return
  end

  unless @session
    EM.next_tick {
      block_given? and yield Exception.new 'failed to start connector component for session component not loaded'
    }
    return
  end

  EM.next_tick { block_given? and yield }
end
stop(force=false) { || ... } click to toggle source

Stop the component

# File lib/citrus/components/connector.rb, line 67
def stop force=false, &block
  if @connector
    @connector.stop force, &block
    @connector = nil
  end
  EM.next_tick { block_given? and yield }
end

Private Instance Methods

bind_events(socket) click to toggle source

Bind events

@param [Object] socket

@private

# File lib/citrus/components/connector.rb, line 147
def bind_events socket
  if @connection
    @connection.increase_conn_count

    conn_count = @connection.get_statistics_info[:conn_count]
    max_conns = @app.cur_server[:max_conns]

    socket.disconnect; return if conn_count > max_conns
  end

  # Create session for connection
  session = get_session socket
  closed = false

  socket.on(:disconnect) {
    return if closed
    closed = true
    if @connection
      @connection.decrease_conn_count session.uid
    end
  }

  socket.on(:error) {
    return if closed
    closed = true
    if @connection
      @connection.decrease_conn_count session.uid
    end
  }

  socket.on(:message) { |msg|
    if @decode
      msg = @decode.call msg
    elsif @connector.decode
      msg = @connector.decode msg
    end
    # discard invalid message
    return unless msg

    handle_message session, msg
  }
end
check_server_type(route) click to toggle source

Get server type from the request message

@param [String] route

@private

# File lib/citrus/components/connector.rb, line 258
def check_server_type route
  return nil unless route
  return nil unless (idx = route.index '.')
  route[0..idx-1]
end
get_connector(args={}) click to toggle source

Get the connector

@param [Hash] args

@private

# File lib/citrus/components/connector.rb, line 108
def get_connector args={}
  unless connector = args[:connector]
    return get_default_connector args
  end

  port = @app.cur_server[:client_port]
  host = @app.cur_server[:host]

  connector.new port, host, args
end
get_default_connector(args={}) click to toggle source

Get the default connector

@param [Hash] args

@private

# File lib/citrus/components/connector.rb, line 124
def get_default_connector args={}
  require 'citrus/connectors/ws_connector'

  port = @app.cur_server[:client_port]
  host = @app.cur_server[:host]

  Connectors::WsConnector.new port, host, args
end
get_session(socket) click to toggle source

Get session

@param [Object] socket

@private

# File lib/citrus/components/connector.rb, line 195
def get_session socket
  sid = socket.id
  session = @session.get sid
  return session if session

  session = @session.create sid, @app.server_id, socket

  socket.on(:disconnect) { session.closed }
  socket.on(:error) { session.closed }

  session.on(:closed) { |session, reason|
    @app.emit :close_session, reason
  }

  session.on(:bind) { |uid|
    if @connection
      @connection.add_logined_user(uid, {
        :login_time => Time.now.to_f,
        :uid => uid,
        :address => socket.remote_address[:ip] + ':' + socket.remote_address[:port]
      })
    end

    @app.emit :bind_session, session
  }

  session.on(:unbind) { |uid|
    @app.emit :unbind_session, session
  }

  session
end
handle_message(session, msg) click to toggle source

Handle message

@param [Object] session @param [Hash] msg

@private

# File lib/citrus/components/connector.rb, line 234
def handle_message session, msg
  type = check_server_type msg['route']
  unless type
    return
  end

  @server.global_handle(msg, session.to_frontend_session) { |err, resp, args|
    unless msg['id']
      return
    end

    resp = {} unless resp
    resp['code'] = 500 if err

    args = { :type => 'response', :user_args => args || {} }
    send(msg['id'], msg['route'], resp, session.id, args) {}
  }
end
host_filter(socket) click to toggle source

Host filter

@param [Object] socket

@private

# File lib/citrus/components/connector.rb, line 138
def host_filter socket
  bind_events socket
end