diff --git a/main/distro/all/all.go b/main/distro/all/all.go index 33e29551d93..ba86a4920dc 100644 --- a/main/distro/all/all.go +++ b/main/distro/all/all.go @@ -77,6 +77,7 @@ import ( _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/assembler/packetconn" _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/stereotype/meek" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/stereotype/mekya" _ "github.com/v2fly/v2ray-core/v5/transport/internet/dtls" diff --git a/testing/scenarios/config/mekya_client.json b/testing/scenarios/config/mekya_client.json new file mode 100644 index 00000000000..1825d25861a --- /dev/null +++ b/testing/scenarios/config/mekya_client.json @@ -0,0 +1,71 @@ +{ + "log": { + "error": { + "level": "Debug", + "type": "Console" + }, + "access": { + "type": "None" + } + }, + "outbounds": [ + { + "protocol": "vmess", + "settings": { + "address": "127.0.0.1", + "port": 17773, + "uuid": "bcc71618-e552-42c2-a2a3-d4c17a9df764" + }, + "streamSettings": { + "transport": "mekya", + "transportSettings": { + "url": "https://127.0.0.1:17773/mrss48bvxrkfq1qzeqte5o61mmvc9gx6hq51", + "maxWriteDelay": 80, + "maxRequestSize": 96000, + "pollingIntervalInitial": 200, + "h2_pool_size": 8, + "kcp": { + "mtu": { + "value": 1450 + }, + "tti": { + "value": 15 + }, + "uplink_capacity": { + "value": 40 + }, + "downlink_capacity": { + "value": 2000 + }, + "congestion": false, + "write_buffer": { + "size": 671088640 + }, + "read_buffer": { + "size": 671088640 + } + } + }, + "security": "tls", + "securitySettings": { + "pinnedPeerCertificateChainSha256": [ + "kqHyvea27Pn+JiSqA72lhu9IKAKeGR+3yCyA8JR1mug=" + ], + "allowInsecureIfPinnedPeerCertificate": true + } + } + } + ], + "inbounds": [ + { + "protocol": "socks", + "settings": { + "udpEnabled": false, + "address": "127.0.0.1", + "packetEncoding": "Packet" + }, + "port": 17774, + "listen": "127.0.0.1" + } + ] +} diff --git a/testing/scenarios/config/mekya_server.json b/testing/scenarios/config/mekya_server.json new file mode 100644 index 00000000000..2d9e32ac40d --- /dev/null +++ b/testing/scenarios/config/mekya_server.json @@ -0,0 +1,69 @@ +{ + "log": { + "error": { + "level": "Debug", + "type": "Console" + }, + "access": { + "type": "None" + } + }, + "outbounds": [ + { + "protocol": "freedom" + } + ], + "inbounds": [ + { + "listen": "127.0.0.1", + "port": 17773, + "protocol": "vmess", + "settings": { + "users": [ + "bcc71618-e552-42c2-a2a3-d4c17a9df764" + ] + }, + "streamSettings": { + "transport": "mekya", + "transportSettings": { + "url": "http://127.0.0.1:12777", + "maxWriteSize": 10485760, + "maxWriteDurationMs": 5000, + "maxSimultaneousWriteConnection": 128, + "packetWritingBuffer": 65536, + "kcp": { + "mtu": { + "value": 1450 + }, + "tti": { + "value": 15 + }, + "uplink_capacity": { + "value": 40 + }, + "downlink_capacity": { + "value": 2000 + }, + "congestion": false, + "write_buffer": { + "size": 671088640 + }, + "read_buffer": { + "size": 671088640 + } + } + }, + "security": "tls", + "securitySettings": { + "certificate": [ + { + "usage": "ENCIPHERMENT", + "certificateFile": "cert/self-signed_cert.pem", + "keyFile": "cert/self-signed_key.pem" + } + ] + } + } + } + ] +} diff --git a/testing/scenarios/mekya_test.go b/testing/scenarios/mekya_test.go new file mode 100644 index 00000000000..de457b1698c --- /dev/null +++ b/testing/scenarios/mekya_test.go @@ -0,0 +1,52 @@ +package scenarios + +import ( + "context" + "os" + "testing" + "time" + + "github.com/v2fly/v2ray-core/v5/common" + "github.com/v2fly/v2ray-core/v5/testing/servers/tcp" + + _ "github.com/v2fly/v2ray-core/v5/main/distro/all" +) + +func TestMekya(t *testing.T) { + tcpServer := tcp.Server{ + MsgProcessor: xor, + } + dest, err := tcpServer.Start() + common.Must(err) + defer tcpServer.Close() + + coreInst, InstMgrIfce := NewInstanceManagerCoreInstance() + defer coreInst.Close() + + common.Must(InstMgrIfce.AddInstance( + context.TODO(), + "mekya_client", + common.Must2(os.ReadFile("config/mekya_client.json")).([]byte), + "jsonv5")) + + common.Must(InstMgrIfce.AddInstance( + context.TODO(), + "mekya_server", + common.Must2(os.ReadFile("config/mekya_server.json")).([]byte), + "jsonv5")) + + common.Must(InstMgrIfce.StartInstance(context.TODO(), "mekya_server")) + common.Must(InstMgrIfce.StartInstance(context.TODO(), "mekya_client")) + + defer func() { + common.Must(InstMgrIfce.StopInstance(context.TODO(), "mekya_server")) + common.Must(InstMgrIfce.StopInstance(context.TODO(), "mekya_client")) + common.Must(InstMgrIfce.UntrackInstance(context.TODO(), "mekya_server")) + common.Must(InstMgrIfce.UntrackInstance(context.TODO(), "mekya_client")) + coreInst.Close() + }() + + if err := testTCPConnViaSocks(17774, dest.Port, 1024, time.Second*2)(); err != nil { + t.Error(err) + } +} diff --git a/transport/internet/request/stereotype/mekya/config.pb.go b/transport/internet/request/stereotype/mekya/config.pb.go new file mode 100644 index 00000000000..1c5e2cd1f78 --- /dev/null +++ b/transport/internet/request/stereotype/mekya/config.pb.go @@ -0,0 +1,266 @@ +package mekya + +import ( + _ "github.com/v2fly/v2ray-core/v5/common/protoext" + kcp "github.com/v2fly/v2ray-core/v5/transport/internet/kcp" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Config struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Kcp *kcp.Config `protobuf:"bytes,1,opt,name=kcp,proto3" json:"kcp,omitempty"` + // Client + MaxWriteDelay int32 `protobuf:"varint,1003,opt,name=max_write_delay,json=maxWriteDelay,proto3" json:"max_write_delay,omitempty"` + MaxRequestSize int32 `protobuf:"varint,1004,opt,name=max_request_size,json=maxRequestSize,proto3" json:"max_request_size,omitempty"` + PollingIntervalInitial int32 `protobuf:"varint,1005,opt,name=polling_interval_initial,json=pollingIntervalInitial,proto3" json:"polling_interval_initial,omitempty"` + // Server + MaxWriteSize int32 `protobuf:"varint,2003,opt,name=max_write_size,json=maxWriteSize,proto3" json:"max_write_size,omitempty"` + MaxWriteDurationMs int32 `protobuf:"varint,2004,opt,name=max_write_duration_ms,json=maxWriteDurationMs,proto3" json:"max_write_duration_ms,omitempty"` + MaxSimultaneousWriteConnection int32 `protobuf:"varint,2005,opt,name=max_simultaneous_write_connection,json=maxSimultaneousWriteConnection,proto3" json:"max_simultaneous_write_connection,omitempty"` + PacketWritingBuffer int32 `protobuf:"varint,2006,opt,name=packet_writing_buffer,json=packetWritingBuffer,proto3" json:"packet_writing_buffer,omitempty"` + // Roundtripper + Url string `protobuf:"bytes,3001,opt,name=url,proto3" json:"url,omitempty"` + H2PoolSize int32 `protobuf:"varint,3003,opt,name=h2_pool_size,json=h2PoolSize,proto3" json:"h2_pool_size,omitempty"` +} + +func (x *Config) Reset() { + *x = Config{} + if protoimpl.UnsafeEnabled { + mi := &file_transport_internet_request_stereotype_mekya_config_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Config) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Config) ProtoMessage() {} + +func (x *Config) ProtoReflect() protoreflect.Message { + mi := &file_transport_internet_request_stereotype_mekya_config_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Config.ProtoReflect.Descriptor instead. +func (*Config) Descriptor() ([]byte, []int) { + return file_transport_internet_request_stereotype_mekya_config_proto_rawDescGZIP(), []int{0} +} + +func (x *Config) GetKcp() *kcp.Config { + if x != nil { + return x.Kcp + } + return nil +} + +func (x *Config) GetMaxWriteDelay() int32 { + if x != nil { + return x.MaxWriteDelay + } + return 0 +} + +func (x *Config) GetMaxRequestSize() int32 { + if x != nil { + return x.MaxRequestSize + } + return 0 +} + +func (x *Config) GetPollingIntervalInitial() int32 { + if x != nil { + return x.PollingIntervalInitial + } + return 0 +} + +func (x *Config) GetMaxWriteSize() int32 { + if x != nil { + return x.MaxWriteSize + } + return 0 +} + +func (x *Config) GetMaxWriteDurationMs() int32 { + if x != nil { + return x.MaxWriteDurationMs + } + return 0 +} + +func (x *Config) GetMaxSimultaneousWriteConnection() int32 { + if x != nil { + return x.MaxSimultaneousWriteConnection + } + return 0 +} + +func (x *Config) GetPacketWritingBuffer() int32 { + if x != nil { + return x.PacketWritingBuffer + } + return 0 +} + +func (x *Config) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *Config) GetH2PoolSize() int32 { + if x != nil { + return x.H2PoolSize + } + return 0 +} + +var File_transport_internet_request_stereotype_mekya_config_proto protoreflect.FileDescriptor + +var file_transport_internet_request_stereotype_mekya_config_proto_rawDesc = []byte{ + 0x0a, 0x38, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2f, 0x73, 0x74, 0x65, + 0x72, 0x65, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2f, 0x6d, 0x65, 0x6b, 0x79, 0x61, 0x2f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x36, 0x76, 0x32, 0x72, 0x61, + 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x73, 0x74, 0x65, 0x72, 0x65, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x65, 0x6b, + 0x79, 0x61, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x23, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x63, 0x70, 0x2f, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x04, 0x0a, 0x06, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x03, 0x6b, 0x63, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2e, 0x6b, 0x63, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x6b, 0x63, + 0x70, 0x12, 0x27, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x64, + 0x65, 0x6c, 0x61, 0x79, 0x18, 0xeb, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6d, 0x61, 0x78, + 0x57, 0x72, 0x69, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x6d, 0x61, + 0x78, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0xec, + 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x39, 0x0a, 0x18, 0x70, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, + 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, + 0x6c, 0x18, 0xed, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x16, 0x70, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, + 0x67, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, + 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x69, + 0x7a, 0x65, 0x18, 0xd3, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x57, 0x72, + 0x69, 0x74, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x6d, 0x61, 0x78, 0x5f, 0x77, + 0x72, 0x69, 0x74, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, + 0x18, 0xd4, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x6d, 0x61, 0x78, 0x57, 0x72, 0x69, 0x74, + 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x4a, 0x0a, 0x21, 0x6d, + 0x61, 0x78, 0x5f, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x74, 0x61, 0x6e, 0x65, 0x6f, 0x75, 0x73, 0x5f, + 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0xd5, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1e, 0x6d, 0x61, 0x78, 0x53, 0x69, 0x6d, 0x75, + 0x6c, 0x74, 0x61, 0x6e, 0x65, 0x6f, 0x75, 0x73, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x15, 0x70, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, + 0x18, 0xd6, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x57, + 0x72, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x12, 0x11, 0x0a, 0x03, + 0x75, 0x72, 0x6c, 0x18, 0xb9, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, + 0x21, 0x0a, 0x0c, 0x68, 0x32, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, + 0xbb, 0x17, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x68, 0x32, 0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x69, + 0x7a, 0x65, 0x3a, 0x1a, 0x82, 0xb5, 0x18, 0x16, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, + 0x6f, 0x72, 0x74, 0x12, 0x05, 0x6d, 0x65, 0x6b, 0x79, 0x61, 0x90, 0xff, 0x29, 0x01, 0x42, 0xc3, + 0x01, 0x0a, 0x3a, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x65, + 0x72, 0x65, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6d, 0x65, 0x6b, 0x79, 0x61, 0x50, 0x01, 0x5a, + 0x4a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, + 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x65, 0x74, 0x2f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2f, 0x73, 0x74, 0x65, 0x72, 0x65, + 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2f, 0x6d, 0x65, 0x6b, 0x79, 0x61, 0xaa, 0x02, 0x36, 0x56, 0x32, + 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x53, 0x74, 0x65, 0x72, 0x65, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x4d, + 0x65, 0x6b, 0x79, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_transport_internet_request_stereotype_mekya_config_proto_rawDescOnce sync.Once + file_transport_internet_request_stereotype_mekya_config_proto_rawDescData = file_transport_internet_request_stereotype_mekya_config_proto_rawDesc +) + +func file_transport_internet_request_stereotype_mekya_config_proto_rawDescGZIP() []byte { + file_transport_internet_request_stereotype_mekya_config_proto_rawDescOnce.Do(func() { + file_transport_internet_request_stereotype_mekya_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_internet_request_stereotype_mekya_config_proto_rawDescData) + }) + return file_transport_internet_request_stereotype_mekya_config_proto_rawDescData +} + +var file_transport_internet_request_stereotype_mekya_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_transport_internet_request_stereotype_mekya_config_proto_goTypes = []any{ + (*Config)(nil), // 0: v2ray.core.transport.internet.request.stereotype.mekya.Config + (*kcp.Config)(nil), // 1: v2ray.core.transport.internet.kcp.Config +} +var file_transport_internet_request_stereotype_mekya_config_proto_depIdxs = []int32{ + 1, // 0: v2ray.core.transport.internet.request.stereotype.mekya.Config.kcp:type_name -> v2ray.core.transport.internet.kcp.Config + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_transport_internet_request_stereotype_mekya_config_proto_init() } +func file_transport_internet_request_stereotype_mekya_config_proto_init() { + if File_transport_internet_request_stereotype_mekya_config_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_transport_internet_request_stereotype_mekya_config_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*Config); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_transport_internet_request_stereotype_mekya_config_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_transport_internet_request_stereotype_mekya_config_proto_goTypes, + DependencyIndexes: file_transport_internet_request_stereotype_mekya_config_proto_depIdxs, + MessageInfos: file_transport_internet_request_stereotype_mekya_config_proto_msgTypes, + }.Build() + File_transport_internet_request_stereotype_mekya_config_proto = out.File + file_transport_internet_request_stereotype_mekya_config_proto_rawDesc = nil + file_transport_internet_request_stereotype_mekya_config_proto_goTypes = nil + file_transport_internet_request_stereotype_mekya_config_proto_depIdxs = nil +} diff --git a/transport/internet/request/stereotype/mekya/config.proto b/transport/internet/request/stereotype/mekya/config.proto new file mode 100644 index 00000000000..8a28cfcdc69 --- /dev/null +++ b/transport/internet/request/stereotype/mekya/config.proto @@ -0,0 +1,35 @@ +syntax = "proto3"; + +package v2ray.core.transport.internet.request.stereotype.mekya; +option csharp_namespace = "V2Ray.Core.Transport.Internet.Request.Stereotype.Mekya"; +option go_package = "github.com/v2fly/v2ray-core/v5/transport/internet/request/stereotype/mekya"; +option java_package = "com.v2ray.core.transport.internet.request.stereotype.mekya"; +option java_multiple_files = true; + +import "common/protoext/extensions.proto"; + +import "transport/internet/kcp/config.proto"; + +message Config{ + option (v2ray.core.common.protoext.message_opt).type = "transport"; + option (v2ray.core.common.protoext.message_opt).short_name = "mekya"; + option (v2ray.core.common.protoext.message_opt).allow_restricted_mode_load = true; + + + v2ray.core.transport.internet.kcp.Config kcp = 1; + + // Client + int32 max_write_delay = 1003; + int32 max_request_size = 1004; + int32 polling_interval_initial = 1005; + + // Server + int32 max_write_size = 2003; + int32 max_write_duration_ms = 2004; + int32 max_simultaneous_write_connection = 2005; + int32 packet_writing_buffer = 2006; + + // Roundtripper + string url = 3001; + int32 h2_pool_size = 3003; +} \ No newline at end of file diff --git a/transport/internet/request/stereotype/mekya/errors.generated.go b/transport/internet/request/stereotype/mekya/errors.generated.go new file mode 100644 index 00000000000..25dcddc2365 --- /dev/null +++ b/transport/internet/request/stereotype/mekya/errors.generated.go @@ -0,0 +1,9 @@ +package mekya + +import "github.com/v2fly/v2ray-core/v5/common/errors" + +type errPathObjHolder struct{} + +func newError(values ...interface{}) *errors.Error { + return errors.New(values...).WithPathObj(errPathObjHolder{}) +} diff --git a/transport/internet/request/stereotype/mekya/mekya.go b/transport/internet/request/stereotype/mekya/mekya.go new file mode 100644 index 00000000000..83196d8e787 --- /dev/null +++ b/transport/internet/request/stereotype/mekya/mekya.go @@ -0,0 +1,83 @@ +package mekya + +import ( + "context" + + "github.com/v2fly/v2ray-core/v5/common" + "github.com/v2fly/v2ray-core/v5/common/net" + "github.com/v2fly/v2ray-core/v5/common/serial" + "github.com/v2fly/v2ray-core/v5/transport/internet" + "github.com/v2fly/v2ray-core/v5/transport/internet/request/assembler/packetconn" + "github.com/v2fly/v2ray-core/v5/transport/internet/request/assembly" + "github.com/v2fly/v2ray-core/v5/transport/internet/request/roundtripper/httprt" +) + +//go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen + +const protocolName = "mekya" + +func init() { + common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { + return nil, newError("meek is a transport") + })) + + common.Must(internet.RegisterTransportDialer(protocolName, mekyaDial)) + common.Must(internet.RegisterTransportListener(protocolName, mekyaListen)) +} + +func mekyaDial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) { + mekyaSetting := streamSettings.ProtocolSettings.(*Config) + packetConnAssembler := &packetconn.ClientConfig{} + packetConnAssembler.PollingIntervalInitial = mekyaSetting.PollingIntervalInitial + packetConnAssembler.MaxRequestSize = mekyaSetting.MaxRequestSize + packetConnAssembler.MaxWriteDelay = mekyaSetting.MaxWriteDelay + packetConnAssembler.UnderlyingTransportName = "kcp" + packetConnAssembler.UnderlyingTransportSetting = serial.ToTypedMessage(mekyaSetting.Kcp) + + httprtSetting := &httprt.ClientConfig{ + Http: &httprt.HTTPConfig{ + UrlPrefix: mekyaSetting.Url, + }, + H2PoolSize: mekyaSetting.H2PoolSize, + } + + request := &assembly.Config{ + Assembler: serial.ToTypedMessage(packetConnAssembler), + Roundtripper: serial.ToTypedMessage(httprtSetting), + } + + constructedSetting := &internet.MemoryStreamConfig{ + ProtocolName: "request", + ProtocolSettings: request, + SecurityType: streamSettings.SecurityType, + SecuritySettings: streamSettings.SecuritySettings, + SocketSettings: streamSettings.SocketSettings, + } + + return internet.Dial(ctx, dest, constructedSetting) +} +func mekyaListen(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, callback internet.ConnHandler) (internet.Listener, error) { + mekyaSetting := streamSettings.ProtocolSettings.(*Config) + packetConnAssembler := &packetconn.ServerConfig{} + packetConnAssembler.MaxWriteSize = mekyaSetting.MaxWriteSize + packetConnAssembler.MaxSimultaneousWriteConnection = mekyaSetting.MaxSimultaneousWriteConnection + packetConnAssembler.MaxWriteDurationMs = mekyaSetting.MaxWriteDurationMs + packetConnAssembler.PacketWritingBuffer = mekyaSetting.PacketWritingBuffer + packetConnAssembler.UnderlyingTransportName = "kcp" + packetConnAssembler.UnderlyingTransportSetting = serial.ToTypedMessage(mekyaSetting.Kcp) + + request := &assembly.Config{ + Assembler: serial.ToTypedMessage(packetConnAssembler), + Roundtripper: serial.ToTypedMessage(&httprt.ServerConfig{}), + } + + constructedSetting := &internet.MemoryStreamConfig{ + ProtocolName: "request", + ProtocolSettings: request, + SecurityType: streamSettings.SecurityType, + SecuritySettings: streamSettings.SecuritySettings, + SocketSettings: streamSettings.SocketSettings, + } + + return internet.ListenTCP(ctx, address, port, constructedSetting, callback) +}