github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/mux/server.go (about) 1 package mux 2 3 import ( 4 "context" 5 "errors" 6 "io" 7 "net" 8 9 "github.com/Asutorufa/yuhaiin/pkg/log" 10 "github.com/Asutorufa/yuhaiin/pkg/net/netapi" 11 "github.com/Asutorufa/yuhaiin/pkg/protos/config/listener" 12 "github.com/libp2p/go-yamux/v4" 13 ) 14 15 type MuxServer struct { 16 net.Listener 17 ctx context.Context 18 cancel context.CancelFunc 19 connChan chan net.Conn 20 } 21 22 func init() { 23 listener.RegisterTransport(NewServer) 24 } 25 26 func NewServer(config *listener.Transport_Mux) func(netapi.Listener) (netapi.Listener, error) { 27 return func(ii netapi.Listener) (netapi.Listener, error) { 28 lis, err := ii.Stream(context.TODO()) 29 if err != nil { 30 return nil, err 31 } 32 33 return netapi.PatchStream(newServer(lis), ii), nil 34 } 35 } 36 37 func newServer(lis net.Listener) *MuxServer { 38 ctx, cancel := context.WithCancel(context.TODO()) 39 mux := &MuxServer{ 40 Listener: lis, 41 ctx: ctx, 42 cancel: cancel, 43 connChan: make(chan net.Conn, 1024), 44 } 45 46 go log.IfErr("yamux server", mux.Run, net.ErrClosed) 47 48 return mux 49 } 50 51 func (m *MuxServer) Accept() (net.Conn, error) { 52 select { 53 case conn := <-m.connChan: 54 return conn, nil 55 case <-m.ctx.Done(): 56 return nil, m.ctx.Err() 57 } 58 } 59 60 func (m *MuxServer) Run() error { 61 for { 62 conn, err := m.Listener.Accept() 63 if err != nil { 64 return err 65 } 66 67 go func() { 68 defer conn.Close() 69 70 session, err := yamux.Server(conn, config, nil) 71 if err != nil { 72 log.Error("yamux server error", "err", err) 73 return 74 } 75 defer session.Close() 76 77 for { 78 c, err := session.AcceptStream() 79 if err != nil { 80 if !errors.Is(err, io.EOF) { 81 log.Error("yamux accept error", "err", err) 82 } 83 return 84 } 85 86 select { 87 case <-m.ctx.Done(): 88 return 89 case m.connChan <- &muxConn{MuxConn: c}: 90 } 91 } 92 }() 93 } 94 } 95 96 func (m *MuxServer) Close() error { 97 m.cancel() 98 return m.Listener.Close() 99 }