github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/app/dispatcher/sniffer.go (about)

     1  // +build !confonly
     2  
     3  package dispatcher
     4  
     5  import (
     6  	"v2ray.com/core/common"
     7  	"v2ray.com/core/common/protocol/bittorrent"
     8  	"v2ray.com/core/common/protocol/http"
     9  	"v2ray.com/core/common/protocol/tls"
    10  )
    11  
    12  type SniffResult interface {
    13  	Protocol() string
    14  	Domain() string
    15  }
    16  
    17  type protocolSniffer func([]byte) (SniffResult, error)
    18  
    19  type Sniffer struct {
    20  	sniffer []protocolSniffer
    21  }
    22  
    23  func NewSniffer() *Sniffer {
    24  	return &Sniffer{
    25  		sniffer: []protocolSniffer{
    26  			func(b []byte) (SniffResult, error) { return http.SniffHTTP(b) },
    27  			func(b []byte) (SniffResult, error) { return tls.SniffTLS(b) },
    28  			func(b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) },
    29  		},
    30  	}
    31  }
    32  
    33  var errUnknownContent = newError("unknown content")
    34  
    35  func (s *Sniffer) Sniff(payload []byte) (SniffResult, error) {
    36  	var pendingSniffer []protocolSniffer
    37  	for _, s := range s.sniffer {
    38  		result, err := s(payload)
    39  		if err == common.ErrNoClue {
    40  			pendingSniffer = append(pendingSniffer, s)
    41  			continue
    42  		}
    43  
    44  		if err == nil && result != nil {
    45  			return result, nil
    46  		}
    47  	}
    48  
    49  	if len(pendingSniffer) > 0 {
    50  		s.sniffer = pendingSniffer
    51  		return nil, common.ErrNoClue
    52  	}
    53  
    54  	return nil, errUnknownContent
    55  }