diff --git a/chain.go b/chain.go index f4dc6dd..f2a5eb0 100644 --- a/chain.go +++ b/chain.go @@ -556,3 +556,7 @@ func (c *ProxyChain) getQuicConn(header http.Header) (net.Conn, error) { conn.remoteAddr, _ = net.ResolveUDPAddr("udp", quicNode.Addr) return conn, nil } + +type Chain struct { + nodes []Node +} diff --git a/client.go b/client.go new file mode 100644 index 0000000..e43cfea --- /dev/null +++ b/client.go @@ -0,0 +1,10 @@ +package gost + +import "net" + +// Client represents a node client +type Client interface { + Connect() (net.Conn, error) + Handshake(conn net.Conn) (net.Conn, error) + Dial(conn net.Conn, addr string) (net.Conn, error) +} diff --git a/node.go b/node.go index bc22387..26b4fdf 100644 --- a/node.go +++ b/node.go @@ -211,3 +211,11 @@ func (node *ProxyNode) keyFile() string { func (node ProxyNode) String() string { return fmt.Sprintf("transport: %s, protocol: %s, addr: %s, whitelist: %v, blacklist: %v", node.Transport, node.Protocol, node.Addr, node.Whitelist, node.Blacklist) } + +// Node represents a proxy node +type Node interface { + Init(opts ...Option) error + Client() Client + Server() Server + Options() Options +} diff --git a/options.go b/options.go new file mode 100644 index 0000000..55bbe16 --- /dev/null +++ b/options.go @@ -0,0 +1,77 @@ +package gost + +import ( + "log" + "reflect" +) + +// Options holds options of node +type Options interface { + Get(opt string) (v interface{}) + Set(opt string, v interface{}) +} + +type Option func(Options) + +type DefaultOptions struct { + Addr string `opt:"addr"` // [host]:port + Protocol string `opt:"protocol"` // protocol: http/socks5/ss + Transport string `opt:"transport"` // transport: ws/wss/tls/http2/tcp/udp/rtcp/rudp +} + +func (o *DefaultOptions) Get(opt string) interface{} { + return GetOption(o, opt) +} + +func (o *DefaultOptions) Set(opt string, v interface{}) { + SetOption(o, opt, v) +} + +func AddrOption(a string) Option { + return func(opts Options) { + SetOption(opts, "addr", a) + } +} + +func ProtocolOption(p string) Option { + return func(opts Options) { + SetOption(opts, "protocol", p) + } +} + +func TransportOption(t string) Option { + return func(opts Options) { + SetOption(opts, "transport", t) + } +} + +func GetOption(i interface{}, opt string) interface{} { + ps := reflect.ValueOf(i) + if ps.Kind() != reflect.Ptr && ps.Kind() != reflect.Interface { + return nil + } + s := ps.Elem() + for n := 0; n < s.NumField(); n++ { + log.Println("tag:", s.Type().Field(n).Tag.Get("opt")) + if opt == s.Type().Field(n).Tag.Get("opt") && s.Field(n).CanInterface() { + // return s.Field(n).Interface() + } + } + return nil +} + +func SetOption(i interface{}, opt string, v interface{}) { + ps := reflect.ValueOf(i) + if ps.Kind() != reflect.Ptr || ps.Kind() != reflect.Interface { + return + } + s := ps.Elem() + + for n := 0; n < s.NumField(); n++ { + if opt == s.Type().Field(n).Tag.Get("opt") && + s.Field(n).IsValid() && s.Field(n).CanSet() { + s.Field(n).Set(reflect.ValueOf(v)) + return + } + } +} diff --git a/server.go b/server.go index fb73e6c..dfd1aac 100644 --- a/server.go +++ b/server.go @@ -295,3 +295,8 @@ func (_ *ProxyServer) transport(conn1, conn2 net.Conn) (err error) { return } + +// Server represents a node server +type Server interface { + Run() error +} diff --git a/tcp/client.go b/tcp/client.go new file mode 100644 index 0000000..5ed219f --- /dev/null +++ b/tcp/client.go @@ -0,0 +1,18 @@ +package tcp + +import "net" + +type nodeClient struct { +} + +func (c *nodeClient) Connect() (net.Conn, error) { + return nil, nil +} + +func (c *nodeClient) Handshake(conn net.Conn) (net.Conn, error) { + return conn, nil +} + +func (c *nodeClient) Dial(conn net.Conn, addr string) (net.Conn, error) { + return nil, nil +} diff --git a/tcp/node.go b/tcp/node.go new file mode 100644 index 0000000..3bfab96 --- /dev/null +++ b/tcp/node.go @@ -0,0 +1,43 @@ +package tcp + +import ( + "github.com/ginuerzh/gost" +) + +type tcpNode struct { + options *tcpNodeOptions + client *nodeClient + server *nodeServer +} + +// NewNode creates a tcpNode with options +func NewNode(opts ...gost.Option) gost.Node { + node := &tcpNode{ + options: new(tcpNodeOptions), + } + for _, opt := range opts { + opt(node.options) + } + + return node +} + +func (node *tcpNode) Init(opts ...gost.Option) error { + for _, opt := range opts { + opt(node.options) + } + + return nil +} + +func (node *tcpNode) Client() gost.Client { + return node.client +} + +func (node *tcpNode) Server() gost.Server { + return node.server +} + +func (node *tcpNode) Options() gost.Options { + return node.options +} diff --git a/tcp/options.go b/tcp/options.go new file mode 100644 index 0000000..87918a5 --- /dev/null +++ b/tcp/options.go @@ -0,0 +1,26 @@ +package tcp + +import ( + "net/url" + + "github.com/ginuerzh/gost" +) + +type tcpNodeOptions struct { + *gost.DefaultOptions + Users []url.Userinfo `opt:"users"` // authentication for proxy +} + +func (o *tcpNodeOptions) Get(opt string) interface{} { + return gost.GetOption(o, opt) +} + +func (o *tcpNodeOptions) Set(opt string, v interface{}) { + gost.SetOption(o, opt, v) +} + +func UsersOption(users ...url.Userinfo) gost.Option { + return func(opts gost.Options) { + gost.SetOption(opts, "users", users) + } +} diff --git a/tcp/options_test.go b/tcp/options_test.go new file mode 100644 index 0000000..ab5bfd5 --- /dev/null +++ b/tcp/options_test.go @@ -0,0 +1,31 @@ +package tcp + +import "testing" +import "net/url" +import "reflect" + +var tests = []struct { + Opt string + Value interface{} +}{ + {"addr", "localhost:8080"}, + {"protocol", "http"}, + {"transport", "tcp"}, + {"users", []url.Userinfo{*url.UserPassword("admin", "123456")}}, +} + +func TestOptions(t *testing.T) { + opts := new(tcpNodeOptions) + for _, test := range tests { + opts.Set(test.Opt, test.Value) + v := opts.Get(test.Opt) + if !reflect.DeepEqual(v, test.Value) { + t.Log("not equal:", test.Opt, v) + t.Fail() + } + } + t.Log("addr:", opts.Addr) + t.Log("protocol:", opts.Protocol) + t.Log("transport:", opts.Transport) + t.Log("users:", opts.Users) +} diff --git a/tcp/server.go b/tcp/server.go new file mode 100644 index 0000000..809ac7f --- /dev/null +++ b/tcp/server.go @@ -0,0 +1,8 @@ +package tcp + +type nodeServer struct { +} + +func (s *nodeServer) Run() error { + return nil +}