2020-11-25 13:01:53 +02:00
|
|
|
// +build !confonly
|
|
|
|
|
|
|
|
package dispatcher
|
|
|
|
|
|
|
|
import (
|
2020-12-04 03:36:16 +02:00
|
|
|
"github.com/xtls/xray-core/common"
|
|
|
|
"github.com/xtls/xray-core/common/protocol/bittorrent"
|
|
|
|
"github.com/xtls/xray-core/common/protocol/http"
|
|
|
|
"github.com/xtls/xray-core/common/protocol/tls"
|
2020-11-25 13:01:53 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type SniffResult interface {
|
|
|
|
Protocol() string
|
|
|
|
Domain() string
|
|
|
|
}
|
|
|
|
|
|
|
|
type protocolSniffer func([]byte) (SniffResult, error)
|
|
|
|
|
|
|
|
type Sniffer struct {
|
|
|
|
sniffer []protocolSniffer
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewSniffer() *Sniffer {
|
|
|
|
return &Sniffer{
|
|
|
|
sniffer: []protocolSniffer{
|
|
|
|
func(b []byte) (SniffResult, error) { return http.SniffHTTP(b) },
|
|
|
|
func(b []byte) (SniffResult, error) { return tls.SniffTLS(b) },
|
|
|
|
func(b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) },
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var errUnknownContent = newError("unknown content")
|
|
|
|
|
|
|
|
func (s *Sniffer) Sniff(payload []byte) (SniffResult, error) {
|
|
|
|
var pendingSniffer []protocolSniffer
|
|
|
|
for _, s := range s.sniffer {
|
|
|
|
result, err := s(payload)
|
|
|
|
if err == common.ErrNoClue {
|
|
|
|
pendingSniffer = append(pendingSniffer, s)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if err == nil && result != nil {
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(pendingSniffer) > 0 {
|
|
|
|
s.sniffer = pendingSniffer
|
|
|
|
return nil, common.ErrNoClue
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, errUnknownContent
|
|
|
|
}
|