github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/common/sniff/sniff.go (about)

     1  package sniff
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"io"
     7  	"net"
     8  	"time"
     9  
    10  	"github.com/inazumav/sing-box/adapter"
    11  	C "github.com/inazumav/sing-box/constant"
    12  	"github.com/sagernet/sing/common/buf"
    13  	E "github.com/sagernet/sing/common/exceptions"
    14  )
    15  
    16  type (
    17  	StreamSniffer = func(ctx context.Context, reader io.Reader) (*adapter.InboundContext, error)
    18  	PacketSniffer = func(ctx context.Context, packet []byte) (*adapter.InboundContext, error)
    19  )
    20  
    21  func PeekStream(ctx context.Context, conn net.Conn, buffer *buf.Buffer, timeout time.Duration, sniffers ...StreamSniffer) (*adapter.InboundContext, error) {
    22  	if timeout == 0 {
    23  		timeout = C.ReadPayloadTimeout
    24  	}
    25  	deadline := time.Now().Add(timeout)
    26  	var errors []error
    27  
    28  	for i := 0; i < 3; i++ {
    29  		err := conn.SetReadDeadline(deadline)
    30  		if err != nil {
    31  			return nil, E.Cause(err, "set read deadline")
    32  		}
    33  		_, err = buffer.ReadOnceFrom(conn)
    34  		err = E.Errors(err, conn.SetReadDeadline(time.Time{}))
    35  		if err != nil {
    36  			if i > 0 {
    37  				break
    38  			}
    39  			return nil, E.Cause(err, "read payload")
    40  		}
    41  		for _, sniffer := range sniffers {
    42  			metadata, err := sniffer(ctx, bytes.NewReader(buffer.Bytes()))
    43  			if metadata != nil {
    44  				return metadata, nil
    45  			}
    46  			errors = append(errors, err)
    47  		}
    48  	}
    49  	return nil, E.Errors(errors...)
    50  }
    51  
    52  func PeekPacket(ctx context.Context, packet []byte, sniffers ...PacketSniffer) (*adapter.InboundContext, error) {
    53  	var errors []error
    54  	for _, sniffer := range sniffers {
    55  		metadata, err := sniffer(ctx, packet)
    56  		if metadata != nil {
    57  			return metadata, nil
    58  		}
    59  		errors = append(errors, err)
    60  	}
    61  	return nil, E.Errors(errors...)
    62  }