61 lines
946 B
Go
61 lines
946 B
Go
package gost
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
)
|
|
|
|
type Chain struct {
|
|
Nodes []Node
|
|
}
|
|
|
|
func NewChain(nodes ...Node) *Chain {
|
|
return &Chain{
|
|
Nodes: nodes,
|
|
}
|
|
}
|
|
|
|
func (c *Chain) Dial(ctx context.Context, addr string) (net.Conn, error) {
|
|
if len(c.Nodes) == 0 {
|
|
return net.Dial("tcp", addr)
|
|
}
|
|
|
|
nodes := c.Nodes
|
|
conn, err := nodes[0].Client.Dial(ctx, nodes[0].Addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
conn, err = nodes[0].Client.Handshake(ctx, conn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for i, node := range nodes {
|
|
if i == len(nodes)-1 {
|
|
break
|
|
}
|
|
|
|
next := nodes[i+1]
|
|
cc, err := node.Client.Connect(ctx, conn, next.Addr)
|
|
if err != nil {
|
|
conn.Close()
|
|
return nil, err
|
|
}
|
|
cc, err = next.Client.Handshake(ctx, cc)
|
|
if err != nil {
|
|
conn.Close()
|
|
return nil, err
|
|
}
|
|
|
|
conn = cc
|
|
}
|
|
|
|
cc, err := nodes[len(nodes)-1].Client.Connect(ctx, conn, addr)
|
|
if err != nil {
|
|
conn.Close()
|
|
return nil, err
|
|
}
|
|
return cc, nil
|
|
}
|