sniffer.go 1.2 KB

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