Class: ShadowsocksRuby::Protocols::ProtocolStack

Inherits:
Object
  • Object
show all
Defined in:
lib/shadowsocks_ruby/protocols/protocol_stack.rb

Overview

Factory class for build protocol stacks

Instance Method Summary collapse

Constructor Details

#initialize(cfg_ary, cipher_name, password, protocol_type) ⇒ Object

Returns ProtocolStack an ProtocolStack object.

Examples:

This is what a cfg_ary Array look like

[ 
  ["some_packet_protocol_name"], # a packet protocol is required
  ["some_cipher_protocol_name", {:cipher => "some_cipher_object"}], # a cipher protocol is optional
  ["some_obfs_protocol_name", {:obfs_params => "..."}] # a obfs protocol is optional
]

Parameters:

  • cfg_ary (Array)
  • cipher_name (String)
  • password (password)
  • protocol_type (String)

    Protocol Type, can be “TCP”, “UDP”


23
24
25
26
27
28
29
30
31
# File 'lib/shadowsocks_ruby/protocols/protocol_stack.rb', line 23

def initialize cfg_ary, cipher_name, password, protocol_type
  @cfg_ary = cfg_ary.map do |protocol_name, param|
    protocol_module = protocol_name.to_camel_case + "Protocol"
    protocol_module = Protocols.const_get(protocol_module).const_get(protocol_type)
    [protocol_module, param ||= {}]
  end
  @cipher_name = cipher_name
  @password = password
end

Instance Method Details

#build!(conn) ⇒ Object

Factory method for build a protocol stack

Parameters:

  • conn (EventMachine::Connection)

Returns:

  • top protocol (packet protocol) in the stack


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/shadowsocks_ruby/protocols/protocol_stack.rb', line 37

def build! conn
  cipher = nil

  protocols = @cfg_ary.map do | protocol_module, params|
    case protocol_module.to_s
    when /#{Protocols::PlainProtocol.to_s}/, /#{Protocols::Socks5Protocol.to_s}/, \
      /#{Protocols::ShadowsocksProtocol.to_s}/, /#{Protocols::HttpSimpleProtocol.to_s}/
      # do nothing, these are known protocols don't need cipher
    when /#{Protocols::TlsTicketProtocol.to_s}/
      # this protocol need a key
      params = {:key => (cipher ||= Cipher.build(@cipher_name, @password)).key}.merge(params)
    else
      params = {:cipher => (cipher ||= Cipher.build(@cipher_name, @password))}.merge(params)
    end

    case
    when conn.is_a?(ShadowsocksRuby::Connections::ClientConnection)
      klass = protocol_module.const_get("Client")
    when conn.is_a?(ShadowsocksRuby::Connections::RemoteServerConnection)
      protocol_module.const_get("RemoteServer")
    when conn.is_a?(ShadowsocksRuby::Connections::LocalBackendConnection)
      protocol_module.const_get("LocalBackend")
    when conn.is_a?(ShadowsocksRuby::Connections::DestinationConnection)
      protocol_module.const_get("Destination")
    end
    
    klass.new(params)
  end


  protocols.each_cons(2) do | p, p1 |
    p.next_protocol = p1
  end

  protocols.last.tap do |p|
    p.next_protocol = conn
  end
  
  protocols.first
end