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  }