mirror of
https://github.com/p4gefau1t/trojan-go.git
synced 2024-04-21 12:21:34 +00:00
95 lines
2.1 KiB
Go
95 lines
2.1 KiB
Go
package simplesocks
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/p4gefau1t/trojan-go/common"
|
|
"github.com/p4gefau1t/trojan-go/log"
|
|
"github.com/p4gefau1t/trojan-go/tunnel"
|
|
"github.com/p4gefau1t/trojan-go/tunnel/trojan"
|
|
)
|
|
|
|
// Server is a simplesocks server
|
|
type Server struct {
|
|
underlay tunnel.Server
|
|
connChan chan tunnel.Conn
|
|
packetChan chan tunnel.PacketConn
|
|
ctx context.Context
|
|
cancel context.CancelFunc
|
|
}
|
|
|
|
func (s *Server) Close() error {
|
|
s.cancel()
|
|
return s.underlay.Close()
|
|
}
|
|
|
|
func (s *Server) acceptLoop() {
|
|
for {
|
|
conn, err := s.underlay.AcceptConn(&Tunnel{})
|
|
if err != nil {
|
|
log.Error(common.NewError("simplesocks failed to accept connection from underlying tunnel").Base(err))
|
|
select {
|
|
case <-s.ctx.Done():
|
|
return
|
|
default:
|
|
}
|
|
continue
|
|
}
|
|
metadata := new(tunnel.Metadata)
|
|
if err := metadata.ReadFrom(conn); err != nil {
|
|
log.Error(common.NewError("simplesocks server faield to read header").Base(err))
|
|
conn.Close()
|
|
continue
|
|
}
|
|
switch metadata.Command {
|
|
case Connect:
|
|
s.connChan <- &Conn{
|
|
metadata: metadata,
|
|
Conn: conn,
|
|
}
|
|
case Associate:
|
|
s.packetChan <- &PacketConn{
|
|
PacketConn: trojan.PacketConn{
|
|
Conn: conn,
|
|
},
|
|
}
|
|
default:
|
|
log.Error(common.NewError(fmt.Sprintf("simplesocks unknown command %d", metadata.Command)))
|
|
conn.Close()
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *Server) AcceptConn(tunnel.Tunnel) (tunnel.Conn, error) {
|
|
select {
|
|
case conn := <-s.connChan:
|
|
return conn, nil
|
|
case <-s.ctx.Done():
|
|
return nil, common.NewError("simplesocks server closed")
|
|
}
|
|
}
|
|
|
|
func (s *Server) AcceptPacket(tunnel.Tunnel) (tunnel.PacketConn, error) {
|
|
select {
|
|
case packetConn := <-s.packetChan:
|
|
return packetConn, nil
|
|
case <-s.ctx.Done():
|
|
return nil, common.NewError("simplesocks server closed")
|
|
}
|
|
}
|
|
|
|
func NewServer(ctx context.Context, underlay tunnel.Server) (*Server, error) {
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
server := &Server{
|
|
underlay: underlay,
|
|
ctx: ctx,
|
|
connChan: make(chan tunnel.Conn, 32),
|
|
packetChan: make(chan tunnel.PacketConn, 32),
|
|
cancel: cancel,
|
|
}
|
|
go server.acceptLoop()
|
|
log.Debug("simplesocks server created")
|
|
return server, nil
|
|
}
|