1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-11-18 02:16:10 -05:00
v2fly/common/protocol/http/sniff.go

95 lines
1.5 KiB
Go
Raw Normal View History

2018-07-16 06:56:50 -04:00
package http
import (
"bytes"
"errors"
"strings"
"v2ray.com/core/common"
2018-12-10 17:08:16 -05:00
"v2ray.com/core/common/net"
2018-07-16 06:56:50 -04:00
)
type version byte
const (
HTTP1 version = iota
HTTP2
)
type SniffHeader struct {
version version
host string
}
func (h *SniffHeader) Protocol() string {
switch h.version {
case HTTP1:
return "http1"
case HTTP2:
return "http2"
default:
return "unknown"
}
}
func (h *SniffHeader) Domain() string {
return h.host
}
var (
methods = [...]string{"get", "post", "head", "put", "delete", "options", "connect"}
errNotHTTPMethod = errors.New("not an HTTP method")
)
func beginWithHTTPMethod(b []byte) error {
2018-07-19 07:31:57 -04:00
for _, m := range &methods {
2018-07-16 06:56:50 -04:00
if len(b) >= len(m) && strings.ToLower(string(b[:len(m)])) == m {
return nil
}
if len(b) < len(m) {
return common.ErrNoClue
2018-07-16 06:56:50 -04:00
}
}
return errNotHTTPMethod
}
func SniffHTTP(b []byte) (*SniffHeader, error) {
if err := beginWithHTTPMethod(b); err != nil {
return nil, err
}
sh := &SniffHeader{
version: HTTP1,
}
headers := bytes.Split(b, []byte{'\n'})
for i := 1; i < len(headers); i++ {
header := headers[i]
if len(header) == 0 {
2018-07-25 17:34:52 -04:00
break
2018-07-16 06:56:50 -04:00
}
parts := bytes.SplitN(header, []byte{':'}, 2)
if len(parts) != 2 {
continue
}
key := strings.ToLower(string(parts[0]))
if key == "host" {
2018-12-10 17:08:16 -05:00
rawHost := strings.ToLower(string(bytes.TrimSpace(parts[1])))
dest, err := ParseHost(rawHost, net.Port(80))
2018-12-10 07:37:17 -05:00
if err != nil {
2018-12-10 17:08:16 -05:00
return nil, err
2018-12-10 07:37:17 -05:00
}
2018-12-10 17:08:16 -05:00
sh.host = dest.Address.String()
2018-07-16 06:56:50 -04:00
}
}
if len(sh.host) > 0 {
return sh, nil
}
return nil, common.ErrNoClue
2018-07-16 06:56:50 -04:00
}