refine http header

pull/314/head
Darien Raymond 2016-11-02 22:26:21 +01:00
parent 1600a59254
commit 0747203132
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
12 changed files with 336 additions and 201 deletions

1
all.go
View File

@ -20,6 +20,7 @@ import (
_ "v2ray.com/core/transport/internet/udp"
_ "v2ray.com/core/transport/internet/ws"
_ "v2ray.com/core/transport/internet/authenticators/http"
_ "v2ray.com/core/transport/internet/authenticators/noop"
_ "v2ray.com/core/transport/internet/authenticators/srtp"
_ "v2ray.com/core/transport/internet/authenticators/utp"

View File

@ -4,6 +4,34 @@ import (
"v2ray.com/core/common/dice"
)
func (this *Version) GetValue() string {
if this == nil {
return "1.1"
}
return this.Value
}
func (this *Method) GetValue() string {
if this == nil {
return "GET"
}
return this.Value
}
func (this *Status) GetCode() string {
if this == nil {
return "200"
}
return this.Code
}
func (this *Status) GetReason() string {
if this == nil {
return "OK"
}
return this.Reason
}
func pickString(arr []string) string {
n := len(arr)
if n == 0 {
@ -30,8 +58,8 @@ func (this *RequestConfig) PickHeaders() []string {
return headers
}
func (this *RequestConfig) GetVersion() string {
return "HTTP/" + this.Version
func (this *RequestConfig) GetFullVersion() string {
return "HTTP/" + this.Version.GetValue()
}
func (this *ResponseConfig) PickHeaders() []string {
@ -48,6 +76,6 @@ func (this *ResponseConfig) PickHeaders() []string {
return headers
}
func (this *ResponseConfig) GetVersion() string {
return "HTTP/" + this.Version
func (this *ResponseConfig) GetFullVersion() string {
return "HTTP/" + this.Version.GetValue()
}

View File

@ -10,9 +10,12 @@ It is generated from these files:
It has these top-level messages:
Header
HeaderEnding
Version
Method
RequestConfig
Status
ResponseConfig
Config
*/
package http
@ -43,20 +46,31 @@ func (m *Header) String() string { return proto.CompactTextString(m)
func (*Header) ProtoMessage() {}
func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type HeaderEnding struct {
// HTTP version. Default value "1.1".
type Version struct {
Value string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"`
}
func (m *HeaderEnding) Reset() { *m = HeaderEnding{} }
func (m *HeaderEnding) String() string { return proto.CompactTextString(m) }
func (*HeaderEnding) ProtoMessage() {}
func (*HeaderEnding) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *Version) Reset() { *m = Version{} }
func (m *Version) String() string { return proto.CompactTextString(m) }
func (*Version) ProtoMessage() {}
func (*Version) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
// HTTP method. Default value "GET".
type Method struct {
Value string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"`
}
func (m *Method) Reset() { *m = Method{} }
func (m *Method) String() string { return proto.CompactTextString(m) }
func (*Method) ProtoMessage() {}
func (*Method) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
type RequestConfig struct {
// Full HTTP version like "1.1".
Version string `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"`
Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"`
// GET, POST, CONNECT etc
Method string `protobuf:"bytes,2,opt,name=method" json:"method,omitempty"`
Method *Method `protobuf:"bytes,2,opt,name=method" json:"method,omitempty"`
// URI like "/login.php"
Uri []string `protobuf:"bytes,3,rep,name=uri" json:"uri,omitempty"`
Header []*Header `protobuf:"bytes,4,rep,name=header" json:"header,omitempty"`
@ -65,7 +79,21 @@ type RequestConfig struct {
func (m *RequestConfig) Reset() { *m = RequestConfig{} }
func (m *RequestConfig) String() string { return proto.CompactTextString(m) }
func (*RequestConfig) ProtoMessage() {}
func (*RequestConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (*RequestConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *RequestConfig) GetVersion() *Version {
if m != nil {
return m.Version
}
return nil
}
func (m *RequestConfig) GetMethod() *Method {
if m != nil {
return m.Method
}
return nil
}
func (m *RequestConfig) GetHeader() []*Header {
if m != nil {
@ -74,17 +102,42 @@ func (m *RequestConfig) GetHeader() []*Header {
return nil
}
type Status struct {
// Status code. Default "200".
Code string `protobuf:"bytes,1,opt,name=code" json:"code,omitempty"`
// Statue reason. Default "OK".
Reason string `protobuf:"bytes,2,opt,name=reason" json:"reason,omitempty"`
}
func (m *Status) Reset() { *m = Status{} }
func (m *Status) String() string { return proto.CompactTextString(m) }
func (*Status) ProtoMessage() {}
func (*Status) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
type ResponseConfig struct {
Version string `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"`
Status string `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"`
Reason string `protobuf:"bytes,3,opt,name=reason" json:"reason,omitempty"`
Header []*Header `protobuf:"bytes,4,rep,name=header" json:"header,omitempty"`
Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"`
Status *Status `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"`
Header []*Header `protobuf:"bytes,3,rep,name=header" json:"header,omitempty"`
}
func (m *ResponseConfig) Reset() { *m = ResponseConfig{} }
func (m *ResponseConfig) String() string { return proto.CompactTextString(m) }
func (*ResponseConfig) ProtoMessage() {}
func (*ResponseConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (*ResponseConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
func (m *ResponseConfig) GetVersion() *Version {
if m != nil {
return m.Version
}
return nil
}
func (m *ResponseConfig) GetStatus() *Status {
if m != nil {
return m.Status
}
return nil
}
func (m *ResponseConfig) GetHeader() []*Header {
if m != nil {
@ -93,11 +146,38 @@ func (m *ResponseConfig) GetHeader() []*Header {
return nil
}
type Config struct {
Request *RequestConfig `protobuf:"bytes,1,opt,name=request" json:"request,omitempty"`
Response *ResponseConfig `protobuf:"bytes,2,opt,name=response" json:"response,omitempty"`
}
func (m *Config) Reset() { *m = Config{} }
func (m *Config) String() string { return proto.CompactTextString(m) }
func (*Config) ProtoMessage() {}
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (m *Config) GetRequest() *RequestConfig {
if m != nil {
return m.Request
}
return nil
}
func (m *Config) GetResponse() *ResponseConfig {
if m != nil {
return m.Response
}
return nil
}
func init() {
proto.RegisterType((*Header)(nil), "v2ray.core.transport.internet.authenticators.http.Header")
proto.RegisterType((*HeaderEnding)(nil), "v2ray.core.transport.internet.authenticators.http.HeaderEnding")
proto.RegisterType((*Version)(nil), "v2ray.core.transport.internet.authenticators.http.Version")
proto.RegisterType((*Method)(nil), "v2ray.core.transport.internet.authenticators.http.Method")
proto.RegisterType((*RequestConfig)(nil), "v2ray.core.transport.internet.authenticators.http.RequestConfig")
proto.RegisterType((*Status)(nil), "v2ray.core.transport.internet.authenticators.http.Status")
proto.RegisterType((*ResponseConfig)(nil), "v2ray.core.transport.internet.authenticators.http.ResponseConfig")
proto.RegisterType((*Config)(nil), "v2ray.core.transport.internet.authenticators.http.Config")
}
func init() {
@ -105,24 +185,30 @@ func init() {
}
var fileDescriptor0 = []byte{
// 303 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x92, 0x31, 0x4b, 0xfc, 0x40,
0x10, 0xc5, 0xc9, 0xe5, 0xfe, 0xf9, 0x73, 0x73, 0x2a, 0xb2, 0x88, 0x6c, 0x79, 0x1c, 0x16, 0x57,
0x6d, 0xf0, 0xc4, 0xc2, 0xf6, 0x44, 0x10, 0x2b, 0x4d, 0x69, 0xb7, 0xe6, 0xc6, 0x4b, 0xc0, 0xec,
0xc4, 0xd9, 0x49, 0xc0, 0x2f, 0x64, 0xe7, 0x77, 0x94, 0x64, 0x13, 0xc5, 0xce, 0x2b, 0xec, 0xf6,
0xcd, 0xce, 0xef, 0xcd, 0x1b, 0x18, 0xd8, 0xb4, 0x6b, 0xb6, 0x6f, 0x26, 0xa7, 0x2a, 0xcd, 0x89,
0x31, 0x15, 0xb6, 0xce, 0xd7, 0xc4, 0x92, 0x96, 0x4e, 0x90, 0x1d, 0x4a, 0x6a, 0x1b, 0x29, 0xd0,
0x49, 0x99, 0x5b, 0x21, 0xf6, 0x69, 0x21, 0x52, 0xa7, 0x39, 0xb9, 0xe7, 0x72, 0x67, 0x6a, 0x26,
0x21, 0x75, 0x3e, 0x7a, 0x30, 0x9a, 0x2f, 0xde, 0x8c, 0xbc, 0xf9, 0xc9, 0x9b, 0x8e, 0x5f, 0xae,
0x21, 0xb9, 0x45, 0xbb, 0x45, 0x56, 0x0a, 0xa6, 0xce, 0x56, 0xa8, 0xa3, 0x45, 0xb4, 0x9a, 0x65,
0xfd, 0x5b, 0x9d, 0xc0, 0xbf, 0xd6, 0xbe, 0x34, 0xa8, 0x27, 0x8b, 0x78, 0x35, 0xcb, 0x82, 0x58,
0x9e, 0xc1, 0x41, 0x60, 0x6e, 0xdc, 0xb6, 0x74, 0xbb, 0xef, 0xae, 0x80, 0x0e, 0x5d, 0xef, 0x11,
0x1c, 0x66, 0xf8, 0xda, 0xa0, 0x97, 0xeb, 0x3e, 0xa4, 0xd2, 0xf0, 0xbf, 0x45, 0xf6, 0x25, 0xb9,
0xa1, 0x73, 0x94, 0xea, 0x14, 0x92, 0x0a, 0xa5, 0xa0, 0xad, 0x9e, 0xf4, 0x1f, 0x83, 0x52, 0xc7,
0x10, 0x37, 0x5c, 0xea, 0xb8, 0x9f, 0xde, 0x3d, 0xd5, 0x03, 0x24, 0x45, 0x3f, 0x5b, 0x4f, 0x17,
0xf1, 0x6a, 0xbe, 0xbe, 0x32, 0x7b, 0xef, 0x6c, 0x42, 0xf8, 0x6c, 0x30, 0x5a, 0x7e, 0x44, 0x70,
0x94, 0xa1, 0xaf, 0xc9, 0x79, 0xfc, 0x4d, 0x52, 0x2f, 0x56, 0x1a, 0x3f, 0x26, 0x0d, 0xaa, 0xab,
0x33, 0x5a, 0x4f, 0x4e, 0xc7, 0xa1, 0x1e, 0xd4, 0x1f, 0xe4, 0xdd, 0xdc, 0xc1, 0x65, 0x4e, 0xd5,
0xfe, 0x3e, 0x9b, 0x79, 0xd8, 0xee, 0xbe, 0xbb, 0x95, 0xc7, 0x69, 0x57, 0x7a, 0x4a, 0xfa, 0xc3,
0xb9, 0xf8, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x78, 0x8c, 0xa7, 0x40, 0x7e, 0x02, 0x00, 0x00,
// 389 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x94, 0xc1, 0x4e, 0xe3, 0x30,
0x10, 0x40, 0xd5, 0xa4, 0x9b, 0x6e, 0xa7, 0xda, 0xd5, 0xca, 0x5a, 0xad, 0x72, 0xda, 0xad, 0x72,
0xea, 0xc9, 0xd1, 0x76, 0x97, 0x03, 0x9c, 0xa0, 0x5c, 0x10, 0x12, 0x12, 0x18, 0xc4, 0xa1, 0x12,
0x07, 0x93, 0x0e, 0x24, 0x12, 0xb1, 0x83, 0xed, 0x54, 0xe2, 0x1f, 0xf8, 0x05, 0xbe, 0x86, 0x1f,
0x43, 0xb1, 0x9d, 0xd2, 0x1e, 0x38, 0x34, 0xc0, 0xcd, 0x4e, 0x66, 0x9e, 0x67, 0xde, 0x58, 0x86,
0xd9, 0x72, 0xaa, 0xf8, 0x03, 0xcd, 0x64, 0x99, 0x66, 0x52, 0x61, 0x6a, 0x14, 0x17, 0xba, 0x92,
0xca, 0xa4, 0x85, 0x30, 0xa8, 0x04, 0x9a, 0x94, 0xd7, 0x26, 0x47, 0x61, 0x8a, 0x8c, 0x1b, 0xa9,
0x74, 0x9a, 0x1b, 0x53, 0xa5, 0x99, 0x14, 0x37, 0xc5, 0x2d, 0xad, 0x94, 0x34, 0x92, 0xfc, 0x6d,
0x19, 0x0a, 0xe9, 0x2a, 0x9f, 0xb6, 0xf9, 0x74, 0x33, 0x9f, 0x36, 0xf9, 0xc9, 0x14, 0xa2, 0x23,
0xe4, 0x0b, 0x54, 0x84, 0x40, 0x5f, 0xf0, 0x12, 0xe3, 0xde, 0xb8, 0x37, 0x19, 0x32, 0xbb, 0x26,
0x3f, 0xe1, 0xcb, 0x92, 0xdf, 0xd5, 0x18, 0x07, 0xe3, 0x70, 0x32, 0x64, 0x6e, 0x93, 0xfc, 0x81,
0xc1, 0x25, 0x2a, 0x5d, 0x48, 0xf1, 0x1a, 0xe0, 0xb2, 0x7c, 0xc0, 0x6f, 0x88, 0x4e, 0xd0, 0xe4,
0x72, 0xf1, 0xc6, 0xff, 0xa7, 0x00, 0xbe, 0x31, 0xbc, 0xaf, 0x51, 0x9b, 0x43, 0x5b, 0x3f, 0xb9,
0x80, 0xc1, 0xd2, 0x21, 0x6d, 0xe4, 0x68, 0xba, 0x47, 0xb7, 0xee, 0x85, 0xfa, 0xa2, 0x58, 0x8b,
0x22, 0x67, 0x10, 0x95, 0xb6, 0x8e, 0x38, 0xb0, 0xd0, 0xdd, 0x0e, 0x50, 0xd7, 0x08, 0xf3, 0x20,
0xf2, 0x03, 0xc2, 0x5a, 0x15, 0x71, 0x68, 0x7d, 0x34, 0xcb, 0xe6, 0x90, 0xdc, 0x1a, 0x8c, 0xfb,
0xe3, 0xb0, 0xe3, 0x21, 0x6e, 0x04, 0xcc, 0x83, 0x92, 0xff, 0x10, 0x9d, 0x1b, 0x6e, 0x6a, 0xdd,
0x0c, 0x25, 0x93, 0x8b, 0xd5, 0x50, 0x9a, 0x35, 0xf9, 0x05, 0x91, 0x42, 0xae, 0xa5, 0xb0, 0x5d,
0x0d, 0x99, 0xdf, 0x25, 0x8f, 0x01, 0x7c, 0x67, 0xa8, 0x2b, 0x29, 0x34, 0x7e, 0xb6, 0x56, 0x6d,
0xcb, 0x7b, 0x87, 0x56, 0xd7, 0x1f, 0xf3, 0xa0, 0x35, 0x89, 0xe1, 0x47, 0x49, 0x7c, 0xee, 0x41,
0xe4, 0x35, 0xcc, 0x61, 0xa0, 0xdc, 0x75, 0xf3, 0x1a, 0xf6, 0x3b, 0xe0, 0x37, 0x2e, 0x2c, 0x6b,
0x81, 0xe4, 0x0a, 0xbe, 0x2a, 0x2f, 0xdd, 0xeb, 0x38, 0xe8, 0x04, 0x5f, 0x9f, 0x1b, 0x5b, 0x21,
0x67, 0xc7, 0xb0, 0x93, 0xc9, 0x72, 0x7b, 0xe2, 0x6c, 0xe4, 0x50, 0xa7, 0xcd, 0xc3, 0x30, 0xef,
0x37, 0x9f, 0xae, 0x23, 0xfb, 0x4a, 0xfc, 0x7b, 0x09, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x1d, 0x02,
0x42, 0x6b, 0x04, 0x00, 0x00,
}

View File

@ -13,16 +13,22 @@ message Header {
repeated string value = 2;
}
message HeaderEnding {
// HTTP version. Default value "1.1".
message Version {
string value = 1;
}
// HTTP method. Default value "GET".
message Method {
string value = 1;
}
message RequestConfig {
// Full HTTP version like "1.1".
string version = 1;
Version version = 1;
// GET, POST, CONNECT etc
string method = 2;
Method method = 2;
// URI like "/login.php"
repeated string uri = 3;
@ -30,12 +36,23 @@ message RequestConfig {
repeated Header header = 4;
}
message Status {
// Status code. Default "200".
string code = 1;
// Statue reason. Default "OK".
string reason = 2;
}
message ResponseConfig {
string version = 1;
Version version = 1;
string status = 2;
Status status = 2;
string reason = 3;
repeated Header header = 3;
}
repeated Header header = 4;
message Config {
RequestConfig request = 1;
ResponseConfig response = 2;
}

View File

@ -2,7 +2,8 @@ package http
import (
"bytes"
"io"
"net"
"v2ray.com/core/common/alloc"
"v2ray.com/core/common/loader"
"v2ray.com/core/transport/internet"
@ -13,122 +14,117 @@ const (
ENDING = CRLF + CRLF
)
type RequestAuthenticator struct {
config *RequestConfig
type HttpConn struct {
net.Conn
buffer *alloc.Buffer
readHeader bool
writeHeaderContent *alloc.Buffer
writeHeader bool
}
func (this *RequestAuthenticator) Seal(writer io.Writer) io.Writer {
header := alloc.NewLocalBuffer(2048)
header.AppendString(this.config.Method).AppendString(" ").AppendString(this.config.PickUri()).AppendString(" ").AppendString(this.config.GetVersion()).AppendString(CRLF)
func NewHttpConn(conn net.Conn, writeHeaderContent *alloc.Buffer) *HttpConn {
return &HttpConn{
Conn: conn,
readHeader: true,
writeHeader: true,
writeHeaderContent: writeHeaderContent,
}
}
headers := this.config.PickHeaders()
func (this *HttpConn) Read(b []byte) (int, error) {
if this.readHeader {
buffer := alloc.NewLocalBuffer(2048)
for {
_, err := buffer.FillFrom(this.Conn)
if err != nil {
return 0, err
}
if n := bytes.Index(buffer.Value, []byte(ENDING)); n != -1 {
buffer.SliceFrom(n + len(ENDING))
break
}
if buffer.Len() >= len(ENDING) {
copy(buffer.Value, buffer.Value[buffer.Len()-len(ENDING):])
buffer.Slice(0, len(ENDING))
}
}
this.buffer = buffer
this.readHeader = false
}
if this.buffer.Len() > 0 {
nBytes, err := this.buffer.Read(b)
if nBytes == this.buffer.Len() {
this.buffer.Release()
this.buffer = nil
}
return nBytes, err
}
return this.Conn.Read(b)
}
func (this *HttpConn) Write(b []byte) (int, error) {
if this.writeHeader {
_, err := this.Conn.Write(this.writeHeaderContent.Value)
this.writeHeaderContent.Release()
if err != nil {
return 0, err
}
this.writeHeader = false
}
return this.Conn.Write(b)
}
type HttpAuthenticator struct {
config *Config
}
func (this HttpAuthenticator) GetClientWriteHeader() *alloc.Buffer {
header := alloc.NewLocalBuffer(2048)
config := this.config.Request
header.AppendString(config.Method.GetValue()).AppendString(" ").AppendString(config.PickUri()).AppendString(" ").AppendString(config.GetFullVersion()).AppendString(CRLF)
headers := config.PickHeaders()
for _, h := range headers {
header.AppendString(h).AppendString(CRLF)
}
header.AppendString(CRLF)
writer.Write(header.Value)
header.Release()
return writer
return header
}
func (this *RequestAuthenticator) Open(reader io.Reader) (io.Reader, error) {
buffer := alloc.NewLocalBuffer(2048)
for {
_, err := buffer.FillFrom(reader)
if err != nil {
return nil, err
}
if n := bytes.Index(buffer.Value, []byte(ENDING)); n != -1 {
buffer.SliceFrom(n + len(ENDING))
return &BufferAndReader{
buffer: buffer,
reader: reader,
}, nil
}
if buffer.Len() >= len(ENDING) {
copy(buffer.Value, buffer.Value[buffer.Len()-len(ENDING):])
buffer.Slice(0, len(ENDING))
}
}
}
type BufferAndReader struct {
buffer *alloc.Buffer
reader io.Reader
}
func (this *BufferAndReader) Read(b []byte) (int, error) {
if this.buffer.Len() == 0 {
return this.reader.Read(b)
}
n, err := this.buffer.Read(b)
if n == this.buffer.Len() {
this.buffer.Release()
this.buffer = nil
}
return n, err
}
type RequestAuthenticatorFactory struct{}
func (RequestAuthenticatorFactory) Create(config interface{}) internet.ConnectionAuthenticator {
return &RequestAuthenticator{
config: config.(*RequestConfig),
}
}
type ResponseAuthenticator struct {
config *ResponseConfig
}
func (this *ResponseAuthenticator) Seal(writer io.Writer) io.Writer {
func (this HttpAuthenticator) GetServerWriteHeader() *alloc.Buffer {
header := alloc.NewLocalBuffer(2048)
header.AppendString(this.config.GetVersion()).AppendString(" ").AppendString(this.config.Status).AppendString(" ").AppendString(this.config.Reason).AppendString(CRLF)
config := this.config.Response
header.AppendString(config.GetFullVersion()).AppendString(" ").AppendString(config.Status.GetCode()).AppendString(" ").AppendString(config.Status.GetReason()).AppendString(CRLF)
headers := this.config.PickHeaders()
headers := config.PickHeaders()
for _, h := range headers {
header.AppendString(h).AppendString(CRLF)
}
header.AppendString(CRLF)
writer.Write(header.Value)
header.Release()
return writer
return header
}
func (this *ResponseAuthenticator) Open(reader io.Reader) (io.Reader, error) {
buffer := alloc.NewLocalBuffer(2048)
for {
_, err := buffer.FillFrom(reader)
if err != nil {
return nil, err
}
if n := bytes.Index(buffer.Value, []byte(ENDING)); n != -1 {
buffer.SliceFrom(n + len(ENDING))
return &BufferAndReader{
buffer: buffer,
reader: reader,
}, nil
}
if buffer.Len() >= len(ENDING) {
copy(buffer.Value, buffer.Value[buffer.Len()-len(ENDING):])
buffer.Slice(0, len(ENDING))
}
}
func (this HttpAuthenticator) Client(conn net.Conn) net.Conn {
return NewHttpConn(conn, this.GetClientWriteHeader())
}
type ResponseAuthenticatorFactory struct{}
func (this HttpAuthenticator) Server(conn net.Conn) net.Conn {
return NewHttpConn(conn, this.GetServerWriteHeader())
}
func (ResponseAuthenticatorFactory) Create(config interface{}) internet.ConnectionAuthenticator {
return &ResponseAuthenticator{
config: config.(*ResponseConfig),
type HttpAuthenticatorFactory struct{}
func (HttpAuthenticatorFactory) Create(config interface{}) internet.ConnectionAuthenticator {
return HttpAuthenticator{
config: config.(*Config),
}
}
func init() {
internet.RegisterConnectionAuthenticator(loader.GetType(new(RequestConfig)), RequestAuthenticatorFactory{})
internet.RegisterConnectionAuthenticator(loader.GetType(new(ResponseConfig)), ResponseAuthenticatorFactory{})
internet.RegisterConnectionAuthenticator(loader.GetType(new(Config)), HttpAuthenticatorFactory{})
}

View File

@ -1,38 +0,0 @@
package http_test
import (
"testing"
"v2ray.com/core/common/alloc"
"v2ray.com/core/testing/assert"
. "v2ray.com/core/transport/internet/authenticators/http"
)
func TestRequestOpenSeal(t *testing.T) {
assert := assert.On(t)
content := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g'}
cache := alloc.NewLargeBuffer()
http := (RequestAuthenticatorFactory{}).Create(&RequestConfig{
Method: "GET",
Uri: []string{"/"},
Version: "1.1",
Header: []*Header{
{
Name: "Content-Length",
Value: []string{"123"},
},
},
})
http.Seal(cache).Write(content)
actualContent := make([]byte, 256)
reader, err := http.Open(cache)
assert.Error(err).IsNil()
n, err := reader.Read(actualContent)
assert.Error(err).IsNil()
assert.Bytes(content).Equals(actualContent[:n])
}

View File

@ -1,7 +1,8 @@
package noop
import (
"io"
"net"
"v2ray.com/core/common/alloc"
"v2ray.com/core/common/loader"
"v2ray.com/core/transport/internet"
@ -25,12 +26,12 @@ func (this NoOpAuthenticatorFactory) Create(config interface{}) internet.Authent
type NoOpConnectionAuthenticator struct{}
func (NoOpConnectionAuthenticator) Open(reader io.Reader) (io.Reader, error) {
return reader, nil
func (NoOpConnectionAuthenticator) Client(conn net.Conn) net.Conn {
return conn
}
func (NoOpConnectionAuthenticator) Seal(writer io.Writer) io.Writer {
return writer
func (NoOpConnectionAuthenticator) Server(conn net.Conn) net.Conn {
return conn
}
type NoOpConnectionAuthenticatorFactory struct{}

View File

@ -1,13 +1,14 @@
package internet
import (
"io"
"net"
"v2ray.com/core/common"
)
type ConnectionAuthenticator interface {
Seal(io.Writer) io.Writer
Open(io.Reader) (io.Reader, error)
Client(net.Conn) net.Conn
Server(net.Conn) net.Conn
}
type ConnectionAuthenticatorFactory interface {

View File

@ -17,6 +17,7 @@ package tcp
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import v2ray_core_common_loader "v2ray.com/core/common/loader"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
@ -39,7 +40,8 @@ func (*ConnectionReuse) ProtoMessage() {}
func (*ConnectionReuse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type Config struct {
ConnectionReuse *ConnectionReuse `protobuf:"bytes,1,opt,name=connection_reuse,json=connectionReuse" json:"connection_reuse,omitempty"`
ConnectionReuse *ConnectionReuse `protobuf:"bytes,1,opt,name=connection_reuse,json=connectionReuse" json:"connection_reuse,omitempty"`
HeaderSettings *v2ray_core_common_loader.TypedSettings `protobuf:"bytes,2,opt,name=header_settings,json=headerSettings" json:"header_settings,omitempty"`
}
func (m *Config) Reset() { *m = Config{} }
@ -54,6 +56,13 @@ func (m *Config) GetConnectionReuse() *ConnectionReuse {
return nil
}
func (m *Config) GetHeaderSettings() *v2ray_core_common_loader.TypedSettings {
if m != nil {
return m.HeaderSettings
}
return nil
}
func init() {
proto.RegisterType((*ConnectionReuse)(nil), "v2ray.core.transport.internet.tcp.ConnectionReuse")
proto.RegisterType((*Config)(nil), "v2ray.core.transport.internet.tcp.Config")
@ -62,17 +71,21 @@ func init() {
func init() { proto.RegisterFile("v2ray.com/core/transport/internet/tcp/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 191 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x8f, 0x41, 0x6b, 0x83, 0x40,
0x10, 0x85, 0x91, 0x82, 0x94, 0xf5, 0x60, 0xf1, 0x50, 0x7a, 0x6c, 0x85, 0x42, 0x7b, 0xd9, 0x85,
0xed, 0xa9, 0x57, 0xfd, 0x03, 0xc1, 0x63, 0x20, 0x04, 0x1d, 0x26, 0x22, 0xc4, 0x99, 0x65, 0x9c,
0x04, 0xf2, 0xef, 0x83, 0x26, 0x0a, 0xc9, 0xc5, 0xe3, 0x2e, 0xdf, 0xf7, 0xde, 0x3c, 0xe3, 0xcf,
0x5e, 0xea, 0x8b, 0x05, 0xee, 0x1d, 0xb0, 0xa0, 0x53, 0xa9, 0x69, 0x08, 0x2c, 0xea, 0x3a, 0x52,
0x14, 0x42, 0x75, 0x0a, 0xc1, 0x01, 0xd3, 0xa1, 0x6b, 0x6d, 0x10, 0x56, 0xce, 0xbe, 0x66, 0x47,
0xd0, 0x2e, 0xbc, 0x9d, 0x79, 0xab, 0x10, 0xf2, 0x5f, 0x93, 0x96, 0x4c, 0x84, 0xa0, 0x1d, 0x53,
0x85, 0xa7, 0x01, 0xb3, 0x77, 0x13, 0x23, 0xd5, 0xcd, 0x11, 0x3f, 0xa2, 0xcf, 0xe8, 0xe7, 0xb5,
0xba, 0xbf, 0xf2, 0xd6, 0xc4, 0xe5, 0x94, 0x9e, 0xed, 0xcc, 0x1b, 0x2c, 0xd2, 0x5e, 0x46, 0x6b,
0x62, 0x13, 0xef, 0xed, 0x6a, 0xa5, 0x7d, 0xea, 0xab, 0x52, 0x78, 0xfc, 0x28, 0xfe, 0xcd, 0x37,
0x70, 0xbf, 0x9e, 0x54, 0x24, 0xb7, 0x7b, 0x36, 0xe3, 0xd8, 0xed, 0x8b, 0x42, 0x68, 0xe2, 0x69,
0xf8, 0xdf, 0x35, 0x00, 0x00, 0xff, 0xff, 0xc1, 0x16, 0x42, 0x0b, 0x2e, 0x01, 0x00, 0x00,
// 249 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x90, 0xc1, 0x4a, 0xc3, 0x60,
0x10, 0x84, 0x89, 0x42, 0x90, 0xbf, 0x60, 0x24, 0x07, 0x29, 0x9e, 0xb4, 0x20, 0xd5, 0xcb, 0xfe,
0x10, 0x4f, 0x5e, 0xdb, 0x17, 0x28, 0xd1, 0x93, 0x20, 0x25, 0xdd, 0xae, 0x35, 0xd0, 0xec, 0xfe,
0x6c, 0x56, 0x21, 0x8f, 0xe6, 0xdb, 0x49, 0x92, 0xa6, 0x94, 0x5c, 0x7a, 0x5c, 0x98, 0x99, 0xfd,
0x66, 0x5c, 0xf6, 0x9b, 0x69, 0xd1, 0x00, 0x4a, 0xe5, 0x51, 0x94, 0xbc, 0x69, 0xc1, 0x75, 0x10,
0x35, 0x5f, 0xb2, 0x91, 0x32, 0x99, 0x37, 0x0c, 0x1e, 0x85, 0xbf, 0xca, 0x1d, 0x04, 0x15, 0x93,
0xf4, 0x61, 0xf0, 0x28, 0xc1, 0x51, 0x0f, 0x83, 0x1e, 0x0c, 0xc3, 0xdd, 0x7c, 0x14, 0x8b, 0x52,
0x55, 0xc2, 0x7e, 0x2f, 0xc5, 0x96, 0xd4, 0x5b, 0x13, 0xa8, 0xcf, 0x9a, 0x3d, 0xbb, 0x64, 0x29,
0xcc, 0x84, 0x56, 0x0a, 0xe7, 0xf4, 0x53, 0x53, 0x7a, 0xeb, 0x62, 0xe2, 0x62, 0xb3, 0xa7, 0x69,
0x74, 0x1f, 0x3d, 0x5d, 0xe5, 0x87, 0x6b, 0xf6, 0x17, 0xb9, 0x78, 0xd9, 0x71, 0xa4, 0x9f, 0xee,
0x06, 0x8f, 0xae, 0xb5, 0xb6, 0xb6, 0x4e, 0x3c, 0xc9, 0x32, 0x38, 0x0b, 0x07, 0xa3, 0x87, 0x79,
0x82, 0x23, 0x82, 0x95, 0x4b, 0xbe, 0xa9, 0x25, 0x5d, 0xd7, 0x64, 0x56, 0xf2, 0xae, 0x9e, 0x5e,
0x74, 0xe9, 0xf3, 0xd3, 0xf4, 0xbe, 0x13, 0xf4, 0x9d, 0xe0, 0xbd, 0x09, 0xb4, 0x7d, 0x3b, 0xc8,
0xf3, 0xeb, 0xde, 0x3f, 0xdc, 0x8b, 0x57, 0xf7, 0x88, 0x52, 0x9d, 0x67, 0x5b, 0x4c, 0xfa, 0x86,
0xab, 0x76, 0x9c, 0x8f, 0x4b, 0xc3, 0xb0, 0x89, 0xbb, 0xa1, 0x5e, 0xfe, 0x03, 0x00, 0x00, 0xff,
0xff, 0xdf, 0xaf, 0x5e, 0x9f, 0xaa, 0x01, 0x00, 0x00,
}

View File

@ -5,9 +5,12 @@ option go_package = "tcp";
option java_package = "com.v2ray.core.transport.internet.tcp";
option java_outer_classname = "ConfigProto";
import "v2ray.com/core/common/loader/type.proto";
message ConnectionReuse {
bool enable = 1;
}
message Config {
ConnectionReuse connection_reuse = 1;
v2ray.core.common.loader.TypedSettings header_settings = 2;
}

View File

@ -1,6 +1,7 @@
package tcp
import (
"errors"
"net"
"crypto/tls"
@ -51,6 +52,17 @@ func Dial(src v2net.Address, dest v2net.Destination, options internet.DialerOpti
conn = tls.Client(conn, config)
}
}
if tcpSettings.HeaderSettings != nil {
headerConfig, err := tcpSettings.HeaderSettings.GetInstance()
if err != nil {
return nil, errors.New("TCP: Failed to get header settings: " + err.Error())
}
auth, err := internet.CreateConnectionAuthenticator(tcpSettings.HeaderSettings.Type, headerConfig)
if err != nil {
return nil, errors.New("TCP: Failed to create header authenticator: " + err.Error())
}
conn = auth.Client(conn)
}
}
return NewConnection(id, conn, globalCache, tcpSettings), nil
}

View File

@ -28,6 +28,7 @@ type TCPListener struct {
listener *net.TCPListener
awaitingConns chan *ConnectionWithError
tlsConfig *tls.Config
authConfig internet.ConnectionAuthenticator
config *Config
}
@ -62,6 +63,17 @@ func ListenTCP(address v2net.Address, port v2net.Port, options internet.ListenOp
l.tlsConfig = tlsConfig.GetTLSConfig()
}
}
if tcpSettings.HeaderSettings != nil {
headerConfig, err := tcpSettings.HeaderSettings.GetInstance()
if err != nil {
return nil, errors.New("TCP: Failed to get header settings: " + err.Error())
}
auth, err := internet.CreateConnectionAuthenticator(tcpSettings.HeaderSettings.Type, headerConfig)
if err != nil {
return nil, errors.New("TCP: Failed to create header authenticator: " + err.Error())
}
l.authConfig = auth
}
go l.KeepAccepting()
return l, nil
}
@ -95,6 +107,9 @@ func (this *TCPListener) KeepAccepting() {
if this.tlsConfig != nil {
conn = tls.Server(conn, this.tlsConfig)
}
if this.authConfig != nil {
conn = this.authConfig.Server(conn)
}
select {
case this.awaitingConns <- &ConnectionWithError{
conn: conn,