- 允许注册
+ 允许注册
@@ -40,10 +40,12 @@
登录设置
@@ -51,17 +53,19 @@
电子邮箱相关
- 启用电子邮箱绑定功能
+ 启用电子邮箱绑定功能
-
+
提示用户未绑定
-
+
+
@@ -73,20 +77,25 @@
-
+
+
激活邮件标题
-
-
+
+
激活邮件内容
-
+
@@ -98,7 +107,7 @@
通过邮箱找回密码
- 启用找回密码功能
+ 启用找回密码功能
@@ -106,20 +115,27 @@
-
+
找回密码邮件标题
-
-
+
+
找回密码邮件内容
-
-
+
+
@@ -130,17 +146,19 @@
手机号码相关
- 启用手机号码绑定功能
+ 启用手机号码绑定功能
-
+
提示用户未绑定
-
+
+
@@ -159,12 +177,14 @@
-
+
激活短信内容
-
+
@@ -176,7 +196,7 @@
CDN服务
- 开通CDN服务
+ 开通CDN服务
@@ -200,12 +220,14 @@
暂时还没有开通任何功能。
- {{feature.name}}
+
+ {{feature.name}}
@@ -232,8 +254,9 @@
DDoS高防
- 开通DDoS高防管理
-
+ 开通DDoS高防管理
+
+
@@ -246,9 +269,10 @@
智能DNS服务
- 开通智能DNS服务
-
-
+ 开通智能DNS服务
+
+
+
@@ -256,5 +280,28 @@
+
+ HTTPDNS服务
+
+
+ 开通HTTPDNS服务
+
+
+
+
+
+
+ 默认分配集群
+
+
+ [未选择]
+ {{cluster.name}}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EdgeAdmin/web/views/@default/users/setting/index.js b/EdgeAdmin/web/views/@default/users/setting/index.js
index 607dbaa..92e50ab 100644
--- a/EdgeAdmin/web/views/@default/users/setting/index.js
+++ b/EdgeAdmin/web/views/@default/users/setting/index.js
@@ -7,7 +7,8 @@ Tea.context(function () {
this.mobileVerificationMoreOptions = false
this.mobileResetPasswordMoreOptions = false
- this.featureOp = "overwrite"
+ // 默认不影响已有用户功能,避免保存注册设置时误改用户功能绑定
+ this.featureOp = "keep"
this.featuresVisible = false
this.showFeatures = function () {
@@ -27,4 +28,4 @@ Tea.context(function () {
})
return names.join(" / ")
}
-})
\ No newline at end of file
+})
diff --git a/EdgeAdmin/web/views/@default/users/update.html b/EdgeAdmin/web/views/@default/users/update.html
index 61f4b8a..c28f825 100644
--- a/EdgeAdmin/web/views/@default/users/update.html
+++ b/EdgeAdmin/web/views/@default/users/update.html
@@ -39,12 +39,22 @@
- 关联集群 *
+ CDN关联集群 *
+
+ HTTPDNS关联集群
+
+
+ [未选择]
+ {{cluster.name}}
+
+
+
+
diff --git a/EdgeAdmin/web/views/@default/users/user.html b/EdgeAdmin/web/views/@default/users/user.html
index 51e28b8..03f06cd 100644
--- a/EdgeAdmin/web/views/@default/users/user.html
+++ b/EdgeAdmin/web/views/@default/users/user.html
@@ -9,12 +9,13 @@
信息未审核 [审核]
已拒绝
- [重新审核]
+ [重新审核]
-
+
@@ -30,9 +31,18 @@
- 关联集群
+ CDN关联集群
- {{user.cluster.name}}
+ {{user.cluster.name}}
+ 没有设置。
+
+
+
+ HTTPDNS关联集群
+
+ {{user.httpdnsCluster.name}}
没有设置。
@@ -106,8 +116,9 @@
认证二维码
-
-
+
+
diff --git a/EdgeCommon/pkg/iplibrary/reader_maxmind.go b/EdgeCommon/pkg/iplibrary/reader_maxmind.go
index 15d3557..828198e 100644
--- a/EdgeCommon/pkg/iplibrary/reader_maxmind.go
+++ b/EdgeCommon/pkg/iplibrary/reader_maxmind.go
@@ -7,9 +7,7 @@ import (
"github.com/oschwald/geoip2-golang"
"net"
"os"
- "path/filepath"
"sync"
- "time"
)
// MaxMindReader MaxMind GeoIP2 Reader
@@ -19,6 +17,9 @@ type MaxMindReader struct {
meta *Meta
initialized bool
mutex sync.RWMutex
+
+ // 临时文件路径,Destroy 时自动清理
+ tmpFiles []string
}
// NewMaxMindReader 创建 MaxMind Reader
@@ -66,27 +67,9 @@ func NewMaxMindReaderFromBytes(cityDBData, asnDBData []byte) (*MaxMindReader, er
return nil, fmt.Errorf("city database data is required")
}
- // 创建临时文件,使用更唯一的文件名避免冲突
- tmpDir := os.TempDir()
- pid := os.Getpid()
- // 使用时间戳增加唯一性,避免同一进程多次调用时的冲突
- timestamp := time.Now().UnixNano()
- cityTmpFile := filepath.Join(tmpDir, fmt.Sprintf("geolite2-city-%d-%d.mmdb", pid, timestamp))
- asnTmpFile := filepath.Join(tmpDir, fmt.Sprintf("geolite2-asn-%d-%d.mmdb", pid, timestamp))
-
- // 如果临时文件已存在,先删除(可能是之前崩溃留下的)
- os.Remove(cityTmpFile)
- os.Remove(asnTmpFile)
-
- // 写入 City 数据库到临时文件
- if err := os.WriteFile(cityTmpFile, cityDBData, 0644); err != nil {
- return nil, fmt.Errorf("write city database to temp file failed: %w", err)
- }
-
- // 打开 City 数据库
- db, err := geoip2.Open(cityTmpFile)
+ // 直接从内存字节加载,避免在 /tmp 持续生成 mmdb 临时文件。
+ db, err := geoip2.FromBytes(cityDBData)
if err != nil {
- os.Remove(cityTmpFile)
return nil, fmt.Errorf("open MaxMind city database failed: %w", err)
}
@@ -94,16 +77,11 @@ func NewMaxMindReaderFromBytes(cityDBData, asnDBData []byte) (*MaxMindReader, er
db: db,
}
- // 写入并打开 ASN 数据库(可选)
+ // 加载 ASN 数据库(可选)
if len(asnDBData) > 0 {
- if err := os.WriteFile(asnTmpFile, asnDBData, 0644); err == nil {
- dbASN, err := geoip2.Open(asnTmpFile)
- if err == nil {
- reader.dbASN = dbASN
- } else {
- // ASN 数据库打开失败,清理临时文件但不影响主功能
- os.Remove(asnTmpFile)
- }
+ dbASN, err := geoip2.FromBytes(asnDBData)
+ if err == nil {
+ reader.dbASN = dbASN
}
}
@@ -174,7 +152,7 @@ func (this *MaxMindReader) Meta() *Meta {
return this.meta
}
-// Destroy 销毁 Reader
+// Destroy 销毁 Reader 并清理临时文件
func (this *MaxMindReader) Destroy() {
this.mutex.Lock()
defer this.mutex.Unlock()
@@ -187,6 +165,10 @@ func (this *MaxMindReader) Destroy() {
this.dbASN.Close()
this.dbASN = nil
}
+ for _, f := range this.tmpFiles {
+ os.Remove(f)
+ }
+ this.tmpFiles = nil
this.initialized = false
}
diff --git a/EdgeCommon/pkg/nodeconfigs/node_roles.go b/EdgeCommon/pkg/nodeconfigs/node_roles.go
index fab0553..4a46434 100644
--- a/EdgeCommon/pkg/nodeconfigs/node_roles.go
+++ b/EdgeCommon/pkg/nodeconfigs/node_roles.go
@@ -10,6 +10,7 @@ const (
NodeRoleDatabase NodeRole = "database"
NodeRoleLog NodeRole = "log"
NodeRoleDNS NodeRole = "dns"
+ NodeRoleHTTPDNS NodeRole = "httpdns"
NodeRoleMonitor NodeRole = "monitor"
NodeRoleNode NodeRole = "node"
NodeRoleCluster NodeRole = "cluster"
diff --git a/EdgeCommon/pkg/rpc/pb/model_httpdns_access_log.pb.go b/EdgeCommon/pkg/rpc/pb/model_httpdns_access_log.pb.go
new file mode 100644
index 0000000..f75b0c1
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/model_httpdns_access_log.pb.go
@@ -0,0 +1,329 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.35.1
+// protoc v3.21.12
+// source: models/model_httpdns_access_log.proto
+
+package pb
+
+import (
+ 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 HTTPDNSAccessLog struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ RequestId string `protobuf:"bytes,2,opt,name=requestId,proto3" json:"requestId,omitempty"`
+ ClusterId int64 `protobuf:"varint,3,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+ NodeId int64 `protobuf:"varint,4,opt,name=nodeId,proto3" json:"nodeId,omitempty"`
+ AppId string `protobuf:"bytes,5,opt,name=appId,proto3" json:"appId,omitempty"`
+ AppName string `protobuf:"bytes,6,opt,name=appName,proto3" json:"appName,omitempty"`
+ Domain string `protobuf:"bytes,7,opt,name=domain,proto3" json:"domain,omitempty"`
+ Qtype string `protobuf:"bytes,8,opt,name=qtype,proto3" json:"qtype,omitempty"`
+ ClientIP string `protobuf:"bytes,9,opt,name=clientIP,proto3" json:"clientIP,omitempty"`
+ ClientRegion string `protobuf:"bytes,10,opt,name=clientRegion,proto3" json:"clientRegion,omitempty"`
+ Carrier string `protobuf:"bytes,11,opt,name=carrier,proto3" json:"carrier,omitempty"`
+ SdkVersion string `protobuf:"bytes,12,opt,name=sdkVersion,proto3" json:"sdkVersion,omitempty"`
+ Os string `protobuf:"bytes,13,opt,name=os,proto3" json:"os,omitempty"`
+ ResultIPs string `protobuf:"bytes,14,opt,name=resultIPs,proto3" json:"resultIPs,omitempty"`
+ Status string `protobuf:"bytes,15,opt,name=status,proto3" json:"status,omitempty"`
+ ErrorCode string `protobuf:"bytes,16,opt,name=errorCode,proto3" json:"errorCode,omitempty"`
+ CostMs int32 `protobuf:"varint,17,opt,name=costMs,proto3" json:"costMs,omitempty"`
+ CreatedAt int64 `protobuf:"varint,18,opt,name=createdAt,proto3" json:"createdAt,omitempty"`
+ Day string `protobuf:"bytes,19,opt,name=day,proto3" json:"day,omitempty"`
+ Summary string `protobuf:"bytes,20,opt,name=summary,proto3" json:"summary,omitempty"`
+ NodeName string `protobuf:"bytes,21,opt,name=nodeName,proto3" json:"nodeName,omitempty"`
+ ClusterName string `protobuf:"bytes,22,opt,name=clusterName,proto3" json:"clusterName,omitempty"`
+}
+
+func (x *HTTPDNSAccessLog) Reset() {
+ *x = HTTPDNSAccessLog{}
+ mi := &file_models_model_httpdns_access_log_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *HTTPDNSAccessLog) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HTTPDNSAccessLog) ProtoMessage() {}
+
+func (x *HTTPDNSAccessLog) ProtoReflect() protoreflect.Message {
+ mi := &file_models_model_httpdns_access_log_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HTTPDNSAccessLog.ProtoReflect.Descriptor instead.
+func (*HTTPDNSAccessLog) Descriptor() ([]byte, []int) {
+ return file_models_model_httpdns_access_log_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *HTTPDNSAccessLog) GetId() int64 {
+ if x != nil {
+ return x.Id
+ }
+ return 0
+}
+
+func (x *HTTPDNSAccessLog) GetRequestId() string {
+ if x != nil {
+ return x.RequestId
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+func (x *HTTPDNSAccessLog) GetNodeId() int64 {
+ if x != nil {
+ return x.NodeId
+ }
+ return 0
+}
+
+func (x *HTTPDNSAccessLog) GetAppId() string {
+ if x != nil {
+ return x.AppId
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetAppName() string {
+ if x != nil {
+ return x.AppName
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetDomain() string {
+ if x != nil {
+ return x.Domain
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetQtype() string {
+ if x != nil {
+ return x.Qtype
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetClientIP() string {
+ if x != nil {
+ return x.ClientIP
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetClientRegion() string {
+ if x != nil {
+ return x.ClientRegion
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetCarrier() string {
+ if x != nil {
+ return x.Carrier
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetSdkVersion() string {
+ if x != nil {
+ return x.SdkVersion
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetOs() string {
+ if x != nil {
+ return x.Os
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetResultIPs() string {
+ if x != nil {
+ return x.ResultIPs
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetStatus() string {
+ if x != nil {
+ return x.Status
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetErrorCode() string {
+ if x != nil {
+ return x.ErrorCode
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetCostMs() int32 {
+ if x != nil {
+ return x.CostMs
+ }
+ return 0
+}
+
+func (x *HTTPDNSAccessLog) GetCreatedAt() int64 {
+ if x != nil {
+ return x.CreatedAt
+ }
+ return 0
+}
+
+func (x *HTTPDNSAccessLog) GetDay() string {
+ if x != nil {
+ return x.Day
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetSummary() string {
+ if x != nil {
+ return x.Summary
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetNodeName() string {
+ if x != nil {
+ return x.NodeName
+ }
+ return ""
+}
+
+func (x *HTTPDNSAccessLog) GetClusterName() string {
+ if x != nil {
+ return x.ClusterName
+ }
+ return ""
+}
+
+var File_models_model_httpdns_access_log_proto protoreflect.FileDescriptor
+
+var file_models_model_httpdns_access_log_proto_rawDesc = []byte{
+ 0x0a, 0x25, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x68,
+ 0x74, 0x74, 0x70, 0x64, 0x6e, 0x73, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f,
+ 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0xd2, 0x04, 0x0a, 0x10,
+ 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67,
+ 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64,
+ 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1c,
+ 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06,
+ 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f,
+ 0x64, 0x65, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70,
+ 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70,
+ 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x07,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x14, 0x0a, 0x05,
+ 0x71, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x74, 0x79,
+ 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x18, 0x09,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x12, 0x22,
+ 0x0a, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x0a,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x67, 0x69,
+ 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x0b, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a,
+ 0x73, 0x64, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0a, 0x73, 0x64, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02,
+ 0x6f, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x09,
+ 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x49, 0x50, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x09, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x49, 0x50, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74,
+ 0x61, 0x74, 0x75, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
+ 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x18,
+ 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65,
+ 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x73, 0x74, 0x4d, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05,
+ 0x52, 0x06, 0x63, 0x6f, 0x73, 0x74, 0x4d, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x72, 0x65, 0x61,
+ 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x61, 0x79, 0x18, 0x13, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x61, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d,
+ 0x61, 0x72, 0x79, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61,
+ 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x15,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20,
+ 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x16, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65,
+ 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_models_model_httpdns_access_log_proto_rawDescOnce sync.Once
+ file_models_model_httpdns_access_log_proto_rawDescData = file_models_model_httpdns_access_log_proto_rawDesc
+)
+
+func file_models_model_httpdns_access_log_proto_rawDescGZIP() []byte {
+ file_models_model_httpdns_access_log_proto_rawDescOnce.Do(func() {
+ file_models_model_httpdns_access_log_proto_rawDescData = protoimpl.X.CompressGZIP(file_models_model_httpdns_access_log_proto_rawDescData)
+ })
+ return file_models_model_httpdns_access_log_proto_rawDescData
+}
+
+var file_models_model_httpdns_access_log_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_models_model_httpdns_access_log_proto_goTypes = []any{
+ (*HTTPDNSAccessLog)(nil), // 0: pb.HTTPDNSAccessLog
+}
+var file_models_model_httpdns_access_log_proto_depIdxs = []int32{
+ 0, // [0:0] is the sub-list for method output_type
+ 0, // [0:0] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_models_model_httpdns_access_log_proto_init() }
+func file_models_model_httpdns_access_log_proto_init() {
+ if File_models_model_httpdns_access_log_proto != nil {
+ return
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_models_model_httpdns_access_log_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_models_model_httpdns_access_log_proto_goTypes,
+ DependencyIndexes: file_models_model_httpdns_access_log_proto_depIdxs,
+ MessageInfos: file_models_model_httpdns_access_log_proto_msgTypes,
+ }.Build()
+ File_models_model_httpdns_access_log_proto = out.File
+ file_models_model_httpdns_access_log_proto_rawDesc = nil
+ file_models_model_httpdns_access_log_proto_goTypes = nil
+ file_models_model_httpdns_access_log_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/model_httpdns_app.pb.go b/EdgeCommon/pkg/rpc/pb/model_httpdns_app.pb.go
new file mode 100644
index 0000000..36c43f1
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/model_httpdns_app.pb.go
@@ -0,0 +1,225 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.36.11
+// protoc v3.21.12
+// source: models/model_httpdns_app.proto
+
+package pb
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+ unsafe "unsafe"
+)
+
+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 HTTPDNSApp struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+ AppId string `protobuf:"bytes,3,opt,name=appId,proto3" json:"appId,omitempty"`
+ IsOn bool `protobuf:"varint,4,opt,name=isOn,proto3" json:"isOn,omitempty"`
+ SniMode string `protobuf:"bytes,7,opt,name=sniMode,proto3" json:"sniMode,omitempty"`
+ SignEnabled bool `protobuf:"varint,8,opt,name=signEnabled,proto3" json:"signEnabled,omitempty"`
+ SignSecret string `protobuf:"bytes,9,opt,name=signSecret,proto3" json:"signSecret,omitempty"`
+ SignUpdatedAt int64 `protobuf:"varint,10,opt,name=signUpdatedAt,proto3" json:"signUpdatedAt,omitempty"`
+ CreatedAt int64 `protobuf:"varint,11,opt,name=createdAt,proto3" json:"createdAt,omitempty"`
+ UpdatedAt int64 `protobuf:"varint,12,opt,name=updatedAt,proto3" json:"updatedAt,omitempty"`
+ UserId int64 `protobuf:"varint,13,opt,name=userId,proto3" json:"userId,omitempty"`
+ ClusterIdsJSON []byte `protobuf:"bytes,14,opt,name=clusterIdsJSON,proto3" json:"clusterIdsJSON,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *HTTPDNSApp) Reset() {
+ *x = HTTPDNSApp{}
+ mi := &file_models_model_httpdns_app_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *HTTPDNSApp) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HTTPDNSApp) ProtoMessage() {}
+
+func (x *HTTPDNSApp) ProtoReflect() protoreflect.Message {
+ mi := &file_models_model_httpdns_app_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HTTPDNSApp.ProtoReflect.Descriptor instead.
+func (*HTTPDNSApp) Descriptor() ([]byte, []int) {
+ return file_models_model_httpdns_app_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *HTTPDNSApp) GetId() int64 {
+ if x != nil {
+ return x.Id
+ }
+ return 0
+}
+
+func (x *HTTPDNSApp) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *HTTPDNSApp) GetAppId() string {
+ if x != nil {
+ return x.AppId
+ }
+ return ""
+}
+
+func (x *HTTPDNSApp) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+func (x *HTTPDNSApp) GetSniMode() string {
+ if x != nil {
+ return x.SniMode
+ }
+ return ""
+}
+
+func (x *HTTPDNSApp) GetSignEnabled() bool {
+ if x != nil {
+ return x.SignEnabled
+ }
+ return false
+}
+
+func (x *HTTPDNSApp) GetSignSecret() string {
+ if x != nil {
+ return x.SignSecret
+ }
+ return ""
+}
+
+func (x *HTTPDNSApp) GetSignUpdatedAt() int64 {
+ if x != nil {
+ return x.SignUpdatedAt
+ }
+ return 0
+}
+
+func (x *HTTPDNSApp) GetCreatedAt() int64 {
+ if x != nil {
+ return x.CreatedAt
+ }
+ return 0
+}
+
+func (x *HTTPDNSApp) GetUpdatedAt() int64 {
+ if x != nil {
+ return x.UpdatedAt
+ }
+ return 0
+}
+
+func (x *HTTPDNSApp) GetUserId() int64 {
+ if x != nil {
+ return x.UserId
+ }
+ return 0
+}
+
+func (x *HTTPDNSApp) GetClusterIdsJSON() []byte {
+ if x != nil {
+ return x.ClusterIdsJSON
+ }
+ return nil
+}
+
+var File_models_model_httpdns_app_proto protoreflect.FileDescriptor
+
+const file_models_model_httpdns_app_proto_rawDesc = "" +
+ "\n" +
+ "\x1emodels/model_httpdns_app.proto\x12\x02pb\"\xe4\x02\n" +
+ "\n" +
+ "HTTPDNSApp\x12\x0e\n" +
+ "\x02id\x18\x01 \x01(\x03R\x02id\x12\x12\n" +
+ "\x04name\x18\x02 \x01(\tR\x04name\x12\x14\n" +
+ "\x05appId\x18\x03 \x01(\tR\x05appId\x12\x12\n" +
+ "\x04isOn\x18\x04 \x01(\bR\x04isOn\x12\x18\n" +
+ "\asniMode\x18\a \x01(\tR\asniMode\x12 \n" +
+ "\vsignEnabled\x18\b \x01(\bR\vsignEnabled\x12\x1e\n" +
+ "\n" +
+ "signSecret\x18\t \x01(\tR\n" +
+ "signSecret\x12$\n" +
+ "\rsignUpdatedAt\x18\n" +
+ " \x01(\x03R\rsignUpdatedAt\x12\x1c\n" +
+ "\tcreatedAt\x18\v \x01(\x03R\tcreatedAt\x12\x1c\n" +
+ "\tupdatedAt\x18\f \x01(\x03R\tupdatedAt\x12\x16\n" +
+ "\x06userId\x18\r \x01(\x03R\x06userId\x12&\n" +
+ "\x0eclusterIdsJSON\x18\x0e \x01(\fR\x0eclusterIdsJSONJ\x04\b\x05\x10\x06J\x04\b\x06\x10\aB\x06Z\x04./pbb\x06proto3"
+
+var (
+ file_models_model_httpdns_app_proto_rawDescOnce sync.Once
+ file_models_model_httpdns_app_proto_rawDescData []byte
+)
+
+func file_models_model_httpdns_app_proto_rawDescGZIP() []byte {
+ file_models_model_httpdns_app_proto_rawDescOnce.Do(func() {
+ file_models_model_httpdns_app_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_models_model_httpdns_app_proto_rawDesc), len(file_models_model_httpdns_app_proto_rawDesc)))
+ })
+ return file_models_model_httpdns_app_proto_rawDescData
+}
+
+var file_models_model_httpdns_app_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_models_model_httpdns_app_proto_goTypes = []any{
+ (*HTTPDNSApp)(nil), // 0: pb.HTTPDNSApp
+}
+var file_models_model_httpdns_app_proto_depIdxs = []int32{
+ 0, // [0:0] is the sub-list for method output_type
+ 0, // [0:0] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_models_model_httpdns_app_proto_init() }
+func file_models_model_httpdns_app_proto_init() {
+ if File_models_model_httpdns_app_proto != nil {
+ return
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_models_model_httpdns_app_proto_rawDesc), len(file_models_model_httpdns_app_proto_rawDesc)),
+ NumEnums: 0,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_models_model_httpdns_app_proto_goTypes,
+ DependencyIndexes: file_models_model_httpdns_app_proto_depIdxs,
+ MessageInfos: file_models_model_httpdns_app_proto_msgTypes,
+ }.Build()
+ File_models_model_httpdns_app_proto = out.File
+ file_models_model_httpdns_app_proto_goTypes = nil
+ file_models_model_httpdns_app_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/model_httpdns_cluster.pb.go b/EdgeCommon/pkg/rpc/pb/model_httpdns_cluster.pb.go
new file mode 100644
index 0000000..4a4935f
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/model_httpdns_cluster.pb.go
@@ -0,0 +1,250 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.35.1
+// protoc v3.21.12
+// source: models/model_httpdns_cluster.proto
+
+package pb
+
+import (
+ 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 HTTPDNSCluster struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ IsOn bool `protobuf:"varint,2,opt,name=isOn,proto3" json:"isOn,omitempty"`
+ IsDefault bool `protobuf:"varint,3,opt,name=isDefault,proto3" json:"isDefault,omitempty"`
+ Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"`
+ ServiceDomain string `protobuf:"bytes,5,opt,name=serviceDomain,proto3" json:"serviceDomain,omitempty"`
+ DefaultTTL int32 `protobuf:"varint,6,opt,name=defaultTTL,proto3" json:"defaultTTL,omitempty"`
+ FallbackTimeoutMs int32 `protobuf:"varint,7,opt,name=fallbackTimeoutMs,proto3" json:"fallbackTimeoutMs,omitempty"`
+ InstallDir string `protobuf:"bytes,8,opt,name=installDir,proto3" json:"installDir,omitempty"`
+ TlsPolicyJSON []byte `protobuf:"bytes,9,opt,name=tlsPolicyJSON,proto3" json:"tlsPolicyJSON,omitempty"`
+ CreatedAt int64 `protobuf:"varint,10,opt,name=createdAt,proto3" json:"createdAt,omitempty"`
+ UpdatedAt int64 `protobuf:"varint,11,opt,name=updatedAt,proto3" json:"updatedAt,omitempty"`
+ AutoRemoteStart bool `protobuf:"varint,12,opt,name=autoRemoteStart,proto3" json:"autoRemoteStart,omitempty"`
+ AccessLogIsOn bool `protobuf:"varint,13,opt,name=accessLogIsOn,proto3" json:"accessLogIsOn,omitempty"`
+ TimeZone string `protobuf:"bytes,14,opt,name=timeZone,proto3" json:"timeZone,omitempty"`
+}
+
+func (x *HTTPDNSCluster) Reset() {
+ *x = HTTPDNSCluster{}
+ mi := &file_models_model_httpdns_cluster_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *HTTPDNSCluster) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HTTPDNSCluster) ProtoMessage() {}
+
+func (x *HTTPDNSCluster) ProtoReflect() protoreflect.Message {
+ mi := &file_models_model_httpdns_cluster_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HTTPDNSCluster.ProtoReflect.Descriptor instead.
+func (*HTTPDNSCluster) Descriptor() ([]byte, []int) {
+ return file_models_model_httpdns_cluster_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *HTTPDNSCluster) GetId() int64 {
+ if x != nil {
+ return x.Id
+ }
+ return 0
+}
+
+func (x *HTTPDNSCluster) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+func (x *HTTPDNSCluster) GetIsDefault() bool {
+ if x != nil {
+ return x.IsDefault
+ }
+ return false
+}
+
+func (x *HTTPDNSCluster) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *HTTPDNSCluster) GetServiceDomain() string {
+ if x != nil {
+ return x.ServiceDomain
+ }
+ return ""
+}
+
+func (x *HTTPDNSCluster) GetDefaultTTL() int32 {
+ if x != nil {
+ return x.DefaultTTL
+ }
+ return 0
+}
+
+func (x *HTTPDNSCluster) GetFallbackTimeoutMs() int32 {
+ if x != nil {
+ return x.FallbackTimeoutMs
+ }
+ return 0
+}
+
+func (x *HTTPDNSCluster) GetInstallDir() string {
+ if x != nil {
+ return x.InstallDir
+ }
+ return ""
+}
+
+func (x *HTTPDNSCluster) GetTlsPolicyJSON() []byte {
+ if x != nil {
+ return x.TlsPolicyJSON
+ }
+ return nil
+}
+
+func (x *HTTPDNSCluster) GetCreatedAt() int64 {
+ if x != nil {
+ return x.CreatedAt
+ }
+ return 0
+}
+
+func (x *HTTPDNSCluster) GetUpdatedAt() int64 {
+ if x != nil {
+ return x.UpdatedAt
+ }
+ return 0
+}
+
+func (x *HTTPDNSCluster) GetAutoRemoteStart() bool {
+ if x != nil {
+ return x.AutoRemoteStart
+ }
+ return false
+}
+
+func (x *HTTPDNSCluster) GetAccessLogIsOn() bool {
+ if x != nil {
+ return x.AccessLogIsOn
+ }
+ return false
+}
+
+func (x *HTTPDNSCluster) GetTimeZone() string {
+ if x != nil {
+ return x.TimeZone
+ }
+ return ""
+}
+
+var File_models_model_httpdns_cluster_proto protoreflect.FileDescriptor
+
+var file_models_model_httpdns_cluster_proto_rawDesc = []byte{
+ 0x0a, 0x22, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x68,
+ 0x74, 0x74, 0x70, 0x64, 0x6e, 0x73, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0xdc, 0x02, 0x0a, 0x0e, 0x48, 0x54, 0x54,
+ 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69,
+ 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x69,
+ 0x73, 0x4f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x12,
+ 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x12, 0x0a,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x6f, 0x6d, 0x61,
+ 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+ 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x66, 0x61, 0x75,
+ 0x6c, 0x74, 0x54, 0x54, 0x4c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x64, 0x65, 0x66,
+ 0x61, 0x75, 0x6c, 0x74, 0x54, 0x54, 0x4c, 0x12, 0x2c, 0x0a, 0x11, 0x66, 0x61, 0x6c, 0x6c, 0x62,
+ 0x61, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x07, 0x20, 0x01,
+ 0x28, 0x05, 0x52, 0x11, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65,
+ 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+ 0x44, 0x69, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61,
+ 0x6c, 0x6c, 0x44, 0x69, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x74, 0x6c, 0x73, 0x50, 0x6f, 0x6c, 0x69,
+ 0x63, 0x79, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x74, 0x6c,
+ 0x73, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x1c, 0x0a, 0x09, 0x63,
+ 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09,
+ 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x70, 0x64,
+ 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x70,
+ 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62,
+ 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_models_model_httpdns_cluster_proto_rawDescOnce sync.Once
+ file_models_model_httpdns_cluster_proto_rawDescData = file_models_model_httpdns_cluster_proto_rawDesc
+)
+
+func file_models_model_httpdns_cluster_proto_rawDescGZIP() []byte {
+ file_models_model_httpdns_cluster_proto_rawDescOnce.Do(func() {
+ file_models_model_httpdns_cluster_proto_rawDescData = protoimpl.X.CompressGZIP(file_models_model_httpdns_cluster_proto_rawDescData)
+ })
+ return file_models_model_httpdns_cluster_proto_rawDescData
+}
+
+var file_models_model_httpdns_cluster_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_models_model_httpdns_cluster_proto_goTypes = []any{
+ (*HTTPDNSCluster)(nil), // 0: pb.HTTPDNSCluster
+}
+var file_models_model_httpdns_cluster_proto_depIdxs = []int32{
+ 0, // [0:0] is the sub-list for method output_type
+ 0, // [0:0] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_models_model_httpdns_cluster_proto_init() }
+func file_models_model_httpdns_cluster_proto_init() {
+ if File_models_model_httpdns_cluster_proto != nil {
+ return
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_models_model_httpdns_cluster_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_models_model_httpdns_cluster_proto_goTypes,
+ DependencyIndexes: file_models_model_httpdns_cluster_proto_depIdxs,
+ MessageInfos: file_models_model_httpdns_cluster_proto_msgTypes,
+ }.Build()
+ File_models_model_httpdns_cluster_proto = out.File
+ file_models_model_httpdns_cluster_proto_rawDesc = nil
+ file_models_model_httpdns_cluster_proto_goTypes = nil
+ file_models_model_httpdns_cluster_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/model_httpdns_domain.pb.go b/EdgeCommon/pkg/rpc/pb/model_httpdns_domain.pb.go
new file mode 100644
index 0000000..0f2c157
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/model_httpdns_domain.pb.go
@@ -0,0 +1,184 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.35.1
+// protoc v3.21.12
+// source: models/model_httpdns_domain.proto
+
+package pb
+
+import (
+ 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 HTTPDNSDomain struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ AppId int64 `protobuf:"varint,2,opt,name=appId,proto3" json:"appId,omitempty"`
+ Domain string `protobuf:"bytes,3,opt,name=domain,proto3" json:"domain,omitempty"`
+ IsOn bool `protobuf:"varint,4,opt,name=isOn,proto3" json:"isOn,omitempty"`
+ CreatedAt int64 `protobuf:"varint,5,opt,name=createdAt,proto3" json:"createdAt,omitempty"`
+ UpdatedAt int64 `protobuf:"varint,6,opt,name=updatedAt,proto3" json:"updatedAt,omitempty"`
+ RuleCount int64 `protobuf:"varint,7,opt,name=ruleCount,proto3" json:"ruleCount,omitempty"`
+}
+
+func (x *HTTPDNSDomain) Reset() {
+ *x = HTTPDNSDomain{}
+ mi := &file_models_model_httpdns_domain_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *HTTPDNSDomain) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HTTPDNSDomain) ProtoMessage() {}
+
+func (x *HTTPDNSDomain) ProtoReflect() protoreflect.Message {
+ mi := &file_models_model_httpdns_domain_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HTTPDNSDomain.ProtoReflect.Descriptor instead.
+func (*HTTPDNSDomain) Descriptor() ([]byte, []int) {
+ return file_models_model_httpdns_domain_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *HTTPDNSDomain) GetId() int64 {
+ if x != nil {
+ return x.Id
+ }
+ return 0
+}
+
+func (x *HTTPDNSDomain) GetAppId() int64 {
+ if x != nil {
+ return x.AppId
+ }
+ return 0
+}
+
+func (x *HTTPDNSDomain) GetDomain() string {
+ if x != nil {
+ return x.Domain
+ }
+ return ""
+}
+
+func (x *HTTPDNSDomain) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+func (x *HTTPDNSDomain) GetCreatedAt() int64 {
+ if x != nil {
+ return x.CreatedAt
+ }
+ return 0
+}
+
+func (x *HTTPDNSDomain) GetUpdatedAt() int64 {
+ if x != nil {
+ return x.UpdatedAt
+ }
+ return 0
+}
+
+func (x *HTTPDNSDomain) GetRuleCount() int64 {
+ if x != nil {
+ return x.RuleCount
+ }
+ return 0
+}
+
+var File_models_model_httpdns_domain_proto protoreflect.FileDescriptor
+
+var file_models_model_httpdns_domain_proto_rawDesc = []byte{
+ 0x0a, 0x21, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x68,
+ 0x74, 0x74, 0x70, 0x64, 0x6e, 0x73, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0xbb, 0x01, 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50,
+ 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70,
+ 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x12,
+ 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x63,
+ 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09,
+ 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x70, 0x64,
+ 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x70,
+ 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x75, 0x6c, 0x65, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x72, 0x75, 0x6c, 0x65,
+ 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_models_model_httpdns_domain_proto_rawDescOnce sync.Once
+ file_models_model_httpdns_domain_proto_rawDescData = file_models_model_httpdns_domain_proto_rawDesc
+)
+
+func file_models_model_httpdns_domain_proto_rawDescGZIP() []byte {
+ file_models_model_httpdns_domain_proto_rawDescOnce.Do(func() {
+ file_models_model_httpdns_domain_proto_rawDescData = protoimpl.X.CompressGZIP(file_models_model_httpdns_domain_proto_rawDescData)
+ })
+ return file_models_model_httpdns_domain_proto_rawDescData
+}
+
+var file_models_model_httpdns_domain_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_models_model_httpdns_domain_proto_goTypes = []any{
+ (*HTTPDNSDomain)(nil), // 0: pb.HTTPDNSDomain
+}
+var file_models_model_httpdns_domain_proto_depIdxs = []int32{
+ 0, // [0:0] is the sub-list for method output_type
+ 0, // [0:0] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_models_model_httpdns_domain_proto_init() }
+func file_models_model_httpdns_domain_proto_init() {
+ if File_models_model_httpdns_domain_proto != nil {
+ return
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_models_model_httpdns_domain_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_models_model_httpdns_domain_proto_goTypes,
+ DependencyIndexes: file_models_model_httpdns_domain_proto_depIdxs,
+ MessageInfos: file_models_model_httpdns_domain_proto_msgTypes,
+ }.Build()
+ File_models_model_httpdns_domain_proto = out.File
+ file_models_model_httpdns_domain_proto_rawDesc = nil
+ file_models_model_httpdns_domain_proto_goTypes = nil
+ file_models_model_httpdns_domain_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/model_httpdns_node.pb.go b/EdgeCommon/pkg/rpc/pb/model_httpdns_node.pb.go
new file mode 100644
index 0000000..204d8bd
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/model_httpdns_node.pb.go
@@ -0,0 +1,256 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.36.11
+// protoc v3.21.12
+// source: models/model_httpdns_node.proto
+
+package pb
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+ unsafe "unsafe"
+)
+
+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 HTTPDNSNode struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ ClusterId int64 `protobuf:"varint,2,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+ Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
+ IsOn bool `protobuf:"varint,4,opt,name=isOn,proto3" json:"isOn,omitempty"`
+ IsUp bool `protobuf:"varint,5,opt,name=isUp,proto3" json:"isUp,omitempty"`
+ IsInstalled bool `protobuf:"varint,6,opt,name=isInstalled,proto3" json:"isInstalled,omitempty"`
+ IsActive bool `protobuf:"varint,7,opt,name=isActive,proto3" json:"isActive,omitempty"`
+ UniqueId string `protobuf:"bytes,8,opt,name=uniqueId,proto3" json:"uniqueId,omitempty"`
+ Secret string `protobuf:"bytes,9,opt,name=secret,proto3" json:"secret,omitempty"`
+ InstallDir string `protobuf:"bytes,10,opt,name=installDir,proto3" json:"installDir,omitempty"`
+ StatusJSON []byte `protobuf:"bytes,11,opt,name=statusJSON,proto3" json:"statusJSON,omitempty"`
+ InstallStatusJSON []byte `protobuf:"bytes,12,opt,name=installStatusJSON,proto3" json:"installStatusJSON,omitempty"`
+ CreatedAt int64 `protobuf:"varint,13,opt,name=createdAt,proto3" json:"createdAt,omitempty"`
+ UpdatedAt int64 `protobuf:"varint,14,opt,name=updatedAt,proto3" json:"updatedAt,omitempty"`
+ NodeLogin *NodeLogin `protobuf:"bytes,15,opt,name=nodeLogin,proto3" json:"nodeLogin,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *HTTPDNSNode) Reset() {
+ *x = HTTPDNSNode{}
+ mi := &file_models_model_httpdns_node_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *HTTPDNSNode) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HTTPDNSNode) ProtoMessage() {}
+
+func (x *HTTPDNSNode) ProtoReflect() protoreflect.Message {
+ mi := &file_models_model_httpdns_node_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HTTPDNSNode.ProtoReflect.Descriptor instead.
+func (*HTTPDNSNode) Descriptor() ([]byte, []int) {
+ return file_models_model_httpdns_node_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *HTTPDNSNode) GetId() int64 {
+ if x != nil {
+ return x.Id
+ }
+ return 0
+}
+
+func (x *HTTPDNSNode) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+func (x *HTTPDNSNode) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *HTTPDNSNode) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+func (x *HTTPDNSNode) GetIsUp() bool {
+ if x != nil {
+ return x.IsUp
+ }
+ return false
+}
+
+func (x *HTTPDNSNode) GetIsInstalled() bool {
+ if x != nil {
+ return x.IsInstalled
+ }
+ return false
+}
+
+func (x *HTTPDNSNode) GetIsActive() bool {
+ if x != nil {
+ return x.IsActive
+ }
+ return false
+}
+
+func (x *HTTPDNSNode) GetUniqueId() string {
+ if x != nil {
+ return x.UniqueId
+ }
+ return ""
+}
+
+func (x *HTTPDNSNode) GetSecret() string {
+ if x != nil {
+ return x.Secret
+ }
+ return ""
+}
+
+func (x *HTTPDNSNode) GetInstallDir() string {
+ if x != nil {
+ return x.InstallDir
+ }
+ return ""
+}
+
+func (x *HTTPDNSNode) GetStatusJSON() []byte {
+ if x != nil {
+ return x.StatusJSON
+ }
+ return nil
+}
+
+func (x *HTTPDNSNode) GetInstallStatusJSON() []byte {
+ if x != nil {
+ return x.InstallStatusJSON
+ }
+ return nil
+}
+
+func (x *HTTPDNSNode) GetCreatedAt() int64 {
+ if x != nil {
+ return x.CreatedAt
+ }
+ return 0
+}
+
+func (x *HTTPDNSNode) GetUpdatedAt() int64 {
+ if x != nil {
+ return x.UpdatedAt
+ }
+ return 0
+}
+
+func (x *HTTPDNSNode) GetNodeLogin() *NodeLogin {
+ if x != nil {
+ return x.NodeLogin
+ }
+ return nil
+}
+
+var File_models_model_httpdns_node_proto protoreflect.FileDescriptor
+
+const file_models_model_httpdns_node_proto_rawDesc = "" +
+ "\n" +
+ "\x1fmodels/model_httpdns_node.proto\x12\x02pb\x1a\x1dmodels/model_node_login.proto\"\xc0\x03\n" +
+ "\vHTTPDNSNode\x12\x0e\n" +
+ "\x02id\x18\x01 \x01(\x03R\x02id\x12\x1c\n" +
+ "\tclusterId\x18\x02 \x01(\x03R\tclusterId\x12\x12\n" +
+ "\x04name\x18\x03 \x01(\tR\x04name\x12\x12\n" +
+ "\x04isOn\x18\x04 \x01(\bR\x04isOn\x12\x12\n" +
+ "\x04isUp\x18\x05 \x01(\bR\x04isUp\x12 \n" +
+ "\visInstalled\x18\x06 \x01(\bR\visInstalled\x12\x1a\n" +
+ "\bisActive\x18\a \x01(\bR\bisActive\x12\x1a\n" +
+ "\buniqueId\x18\b \x01(\tR\buniqueId\x12\x16\n" +
+ "\x06secret\x18\t \x01(\tR\x06secret\x12\x1e\n" +
+ "\n" +
+ "installDir\x18\n" +
+ " \x01(\tR\n" +
+ "installDir\x12\x1e\n" +
+ "\n" +
+ "statusJSON\x18\v \x01(\fR\n" +
+ "statusJSON\x12,\n" +
+ "\x11installStatusJSON\x18\f \x01(\fR\x11installStatusJSON\x12\x1c\n" +
+ "\tcreatedAt\x18\r \x01(\x03R\tcreatedAt\x12\x1c\n" +
+ "\tupdatedAt\x18\x0e \x01(\x03R\tupdatedAt\x12+\n" +
+ "\tnodeLogin\x18\x0f \x01(\v2\r.pb.NodeLoginR\tnodeLoginB\x06Z\x04./pbb\x06proto3"
+
+var (
+ file_models_model_httpdns_node_proto_rawDescOnce sync.Once
+ file_models_model_httpdns_node_proto_rawDescData []byte
+)
+
+func file_models_model_httpdns_node_proto_rawDescGZIP() []byte {
+ file_models_model_httpdns_node_proto_rawDescOnce.Do(func() {
+ file_models_model_httpdns_node_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_models_model_httpdns_node_proto_rawDesc), len(file_models_model_httpdns_node_proto_rawDesc)))
+ })
+ return file_models_model_httpdns_node_proto_rawDescData
+}
+
+var file_models_model_httpdns_node_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_models_model_httpdns_node_proto_goTypes = []any{
+ (*HTTPDNSNode)(nil), // 0: pb.HTTPDNSNode
+ (*NodeLogin)(nil), // 1: pb.NodeLogin
+}
+var file_models_model_httpdns_node_proto_depIdxs = []int32{
+ 1, // 0: pb.HTTPDNSNode.nodeLogin:type_name -> pb.NodeLogin
+ 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_models_model_httpdns_node_proto_init() }
+func file_models_model_httpdns_node_proto_init() {
+ if File_models_model_httpdns_node_proto != nil {
+ return
+ }
+ file_models_model_node_login_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_models_model_httpdns_node_proto_rawDesc), len(file_models_model_httpdns_node_proto_rawDesc)),
+ NumEnums: 0,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_models_model_httpdns_node_proto_goTypes,
+ DependencyIndexes: file_models_model_httpdns_node_proto_depIdxs,
+ MessageInfos: file_models_model_httpdns_node_proto_msgTypes,
+ }.Build()
+ File_models_model_httpdns_node_proto = out.File
+ file_models_model_httpdns_node_proto_goTypes = nil
+ file_models_model_httpdns_node_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/model_httpdns_rule.pb.go b/EdgeCommon/pkg/rpc/pb/model_httpdns_rule.pb.go
new file mode 100644
index 0000000..7d01941
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/model_httpdns_rule.pb.go
@@ -0,0 +1,363 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.35.1
+// protoc v3.21.12
+// source: models/model_httpdns_rule.proto
+
+package pb
+
+import (
+ 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 HTTPDNSRuleRecord struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ RuleId int64 `protobuf:"varint,2,opt,name=ruleId,proto3" json:"ruleId,omitempty"`
+ RecordType string `protobuf:"bytes,3,opt,name=recordType,proto3" json:"recordType,omitempty"`
+ RecordValue string `protobuf:"bytes,4,opt,name=recordValue,proto3" json:"recordValue,omitempty"`
+ Weight int32 `protobuf:"varint,5,opt,name=weight,proto3" json:"weight,omitempty"`
+ Sort int32 `protobuf:"varint,6,opt,name=sort,proto3" json:"sort,omitempty"`
+}
+
+func (x *HTTPDNSRuleRecord) Reset() {
+ *x = HTTPDNSRuleRecord{}
+ mi := &file_models_model_httpdns_rule_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *HTTPDNSRuleRecord) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HTTPDNSRuleRecord) ProtoMessage() {}
+
+func (x *HTTPDNSRuleRecord) ProtoReflect() protoreflect.Message {
+ mi := &file_models_model_httpdns_rule_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HTTPDNSRuleRecord.ProtoReflect.Descriptor instead.
+func (*HTTPDNSRuleRecord) Descriptor() ([]byte, []int) {
+ return file_models_model_httpdns_rule_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *HTTPDNSRuleRecord) GetId() int64 {
+ if x != nil {
+ return x.Id
+ }
+ return 0
+}
+
+func (x *HTTPDNSRuleRecord) GetRuleId() int64 {
+ if x != nil {
+ return x.RuleId
+ }
+ return 0
+}
+
+func (x *HTTPDNSRuleRecord) GetRecordType() string {
+ if x != nil {
+ return x.RecordType
+ }
+ return ""
+}
+
+func (x *HTTPDNSRuleRecord) GetRecordValue() string {
+ if x != nil {
+ return x.RecordValue
+ }
+ return ""
+}
+
+func (x *HTTPDNSRuleRecord) GetWeight() int32 {
+ if x != nil {
+ return x.Weight
+ }
+ return 0
+}
+
+func (x *HTTPDNSRuleRecord) GetSort() int32 {
+ if x != nil {
+ return x.Sort
+ }
+ return 0
+}
+
+type HTTPDNSCustomRule struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ AppId int64 `protobuf:"varint,2,opt,name=appId,proto3" json:"appId,omitempty"`
+ DomainId int64 `protobuf:"varint,3,opt,name=domainId,proto3" json:"domainId,omitempty"`
+ RuleName string `protobuf:"bytes,4,opt,name=ruleName,proto3" json:"ruleName,omitempty"`
+ LineScope string `protobuf:"bytes,5,opt,name=lineScope,proto3" json:"lineScope,omitempty"`
+ LineCarrier string `protobuf:"bytes,6,opt,name=lineCarrier,proto3" json:"lineCarrier,omitempty"`
+ LineRegion string `protobuf:"bytes,7,opt,name=lineRegion,proto3" json:"lineRegion,omitempty"`
+ LineProvince string `protobuf:"bytes,8,opt,name=lineProvince,proto3" json:"lineProvince,omitempty"`
+ LineContinent string `protobuf:"bytes,9,opt,name=lineContinent,proto3" json:"lineContinent,omitempty"`
+ LineCountry string `protobuf:"bytes,10,opt,name=lineCountry,proto3" json:"lineCountry,omitempty"`
+ Ttl int32 `protobuf:"varint,11,opt,name=ttl,proto3" json:"ttl,omitempty"`
+ IsOn bool `protobuf:"varint,12,opt,name=isOn,proto3" json:"isOn,omitempty"`
+ Priority int32 `protobuf:"varint,13,opt,name=priority,proto3" json:"priority,omitempty"`
+ UpdatedAt int64 `protobuf:"varint,14,opt,name=updatedAt,proto3" json:"updatedAt,omitempty"`
+ Records []*HTTPDNSRuleRecord `protobuf:"bytes,15,rep,name=records,proto3" json:"records,omitempty"`
+}
+
+func (x *HTTPDNSCustomRule) Reset() {
+ *x = HTTPDNSCustomRule{}
+ mi := &file_models_model_httpdns_rule_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *HTTPDNSCustomRule) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HTTPDNSCustomRule) ProtoMessage() {}
+
+func (x *HTTPDNSCustomRule) ProtoReflect() protoreflect.Message {
+ mi := &file_models_model_httpdns_rule_proto_msgTypes[1]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HTTPDNSCustomRule.ProtoReflect.Descriptor instead.
+func (*HTTPDNSCustomRule) Descriptor() ([]byte, []int) {
+ return file_models_model_httpdns_rule_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *HTTPDNSCustomRule) GetId() int64 {
+ if x != nil {
+ return x.Id
+ }
+ return 0
+}
+
+func (x *HTTPDNSCustomRule) GetAppId() int64 {
+ if x != nil {
+ return x.AppId
+ }
+ return 0
+}
+
+func (x *HTTPDNSCustomRule) GetDomainId() int64 {
+ if x != nil {
+ return x.DomainId
+ }
+ return 0
+}
+
+func (x *HTTPDNSCustomRule) GetRuleName() string {
+ if x != nil {
+ return x.RuleName
+ }
+ return ""
+}
+
+func (x *HTTPDNSCustomRule) GetLineScope() string {
+ if x != nil {
+ return x.LineScope
+ }
+ return ""
+}
+
+func (x *HTTPDNSCustomRule) GetLineCarrier() string {
+ if x != nil {
+ return x.LineCarrier
+ }
+ return ""
+}
+
+func (x *HTTPDNSCustomRule) GetLineRegion() string {
+ if x != nil {
+ return x.LineRegion
+ }
+ return ""
+}
+
+func (x *HTTPDNSCustomRule) GetLineProvince() string {
+ if x != nil {
+ return x.LineProvince
+ }
+ return ""
+}
+
+func (x *HTTPDNSCustomRule) GetLineContinent() string {
+ if x != nil {
+ return x.LineContinent
+ }
+ return ""
+}
+
+func (x *HTTPDNSCustomRule) GetLineCountry() string {
+ if x != nil {
+ return x.LineCountry
+ }
+ return ""
+}
+
+func (x *HTTPDNSCustomRule) GetTtl() int32 {
+ if x != nil {
+ return x.Ttl
+ }
+ return 0
+}
+
+func (x *HTTPDNSCustomRule) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+func (x *HTTPDNSCustomRule) GetPriority() int32 {
+ if x != nil {
+ return x.Priority
+ }
+ return 0
+}
+
+func (x *HTTPDNSCustomRule) GetUpdatedAt() int64 {
+ if x != nil {
+ return x.UpdatedAt
+ }
+ return 0
+}
+
+func (x *HTTPDNSCustomRule) GetRecords() []*HTTPDNSRuleRecord {
+ if x != nil {
+ return x.Records
+ }
+ return nil
+}
+
+var File_models_model_httpdns_rule_proto protoreflect.FileDescriptor
+
+var file_models_model_httpdns_rule_proto_rawDesc = []byte{
+ 0x0a, 0x1f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x68,
+ 0x74, 0x74, 0x70, 0x64, 0x6e, 0x73, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0xa9, 0x01, 0x0a, 0x11, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e,
+ 0x53, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69,
+ 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72,
+ 0x75, 0x6c, 0x65, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x72, 0x75, 0x6c,
+ 0x65, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x79, 0x70,
+ 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54,
+ 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x56, 0x61, 0x6c,
+ 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18,
+ 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x12, 0x0a,
+ 0x04, 0x73, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x73, 0x6f, 0x72,
+ 0x74, 0x22, 0xce, 0x03, 0x0a, 0x11, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73,
+ 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x12, 0x1a, 0x0a,
+ 0x08, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x08, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x75, 0x6c,
+ 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x75, 0x6c,
+ 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x63, 0x6f,
+ 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x63,
+ 0x6f, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x61, 0x72, 0x72, 0x69,
+ 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x61,
+ 0x72, 0x72, 0x69, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x6c, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x67,
+ 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x69, 0x6e, 0x65, 0x52,
+ 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f,
+ 0x76, 0x69, 0x6e, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x69, 0x6e,
+ 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x6e, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x6c, 0x69, 0x6e,
+ 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0d, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x12,
+ 0x20, 0x0a, 0x0b, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x0a,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72,
+ 0x79, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03,
+ 0x74, 0x74, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72,
+ 0x69, 0x74, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72,
+ 0x69, 0x74, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74,
+ 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41,
+ 0x74, 0x12, 0x2f, 0x0a, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x0f, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52,
+ 0x75, 0x6c, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72,
+ 0x64, 0x73, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x33,
+}
+
+var (
+ file_models_model_httpdns_rule_proto_rawDescOnce sync.Once
+ file_models_model_httpdns_rule_proto_rawDescData = file_models_model_httpdns_rule_proto_rawDesc
+)
+
+func file_models_model_httpdns_rule_proto_rawDescGZIP() []byte {
+ file_models_model_httpdns_rule_proto_rawDescOnce.Do(func() {
+ file_models_model_httpdns_rule_proto_rawDescData = protoimpl.X.CompressGZIP(file_models_model_httpdns_rule_proto_rawDescData)
+ })
+ return file_models_model_httpdns_rule_proto_rawDescData
+}
+
+var file_models_model_httpdns_rule_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_models_model_httpdns_rule_proto_goTypes = []any{
+ (*HTTPDNSRuleRecord)(nil), // 0: pb.HTTPDNSRuleRecord
+ (*HTTPDNSCustomRule)(nil), // 1: pb.HTTPDNSCustomRule
+}
+var file_models_model_httpdns_rule_proto_depIdxs = []int32{
+ 0, // 0: pb.HTTPDNSCustomRule.records:type_name -> pb.HTTPDNSRuleRecord
+ 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_models_model_httpdns_rule_proto_init() }
+func file_models_model_httpdns_rule_proto_init() {
+ if File_models_model_httpdns_rule_proto != nil {
+ return
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_models_model_httpdns_rule_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_models_model_httpdns_rule_proto_goTypes,
+ DependencyIndexes: file_models_model_httpdns_rule_proto_depIdxs,
+ MessageInfos: file_models_model_httpdns_rule_proto_msgTypes,
+ }.Build()
+ File_models_model_httpdns_rule_proto = out.File
+ file_models_model_httpdns_rule_proto_rawDesc = nil
+ file_models_model_httpdns_rule_proto_goTypes = nil
+ file_models_model_httpdns_rule_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/model_httpdns_runtime_log.pb.go b/EdgeCommon/pkg/rpc/pb/model_httpdns_runtime_log.pb.go
new file mode 100644
index 0000000..e408505
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/model_httpdns_runtime_log.pb.go
@@ -0,0 +1,242 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.35.1
+// protoc v3.21.12
+// source: models/model_httpdns_runtime_log.proto
+
+package pb
+
+import (
+ 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 HTTPDNSRuntimeLog struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ ClusterId int64 `protobuf:"varint,2,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+ NodeId int64 `protobuf:"varint,3,opt,name=nodeId,proto3" json:"nodeId,omitempty"`
+ Level string `protobuf:"bytes,4,opt,name=level,proto3" json:"level,omitempty"`
+ Type string `protobuf:"bytes,5,opt,name=type,proto3" json:"type,omitempty"`
+ Module string `protobuf:"bytes,6,opt,name=module,proto3" json:"module,omitempty"`
+ Description string `protobuf:"bytes,7,opt,name=description,proto3" json:"description,omitempty"`
+ Count int64 `protobuf:"varint,8,opt,name=count,proto3" json:"count,omitempty"`
+ RequestId string `protobuf:"bytes,9,opt,name=requestId,proto3" json:"requestId,omitempty"`
+ CreatedAt int64 `protobuf:"varint,10,opt,name=createdAt,proto3" json:"createdAt,omitempty"`
+ Day string `protobuf:"bytes,11,opt,name=day,proto3" json:"day,omitempty"`
+ ClusterName string `protobuf:"bytes,12,opt,name=clusterName,proto3" json:"clusterName,omitempty"`
+ NodeName string `protobuf:"bytes,13,opt,name=nodeName,proto3" json:"nodeName,omitempty"`
+}
+
+func (x *HTTPDNSRuntimeLog) Reset() {
+ *x = HTTPDNSRuntimeLog{}
+ mi := &file_models_model_httpdns_runtime_log_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *HTTPDNSRuntimeLog) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HTTPDNSRuntimeLog) ProtoMessage() {}
+
+func (x *HTTPDNSRuntimeLog) ProtoReflect() protoreflect.Message {
+ mi := &file_models_model_httpdns_runtime_log_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HTTPDNSRuntimeLog.ProtoReflect.Descriptor instead.
+func (*HTTPDNSRuntimeLog) Descriptor() ([]byte, []int) {
+ return file_models_model_httpdns_runtime_log_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *HTTPDNSRuntimeLog) GetId() int64 {
+ if x != nil {
+ return x.Id
+ }
+ return 0
+}
+
+func (x *HTTPDNSRuntimeLog) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+func (x *HTTPDNSRuntimeLog) GetNodeId() int64 {
+ if x != nil {
+ return x.NodeId
+ }
+ return 0
+}
+
+func (x *HTTPDNSRuntimeLog) GetLevel() string {
+ if x != nil {
+ return x.Level
+ }
+ return ""
+}
+
+func (x *HTTPDNSRuntimeLog) GetType() string {
+ if x != nil {
+ return x.Type
+ }
+ return ""
+}
+
+func (x *HTTPDNSRuntimeLog) GetModule() string {
+ if x != nil {
+ return x.Module
+ }
+ return ""
+}
+
+func (x *HTTPDNSRuntimeLog) GetDescription() string {
+ if x != nil {
+ return x.Description
+ }
+ return ""
+}
+
+func (x *HTTPDNSRuntimeLog) GetCount() int64 {
+ if x != nil {
+ return x.Count
+ }
+ return 0
+}
+
+func (x *HTTPDNSRuntimeLog) GetRequestId() string {
+ if x != nil {
+ return x.RequestId
+ }
+ return ""
+}
+
+func (x *HTTPDNSRuntimeLog) GetCreatedAt() int64 {
+ if x != nil {
+ return x.CreatedAt
+ }
+ return 0
+}
+
+func (x *HTTPDNSRuntimeLog) GetDay() string {
+ if x != nil {
+ return x.Day
+ }
+ return ""
+}
+
+func (x *HTTPDNSRuntimeLog) GetClusterName() string {
+ if x != nil {
+ return x.ClusterName
+ }
+ return ""
+}
+
+func (x *HTTPDNSRuntimeLog) GetNodeName() string {
+ if x != nil {
+ return x.NodeName
+ }
+ return ""
+}
+
+var File_models_model_httpdns_runtime_log_proto protoreflect.FileDescriptor
+
+var file_models_model_httpdns_runtime_log_proto_rawDesc = []byte{
+ 0x0a, 0x26, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x68,
+ 0x74, 0x74, 0x70, 0x64, 0x6e, 0x73, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6c,
+ 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x22, 0xdf, 0x02, 0x0a,
+ 0x11, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4c,
+ 0x6f, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02,
+ 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64,
+ 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65,
+ 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x12,
+ 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79,
+ 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05,
+ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x18,
+ 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64,
+ 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x0a, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x10,
+ 0x0a, 0x03, 0x64, 0x61, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x61, 0x79,
+ 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18,
+ 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61,
+ 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0d,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x06,
+ 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_models_model_httpdns_runtime_log_proto_rawDescOnce sync.Once
+ file_models_model_httpdns_runtime_log_proto_rawDescData = file_models_model_httpdns_runtime_log_proto_rawDesc
+)
+
+func file_models_model_httpdns_runtime_log_proto_rawDescGZIP() []byte {
+ file_models_model_httpdns_runtime_log_proto_rawDescOnce.Do(func() {
+ file_models_model_httpdns_runtime_log_proto_rawDescData = protoimpl.X.CompressGZIP(file_models_model_httpdns_runtime_log_proto_rawDescData)
+ })
+ return file_models_model_httpdns_runtime_log_proto_rawDescData
+}
+
+var file_models_model_httpdns_runtime_log_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_models_model_httpdns_runtime_log_proto_goTypes = []any{
+ (*HTTPDNSRuntimeLog)(nil), // 0: pb.HTTPDNSRuntimeLog
+}
+var file_models_model_httpdns_runtime_log_proto_depIdxs = []int32{
+ 0, // [0:0] is the sub-list for method output_type
+ 0, // [0:0] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_models_model_httpdns_runtime_log_proto_init() }
+func file_models_model_httpdns_runtime_log_proto_init() {
+ if File_models_model_httpdns_runtime_log_proto != nil {
+ return
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_models_model_httpdns_runtime_log_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_models_model_httpdns_runtime_log_proto_goTypes,
+ DependencyIndexes: file_models_model_httpdns_runtime_log_proto_depIdxs,
+ MessageInfos: file_models_model_httpdns_runtime_log_proto_msgTypes,
+ }.Build()
+ File_models_model_httpdns_runtime_log_proto = out.File
+ file_models_model_httpdns_runtime_log_proto_rawDesc = nil
+ file_models_model_httpdns_runtime_log_proto_goTypes = nil
+ file_models_model_httpdns_runtime_log_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/model_user.pb.go b/EdgeCommon/pkg/rpc/pb/model_user.pb.go
index c2f9bb3..8724012 100644
--- a/EdgeCommon/pkg/rpc/pb/model_user.pb.go
+++ b/EdgeCommon/pkg/rpc/pb/model_user.pb.go
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.36.0
-// protoc v6.33.2
+// protoc-gen-go v1.36.11
+// protoc v3.21.12
// source: models/model_user.proto
package pb
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
+ unsafe "unsafe"
)
const (
@@ -42,6 +43,7 @@ type User struct {
IsEnterpriseIdentified bool `protobuf:"varint,18,opt,name=isEnterpriseIdentified,proto3" json:"isEnterpriseIdentified,omitempty"` // 是否已通过企业验证
BandwidthAlgo string `protobuf:"bytes,21,opt,name=bandwidthAlgo,proto3" json:"bandwidthAlgo,omitempty"` // 带宽算法
Lang string `protobuf:"bytes,22,opt,name=lang,proto3" json:"lang,omitempty"` // 语言代号
+ HttpdnsClusterIdsJSON []byte `protobuf:"bytes,24,opt,name=httpdnsClusterIdsJSON,proto3" json:"httpdnsClusterIdsJSON,omitempty"` // HTTPDNS关联集群ID列表
OtpLogin *Login `protobuf:"bytes,19,opt,name=otpLogin,proto3" json:"otpLogin,omitempty"` // OTP认证
NodeCluster *NodeCluster `protobuf:"bytes,10,opt,name=nodeCluster,proto3" json:"nodeCluster,omitempty"` // 集群信息
Features []*UserFeature `protobuf:"bytes,11,rep,name=features,proto3" json:"features,omitempty"` // 开通功能
@@ -219,6 +221,13 @@ func (x *User) GetLang() string {
return ""
}
+func (x *User) GetHttpdnsClusterIdsJSON() []byte {
+ if x != nil {
+ return x.HttpdnsClusterIdsJSON
+ }
+ return nil
+}
+
func (x *User) GetOtpLogin() *Login {
if x != nil {
return x.OtpLogin
@@ -242,74 +251,48 @@ func (x *User) GetFeatures() []*UserFeature {
var File_models_model_user_proto protoreflect.FileDescriptor
-var file_models_model_user_proto_rawDesc = []byte{
- 0x0a, 0x17, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x75,
- 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x1f, 0x6d,
- 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65,
- 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f,
- 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x75, 0x73, 0x65,
- 0x72, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
- 0x18, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6c, 0x6f,
- 0x67, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xfd, 0x05, 0x0a, 0x04, 0x55, 0x73,
- 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02,
- 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a,
- 0x0a, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f,
- 0x62, 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x62, 0x69,
- 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x03, 0x74, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x06, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x76, 0x65,
- 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x14, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x0d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x6d, 0x61, 0x69, 0x6c,
- 0x12, 0x26, 0x0a, 0x0e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4d, 0x6f, 0x62, 0x69,
- 0x6c, 0x65, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69,
- 0x65, 0x64, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x61,
- 0x72, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x61, 0x72, 0x6b,
- 0x12, 0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04,
- 0x69, 0x73, 0x4f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41,
- 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
- 0x41, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64,
- 0x49, 0x50, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
- 0x65, 0x72, 0x65, 0x64, 0x49, 0x50, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69,
- 0x66, 0x69, 0x65, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x56, 0x65,
- 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x52, 0x65, 0x6a, 0x65,
- 0x63, 0x74, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x52, 0x65,
- 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74,
- 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65,
- 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73,
- 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69,
- 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x36, 0x0a, 0x16, 0x69, 0x73, 0x49, 0x6e,
- 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69,
- 0x65, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x69, 0x73, 0x49, 0x6e, 0x64, 0x69,
- 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64,
- 0x12, 0x36, 0x0a, 0x16, 0x69, 0x73, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65,
- 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x16, 0x69, 0x73, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x49, 0x64,
- 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x61, 0x6e, 0x64,
- 0x77, 0x69, 0x64, 0x74, 0x68, 0x41, 0x6c, 0x67, 0x6f, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x0d, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x41, 0x6c, 0x67, 0x6f, 0x12, 0x12,
- 0x0a, 0x04, 0x6c, 0x61, 0x6e, 0x67, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x61,
- 0x6e, 0x67, 0x12, 0x25, 0x0a, 0x08, 0x6f, 0x74, 0x70, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x18, 0x13,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52,
- 0x08, 0x6f, 0x74, 0x70, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x31, 0x0a, 0x0b, 0x6e, 0x6f, 0x64,
- 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f,
- 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52,
- 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x08,
- 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f,
- 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52,
- 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70,
- 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+const file_models_model_user_proto_rawDesc = "" +
+ "\n" +
+ "\x17models/model_user.proto\x12\x02pb\x1a\x1fmodels/model_node_cluster.proto\x1a\x1fmodels/model_user_feature.proto\x1a\x18models/model_login.proto\"\xb3\x06\n" +
+ "\x04User\x12\x0e\n" +
+ "\x02id\x18\x01 \x01(\x03R\x02id\x12\x1a\n" +
+ "\busername\x18\x02 \x01(\tR\busername\x12\x1a\n" +
+ "\bfullname\x18\x03 \x01(\tR\bfullname\x12\x16\n" +
+ "\x06mobile\x18\x04 \x01(\tR\x06mobile\x12\x10\n" +
+ "\x03tel\x18\x05 \x01(\tR\x03tel\x12\x14\n" +
+ "\x05email\x18\x06 \x01(\tR\x05email\x12$\n" +
+ "\rverifiedEmail\x18\x14 \x01(\tR\rverifiedEmail\x12&\n" +
+ "\x0everifiedMobile\x18\x17 \x01(\tR\x0everifiedMobile\x12\x16\n" +
+ "\x06remark\x18\a \x01(\tR\x06remark\x12\x12\n" +
+ "\x04isOn\x18\b \x01(\bR\x04isOn\x12\x1c\n" +
+ "\tcreatedAt\x18\t \x01(\x03R\tcreatedAt\x12\"\n" +
+ "\fregisteredIP\x18\f \x01(\tR\fregisteredIP\x12\x1e\n" +
+ "\n" +
+ "isVerified\x18\r \x01(\bR\n" +
+ "isVerified\x12\x1e\n" +
+ "\n" +
+ "isRejected\x18\x0e \x01(\bR\n" +
+ "isRejected\x12\"\n" +
+ "\frejectReason\x18\x0f \x01(\tR\frejectReason\x12\x1c\n" +
+ "\tisDeleted\x18\x10 \x01(\bR\tisDeleted\x126\n" +
+ "\x16isIndividualIdentified\x18\x11 \x01(\bR\x16isIndividualIdentified\x126\n" +
+ "\x16isEnterpriseIdentified\x18\x12 \x01(\bR\x16isEnterpriseIdentified\x12$\n" +
+ "\rbandwidthAlgo\x18\x15 \x01(\tR\rbandwidthAlgo\x12\x12\n" +
+ "\x04lang\x18\x16 \x01(\tR\x04lang\x124\n" +
+ "\x15httpdnsClusterIdsJSON\x18\x18 \x01(\fR\x15httpdnsClusterIdsJSON\x12%\n" +
+ "\botpLogin\x18\x13 \x01(\v2\t.pb.LoginR\botpLogin\x121\n" +
+ "\vnodeCluster\x18\n" +
+ " \x01(\v2\x0f.pb.NodeClusterR\vnodeCluster\x12+\n" +
+ "\bfeatures\x18\v \x03(\v2\x0f.pb.UserFeatureR\bfeaturesB\x06Z\x04./pbb\x06proto3"
var (
file_models_model_user_proto_rawDescOnce sync.Once
- file_models_model_user_proto_rawDescData = file_models_model_user_proto_rawDesc
+ file_models_model_user_proto_rawDescData []byte
)
func file_models_model_user_proto_rawDescGZIP() []byte {
file_models_model_user_proto_rawDescOnce.Do(func() {
- file_models_model_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_models_model_user_proto_rawDescData)
+ file_models_model_user_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_models_model_user_proto_rawDesc), len(file_models_model_user_proto_rawDesc)))
})
return file_models_model_user_proto_rawDescData
}
@@ -344,7 +327,7 @@ func file_models_model_user_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_models_model_user_proto_rawDesc,
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_models_model_user_proto_rawDesc), len(file_models_model_user_proto_rawDesc)),
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
@@ -355,7 +338,6 @@ func file_models_model_user_proto_init() {
MessageInfos: file_models_model_user_proto_msgTypes,
}.Build()
File_models_model_user_proto = out.File
- file_models_model_user_proto_rawDesc = nil
file_models_model_user_proto_goTypes = nil
file_models_model_user_proto_depIdxs = nil
}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_access_log.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_access_log.pb.go
new file mode 100644
index 0000000..291a198
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_access_log.pb.go
@@ -0,0 +1,377 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.35.1
+// protoc v3.21.12
+// source: service_httpdns_access_log.proto
+
+package pb
+
+import (
+ 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 CreateHTTPDNSAccessLogsRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Logs []*HTTPDNSAccessLog `protobuf:"bytes,1,rep,name=logs,proto3" json:"logs,omitempty"`
+}
+
+func (x *CreateHTTPDNSAccessLogsRequest) Reset() {
+ *x = CreateHTTPDNSAccessLogsRequest{}
+ mi := &file_service_httpdns_access_log_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSAccessLogsRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSAccessLogsRequest) ProtoMessage() {}
+
+func (x *CreateHTTPDNSAccessLogsRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_access_log_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSAccessLogsRequest.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSAccessLogsRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_access_log_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CreateHTTPDNSAccessLogsRequest) GetLogs() []*HTTPDNSAccessLog {
+ if x != nil {
+ return x.Logs
+ }
+ return nil
+}
+
+type CreateHTTPDNSAccessLogsResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *CreateHTTPDNSAccessLogsResponse) Reset() {
+ *x = CreateHTTPDNSAccessLogsResponse{}
+ mi := &file_service_httpdns_access_log_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSAccessLogsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSAccessLogsResponse) ProtoMessage() {}
+
+func (x *CreateHTTPDNSAccessLogsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_access_log_proto_msgTypes[1]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSAccessLogsResponse.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSAccessLogsResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_access_log_proto_rawDescGZIP(), []int{1}
+}
+
+type ListHTTPDNSAccessLogsRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Day string `protobuf:"bytes,1,opt,name=day,proto3" json:"day,omitempty"`
+ ClusterId int64 `protobuf:"varint,2,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+ NodeId int64 `protobuf:"varint,3,opt,name=nodeId,proto3" json:"nodeId,omitempty"`
+ AppId string `protobuf:"bytes,4,opt,name=appId,proto3" json:"appId,omitempty"`
+ Domain string `protobuf:"bytes,5,opt,name=domain,proto3" json:"domain,omitempty"`
+ Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"`
+ Keyword string `protobuf:"bytes,7,opt,name=keyword,proto3" json:"keyword,omitempty"`
+ Offset int64 `protobuf:"varint,8,opt,name=offset,proto3" json:"offset,omitempty"`
+ Size int64 `protobuf:"varint,9,opt,name=size,proto3" json:"size,omitempty"`
+}
+
+func (x *ListHTTPDNSAccessLogsRequest) Reset() {
+ *x = ListHTTPDNSAccessLogsRequest{}
+ mi := &file_service_httpdns_access_log_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSAccessLogsRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSAccessLogsRequest) ProtoMessage() {}
+
+func (x *ListHTTPDNSAccessLogsRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_access_log_proto_msgTypes[2]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSAccessLogsRequest.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSAccessLogsRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_access_log_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *ListHTTPDNSAccessLogsRequest) GetDay() string {
+ if x != nil {
+ return x.Day
+ }
+ return ""
+}
+
+func (x *ListHTTPDNSAccessLogsRequest) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+func (x *ListHTTPDNSAccessLogsRequest) GetNodeId() int64 {
+ if x != nil {
+ return x.NodeId
+ }
+ return 0
+}
+
+func (x *ListHTTPDNSAccessLogsRequest) GetAppId() string {
+ if x != nil {
+ return x.AppId
+ }
+ return ""
+}
+
+func (x *ListHTTPDNSAccessLogsRequest) GetDomain() string {
+ if x != nil {
+ return x.Domain
+ }
+ return ""
+}
+
+func (x *ListHTTPDNSAccessLogsRequest) GetStatus() string {
+ if x != nil {
+ return x.Status
+ }
+ return ""
+}
+
+func (x *ListHTTPDNSAccessLogsRequest) GetKeyword() string {
+ if x != nil {
+ return x.Keyword
+ }
+ return ""
+}
+
+func (x *ListHTTPDNSAccessLogsRequest) GetOffset() int64 {
+ if x != nil {
+ return x.Offset
+ }
+ return 0
+}
+
+func (x *ListHTTPDNSAccessLogsRequest) GetSize() int64 {
+ if x != nil {
+ return x.Size
+ }
+ return 0
+}
+
+type ListHTTPDNSAccessLogsResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Logs []*HTTPDNSAccessLog `protobuf:"bytes,1,rep,name=logs,proto3" json:"logs,omitempty"`
+ Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"`
+}
+
+func (x *ListHTTPDNSAccessLogsResponse) Reset() {
+ *x = ListHTTPDNSAccessLogsResponse{}
+ mi := &file_service_httpdns_access_log_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSAccessLogsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSAccessLogsResponse) ProtoMessage() {}
+
+func (x *ListHTTPDNSAccessLogsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_access_log_proto_msgTypes[3]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSAccessLogsResponse.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSAccessLogsResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_access_log_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *ListHTTPDNSAccessLogsResponse) GetLogs() []*HTTPDNSAccessLog {
+ if x != nil {
+ return x.Logs
+ }
+ return nil
+}
+
+func (x *ListHTTPDNSAccessLogsResponse) GetTotal() int64 {
+ if x != nil {
+ return x.Total
+ }
+ return 0
+}
+
+var File_service_httpdns_access_log_proto protoreflect.FileDescriptor
+
+var file_service_httpdns_access_log_proto_rawDesc = []byte{
+ 0x0a, 0x20, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x64, 0x6e,
+ 0x73, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x25, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d,
+ 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x64, 0x6e, 0x73, 0x5f, 0x61, 0x63, 0x63,
+ 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4a, 0x0a,
+ 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x41, 0x63,
+ 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+ 0x28, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e,
+ 0x70, 0x62, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73,
+ 0x4c, 0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x22, 0x21, 0x0a, 0x1f, 0x43, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73,
+ 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xf2, 0x01, 0x0a,
+ 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x41, 0x63, 0x63, 0x65,
+ 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a,
+ 0x03, 0x64, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x61, 0x79, 0x12,
+ 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a,
+ 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e,
+ 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64,
+ 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6b,
+ 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65,
+ 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18,
+ 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a,
+ 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a,
+ 0x65, 0x22, 0x5f, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53,
+ 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x14, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x41, 0x63, 0x63,
+ 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x14, 0x0a, 0x05,
+ 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74,
+ 0x61, 0x6c, 0x32, 0xdb, 0x01, 0x0a, 0x17, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x41, 0x63,
+ 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x62,
+ 0x0a, 0x17, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x41,
+ 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x62, 0x2e, 0x43,
+ 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x41, 0x63, 0x63, 0x65,
+ 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e,
+ 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53,
+ 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x15, 0x6c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e,
+ 0x53, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x20, 0x2e, 0x70, 0x62,
+ 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x41, 0x63, 0x63, 0x65,
+ 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e,
+ 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x41, 0x63,
+ 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_service_httpdns_access_log_proto_rawDescOnce sync.Once
+ file_service_httpdns_access_log_proto_rawDescData = file_service_httpdns_access_log_proto_rawDesc
+)
+
+func file_service_httpdns_access_log_proto_rawDescGZIP() []byte {
+ file_service_httpdns_access_log_proto_rawDescOnce.Do(func() {
+ file_service_httpdns_access_log_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_httpdns_access_log_proto_rawDescData)
+ })
+ return file_service_httpdns_access_log_proto_rawDescData
+}
+
+var file_service_httpdns_access_log_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_service_httpdns_access_log_proto_goTypes = []any{
+ (*CreateHTTPDNSAccessLogsRequest)(nil), // 0: pb.CreateHTTPDNSAccessLogsRequest
+ (*CreateHTTPDNSAccessLogsResponse)(nil), // 1: pb.CreateHTTPDNSAccessLogsResponse
+ (*ListHTTPDNSAccessLogsRequest)(nil), // 2: pb.ListHTTPDNSAccessLogsRequest
+ (*ListHTTPDNSAccessLogsResponse)(nil), // 3: pb.ListHTTPDNSAccessLogsResponse
+ (*HTTPDNSAccessLog)(nil), // 4: pb.HTTPDNSAccessLog
+}
+var file_service_httpdns_access_log_proto_depIdxs = []int32{
+ 4, // 0: pb.CreateHTTPDNSAccessLogsRequest.logs:type_name -> pb.HTTPDNSAccessLog
+ 4, // 1: pb.ListHTTPDNSAccessLogsResponse.logs:type_name -> pb.HTTPDNSAccessLog
+ 0, // 2: pb.HTTPDNSAccessLogService.createHTTPDNSAccessLogs:input_type -> pb.CreateHTTPDNSAccessLogsRequest
+ 2, // 3: pb.HTTPDNSAccessLogService.listHTTPDNSAccessLogs:input_type -> pb.ListHTTPDNSAccessLogsRequest
+ 1, // 4: pb.HTTPDNSAccessLogService.createHTTPDNSAccessLogs:output_type -> pb.CreateHTTPDNSAccessLogsResponse
+ 3, // 5: pb.HTTPDNSAccessLogService.listHTTPDNSAccessLogs:output_type -> pb.ListHTTPDNSAccessLogsResponse
+ 4, // [4:6] is the sub-list for method output_type
+ 2, // [2:4] is the sub-list for method input_type
+ 2, // [2:2] is the sub-list for extension type_name
+ 2, // [2:2] is the sub-list for extension extendee
+ 0, // [0:2] is the sub-list for field type_name
+}
+
+func init() { file_service_httpdns_access_log_proto_init() }
+func file_service_httpdns_access_log_proto_init() {
+ if File_service_httpdns_access_log_proto != nil {
+ return
+ }
+ file_models_model_httpdns_access_log_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_service_httpdns_access_log_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 4,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_service_httpdns_access_log_proto_goTypes,
+ DependencyIndexes: file_service_httpdns_access_log_proto_depIdxs,
+ MessageInfos: file_service_httpdns_access_log_proto_msgTypes,
+ }.Build()
+ File_service_httpdns_access_log_proto = out.File
+ file_service_httpdns_access_log_proto_rawDesc = nil
+ file_service_httpdns_access_log_proto_goTypes = nil
+ file_service_httpdns_access_log_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_access_log_grpc.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_access_log_grpc.pb.go
new file mode 100644
index 0000000..72f8c12
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_access_log_grpc.pb.go
@@ -0,0 +1,157 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.5.1
+// - protoc v3.21.12
+// source: service_httpdns_access_log.proto
+
+package pb
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.64.0 or later.
+const _ = grpc.SupportPackageIsVersion9
+
+const (
+ HTTPDNSAccessLogService_CreateHTTPDNSAccessLogs_FullMethodName = "/pb.HTTPDNSAccessLogService/createHTTPDNSAccessLogs"
+ HTTPDNSAccessLogService_ListHTTPDNSAccessLogs_FullMethodName = "/pb.HTTPDNSAccessLogService/listHTTPDNSAccessLogs"
+)
+
+// HTTPDNSAccessLogServiceClient is the client API for HTTPDNSAccessLogService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type HTTPDNSAccessLogServiceClient interface {
+ CreateHTTPDNSAccessLogs(ctx context.Context, in *CreateHTTPDNSAccessLogsRequest, opts ...grpc.CallOption) (*CreateHTTPDNSAccessLogsResponse, error)
+ ListHTTPDNSAccessLogs(ctx context.Context, in *ListHTTPDNSAccessLogsRequest, opts ...grpc.CallOption) (*ListHTTPDNSAccessLogsResponse, error)
+}
+
+type hTTPDNSAccessLogServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewHTTPDNSAccessLogServiceClient(cc grpc.ClientConnInterface) HTTPDNSAccessLogServiceClient {
+ return &hTTPDNSAccessLogServiceClient{cc}
+}
+
+func (c *hTTPDNSAccessLogServiceClient) CreateHTTPDNSAccessLogs(ctx context.Context, in *CreateHTTPDNSAccessLogsRequest, opts ...grpc.CallOption) (*CreateHTTPDNSAccessLogsResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(CreateHTTPDNSAccessLogsResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSAccessLogService_CreateHTTPDNSAccessLogs_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSAccessLogServiceClient) ListHTTPDNSAccessLogs(ctx context.Context, in *ListHTTPDNSAccessLogsRequest, opts ...grpc.CallOption) (*ListHTTPDNSAccessLogsResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(ListHTTPDNSAccessLogsResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSAccessLogService_ListHTTPDNSAccessLogs_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// HTTPDNSAccessLogServiceServer is the server API for HTTPDNSAccessLogService service.
+// All implementations should embed UnimplementedHTTPDNSAccessLogServiceServer
+// for forward compatibility.
+type HTTPDNSAccessLogServiceServer interface {
+ CreateHTTPDNSAccessLogs(context.Context, *CreateHTTPDNSAccessLogsRequest) (*CreateHTTPDNSAccessLogsResponse, error)
+ ListHTTPDNSAccessLogs(context.Context, *ListHTTPDNSAccessLogsRequest) (*ListHTTPDNSAccessLogsResponse, error)
+}
+
+// UnimplementedHTTPDNSAccessLogServiceServer should be embedded to have
+// forward compatible implementations.
+//
+// NOTE: this should be embedded by value instead of pointer to avoid a nil
+// pointer dereference when methods are called.
+type UnimplementedHTTPDNSAccessLogServiceServer struct{}
+
+func (UnimplementedHTTPDNSAccessLogServiceServer) CreateHTTPDNSAccessLogs(context.Context, *CreateHTTPDNSAccessLogsRequest) (*CreateHTTPDNSAccessLogsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method CreateHTTPDNSAccessLogs not implemented")
+}
+func (UnimplementedHTTPDNSAccessLogServiceServer) ListHTTPDNSAccessLogs(context.Context, *ListHTTPDNSAccessLogsRequest) (*ListHTTPDNSAccessLogsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method ListHTTPDNSAccessLogs not implemented")
+}
+func (UnimplementedHTTPDNSAccessLogServiceServer) testEmbeddedByValue() {}
+
+// UnsafeHTTPDNSAccessLogServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to HTTPDNSAccessLogServiceServer will
+// result in compilation errors.
+type UnsafeHTTPDNSAccessLogServiceServer interface {
+ mustEmbedUnimplementedHTTPDNSAccessLogServiceServer()
+}
+
+func RegisterHTTPDNSAccessLogServiceServer(s grpc.ServiceRegistrar, srv HTTPDNSAccessLogServiceServer) {
+ // If the following call pancis, it indicates UnimplementedHTTPDNSAccessLogServiceServer was
+ // embedded by pointer and is nil. This will cause panics if an
+ // unimplemented method is ever invoked, so we test this at initialization
+ // time to prevent it from happening at runtime later due to I/O.
+ if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
+ t.testEmbeddedByValue()
+ }
+ s.RegisterService(&HTTPDNSAccessLogService_ServiceDesc, srv)
+}
+
+func _HTTPDNSAccessLogService_CreateHTTPDNSAccessLogs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CreateHTTPDNSAccessLogsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSAccessLogServiceServer).CreateHTTPDNSAccessLogs(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSAccessLogService_CreateHTTPDNSAccessLogs_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSAccessLogServiceServer).CreateHTTPDNSAccessLogs(ctx, req.(*CreateHTTPDNSAccessLogsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSAccessLogService_ListHTTPDNSAccessLogs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ListHTTPDNSAccessLogsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSAccessLogServiceServer).ListHTTPDNSAccessLogs(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSAccessLogService_ListHTTPDNSAccessLogs_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSAccessLogServiceServer).ListHTTPDNSAccessLogs(ctx, req.(*ListHTTPDNSAccessLogsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// HTTPDNSAccessLogService_ServiceDesc is the grpc.ServiceDesc for HTTPDNSAccessLogService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var HTTPDNSAccessLogService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "pb.HTTPDNSAccessLogService",
+ HandlerType: (*HTTPDNSAccessLogServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "createHTTPDNSAccessLogs",
+ Handler: _HTTPDNSAccessLogService_CreateHTTPDNSAccessLogs_Handler,
+ },
+ {
+ MethodName: "listHTTPDNSAccessLogs",
+ Handler: _HTTPDNSAccessLogService_ListHTTPDNSAccessLogs_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "service_httpdns_access_log.proto",
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_app.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_app.pb.go
new file mode 100644
index 0000000..45cfd7d
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_app.pb.go
@@ -0,0 +1,828 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.36.11
+// protoc v3.21.12
+// source: service_httpdns_app.proto
+
+package pb
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+ unsafe "unsafe"
+)
+
+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 CreateHTTPDNSAppRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ AppId string `protobuf:"bytes,2,opt,name=appId,proto3" json:"appId,omitempty"`
+ IsOn bool `protobuf:"varint,5,opt,name=isOn,proto3" json:"isOn,omitempty"`
+ SignEnabled bool `protobuf:"varint,6,opt,name=signEnabled,proto3" json:"signEnabled,omitempty"`
+ UserId int64 `protobuf:"varint,7,opt,name=userId,proto3" json:"userId,omitempty"`
+ ClusterIdsJSON []byte `protobuf:"bytes,8,opt,name=clusterIdsJSON,proto3" json:"clusterIdsJSON,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *CreateHTTPDNSAppRequest) Reset() {
+ *x = CreateHTTPDNSAppRequest{}
+ mi := &file_service_httpdns_app_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSAppRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSAppRequest) ProtoMessage() {}
+
+func (x *CreateHTTPDNSAppRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSAppRequest.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSAppRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CreateHTTPDNSAppRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *CreateHTTPDNSAppRequest) GetAppId() string {
+ if x != nil {
+ return x.AppId
+ }
+ return ""
+}
+
+func (x *CreateHTTPDNSAppRequest) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+func (x *CreateHTTPDNSAppRequest) GetSignEnabled() bool {
+ if x != nil {
+ return x.SignEnabled
+ }
+ return false
+}
+
+func (x *CreateHTTPDNSAppRequest) GetUserId() int64 {
+ if x != nil {
+ return x.UserId
+ }
+ return 0
+}
+
+func (x *CreateHTTPDNSAppRequest) GetClusterIdsJSON() []byte {
+ if x != nil {
+ return x.ClusterIdsJSON
+ }
+ return nil
+}
+
+type CreateHTTPDNSAppResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ AppDbId int64 `protobuf:"varint,1,opt,name=appDbId,proto3" json:"appDbId,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *CreateHTTPDNSAppResponse) Reset() {
+ *x = CreateHTTPDNSAppResponse{}
+ mi := &file_service_httpdns_app_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSAppResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSAppResponse) ProtoMessage() {}
+
+func (x *CreateHTTPDNSAppResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[1]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSAppResponse.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSAppResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *CreateHTTPDNSAppResponse) GetAppDbId() int64 {
+ if x != nil {
+ return x.AppDbId
+ }
+ return 0
+}
+
+type UpdateHTTPDNSAppRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ AppDbId int64 `protobuf:"varint,1,opt,name=appDbId,proto3" json:"appDbId,omitempty"`
+ Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+ IsOn bool `protobuf:"varint,5,opt,name=isOn,proto3" json:"isOn,omitempty"`
+ UserId int64 `protobuf:"varint,6,opt,name=userId,proto3" json:"userId,omitempty"`
+ ClusterIdsJSON []byte `protobuf:"bytes,7,opt,name=clusterIdsJSON,proto3" json:"clusterIdsJSON,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *UpdateHTTPDNSAppRequest) Reset() {
+ *x = UpdateHTTPDNSAppRequest{}
+ mi := &file_service_httpdns_app_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *UpdateHTTPDNSAppRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateHTTPDNSAppRequest) ProtoMessage() {}
+
+func (x *UpdateHTTPDNSAppRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[2]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateHTTPDNSAppRequest.ProtoReflect.Descriptor instead.
+func (*UpdateHTTPDNSAppRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *UpdateHTTPDNSAppRequest) GetAppDbId() int64 {
+ if x != nil {
+ return x.AppDbId
+ }
+ return 0
+}
+
+func (x *UpdateHTTPDNSAppRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *UpdateHTTPDNSAppRequest) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+func (x *UpdateHTTPDNSAppRequest) GetUserId() int64 {
+ if x != nil {
+ return x.UserId
+ }
+ return 0
+}
+
+func (x *UpdateHTTPDNSAppRequest) GetClusterIdsJSON() []byte {
+ if x != nil {
+ return x.ClusterIdsJSON
+ }
+ return nil
+}
+
+type DeleteHTTPDNSAppRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ AppDbId int64 `protobuf:"varint,1,opt,name=appDbId,proto3" json:"appDbId,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *DeleteHTTPDNSAppRequest) Reset() {
+ *x = DeleteHTTPDNSAppRequest{}
+ mi := &file_service_httpdns_app_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *DeleteHTTPDNSAppRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DeleteHTTPDNSAppRequest) ProtoMessage() {}
+
+func (x *DeleteHTTPDNSAppRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[3]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use DeleteHTTPDNSAppRequest.ProtoReflect.Descriptor instead.
+func (*DeleteHTTPDNSAppRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *DeleteHTTPDNSAppRequest) GetAppDbId() int64 {
+ if x != nil {
+ return x.AppDbId
+ }
+ return 0
+}
+
+type FindHTTPDNSAppRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ AppDbId int64 `protobuf:"varint,1,opt,name=appDbId,proto3" json:"appDbId,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *FindHTTPDNSAppRequest) Reset() {
+ *x = FindHTTPDNSAppRequest{}
+ mi := &file_service_httpdns_app_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *FindHTTPDNSAppRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FindHTTPDNSAppRequest) ProtoMessage() {}
+
+func (x *FindHTTPDNSAppRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[4]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FindHTTPDNSAppRequest.ProtoReflect.Descriptor instead.
+func (*FindHTTPDNSAppRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *FindHTTPDNSAppRequest) GetAppDbId() int64 {
+ if x != nil {
+ return x.AppDbId
+ }
+ return 0
+}
+
+type FindHTTPDNSAppResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ App *HTTPDNSApp `protobuf:"bytes,1,opt,name=app,proto3" json:"app,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *FindHTTPDNSAppResponse) Reset() {
+ *x = FindHTTPDNSAppResponse{}
+ mi := &file_service_httpdns_app_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *FindHTTPDNSAppResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FindHTTPDNSAppResponse) ProtoMessage() {}
+
+func (x *FindHTTPDNSAppResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[5]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FindHTTPDNSAppResponse.ProtoReflect.Descriptor instead.
+func (*FindHTTPDNSAppResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *FindHTTPDNSAppResponse) GetApp() *HTTPDNSApp {
+ if x != nil {
+ return x.App
+ }
+ return nil
+}
+
+type ListHTTPDNSAppsRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Offset int64 `protobuf:"varint,1,opt,name=offset,proto3" json:"offset,omitempty"`
+ Size int64 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"`
+ Keyword string `protobuf:"bytes,3,opt,name=keyword,proto3" json:"keyword,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *ListHTTPDNSAppsRequest) Reset() {
+ *x = ListHTTPDNSAppsRequest{}
+ mi := &file_service_httpdns_app_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSAppsRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSAppsRequest) ProtoMessage() {}
+
+func (x *ListHTTPDNSAppsRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[6]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSAppsRequest.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSAppsRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *ListHTTPDNSAppsRequest) GetOffset() int64 {
+ if x != nil {
+ return x.Offset
+ }
+ return 0
+}
+
+func (x *ListHTTPDNSAppsRequest) GetSize() int64 {
+ if x != nil {
+ return x.Size
+ }
+ return 0
+}
+
+func (x *ListHTTPDNSAppsRequest) GetKeyword() string {
+ if x != nil {
+ return x.Keyword
+ }
+ return ""
+}
+
+type ListHTTPDNSAppsResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Apps []*HTTPDNSApp `protobuf:"bytes,1,rep,name=apps,proto3" json:"apps,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *ListHTTPDNSAppsResponse) Reset() {
+ *x = ListHTTPDNSAppsResponse{}
+ mi := &file_service_httpdns_app_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSAppsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSAppsResponse) ProtoMessage() {}
+
+func (x *ListHTTPDNSAppsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[7]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSAppsResponse.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSAppsResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *ListHTTPDNSAppsResponse) GetApps() []*HTTPDNSApp {
+ if x != nil {
+ return x.Apps
+ }
+ return nil
+}
+
+type FindAllHTTPDNSAppsRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *FindAllHTTPDNSAppsRequest) Reset() {
+ *x = FindAllHTTPDNSAppsRequest{}
+ mi := &file_service_httpdns_app_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *FindAllHTTPDNSAppsRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FindAllHTTPDNSAppsRequest) ProtoMessage() {}
+
+func (x *FindAllHTTPDNSAppsRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[8]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FindAllHTTPDNSAppsRequest.ProtoReflect.Descriptor instead.
+func (*FindAllHTTPDNSAppsRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{8}
+}
+
+type FindAllHTTPDNSAppsResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Apps []*HTTPDNSApp `protobuf:"bytes,1,rep,name=apps,proto3" json:"apps,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *FindAllHTTPDNSAppsResponse) Reset() {
+ *x = FindAllHTTPDNSAppsResponse{}
+ mi := &file_service_httpdns_app_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *FindAllHTTPDNSAppsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FindAllHTTPDNSAppsResponse) ProtoMessage() {}
+
+func (x *FindAllHTTPDNSAppsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[9]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FindAllHTTPDNSAppsResponse.ProtoReflect.Descriptor instead.
+func (*FindAllHTTPDNSAppsResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *FindAllHTTPDNSAppsResponse) GetApps() []*HTTPDNSApp {
+ if x != nil {
+ return x.Apps
+ }
+ return nil
+}
+
+type UpdateHTTPDNSAppSignEnabledRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ AppDbId int64 `protobuf:"varint,1,opt,name=appDbId,proto3" json:"appDbId,omitempty"`
+ SignEnabled bool `protobuf:"varint,2,opt,name=signEnabled,proto3" json:"signEnabled,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *UpdateHTTPDNSAppSignEnabledRequest) Reset() {
+ *x = UpdateHTTPDNSAppSignEnabledRequest{}
+ mi := &file_service_httpdns_app_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *UpdateHTTPDNSAppSignEnabledRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateHTTPDNSAppSignEnabledRequest) ProtoMessage() {}
+
+func (x *UpdateHTTPDNSAppSignEnabledRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[10]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateHTTPDNSAppSignEnabledRequest.ProtoReflect.Descriptor instead.
+func (*UpdateHTTPDNSAppSignEnabledRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *UpdateHTTPDNSAppSignEnabledRequest) GetAppDbId() int64 {
+ if x != nil {
+ return x.AppDbId
+ }
+ return 0
+}
+
+func (x *UpdateHTTPDNSAppSignEnabledRequest) GetSignEnabled() bool {
+ if x != nil {
+ return x.SignEnabled
+ }
+ return false
+}
+
+type ResetHTTPDNSAppSignSecretRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ AppDbId int64 `protobuf:"varint,1,opt,name=appDbId,proto3" json:"appDbId,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *ResetHTTPDNSAppSignSecretRequest) Reset() {
+ *x = ResetHTTPDNSAppSignSecretRequest{}
+ mi := &file_service_httpdns_app_proto_msgTypes[11]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ResetHTTPDNSAppSignSecretRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ResetHTTPDNSAppSignSecretRequest) ProtoMessage() {}
+
+func (x *ResetHTTPDNSAppSignSecretRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[11]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ResetHTTPDNSAppSignSecretRequest.ProtoReflect.Descriptor instead.
+func (*ResetHTTPDNSAppSignSecretRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *ResetHTTPDNSAppSignSecretRequest) GetAppDbId() int64 {
+ if x != nil {
+ return x.AppDbId
+ }
+ return 0
+}
+
+type ResetHTTPDNSAppSignSecretResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ SignSecret string `protobuf:"bytes,1,opt,name=signSecret,proto3" json:"signSecret,omitempty"`
+ UpdatedAt int64 `protobuf:"varint,2,opt,name=updatedAt,proto3" json:"updatedAt,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *ResetHTTPDNSAppSignSecretResponse) Reset() {
+ *x = ResetHTTPDNSAppSignSecretResponse{}
+ mi := &file_service_httpdns_app_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ResetHTTPDNSAppSignSecretResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ResetHTTPDNSAppSignSecretResponse) ProtoMessage() {}
+
+func (x *ResetHTTPDNSAppSignSecretResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_app_proto_msgTypes[12]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ResetHTTPDNSAppSignSecretResponse.ProtoReflect.Descriptor instead.
+func (*ResetHTTPDNSAppSignSecretResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_app_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *ResetHTTPDNSAppSignSecretResponse) GetSignSecret() string {
+ if x != nil {
+ return x.SignSecret
+ }
+ return ""
+}
+
+func (x *ResetHTTPDNSAppSignSecretResponse) GetUpdatedAt() int64 {
+ if x != nil {
+ return x.UpdatedAt
+ }
+ return 0
+}
+
+var File_service_httpdns_app_proto protoreflect.FileDescriptor
+
+const file_service_httpdns_app_proto_rawDesc = "" +
+ "\n" +
+ "\x19service_httpdns_app.proto\x12\x02pb\x1a\x1emodels/model_httpdns_app.proto\x1a\x19models/rpc_messages.proto\"\xc5\x01\n" +
+ "\x17CreateHTTPDNSAppRequest\x12\x12\n" +
+ "\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" +
+ "\x05appId\x18\x02 \x01(\tR\x05appId\x12\x12\n" +
+ "\x04isOn\x18\x05 \x01(\bR\x04isOn\x12 \n" +
+ "\vsignEnabled\x18\x06 \x01(\bR\vsignEnabled\x12\x16\n" +
+ "\x06userId\x18\a \x01(\x03R\x06userId\x12&\n" +
+ "\x0eclusterIdsJSON\x18\b \x01(\fR\x0eclusterIdsJSONJ\x04\b\x03\x10\x04J\x04\b\x04\x10\x05\"4\n" +
+ "\x18CreateHTTPDNSAppResponse\x12\x18\n" +
+ "\aappDbId\x18\x01 \x01(\x03R\aappDbId\"\xa7\x01\n" +
+ "\x17UpdateHTTPDNSAppRequest\x12\x18\n" +
+ "\aappDbId\x18\x01 \x01(\x03R\aappDbId\x12\x12\n" +
+ "\x04name\x18\x02 \x01(\tR\x04name\x12\x12\n" +
+ "\x04isOn\x18\x05 \x01(\bR\x04isOn\x12\x16\n" +
+ "\x06userId\x18\x06 \x01(\x03R\x06userId\x12&\n" +
+ "\x0eclusterIdsJSON\x18\a \x01(\fR\x0eclusterIdsJSONJ\x04\b\x03\x10\x04J\x04\b\x04\x10\x05\"3\n" +
+ "\x17DeleteHTTPDNSAppRequest\x12\x18\n" +
+ "\aappDbId\x18\x01 \x01(\x03R\aappDbId\"1\n" +
+ "\x15FindHTTPDNSAppRequest\x12\x18\n" +
+ "\aappDbId\x18\x01 \x01(\x03R\aappDbId\":\n" +
+ "\x16FindHTTPDNSAppResponse\x12 \n" +
+ "\x03app\x18\x01 \x01(\v2\x0e.pb.HTTPDNSAppR\x03app\"^\n" +
+ "\x16ListHTTPDNSAppsRequest\x12\x16\n" +
+ "\x06offset\x18\x01 \x01(\x03R\x06offset\x12\x12\n" +
+ "\x04size\x18\x02 \x01(\x03R\x04size\x12\x18\n" +
+ "\akeyword\x18\x03 \x01(\tR\akeyword\"=\n" +
+ "\x17ListHTTPDNSAppsResponse\x12\"\n" +
+ "\x04apps\x18\x01 \x03(\v2\x0e.pb.HTTPDNSAppR\x04apps\"\x1b\n" +
+ "\x19FindAllHTTPDNSAppsRequest\"@\n" +
+ "\x1aFindAllHTTPDNSAppsResponse\x12\"\n" +
+ "\x04apps\x18\x01 \x03(\v2\x0e.pb.HTTPDNSAppR\x04apps\"`\n" +
+ "\"UpdateHTTPDNSAppSignEnabledRequest\x12\x18\n" +
+ "\aappDbId\x18\x01 \x01(\x03R\aappDbId\x12 \n" +
+ "\vsignEnabled\x18\x02 \x01(\bR\vsignEnabled\"<\n" +
+ " ResetHTTPDNSAppSignSecretRequest\x12\x18\n" +
+ "\aappDbId\x18\x01 \x01(\x03R\aappDbId\"a\n" +
+ "!ResetHTTPDNSAppSignSecretResponse\x12\x1e\n" +
+ "\n" +
+ "signSecret\x18\x01 \x01(\tR\n" +
+ "signSecret\x12\x1c\n" +
+ "\tupdatedAt\x18\x02 \x01(\x03R\tupdatedAt2\x8f\x05\n" +
+ "\x11HTTPDNSAppService\x12M\n" +
+ "\x10createHTTPDNSApp\x12\x1b.pb.CreateHTTPDNSAppRequest\x1a\x1c.pb.CreateHTTPDNSAppResponse\x12?\n" +
+ "\x10updateHTTPDNSApp\x12\x1b.pb.UpdateHTTPDNSAppRequest\x1a\x0e.pb.RPCSuccess\x12?\n" +
+ "\x10deleteHTTPDNSApp\x12\x1b.pb.DeleteHTTPDNSAppRequest\x1a\x0e.pb.RPCSuccess\x12G\n" +
+ "\x0efindHTTPDNSApp\x12\x19.pb.FindHTTPDNSAppRequest\x1a\x1a.pb.FindHTTPDNSAppResponse\x12J\n" +
+ "\x0flistHTTPDNSApps\x12\x1a.pb.ListHTTPDNSAppsRequest\x1a\x1b.pb.ListHTTPDNSAppsResponse\x12S\n" +
+ "\x12findAllHTTPDNSApps\x12\x1d.pb.FindAllHTTPDNSAppsRequest\x1a\x1e.pb.FindAllHTTPDNSAppsResponse\x12U\n" +
+ "\x1bupdateHTTPDNSAppSignEnabled\x12&.pb.UpdateHTTPDNSAppSignEnabledRequest\x1a\x0e.pb.RPCSuccess\x12h\n" +
+ "\x19resetHTTPDNSAppSignSecret\x12$.pb.ResetHTTPDNSAppSignSecretRequest\x1a%.pb.ResetHTTPDNSAppSignSecretResponseB\x06Z\x04./pbb\x06proto3"
+
+var (
+ file_service_httpdns_app_proto_rawDescOnce sync.Once
+ file_service_httpdns_app_proto_rawDescData []byte
+)
+
+func file_service_httpdns_app_proto_rawDescGZIP() []byte {
+ file_service_httpdns_app_proto_rawDescOnce.Do(func() {
+ file_service_httpdns_app_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_service_httpdns_app_proto_rawDesc), len(file_service_httpdns_app_proto_rawDesc)))
+ })
+ return file_service_httpdns_app_proto_rawDescData
+}
+
+var file_service_httpdns_app_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
+var file_service_httpdns_app_proto_goTypes = []any{
+ (*CreateHTTPDNSAppRequest)(nil), // 0: pb.CreateHTTPDNSAppRequest
+ (*CreateHTTPDNSAppResponse)(nil), // 1: pb.CreateHTTPDNSAppResponse
+ (*UpdateHTTPDNSAppRequest)(nil), // 2: pb.UpdateHTTPDNSAppRequest
+ (*DeleteHTTPDNSAppRequest)(nil), // 3: pb.DeleteHTTPDNSAppRequest
+ (*FindHTTPDNSAppRequest)(nil), // 4: pb.FindHTTPDNSAppRequest
+ (*FindHTTPDNSAppResponse)(nil), // 5: pb.FindHTTPDNSAppResponse
+ (*ListHTTPDNSAppsRequest)(nil), // 6: pb.ListHTTPDNSAppsRequest
+ (*ListHTTPDNSAppsResponse)(nil), // 7: pb.ListHTTPDNSAppsResponse
+ (*FindAllHTTPDNSAppsRequest)(nil), // 8: pb.FindAllHTTPDNSAppsRequest
+ (*FindAllHTTPDNSAppsResponse)(nil), // 9: pb.FindAllHTTPDNSAppsResponse
+ (*UpdateHTTPDNSAppSignEnabledRequest)(nil), // 10: pb.UpdateHTTPDNSAppSignEnabledRequest
+ (*ResetHTTPDNSAppSignSecretRequest)(nil), // 11: pb.ResetHTTPDNSAppSignSecretRequest
+ (*ResetHTTPDNSAppSignSecretResponse)(nil), // 12: pb.ResetHTTPDNSAppSignSecretResponse
+ (*HTTPDNSApp)(nil), // 13: pb.HTTPDNSApp
+ (*RPCSuccess)(nil), // 14: pb.RPCSuccess
+}
+var file_service_httpdns_app_proto_depIdxs = []int32{
+ 13, // 0: pb.FindHTTPDNSAppResponse.app:type_name -> pb.HTTPDNSApp
+ 13, // 1: pb.ListHTTPDNSAppsResponse.apps:type_name -> pb.HTTPDNSApp
+ 13, // 2: pb.FindAllHTTPDNSAppsResponse.apps:type_name -> pb.HTTPDNSApp
+ 0, // 3: pb.HTTPDNSAppService.createHTTPDNSApp:input_type -> pb.CreateHTTPDNSAppRequest
+ 2, // 4: pb.HTTPDNSAppService.updateHTTPDNSApp:input_type -> pb.UpdateHTTPDNSAppRequest
+ 3, // 5: pb.HTTPDNSAppService.deleteHTTPDNSApp:input_type -> pb.DeleteHTTPDNSAppRequest
+ 4, // 6: pb.HTTPDNSAppService.findHTTPDNSApp:input_type -> pb.FindHTTPDNSAppRequest
+ 6, // 7: pb.HTTPDNSAppService.listHTTPDNSApps:input_type -> pb.ListHTTPDNSAppsRequest
+ 8, // 8: pb.HTTPDNSAppService.findAllHTTPDNSApps:input_type -> pb.FindAllHTTPDNSAppsRequest
+ 10, // 9: pb.HTTPDNSAppService.updateHTTPDNSAppSignEnabled:input_type -> pb.UpdateHTTPDNSAppSignEnabledRequest
+ 11, // 10: pb.HTTPDNSAppService.resetHTTPDNSAppSignSecret:input_type -> pb.ResetHTTPDNSAppSignSecretRequest
+ 1, // 11: pb.HTTPDNSAppService.createHTTPDNSApp:output_type -> pb.CreateHTTPDNSAppResponse
+ 14, // 12: pb.HTTPDNSAppService.updateHTTPDNSApp:output_type -> pb.RPCSuccess
+ 14, // 13: pb.HTTPDNSAppService.deleteHTTPDNSApp:output_type -> pb.RPCSuccess
+ 5, // 14: pb.HTTPDNSAppService.findHTTPDNSApp:output_type -> pb.FindHTTPDNSAppResponse
+ 7, // 15: pb.HTTPDNSAppService.listHTTPDNSApps:output_type -> pb.ListHTTPDNSAppsResponse
+ 9, // 16: pb.HTTPDNSAppService.findAllHTTPDNSApps:output_type -> pb.FindAllHTTPDNSAppsResponse
+ 14, // 17: pb.HTTPDNSAppService.updateHTTPDNSAppSignEnabled:output_type -> pb.RPCSuccess
+ 12, // 18: pb.HTTPDNSAppService.resetHTTPDNSAppSignSecret:output_type -> pb.ResetHTTPDNSAppSignSecretResponse
+ 11, // [11:19] is the sub-list for method output_type
+ 3, // [3:11] is the sub-list for method input_type
+ 3, // [3:3] is the sub-list for extension type_name
+ 3, // [3:3] is the sub-list for extension extendee
+ 0, // [0:3] is the sub-list for field type_name
+}
+
+func init() { file_service_httpdns_app_proto_init() }
+func file_service_httpdns_app_proto_init() {
+ if File_service_httpdns_app_proto != nil {
+ return
+ }
+ file_models_model_httpdns_app_proto_init()
+ file_models_rpc_messages_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_service_httpdns_app_proto_rawDesc), len(file_service_httpdns_app_proto_rawDesc)),
+ NumEnums: 0,
+ NumMessages: 13,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_service_httpdns_app_proto_goTypes,
+ DependencyIndexes: file_service_httpdns_app_proto_depIdxs,
+ MessageInfos: file_service_httpdns_app_proto_msgTypes,
+ }.Build()
+ File_service_httpdns_app_proto = out.File
+ file_service_httpdns_app_proto_goTypes = nil
+ file_service_httpdns_app_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_app_grpc.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_app_grpc.pb.go
new file mode 100644
index 0000000..6f5242c
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_app_grpc.pb.go
@@ -0,0 +1,387 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.6.1
+// - protoc v3.21.12
+// source: service_httpdns_app.proto
+
+package pb
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.64.0 or later.
+const _ = grpc.SupportPackageIsVersion9
+
+const (
+ HTTPDNSAppService_CreateHTTPDNSApp_FullMethodName = "/pb.HTTPDNSAppService/createHTTPDNSApp"
+ HTTPDNSAppService_UpdateHTTPDNSApp_FullMethodName = "/pb.HTTPDNSAppService/updateHTTPDNSApp"
+ HTTPDNSAppService_DeleteHTTPDNSApp_FullMethodName = "/pb.HTTPDNSAppService/deleteHTTPDNSApp"
+ HTTPDNSAppService_FindHTTPDNSApp_FullMethodName = "/pb.HTTPDNSAppService/findHTTPDNSApp"
+ HTTPDNSAppService_ListHTTPDNSApps_FullMethodName = "/pb.HTTPDNSAppService/listHTTPDNSApps"
+ HTTPDNSAppService_FindAllHTTPDNSApps_FullMethodName = "/pb.HTTPDNSAppService/findAllHTTPDNSApps"
+ HTTPDNSAppService_UpdateHTTPDNSAppSignEnabled_FullMethodName = "/pb.HTTPDNSAppService/updateHTTPDNSAppSignEnabled"
+ HTTPDNSAppService_ResetHTTPDNSAppSignSecret_FullMethodName = "/pb.HTTPDNSAppService/resetHTTPDNSAppSignSecret"
+)
+
+// HTTPDNSAppServiceClient is the client API for HTTPDNSAppService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type HTTPDNSAppServiceClient interface {
+ CreateHTTPDNSApp(ctx context.Context, in *CreateHTTPDNSAppRequest, opts ...grpc.CallOption) (*CreateHTTPDNSAppResponse, error)
+ UpdateHTTPDNSApp(ctx context.Context, in *UpdateHTTPDNSAppRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ DeleteHTTPDNSApp(ctx context.Context, in *DeleteHTTPDNSAppRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ FindHTTPDNSApp(ctx context.Context, in *FindHTTPDNSAppRequest, opts ...grpc.CallOption) (*FindHTTPDNSAppResponse, error)
+ ListHTTPDNSApps(ctx context.Context, in *ListHTTPDNSAppsRequest, opts ...grpc.CallOption) (*ListHTTPDNSAppsResponse, error)
+ FindAllHTTPDNSApps(ctx context.Context, in *FindAllHTTPDNSAppsRequest, opts ...grpc.CallOption) (*FindAllHTTPDNSAppsResponse, error)
+ UpdateHTTPDNSAppSignEnabled(ctx context.Context, in *UpdateHTTPDNSAppSignEnabledRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ ResetHTTPDNSAppSignSecret(ctx context.Context, in *ResetHTTPDNSAppSignSecretRequest, opts ...grpc.CallOption) (*ResetHTTPDNSAppSignSecretResponse, error)
+}
+
+type hTTPDNSAppServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewHTTPDNSAppServiceClient(cc grpc.ClientConnInterface) HTTPDNSAppServiceClient {
+ return &hTTPDNSAppServiceClient{cc}
+}
+
+func (c *hTTPDNSAppServiceClient) CreateHTTPDNSApp(ctx context.Context, in *CreateHTTPDNSAppRequest, opts ...grpc.CallOption) (*CreateHTTPDNSAppResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(CreateHTTPDNSAppResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSAppService_CreateHTTPDNSApp_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSAppServiceClient) UpdateHTTPDNSApp(ctx context.Context, in *UpdateHTTPDNSAppRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSAppService_UpdateHTTPDNSApp_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSAppServiceClient) DeleteHTTPDNSApp(ctx context.Context, in *DeleteHTTPDNSAppRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSAppService_DeleteHTTPDNSApp_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSAppServiceClient) FindHTTPDNSApp(ctx context.Context, in *FindHTTPDNSAppRequest, opts ...grpc.CallOption) (*FindHTTPDNSAppResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(FindHTTPDNSAppResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSAppService_FindHTTPDNSApp_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSAppServiceClient) ListHTTPDNSApps(ctx context.Context, in *ListHTTPDNSAppsRequest, opts ...grpc.CallOption) (*ListHTTPDNSAppsResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(ListHTTPDNSAppsResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSAppService_ListHTTPDNSApps_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSAppServiceClient) FindAllHTTPDNSApps(ctx context.Context, in *FindAllHTTPDNSAppsRequest, opts ...grpc.CallOption) (*FindAllHTTPDNSAppsResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(FindAllHTTPDNSAppsResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSAppService_FindAllHTTPDNSApps_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSAppServiceClient) UpdateHTTPDNSAppSignEnabled(ctx context.Context, in *UpdateHTTPDNSAppSignEnabledRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSAppService_UpdateHTTPDNSAppSignEnabled_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSAppServiceClient) ResetHTTPDNSAppSignSecret(ctx context.Context, in *ResetHTTPDNSAppSignSecretRequest, opts ...grpc.CallOption) (*ResetHTTPDNSAppSignSecretResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(ResetHTTPDNSAppSignSecretResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSAppService_ResetHTTPDNSAppSignSecret_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// HTTPDNSAppServiceServer is the server API for HTTPDNSAppService service.
+// All implementations must embed UnimplementedHTTPDNSAppServiceServer
+// for forward compatibility.
+type HTTPDNSAppServiceServer interface {
+ CreateHTTPDNSApp(context.Context, *CreateHTTPDNSAppRequest) (*CreateHTTPDNSAppResponse, error)
+ UpdateHTTPDNSApp(context.Context, *UpdateHTTPDNSAppRequest) (*RPCSuccess, error)
+ DeleteHTTPDNSApp(context.Context, *DeleteHTTPDNSAppRequest) (*RPCSuccess, error)
+ FindHTTPDNSApp(context.Context, *FindHTTPDNSAppRequest) (*FindHTTPDNSAppResponse, error)
+ ListHTTPDNSApps(context.Context, *ListHTTPDNSAppsRequest) (*ListHTTPDNSAppsResponse, error)
+ FindAllHTTPDNSApps(context.Context, *FindAllHTTPDNSAppsRequest) (*FindAllHTTPDNSAppsResponse, error)
+ UpdateHTTPDNSAppSignEnabled(context.Context, *UpdateHTTPDNSAppSignEnabledRequest) (*RPCSuccess, error)
+ ResetHTTPDNSAppSignSecret(context.Context, *ResetHTTPDNSAppSignSecretRequest) (*ResetHTTPDNSAppSignSecretResponse, error)
+ mustEmbedUnimplementedHTTPDNSAppServiceServer()
+}
+
+// UnimplementedHTTPDNSAppServiceServer must be embedded to have
+// forward compatible implementations.
+//
+// NOTE: this should be embedded by value instead of pointer to avoid a nil
+// pointer dereference when methods are called.
+type UnimplementedHTTPDNSAppServiceServer struct{}
+
+func (UnimplementedHTTPDNSAppServiceServer) CreateHTTPDNSApp(context.Context, *CreateHTTPDNSAppRequest) (*CreateHTTPDNSAppResponse, error) {
+ return nil, status.Error(codes.Unimplemented, "method CreateHTTPDNSApp not implemented")
+}
+func (UnimplementedHTTPDNSAppServiceServer) UpdateHTTPDNSApp(context.Context, *UpdateHTTPDNSAppRequest) (*RPCSuccess, error) {
+ return nil, status.Error(codes.Unimplemented, "method UpdateHTTPDNSApp not implemented")
+}
+func (UnimplementedHTTPDNSAppServiceServer) DeleteHTTPDNSApp(context.Context, *DeleteHTTPDNSAppRequest) (*RPCSuccess, error) {
+ return nil, status.Error(codes.Unimplemented, "method DeleteHTTPDNSApp not implemented")
+}
+func (UnimplementedHTTPDNSAppServiceServer) FindHTTPDNSApp(context.Context, *FindHTTPDNSAppRequest) (*FindHTTPDNSAppResponse, error) {
+ return nil, status.Error(codes.Unimplemented, "method FindHTTPDNSApp not implemented")
+}
+func (UnimplementedHTTPDNSAppServiceServer) ListHTTPDNSApps(context.Context, *ListHTTPDNSAppsRequest) (*ListHTTPDNSAppsResponse, error) {
+ return nil, status.Error(codes.Unimplemented, "method ListHTTPDNSApps not implemented")
+}
+func (UnimplementedHTTPDNSAppServiceServer) FindAllHTTPDNSApps(context.Context, *FindAllHTTPDNSAppsRequest) (*FindAllHTTPDNSAppsResponse, error) {
+ return nil, status.Error(codes.Unimplemented, "method FindAllHTTPDNSApps not implemented")
+}
+func (UnimplementedHTTPDNSAppServiceServer) UpdateHTTPDNSAppSignEnabled(context.Context, *UpdateHTTPDNSAppSignEnabledRequest) (*RPCSuccess, error) {
+ return nil, status.Error(codes.Unimplemented, "method UpdateHTTPDNSAppSignEnabled not implemented")
+}
+func (UnimplementedHTTPDNSAppServiceServer) ResetHTTPDNSAppSignSecret(context.Context, *ResetHTTPDNSAppSignSecretRequest) (*ResetHTTPDNSAppSignSecretResponse, error) {
+ return nil, status.Error(codes.Unimplemented, "method ResetHTTPDNSAppSignSecret not implemented")
+}
+func (UnimplementedHTTPDNSAppServiceServer) mustEmbedUnimplementedHTTPDNSAppServiceServer() {}
+func (UnimplementedHTTPDNSAppServiceServer) testEmbeddedByValue() {}
+
+// UnsafeHTTPDNSAppServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to HTTPDNSAppServiceServer will
+// result in compilation errors.
+type UnsafeHTTPDNSAppServiceServer interface {
+ mustEmbedUnimplementedHTTPDNSAppServiceServer()
+}
+
+func RegisterHTTPDNSAppServiceServer(s grpc.ServiceRegistrar, srv HTTPDNSAppServiceServer) {
+ // If the following call panics, it indicates UnimplementedHTTPDNSAppServiceServer was
+ // embedded by pointer and is nil. This will cause panics if an
+ // unimplemented method is ever invoked, so we test this at initialization
+ // time to prevent it from happening at runtime later due to I/O.
+ if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
+ t.testEmbeddedByValue()
+ }
+ s.RegisterService(&HTTPDNSAppService_ServiceDesc, srv)
+}
+
+func _HTTPDNSAppService_CreateHTTPDNSApp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CreateHTTPDNSAppRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSAppServiceServer).CreateHTTPDNSApp(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSAppService_CreateHTTPDNSApp_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSAppServiceServer).CreateHTTPDNSApp(ctx, req.(*CreateHTTPDNSAppRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSAppService_UpdateHTTPDNSApp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpdateHTTPDNSAppRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSAppServiceServer).UpdateHTTPDNSApp(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSAppService_UpdateHTTPDNSApp_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSAppServiceServer).UpdateHTTPDNSApp(ctx, req.(*UpdateHTTPDNSAppRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSAppService_DeleteHTTPDNSApp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(DeleteHTTPDNSAppRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSAppServiceServer).DeleteHTTPDNSApp(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSAppService_DeleteHTTPDNSApp_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSAppServiceServer).DeleteHTTPDNSApp(ctx, req.(*DeleteHTTPDNSAppRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSAppService_FindHTTPDNSApp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(FindHTTPDNSAppRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSAppServiceServer).FindHTTPDNSApp(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSAppService_FindHTTPDNSApp_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSAppServiceServer).FindHTTPDNSApp(ctx, req.(*FindHTTPDNSAppRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSAppService_ListHTTPDNSApps_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ListHTTPDNSAppsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSAppServiceServer).ListHTTPDNSApps(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSAppService_ListHTTPDNSApps_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSAppServiceServer).ListHTTPDNSApps(ctx, req.(*ListHTTPDNSAppsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSAppService_FindAllHTTPDNSApps_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(FindAllHTTPDNSAppsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSAppServiceServer).FindAllHTTPDNSApps(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSAppService_FindAllHTTPDNSApps_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSAppServiceServer).FindAllHTTPDNSApps(ctx, req.(*FindAllHTTPDNSAppsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSAppService_UpdateHTTPDNSAppSignEnabled_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpdateHTTPDNSAppSignEnabledRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSAppServiceServer).UpdateHTTPDNSAppSignEnabled(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSAppService_UpdateHTTPDNSAppSignEnabled_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSAppServiceServer).UpdateHTTPDNSAppSignEnabled(ctx, req.(*UpdateHTTPDNSAppSignEnabledRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSAppService_ResetHTTPDNSAppSignSecret_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ResetHTTPDNSAppSignSecretRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSAppServiceServer).ResetHTTPDNSAppSignSecret(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSAppService_ResetHTTPDNSAppSignSecret_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSAppServiceServer).ResetHTTPDNSAppSignSecret(ctx, req.(*ResetHTTPDNSAppSignSecretRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// HTTPDNSAppService_ServiceDesc is the grpc.ServiceDesc for HTTPDNSAppService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var HTTPDNSAppService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "pb.HTTPDNSAppService",
+ HandlerType: (*HTTPDNSAppServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "createHTTPDNSApp",
+ Handler: _HTTPDNSAppService_CreateHTTPDNSApp_Handler,
+ },
+ {
+ MethodName: "updateHTTPDNSApp",
+ Handler: _HTTPDNSAppService_UpdateHTTPDNSApp_Handler,
+ },
+ {
+ MethodName: "deleteHTTPDNSApp",
+ Handler: _HTTPDNSAppService_DeleteHTTPDNSApp_Handler,
+ },
+ {
+ MethodName: "findHTTPDNSApp",
+ Handler: _HTTPDNSAppService_FindHTTPDNSApp_Handler,
+ },
+ {
+ MethodName: "listHTTPDNSApps",
+ Handler: _HTTPDNSAppService_ListHTTPDNSApps_Handler,
+ },
+ {
+ MethodName: "findAllHTTPDNSApps",
+ Handler: _HTTPDNSAppService_FindAllHTTPDNSApps_Handler,
+ },
+ {
+ MethodName: "updateHTTPDNSAppSignEnabled",
+ Handler: _HTTPDNSAppService_UpdateHTTPDNSAppSignEnabled_Handler,
+ },
+ {
+ MethodName: "resetHTTPDNSAppSignSecret",
+ Handler: _HTTPDNSAppService_ResetHTTPDNSAppSignSecret_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "service_httpdns_app.proto",
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_cluster.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_cluster.pb.go
new file mode 100644
index 0000000..8120273
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_cluster.pb.go
@@ -0,0 +1,1015 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.35.1
+// protoc v3.21.12
+// source: service_httpdns_cluster.proto
+
+package pb
+
+import (
+ 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 CreateHTTPDNSClusterRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ ServiceDomain string `protobuf:"bytes,2,opt,name=serviceDomain,proto3" json:"serviceDomain,omitempty"`
+ DefaultTTL int32 `protobuf:"varint,3,opt,name=defaultTTL,proto3" json:"defaultTTL,omitempty"`
+ FallbackTimeoutMs int32 `protobuf:"varint,4,opt,name=fallbackTimeoutMs,proto3" json:"fallbackTimeoutMs,omitempty"`
+ InstallDir string `protobuf:"bytes,5,opt,name=installDir,proto3" json:"installDir,omitempty"`
+ TlsPolicyJSON []byte `protobuf:"bytes,6,opt,name=tlsPolicyJSON,proto3" json:"tlsPolicyJSON,omitempty"`
+ IsOn bool `protobuf:"varint,7,opt,name=isOn,proto3" json:"isOn,omitempty"`
+ IsDefault bool `protobuf:"varint,8,opt,name=isDefault,proto3" json:"isDefault,omitempty"`
+ AutoRemoteStart bool `protobuf:"varint,9,opt,name=autoRemoteStart,proto3" json:"autoRemoteStart,omitempty"`
+ AccessLogIsOn bool `protobuf:"varint,10,opt,name=accessLogIsOn,proto3" json:"accessLogIsOn,omitempty"`
+ TimeZone string `protobuf:"bytes,11,opt,name=timeZone,proto3" json:"timeZone,omitempty"`
+}
+
+func (x *CreateHTTPDNSClusterRequest) Reset() {
+ *x = CreateHTTPDNSClusterRequest{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSClusterRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSClusterRequest) ProtoMessage() {}
+
+func (x *CreateHTTPDNSClusterRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSClusterRequest.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSClusterRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CreateHTTPDNSClusterRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *CreateHTTPDNSClusterRequest) GetServiceDomain() string {
+ if x != nil {
+ return x.ServiceDomain
+ }
+ return ""
+}
+
+func (x *CreateHTTPDNSClusterRequest) GetDefaultTTL() int32 {
+ if x != nil {
+ return x.DefaultTTL
+ }
+ return 0
+}
+
+func (x *CreateHTTPDNSClusterRequest) GetFallbackTimeoutMs() int32 {
+ if x != nil {
+ return x.FallbackTimeoutMs
+ }
+ return 0
+}
+
+func (x *CreateHTTPDNSClusterRequest) GetInstallDir() string {
+ if x != nil {
+ return x.InstallDir
+ }
+ return ""
+}
+
+func (x *CreateHTTPDNSClusterRequest) GetTlsPolicyJSON() []byte {
+ if x != nil {
+ return x.TlsPolicyJSON
+ }
+ return nil
+}
+
+func (x *CreateHTTPDNSClusterRequest) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+func (x *CreateHTTPDNSClusterRequest) GetIsDefault() bool {
+ if x != nil {
+ return x.IsDefault
+ }
+ return false
+}
+
+func (x *CreateHTTPDNSClusterRequest) GetAutoRemoteStart() bool {
+ if x != nil {
+ return x.AutoRemoteStart
+ }
+ return false
+}
+
+func (x *CreateHTTPDNSClusterRequest) GetAccessLogIsOn() bool {
+ if x != nil {
+ return x.AccessLogIsOn
+ }
+ return false
+}
+
+func (x *CreateHTTPDNSClusterRequest) GetTimeZone() string {
+ if x != nil {
+ return x.TimeZone
+ }
+ return ""
+}
+
+type CreateHTTPDNSClusterResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+}
+
+func (x *CreateHTTPDNSClusterResponse) Reset() {
+ *x = CreateHTTPDNSClusterResponse{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSClusterResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSClusterResponse) ProtoMessage() {}
+
+func (x *CreateHTTPDNSClusterResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[1]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSClusterResponse.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSClusterResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *CreateHTTPDNSClusterResponse) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+type UpdateHTTPDNSClusterRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+ Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+ ServiceDomain string `protobuf:"bytes,3,opt,name=serviceDomain,proto3" json:"serviceDomain,omitempty"`
+ DefaultTTL int32 `protobuf:"varint,4,opt,name=defaultTTL,proto3" json:"defaultTTL,omitempty"`
+ FallbackTimeoutMs int32 `protobuf:"varint,5,opt,name=fallbackTimeoutMs,proto3" json:"fallbackTimeoutMs,omitempty"`
+ InstallDir string `protobuf:"bytes,6,opt,name=installDir,proto3" json:"installDir,omitempty"`
+ TlsPolicyJSON []byte `protobuf:"bytes,7,opt,name=tlsPolicyJSON,proto3" json:"tlsPolicyJSON,omitempty"`
+ IsOn bool `protobuf:"varint,8,opt,name=isOn,proto3" json:"isOn,omitempty"`
+ IsDefault bool `protobuf:"varint,9,opt,name=isDefault,proto3" json:"isDefault,omitempty"`
+ AutoRemoteStart bool `protobuf:"varint,10,opt,name=autoRemoteStart,proto3" json:"autoRemoteStart,omitempty"`
+ AccessLogIsOn bool `protobuf:"varint,11,opt,name=accessLogIsOn,proto3" json:"accessLogIsOn,omitempty"`
+ TimeZone string `protobuf:"bytes,12,opt,name=timeZone,proto3" json:"timeZone,omitempty"`
+}
+
+func (x *UpdateHTTPDNSClusterRequest) Reset() {
+ *x = UpdateHTTPDNSClusterRequest{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *UpdateHTTPDNSClusterRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateHTTPDNSClusterRequest) ProtoMessage() {}
+
+func (x *UpdateHTTPDNSClusterRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[2]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateHTTPDNSClusterRequest.ProtoReflect.Descriptor instead.
+func (*UpdateHTTPDNSClusterRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *UpdateHTTPDNSClusterRequest) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+func (x *UpdateHTTPDNSClusterRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *UpdateHTTPDNSClusterRequest) GetServiceDomain() string {
+ if x != nil {
+ return x.ServiceDomain
+ }
+ return ""
+}
+
+func (x *UpdateHTTPDNSClusterRequest) GetDefaultTTL() int32 {
+ if x != nil {
+ return x.DefaultTTL
+ }
+ return 0
+}
+
+func (x *UpdateHTTPDNSClusterRequest) GetFallbackTimeoutMs() int32 {
+ if x != nil {
+ return x.FallbackTimeoutMs
+ }
+ return 0
+}
+
+func (x *UpdateHTTPDNSClusterRequest) GetInstallDir() string {
+ if x != nil {
+ return x.InstallDir
+ }
+ return ""
+}
+
+func (x *UpdateHTTPDNSClusterRequest) GetTlsPolicyJSON() []byte {
+ if x != nil {
+ return x.TlsPolicyJSON
+ }
+ return nil
+}
+
+func (x *UpdateHTTPDNSClusterRequest) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+func (x *UpdateHTTPDNSClusterRequest) GetIsDefault() bool {
+ if x != nil {
+ return x.IsDefault
+ }
+ return false
+}
+
+func (x *UpdateHTTPDNSClusterRequest) GetAutoRemoteStart() bool {
+ if x != nil {
+ return x.AutoRemoteStart
+ }
+ return false
+}
+
+func (x *UpdateHTTPDNSClusterRequest) GetAccessLogIsOn() bool {
+ if x != nil {
+ return x.AccessLogIsOn
+ }
+ return false
+}
+
+func (x *UpdateHTTPDNSClusterRequest) GetTimeZone() string {
+ if x != nil {
+ return x.TimeZone
+ }
+ return ""
+}
+
+type DeleteHTTPDNSClusterRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+}
+
+func (x *DeleteHTTPDNSClusterRequest) Reset() {
+ *x = DeleteHTTPDNSClusterRequest{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *DeleteHTTPDNSClusterRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DeleteHTTPDNSClusterRequest) ProtoMessage() {}
+
+func (x *DeleteHTTPDNSClusterRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[3]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use DeleteHTTPDNSClusterRequest.ProtoReflect.Descriptor instead.
+func (*DeleteHTTPDNSClusterRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *DeleteHTTPDNSClusterRequest) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+type FindHTTPDNSClusterRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+}
+
+func (x *FindHTTPDNSClusterRequest) Reset() {
+ *x = FindHTTPDNSClusterRequest{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *FindHTTPDNSClusterRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FindHTTPDNSClusterRequest) ProtoMessage() {}
+
+func (x *FindHTTPDNSClusterRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[4]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FindHTTPDNSClusterRequest.ProtoReflect.Descriptor instead.
+func (*FindHTTPDNSClusterRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *FindHTTPDNSClusterRequest) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+type FindHTTPDNSClusterResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Cluster *HTTPDNSCluster `protobuf:"bytes,1,opt,name=cluster,proto3" json:"cluster,omitempty"`
+}
+
+func (x *FindHTTPDNSClusterResponse) Reset() {
+ *x = FindHTTPDNSClusterResponse{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *FindHTTPDNSClusterResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FindHTTPDNSClusterResponse) ProtoMessage() {}
+
+func (x *FindHTTPDNSClusterResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[5]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FindHTTPDNSClusterResponse.ProtoReflect.Descriptor instead.
+func (*FindHTTPDNSClusterResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *FindHTTPDNSClusterResponse) GetCluster() *HTTPDNSCluster {
+ if x != nil {
+ return x.Cluster
+ }
+ return nil
+}
+
+type ListHTTPDNSClustersRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Offset int64 `protobuf:"varint,1,opt,name=offset,proto3" json:"offset,omitempty"`
+ Size int64 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"`
+ Keyword string `protobuf:"bytes,3,opt,name=keyword,proto3" json:"keyword,omitempty"`
+}
+
+func (x *ListHTTPDNSClustersRequest) Reset() {
+ *x = ListHTTPDNSClustersRequest{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSClustersRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSClustersRequest) ProtoMessage() {}
+
+func (x *ListHTTPDNSClustersRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[6]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSClustersRequest.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSClustersRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *ListHTTPDNSClustersRequest) GetOffset() int64 {
+ if x != nil {
+ return x.Offset
+ }
+ return 0
+}
+
+func (x *ListHTTPDNSClustersRequest) GetSize() int64 {
+ if x != nil {
+ return x.Size
+ }
+ return 0
+}
+
+func (x *ListHTTPDNSClustersRequest) GetKeyword() string {
+ if x != nil {
+ return x.Keyword
+ }
+ return ""
+}
+
+type ListHTTPDNSClustersResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Clusters []*HTTPDNSCluster `protobuf:"bytes,1,rep,name=clusters,proto3" json:"clusters,omitempty"`
+}
+
+func (x *ListHTTPDNSClustersResponse) Reset() {
+ *x = ListHTTPDNSClustersResponse{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSClustersResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSClustersResponse) ProtoMessage() {}
+
+func (x *ListHTTPDNSClustersResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[7]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSClustersResponse.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSClustersResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *ListHTTPDNSClustersResponse) GetClusters() []*HTTPDNSCluster {
+ if x != nil {
+ return x.Clusters
+ }
+ return nil
+}
+
+type FindAllHTTPDNSClustersRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *FindAllHTTPDNSClustersRequest) Reset() {
+ *x = FindAllHTTPDNSClustersRequest{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *FindAllHTTPDNSClustersRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FindAllHTTPDNSClustersRequest) ProtoMessage() {}
+
+func (x *FindAllHTTPDNSClustersRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[8]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FindAllHTTPDNSClustersRequest.ProtoReflect.Descriptor instead.
+func (*FindAllHTTPDNSClustersRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{8}
+}
+
+type FindAllHTTPDNSClustersResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Clusters []*HTTPDNSCluster `protobuf:"bytes,1,rep,name=clusters,proto3" json:"clusters,omitempty"`
+}
+
+func (x *FindAllHTTPDNSClustersResponse) Reset() {
+ *x = FindAllHTTPDNSClustersResponse{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *FindAllHTTPDNSClustersResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FindAllHTTPDNSClustersResponse) ProtoMessage() {}
+
+func (x *FindAllHTTPDNSClustersResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[9]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FindAllHTTPDNSClustersResponse.ProtoReflect.Descriptor instead.
+func (*FindAllHTTPDNSClustersResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *FindAllHTTPDNSClustersResponse) GetClusters() []*HTTPDNSCluster {
+ if x != nil {
+ return x.Clusters
+ }
+ return nil
+}
+
+type UpdateHTTPDNSClusterDefaultRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+}
+
+func (x *UpdateHTTPDNSClusterDefaultRequest) Reset() {
+ *x = UpdateHTTPDNSClusterDefaultRequest{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *UpdateHTTPDNSClusterDefaultRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateHTTPDNSClusterDefaultRequest) ProtoMessage() {}
+
+func (x *UpdateHTTPDNSClusterDefaultRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[10]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateHTTPDNSClusterDefaultRequest.ProtoReflect.Descriptor instead.
+func (*UpdateHTTPDNSClusterDefaultRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *UpdateHTTPDNSClusterDefaultRequest) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+type ListHTTPDNSNodesWithClusterIdRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+}
+
+func (x *ListHTTPDNSNodesWithClusterIdRequest) Reset() {
+ *x = ListHTTPDNSNodesWithClusterIdRequest{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[11]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSNodesWithClusterIdRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSNodesWithClusterIdRequest) ProtoMessage() {}
+
+func (x *ListHTTPDNSNodesWithClusterIdRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[11]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSNodesWithClusterIdRequest.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSNodesWithClusterIdRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *ListHTTPDNSNodesWithClusterIdRequest) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+type ListHTTPDNSNodesWithClusterIdResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Nodes []*HTTPDNSNode `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
+}
+
+func (x *ListHTTPDNSNodesWithClusterIdResponse) Reset() {
+ *x = ListHTTPDNSNodesWithClusterIdResponse{}
+ mi := &file_service_httpdns_cluster_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSNodesWithClusterIdResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSNodesWithClusterIdResponse) ProtoMessage() {}
+
+func (x *ListHTTPDNSNodesWithClusterIdResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_cluster_proto_msgTypes[12]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSNodesWithClusterIdResponse.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSNodesWithClusterIdResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_cluster_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *ListHTTPDNSNodesWithClusterIdResponse) GetNodes() []*HTTPDNSNode {
+ if x != nil {
+ return x.Nodes
+ }
+ return nil
+}
+
+var File_service_httpdns_cluster_proto protoreflect.FileDescriptor
+
+var file_service_httpdns_cluster_proto_rawDesc = []byte{
+ 0x0a, 0x1d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x64, 0x6e,
+ 0x73, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+ 0x02, 0x70, 0x62, 0x1a, 0x22, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65,
+ 0x6c, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x64, 0x6e, 0x73, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65,
+ 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f,
+ 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x64, 0x6e, 0x73, 0x5f, 0x6e, 0x6f,
+ 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73,
+ 0x2f, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x22, 0x9d, 0x02, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54,
+ 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69,
+ 0x63, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
+ 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x1e, 0x0a,
+ 0x0a, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x54, 0x54, 0x4c, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x0a, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x54, 0x54, 0x4c, 0x12, 0x2c, 0x0a,
+ 0x11, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
+ 0x4d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61,
+ 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69,
+ 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x44, 0x69, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x44, 0x69, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x74,
+ 0x6c, 0x73, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x06, 0x20, 0x01,
+ 0x28, 0x0c, 0x52, 0x0d, 0x74, 0x6c, 0x73, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4a, 0x53, 0x4f,
+ 0x4e, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75,
+ 0x6c, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x44, 0x65, 0x66, 0x61,
+ 0x75, 0x6c, 0x74, 0x22, 0x3c, 0x0a, 0x1c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54,
+ 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49,
+ 0x64, 0x22, 0xbb, 0x02, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50,
+ 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12,
+ 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x6f,
+ 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76,
+ 0x69, 0x63, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x66,
+ 0x61, 0x75, 0x6c, 0x74, 0x54, 0x54, 0x4c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x64,
+ 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x54, 0x54, 0x4c, 0x12, 0x2c, 0x0a, 0x11, 0x66, 0x61, 0x6c,
+ 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x05,
+ 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x69,
+ 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61,
+ 0x6c, 0x6c, 0x44, 0x69, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73,
+ 0x74, 0x61, 0x6c, 0x6c, 0x44, 0x69, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x74, 0x6c, 0x73, 0x50, 0x6f,
+ 0x6c, 0x69, 0x63, 0x79, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d,
+ 0x74, 0x6c, 0x73, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x12, 0x0a,
+ 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f,
+ 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x09,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22,
+ 0x3b, 0x0a, 0x1b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53,
+ 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c,
+ 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0x39, 0x0a, 0x19,
+ 0x46, 0x69, 0x6e, 0x64, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74,
+ 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75,
+ 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6c,
+ 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0x4a, 0x0a, 0x1a, 0x46, 0x69, 0x6e, 0x64, 0x48,
+ 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x54, 0x54, 0x50,
+ 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73,
+ 0x74, 0x65, 0x72, 0x22, 0x62, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44,
+ 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a,
+ 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a,
+ 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
+ 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x4d, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x48,
+ 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65,
+ 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x54,
+ 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c,
+ 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x22, 0x1f, 0x0a, 0x1d, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x6c,
+ 0x6c, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x50, 0x0a, 0x1e, 0x46, 0x69, 0x6e, 0x64, 0x41,
+ 0x6c, 0x6c, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
+ 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x08, 0x63, 0x6c, 0x75,
+ 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62,
+ 0x2e, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52,
+ 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x22, 0x42, 0x0a, 0x22, 0x55, 0x70, 0x64,
+ 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65,
+ 0x72, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+ 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0x44, 0x0a,
+ 0x24, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x4e, 0x6f, 0x64, 0x65,
+ 0x73, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
+ 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65,
+ 0x72, 0x49, 0x64, 0x22, 0x4e, 0x0a, 0x25, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44,
+ 0x4e, 0x53, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x75, 0x73, 0x74,
+ 0x65, 0x72, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05,
+ 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62,
+ 0x2e, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f,
+ 0x64, 0x65, 0x73, 0x32, 0xdf, 0x05, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43,
+ 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x59, 0x0a,
+ 0x14, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c,
+ 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
+ 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61,
+ 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x14, 0x75, 0x70, 0x64, 0x61,
+ 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
+ 0x12, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50,
+ 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73,
+ 0x73, 0x12, 0x47, 0x0a, 0x14, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44,
+ 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x44,
+ 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73,
+ 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e,
+ 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x53, 0x0a, 0x12, 0x66, 0x69,
+ 0x6e, 0x64, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
+ 0x12, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e,
+ 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+ 0x1e, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53,
+ 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+ 0x56, 0x0a, 0x13, 0x6c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c,
+ 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1e, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74,
+ 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74,
+ 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x16, 0x66, 0x69, 0x6e, 0x64, 0x41,
+ 0x6c, 0x6c, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
+ 0x73, 0x12, 0x21, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x6c, 0x6c, 0x48, 0x54,
+ 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x6c,
+ 0x6c, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x1b, 0x75, 0x70, 0x64, 0x61,
+ 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
+ 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x26, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64,
+ 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65,
+ 0x72, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+ 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12,
+ 0x74, 0x0a, 0x1d, 0x6c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x4e, 0x6f,
+ 0x64, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64,
+ 0x12, 0x28, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e,
+ 0x53, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65,
+ 0x72, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x62, 0x2e,
+ 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x4e, 0x6f, 0x64, 0x65, 0x73,
+ 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_service_httpdns_cluster_proto_rawDescOnce sync.Once
+ file_service_httpdns_cluster_proto_rawDescData = file_service_httpdns_cluster_proto_rawDesc
+)
+
+func file_service_httpdns_cluster_proto_rawDescGZIP() []byte {
+ file_service_httpdns_cluster_proto_rawDescOnce.Do(func() {
+ file_service_httpdns_cluster_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_httpdns_cluster_proto_rawDescData)
+ })
+ return file_service_httpdns_cluster_proto_rawDescData
+}
+
+var file_service_httpdns_cluster_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
+var file_service_httpdns_cluster_proto_goTypes = []any{
+ (*CreateHTTPDNSClusterRequest)(nil), // 0: pb.CreateHTTPDNSClusterRequest
+ (*CreateHTTPDNSClusterResponse)(nil), // 1: pb.CreateHTTPDNSClusterResponse
+ (*UpdateHTTPDNSClusterRequest)(nil), // 2: pb.UpdateHTTPDNSClusterRequest
+ (*DeleteHTTPDNSClusterRequest)(nil), // 3: pb.DeleteHTTPDNSClusterRequest
+ (*FindHTTPDNSClusterRequest)(nil), // 4: pb.FindHTTPDNSClusterRequest
+ (*FindHTTPDNSClusterResponse)(nil), // 5: pb.FindHTTPDNSClusterResponse
+ (*ListHTTPDNSClustersRequest)(nil), // 6: pb.ListHTTPDNSClustersRequest
+ (*ListHTTPDNSClustersResponse)(nil), // 7: pb.ListHTTPDNSClustersResponse
+ (*FindAllHTTPDNSClustersRequest)(nil), // 8: pb.FindAllHTTPDNSClustersRequest
+ (*FindAllHTTPDNSClustersResponse)(nil), // 9: pb.FindAllHTTPDNSClustersResponse
+ (*UpdateHTTPDNSClusterDefaultRequest)(nil), // 10: pb.UpdateHTTPDNSClusterDefaultRequest
+ (*ListHTTPDNSNodesWithClusterIdRequest)(nil), // 11: pb.ListHTTPDNSNodesWithClusterIdRequest
+ (*ListHTTPDNSNodesWithClusterIdResponse)(nil), // 12: pb.ListHTTPDNSNodesWithClusterIdResponse
+ (*HTTPDNSCluster)(nil), // 13: pb.HTTPDNSCluster
+ (*HTTPDNSNode)(nil), // 14: pb.HTTPDNSNode
+ (*RPCSuccess)(nil), // 15: pb.RPCSuccess
+}
+var file_service_httpdns_cluster_proto_depIdxs = []int32{
+ 13, // 0: pb.FindHTTPDNSClusterResponse.cluster:type_name -> pb.HTTPDNSCluster
+ 13, // 1: pb.ListHTTPDNSClustersResponse.clusters:type_name -> pb.HTTPDNSCluster
+ 13, // 2: pb.FindAllHTTPDNSClustersResponse.clusters:type_name -> pb.HTTPDNSCluster
+ 14, // 3: pb.ListHTTPDNSNodesWithClusterIdResponse.nodes:type_name -> pb.HTTPDNSNode
+ 0, // 4: pb.HTTPDNSClusterService.createHTTPDNSCluster:input_type -> pb.CreateHTTPDNSClusterRequest
+ 2, // 5: pb.HTTPDNSClusterService.updateHTTPDNSCluster:input_type -> pb.UpdateHTTPDNSClusterRequest
+ 3, // 6: pb.HTTPDNSClusterService.deleteHTTPDNSCluster:input_type -> pb.DeleteHTTPDNSClusterRequest
+ 4, // 7: pb.HTTPDNSClusterService.findHTTPDNSCluster:input_type -> pb.FindHTTPDNSClusterRequest
+ 6, // 8: pb.HTTPDNSClusterService.listHTTPDNSClusters:input_type -> pb.ListHTTPDNSClustersRequest
+ 8, // 9: pb.HTTPDNSClusterService.findAllHTTPDNSClusters:input_type -> pb.FindAllHTTPDNSClustersRequest
+ 10, // 10: pb.HTTPDNSClusterService.updateHTTPDNSClusterDefault:input_type -> pb.UpdateHTTPDNSClusterDefaultRequest
+ 11, // 11: pb.HTTPDNSClusterService.listHTTPDNSNodesWithClusterId:input_type -> pb.ListHTTPDNSNodesWithClusterIdRequest
+ 1, // 12: pb.HTTPDNSClusterService.createHTTPDNSCluster:output_type -> pb.CreateHTTPDNSClusterResponse
+ 15, // 13: pb.HTTPDNSClusterService.updateHTTPDNSCluster:output_type -> pb.RPCSuccess
+ 15, // 14: pb.HTTPDNSClusterService.deleteHTTPDNSCluster:output_type -> pb.RPCSuccess
+ 5, // 15: pb.HTTPDNSClusterService.findHTTPDNSCluster:output_type -> pb.FindHTTPDNSClusterResponse
+ 7, // 16: pb.HTTPDNSClusterService.listHTTPDNSClusters:output_type -> pb.ListHTTPDNSClustersResponse
+ 9, // 17: pb.HTTPDNSClusterService.findAllHTTPDNSClusters:output_type -> pb.FindAllHTTPDNSClustersResponse
+ 15, // 18: pb.HTTPDNSClusterService.updateHTTPDNSClusterDefault:output_type -> pb.RPCSuccess
+ 12, // 19: pb.HTTPDNSClusterService.listHTTPDNSNodesWithClusterId:output_type -> pb.ListHTTPDNSNodesWithClusterIdResponse
+ 12, // [12:20] is the sub-list for method output_type
+ 4, // [4:12] is the sub-list for method input_type
+ 4, // [4:4] is the sub-list for extension type_name
+ 4, // [4:4] is the sub-list for extension extendee
+ 0, // [0:4] is the sub-list for field type_name
+}
+
+func init() { file_service_httpdns_cluster_proto_init() }
+func file_service_httpdns_cluster_proto_init() {
+ if File_service_httpdns_cluster_proto != nil {
+ return
+ }
+ file_models_model_httpdns_cluster_proto_init()
+ file_models_model_httpdns_node_proto_init()
+ file_models_rpc_messages_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_service_httpdns_cluster_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 13,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_service_httpdns_cluster_proto_goTypes,
+ DependencyIndexes: file_service_httpdns_cluster_proto_depIdxs,
+ MessageInfos: file_service_httpdns_cluster_proto_msgTypes,
+ }.Build()
+ File_service_httpdns_cluster_proto = out.File
+ file_service_httpdns_cluster_proto_rawDesc = nil
+ file_service_httpdns_cluster_proto_goTypes = nil
+ file_service_httpdns_cluster_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_cluster_grpc.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_cluster_grpc.pb.go
new file mode 100644
index 0000000..825f8b6
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_cluster_grpc.pb.go
@@ -0,0 +1,385 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.5.1
+// - protoc v3.21.12
+// source: service_httpdns_cluster.proto
+
+package pb
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.64.0 or later.
+const _ = grpc.SupportPackageIsVersion9
+
+const (
+ HTTPDNSClusterService_CreateHTTPDNSCluster_FullMethodName = "/pb.HTTPDNSClusterService/createHTTPDNSCluster"
+ HTTPDNSClusterService_UpdateHTTPDNSCluster_FullMethodName = "/pb.HTTPDNSClusterService/updateHTTPDNSCluster"
+ HTTPDNSClusterService_DeleteHTTPDNSCluster_FullMethodName = "/pb.HTTPDNSClusterService/deleteHTTPDNSCluster"
+ HTTPDNSClusterService_FindHTTPDNSCluster_FullMethodName = "/pb.HTTPDNSClusterService/findHTTPDNSCluster"
+ HTTPDNSClusterService_ListHTTPDNSClusters_FullMethodName = "/pb.HTTPDNSClusterService/listHTTPDNSClusters"
+ HTTPDNSClusterService_FindAllHTTPDNSClusters_FullMethodName = "/pb.HTTPDNSClusterService/findAllHTTPDNSClusters"
+ HTTPDNSClusterService_UpdateHTTPDNSClusterDefault_FullMethodName = "/pb.HTTPDNSClusterService/updateHTTPDNSClusterDefault"
+ HTTPDNSClusterService_ListHTTPDNSNodesWithClusterId_FullMethodName = "/pb.HTTPDNSClusterService/listHTTPDNSNodesWithClusterId"
+)
+
+// HTTPDNSClusterServiceClient is the client API for HTTPDNSClusterService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type HTTPDNSClusterServiceClient interface {
+ CreateHTTPDNSCluster(ctx context.Context, in *CreateHTTPDNSClusterRequest, opts ...grpc.CallOption) (*CreateHTTPDNSClusterResponse, error)
+ UpdateHTTPDNSCluster(ctx context.Context, in *UpdateHTTPDNSClusterRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ DeleteHTTPDNSCluster(ctx context.Context, in *DeleteHTTPDNSClusterRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ FindHTTPDNSCluster(ctx context.Context, in *FindHTTPDNSClusterRequest, opts ...grpc.CallOption) (*FindHTTPDNSClusterResponse, error)
+ ListHTTPDNSClusters(ctx context.Context, in *ListHTTPDNSClustersRequest, opts ...grpc.CallOption) (*ListHTTPDNSClustersResponse, error)
+ FindAllHTTPDNSClusters(ctx context.Context, in *FindAllHTTPDNSClustersRequest, opts ...grpc.CallOption) (*FindAllHTTPDNSClustersResponse, error)
+ UpdateHTTPDNSClusterDefault(ctx context.Context, in *UpdateHTTPDNSClusterDefaultRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ ListHTTPDNSNodesWithClusterId(ctx context.Context, in *ListHTTPDNSNodesWithClusterIdRequest, opts ...grpc.CallOption) (*ListHTTPDNSNodesWithClusterIdResponse, error)
+}
+
+type hTTPDNSClusterServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewHTTPDNSClusterServiceClient(cc grpc.ClientConnInterface) HTTPDNSClusterServiceClient {
+ return &hTTPDNSClusterServiceClient{cc}
+}
+
+func (c *hTTPDNSClusterServiceClient) CreateHTTPDNSCluster(ctx context.Context, in *CreateHTTPDNSClusterRequest, opts ...grpc.CallOption) (*CreateHTTPDNSClusterResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(CreateHTTPDNSClusterResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSClusterService_CreateHTTPDNSCluster_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSClusterServiceClient) UpdateHTTPDNSCluster(ctx context.Context, in *UpdateHTTPDNSClusterRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSClusterService_UpdateHTTPDNSCluster_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSClusterServiceClient) DeleteHTTPDNSCluster(ctx context.Context, in *DeleteHTTPDNSClusterRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSClusterService_DeleteHTTPDNSCluster_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSClusterServiceClient) FindHTTPDNSCluster(ctx context.Context, in *FindHTTPDNSClusterRequest, opts ...grpc.CallOption) (*FindHTTPDNSClusterResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(FindHTTPDNSClusterResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSClusterService_FindHTTPDNSCluster_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSClusterServiceClient) ListHTTPDNSClusters(ctx context.Context, in *ListHTTPDNSClustersRequest, opts ...grpc.CallOption) (*ListHTTPDNSClustersResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(ListHTTPDNSClustersResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSClusterService_ListHTTPDNSClusters_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSClusterServiceClient) FindAllHTTPDNSClusters(ctx context.Context, in *FindAllHTTPDNSClustersRequest, opts ...grpc.CallOption) (*FindAllHTTPDNSClustersResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(FindAllHTTPDNSClustersResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSClusterService_FindAllHTTPDNSClusters_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSClusterServiceClient) UpdateHTTPDNSClusterDefault(ctx context.Context, in *UpdateHTTPDNSClusterDefaultRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSClusterService_UpdateHTTPDNSClusterDefault_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSClusterServiceClient) ListHTTPDNSNodesWithClusterId(ctx context.Context, in *ListHTTPDNSNodesWithClusterIdRequest, opts ...grpc.CallOption) (*ListHTTPDNSNodesWithClusterIdResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(ListHTTPDNSNodesWithClusterIdResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSClusterService_ListHTTPDNSNodesWithClusterId_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// HTTPDNSClusterServiceServer is the server API for HTTPDNSClusterService service.
+// All implementations should embed UnimplementedHTTPDNSClusterServiceServer
+// for forward compatibility.
+type HTTPDNSClusterServiceServer interface {
+ CreateHTTPDNSCluster(context.Context, *CreateHTTPDNSClusterRequest) (*CreateHTTPDNSClusterResponse, error)
+ UpdateHTTPDNSCluster(context.Context, *UpdateHTTPDNSClusterRequest) (*RPCSuccess, error)
+ DeleteHTTPDNSCluster(context.Context, *DeleteHTTPDNSClusterRequest) (*RPCSuccess, error)
+ FindHTTPDNSCluster(context.Context, *FindHTTPDNSClusterRequest) (*FindHTTPDNSClusterResponse, error)
+ ListHTTPDNSClusters(context.Context, *ListHTTPDNSClustersRequest) (*ListHTTPDNSClustersResponse, error)
+ FindAllHTTPDNSClusters(context.Context, *FindAllHTTPDNSClustersRequest) (*FindAllHTTPDNSClustersResponse, error)
+ UpdateHTTPDNSClusterDefault(context.Context, *UpdateHTTPDNSClusterDefaultRequest) (*RPCSuccess, error)
+ ListHTTPDNSNodesWithClusterId(context.Context, *ListHTTPDNSNodesWithClusterIdRequest) (*ListHTTPDNSNodesWithClusterIdResponse, error)
+}
+
+// UnimplementedHTTPDNSClusterServiceServer should be embedded to have
+// forward compatible implementations.
+//
+// NOTE: this should be embedded by value instead of pointer to avoid a nil
+// pointer dereference when methods are called.
+type UnimplementedHTTPDNSClusterServiceServer struct{}
+
+func (UnimplementedHTTPDNSClusterServiceServer) CreateHTTPDNSCluster(context.Context, *CreateHTTPDNSClusterRequest) (*CreateHTTPDNSClusterResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method CreateHTTPDNSCluster not implemented")
+}
+func (UnimplementedHTTPDNSClusterServiceServer) UpdateHTTPDNSCluster(context.Context, *UpdateHTTPDNSClusterRequest) (*RPCSuccess, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UpdateHTTPDNSCluster not implemented")
+}
+func (UnimplementedHTTPDNSClusterServiceServer) DeleteHTTPDNSCluster(context.Context, *DeleteHTTPDNSClusterRequest) (*RPCSuccess, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method DeleteHTTPDNSCluster not implemented")
+}
+func (UnimplementedHTTPDNSClusterServiceServer) FindHTTPDNSCluster(context.Context, *FindHTTPDNSClusterRequest) (*FindHTTPDNSClusterResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method FindHTTPDNSCluster not implemented")
+}
+func (UnimplementedHTTPDNSClusterServiceServer) ListHTTPDNSClusters(context.Context, *ListHTTPDNSClustersRequest) (*ListHTTPDNSClustersResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method ListHTTPDNSClusters not implemented")
+}
+func (UnimplementedHTTPDNSClusterServiceServer) FindAllHTTPDNSClusters(context.Context, *FindAllHTTPDNSClustersRequest) (*FindAllHTTPDNSClustersResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method FindAllHTTPDNSClusters not implemented")
+}
+func (UnimplementedHTTPDNSClusterServiceServer) UpdateHTTPDNSClusterDefault(context.Context, *UpdateHTTPDNSClusterDefaultRequest) (*RPCSuccess, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UpdateHTTPDNSClusterDefault not implemented")
+}
+func (UnimplementedHTTPDNSClusterServiceServer) ListHTTPDNSNodesWithClusterId(context.Context, *ListHTTPDNSNodesWithClusterIdRequest) (*ListHTTPDNSNodesWithClusterIdResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method ListHTTPDNSNodesWithClusterId not implemented")
+}
+func (UnimplementedHTTPDNSClusterServiceServer) testEmbeddedByValue() {}
+
+// UnsafeHTTPDNSClusterServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to HTTPDNSClusterServiceServer will
+// result in compilation errors.
+type UnsafeHTTPDNSClusterServiceServer interface {
+ mustEmbedUnimplementedHTTPDNSClusterServiceServer()
+}
+
+func RegisterHTTPDNSClusterServiceServer(s grpc.ServiceRegistrar, srv HTTPDNSClusterServiceServer) {
+ // If the following call pancis, it indicates UnimplementedHTTPDNSClusterServiceServer was
+ // embedded by pointer and is nil. This will cause panics if an
+ // unimplemented method is ever invoked, so we test this at initialization
+ // time to prevent it from happening at runtime later due to I/O.
+ if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
+ t.testEmbeddedByValue()
+ }
+ s.RegisterService(&HTTPDNSClusterService_ServiceDesc, srv)
+}
+
+func _HTTPDNSClusterService_CreateHTTPDNSCluster_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CreateHTTPDNSClusterRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSClusterServiceServer).CreateHTTPDNSCluster(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSClusterService_CreateHTTPDNSCluster_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSClusterServiceServer).CreateHTTPDNSCluster(ctx, req.(*CreateHTTPDNSClusterRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSClusterService_UpdateHTTPDNSCluster_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpdateHTTPDNSClusterRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSClusterServiceServer).UpdateHTTPDNSCluster(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSClusterService_UpdateHTTPDNSCluster_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSClusterServiceServer).UpdateHTTPDNSCluster(ctx, req.(*UpdateHTTPDNSClusterRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSClusterService_DeleteHTTPDNSCluster_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(DeleteHTTPDNSClusterRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSClusterServiceServer).DeleteHTTPDNSCluster(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSClusterService_DeleteHTTPDNSCluster_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSClusterServiceServer).DeleteHTTPDNSCluster(ctx, req.(*DeleteHTTPDNSClusterRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSClusterService_FindHTTPDNSCluster_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(FindHTTPDNSClusterRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSClusterServiceServer).FindHTTPDNSCluster(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSClusterService_FindHTTPDNSCluster_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSClusterServiceServer).FindHTTPDNSCluster(ctx, req.(*FindHTTPDNSClusterRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSClusterService_ListHTTPDNSClusters_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ListHTTPDNSClustersRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSClusterServiceServer).ListHTTPDNSClusters(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSClusterService_ListHTTPDNSClusters_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSClusterServiceServer).ListHTTPDNSClusters(ctx, req.(*ListHTTPDNSClustersRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSClusterService_FindAllHTTPDNSClusters_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(FindAllHTTPDNSClustersRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSClusterServiceServer).FindAllHTTPDNSClusters(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSClusterService_FindAllHTTPDNSClusters_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSClusterServiceServer).FindAllHTTPDNSClusters(ctx, req.(*FindAllHTTPDNSClustersRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSClusterService_UpdateHTTPDNSClusterDefault_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpdateHTTPDNSClusterDefaultRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSClusterServiceServer).UpdateHTTPDNSClusterDefault(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSClusterService_UpdateHTTPDNSClusterDefault_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSClusterServiceServer).UpdateHTTPDNSClusterDefault(ctx, req.(*UpdateHTTPDNSClusterDefaultRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSClusterService_ListHTTPDNSNodesWithClusterId_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ListHTTPDNSNodesWithClusterIdRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSClusterServiceServer).ListHTTPDNSNodesWithClusterId(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSClusterService_ListHTTPDNSNodesWithClusterId_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSClusterServiceServer).ListHTTPDNSNodesWithClusterId(ctx, req.(*ListHTTPDNSNodesWithClusterIdRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// HTTPDNSClusterService_ServiceDesc is the grpc.ServiceDesc for HTTPDNSClusterService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var HTTPDNSClusterService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "pb.HTTPDNSClusterService",
+ HandlerType: (*HTTPDNSClusterServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "createHTTPDNSCluster",
+ Handler: _HTTPDNSClusterService_CreateHTTPDNSCluster_Handler,
+ },
+ {
+ MethodName: "updateHTTPDNSCluster",
+ Handler: _HTTPDNSClusterService_UpdateHTTPDNSCluster_Handler,
+ },
+ {
+ MethodName: "deleteHTTPDNSCluster",
+ Handler: _HTTPDNSClusterService_DeleteHTTPDNSCluster_Handler,
+ },
+ {
+ MethodName: "findHTTPDNSCluster",
+ Handler: _HTTPDNSClusterService_FindHTTPDNSCluster_Handler,
+ },
+ {
+ MethodName: "listHTTPDNSClusters",
+ Handler: _HTTPDNSClusterService_ListHTTPDNSClusters_Handler,
+ },
+ {
+ MethodName: "findAllHTTPDNSClusters",
+ Handler: _HTTPDNSClusterService_FindAllHTTPDNSClusters_Handler,
+ },
+ {
+ MethodName: "updateHTTPDNSClusterDefault",
+ Handler: _HTTPDNSClusterService_UpdateHTTPDNSClusterDefault_Handler,
+ },
+ {
+ MethodName: "listHTTPDNSNodesWithClusterId",
+ Handler: _HTTPDNSClusterService_ListHTTPDNSNodesWithClusterId_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "service_httpdns_cluster.proto",
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_domain.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_domain.pb.go
new file mode 100644
index 0000000..3adb6ae
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_domain.pb.go
@@ -0,0 +1,456 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.35.1
+// protoc v3.21.12
+// source: service_httpdns_domain.proto
+
+package pb
+
+import (
+ 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 CreateHTTPDNSDomainRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ AppDbId int64 `protobuf:"varint,1,opt,name=appDbId,proto3" json:"appDbId,omitempty"`
+ Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
+ IsOn bool `protobuf:"varint,3,opt,name=isOn,proto3" json:"isOn,omitempty"`
+}
+
+func (x *CreateHTTPDNSDomainRequest) Reset() {
+ *x = CreateHTTPDNSDomainRequest{}
+ mi := &file_service_httpdns_domain_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSDomainRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSDomainRequest) ProtoMessage() {}
+
+func (x *CreateHTTPDNSDomainRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_domain_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSDomainRequest.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSDomainRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_domain_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CreateHTTPDNSDomainRequest) GetAppDbId() int64 {
+ if x != nil {
+ return x.AppDbId
+ }
+ return 0
+}
+
+func (x *CreateHTTPDNSDomainRequest) GetDomain() string {
+ if x != nil {
+ return x.Domain
+ }
+ return ""
+}
+
+func (x *CreateHTTPDNSDomainRequest) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+type CreateHTTPDNSDomainResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ DomainId int64 `protobuf:"varint,1,opt,name=domainId,proto3" json:"domainId,omitempty"`
+}
+
+func (x *CreateHTTPDNSDomainResponse) Reset() {
+ *x = CreateHTTPDNSDomainResponse{}
+ mi := &file_service_httpdns_domain_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSDomainResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSDomainResponse) ProtoMessage() {}
+
+func (x *CreateHTTPDNSDomainResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_domain_proto_msgTypes[1]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSDomainResponse.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSDomainResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_domain_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *CreateHTTPDNSDomainResponse) GetDomainId() int64 {
+ if x != nil {
+ return x.DomainId
+ }
+ return 0
+}
+
+type DeleteHTTPDNSDomainRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ DomainId int64 `protobuf:"varint,1,opt,name=domainId,proto3" json:"domainId,omitempty"`
+}
+
+func (x *DeleteHTTPDNSDomainRequest) Reset() {
+ *x = DeleteHTTPDNSDomainRequest{}
+ mi := &file_service_httpdns_domain_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *DeleteHTTPDNSDomainRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DeleteHTTPDNSDomainRequest) ProtoMessage() {}
+
+func (x *DeleteHTTPDNSDomainRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_domain_proto_msgTypes[2]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use DeleteHTTPDNSDomainRequest.ProtoReflect.Descriptor instead.
+func (*DeleteHTTPDNSDomainRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_domain_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *DeleteHTTPDNSDomainRequest) GetDomainId() int64 {
+ if x != nil {
+ return x.DomainId
+ }
+ return 0
+}
+
+type UpdateHTTPDNSDomainStatusRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ DomainId int64 `protobuf:"varint,1,opt,name=domainId,proto3" json:"domainId,omitempty"`
+ IsOn bool `protobuf:"varint,2,opt,name=isOn,proto3" json:"isOn,omitempty"`
+}
+
+func (x *UpdateHTTPDNSDomainStatusRequest) Reset() {
+ *x = UpdateHTTPDNSDomainStatusRequest{}
+ mi := &file_service_httpdns_domain_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *UpdateHTTPDNSDomainStatusRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateHTTPDNSDomainStatusRequest) ProtoMessage() {}
+
+func (x *UpdateHTTPDNSDomainStatusRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_domain_proto_msgTypes[3]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateHTTPDNSDomainStatusRequest.ProtoReflect.Descriptor instead.
+func (*UpdateHTTPDNSDomainStatusRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_domain_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *UpdateHTTPDNSDomainStatusRequest) GetDomainId() int64 {
+ if x != nil {
+ return x.DomainId
+ }
+ return 0
+}
+
+func (x *UpdateHTTPDNSDomainStatusRequest) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+type ListHTTPDNSDomainsWithAppIdRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ AppDbId int64 `protobuf:"varint,1,opt,name=appDbId,proto3" json:"appDbId,omitempty"`
+ Keyword string `protobuf:"bytes,2,opt,name=keyword,proto3" json:"keyword,omitempty"`
+}
+
+func (x *ListHTTPDNSDomainsWithAppIdRequest) Reset() {
+ *x = ListHTTPDNSDomainsWithAppIdRequest{}
+ mi := &file_service_httpdns_domain_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSDomainsWithAppIdRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSDomainsWithAppIdRequest) ProtoMessage() {}
+
+func (x *ListHTTPDNSDomainsWithAppIdRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_domain_proto_msgTypes[4]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSDomainsWithAppIdRequest.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSDomainsWithAppIdRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_domain_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *ListHTTPDNSDomainsWithAppIdRequest) GetAppDbId() int64 {
+ if x != nil {
+ return x.AppDbId
+ }
+ return 0
+}
+
+func (x *ListHTTPDNSDomainsWithAppIdRequest) GetKeyword() string {
+ if x != nil {
+ return x.Keyword
+ }
+ return ""
+}
+
+type ListHTTPDNSDomainsWithAppIdResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Domains []*HTTPDNSDomain `protobuf:"bytes,1,rep,name=domains,proto3" json:"domains,omitempty"`
+}
+
+func (x *ListHTTPDNSDomainsWithAppIdResponse) Reset() {
+ *x = ListHTTPDNSDomainsWithAppIdResponse{}
+ mi := &file_service_httpdns_domain_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSDomainsWithAppIdResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSDomainsWithAppIdResponse) ProtoMessage() {}
+
+func (x *ListHTTPDNSDomainsWithAppIdResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_domain_proto_msgTypes[5]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSDomainsWithAppIdResponse.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSDomainsWithAppIdResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_domain_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *ListHTTPDNSDomainsWithAppIdResponse) GetDomains() []*HTTPDNSDomain {
+ if x != nil {
+ return x.Domains
+ }
+ return nil
+}
+
+var File_service_httpdns_domain_proto protoreflect.FileDescriptor
+
+var file_service_httpdns_domain_proto_rawDesc = []byte{
+ 0x0a, 0x1c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x64, 0x6e,
+ 0x73, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02,
+ 0x70, 0x62, 0x1a, 0x21, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
+ 0x5f, 0x68, 0x74, 0x74, 0x70, 0x64, 0x6e, 0x73, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x72, 0x70,
+ 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x22, 0x62, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e,
+ 0x53, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18,
+ 0x0a, 0x07, 0x61, 0x70, 0x70, 0x44, 0x62, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x07, 0x61, 0x70, 0x70, 0x44, 0x62, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61,
+ 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
+ 0x12, 0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04,
+ 0x69, 0x73, 0x4f, 0x6e, 0x22, 0x39, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54,
+ 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22,
+ 0x38, 0x0a, 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53,
+ 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a,
+ 0x08, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x08, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x52, 0x0a, 0x20, 0x55, 0x70, 0x64,
+ 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
+ 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a,
+ 0x08, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x08, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f,
+ 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x22, 0x58, 0x0a,
+ 0x22, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61,
+ 0x69, 0x6e, 0x73, 0x57, 0x69, 0x74, 0x68, 0x41, 0x70, 0x70, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x44, 0x62, 0x49, 0x64, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x61, 0x70, 0x70, 0x44, 0x62, 0x49, 0x64, 0x12, 0x18, 0x0a,
+ 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
+ 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x52, 0x0a, 0x23, 0x4c, 0x69, 0x73, 0x74, 0x48,
+ 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x57, 0x69, 0x74,
+ 0x68, 0x41, 0x70, 0x70, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b,
+ 0x0a, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61,
+ 0x69, 0x6e, 0x52, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x32, 0xf8, 0x02, 0x0a, 0x14,
+ 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x72,
+ 0x76, 0x69, 0x63, 0x65, 0x12, 0x56, 0x0a, 0x13, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54,
+ 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x1e, 0x2e, 0x70, 0x62,
+ 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f,
+ 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x62,
+ 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f,
+ 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x13,
+ 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x12, 0x1e, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48,
+ 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63,
+ 0x65, 0x73, 0x73, 0x12, 0x51, 0x0a, 0x19, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54,
+ 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
+ 0x12, 0x24, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50,
+ 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53,
+ 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x6e, 0x0a, 0x1b, 0x6c, 0x69, 0x73, 0x74, 0x48, 0x54,
+ 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x57, 0x69, 0x74, 0x68,
+ 0x41, 0x70, 0x70, 0x49, 0x64, 0x12, 0x26, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48,
+ 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x57, 0x69, 0x74,
+ 0x68, 0x41, 0x70, 0x70, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e,
+ 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x44, 0x6f,
+ 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x57, 0x69, 0x74, 0x68, 0x41, 0x70, 0x70, 0x49, 0x64, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_service_httpdns_domain_proto_rawDescOnce sync.Once
+ file_service_httpdns_domain_proto_rawDescData = file_service_httpdns_domain_proto_rawDesc
+)
+
+func file_service_httpdns_domain_proto_rawDescGZIP() []byte {
+ file_service_httpdns_domain_proto_rawDescOnce.Do(func() {
+ file_service_httpdns_domain_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_httpdns_domain_proto_rawDescData)
+ })
+ return file_service_httpdns_domain_proto_rawDescData
+}
+
+var file_service_httpdns_domain_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
+var file_service_httpdns_domain_proto_goTypes = []any{
+ (*CreateHTTPDNSDomainRequest)(nil), // 0: pb.CreateHTTPDNSDomainRequest
+ (*CreateHTTPDNSDomainResponse)(nil), // 1: pb.CreateHTTPDNSDomainResponse
+ (*DeleteHTTPDNSDomainRequest)(nil), // 2: pb.DeleteHTTPDNSDomainRequest
+ (*UpdateHTTPDNSDomainStatusRequest)(nil), // 3: pb.UpdateHTTPDNSDomainStatusRequest
+ (*ListHTTPDNSDomainsWithAppIdRequest)(nil), // 4: pb.ListHTTPDNSDomainsWithAppIdRequest
+ (*ListHTTPDNSDomainsWithAppIdResponse)(nil), // 5: pb.ListHTTPDNSDomainsWithAppIdResponse
+ (*HTTPDNSDomain)(nil), // 6: pb.HTTPDNSDomain
+ (*RPCSuccess)(nil), // 7: pb.RPCSuccess
+}
+var file_service_httpdns_domain_proto_depIdxs = []int32{
+ 6, // 0: pb.ListHTTPDNSDomainsWithAppIdResponse.domains:type_name -> pb.HTTPDNSDomain
+ 0, // 1: pb.HTTPDNSDomainService.createHTTPDNSDomain:input_type -> pb.CreateHTTPDNSDomainRequest
+ 2, // 2: pb.HTTPDNSDomainService.deleteHTTPDNSDomain:input_type -> pb.DeleteHTTPDNSDomainRequest
+ 3, // 3: pb.HTTPDNSDomainService.updateHTTPDNSDomainStatus:input_type -> pb.UpdateHTTPDNSDomainStatusRequest
+ 4, // 4: pb.HTTPDNSDomainService.listHTTPDNSDomainsWithAppId:input_type -> pb.ListHTTPDNSDomainsWithAppIdRequest
+ 1, // 5: pb.HTTPDNSDomainService.createHTTPDNSDomain:output_type -> pb.CreateHTTPDNSDomainResponse
+ 7, // 6: pb.HTTPDNSDomainService.deleteHTTPDNSDomain:output_type -> pb.RPCSuccess
+ 7, // 7: pb.HTTPDNSDomainService.updateHTTPDNSDomainStatus:output_type -> pb.RPCSuccess
+ 5, // 8: pb.HTTPDNSDomainService.listHTTPDNSDomainsWithAppId:output_type -> pb.ListHTTPDNSDomainsWithAppIdResponse
+ 5, // [5:9] is the sub-list for method output_type
+ 1, // [1:5] 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_service_httpdns_domain_proto_init() }
+func file_service_httpdns_domain_proto_init() {
+ if File_service_httpdns_domain_proto != nil {
+ return
+ }
+ file_models_model_httpdns_domain_proto_init()
+ file_models_rpc_messages_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_service_httpdns_domain_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 6,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_service_httpdns_domain_proto_goTypes,
+ DependencyIndexes: file_service_httpdns_domain_proto_depIdxs,
+ MessageInfos: file_service_httpdns_domain_proto_msgTypes,
+ }.Build()
+ File_service_httpdns_domain_proto = out.File
+ file_service_httpdns_domain_proto_rawDesc = nil
+ file_service_httpdns_domain_proto_goTypes = nil
+ file_service_httpdns_domain_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_domain_grpc.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_domain_grpc.pb.go
new file mode 100644
index 0000000..d04f113
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_domain_grpc.pb.go
@@ -0,0 +1,233 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.5.1
+// - protoc v3.21.12
+// source: service_httpdns_domain.proto
+
+package pb
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.64.0 or later.
+const _ = grpc.SupportPackageIsVersion9
+
+const (
+ HTTPDNSDomainService_CreateHTTPDNSDomain_FullMethodName = "/pb.HTTPDNSDomainService/createHTTPDNSDomain"
+ HTTPDNSDomainService_DeleteHTTPDNSDomain_FullMethodName = "/pb.HTTPDNSDomainService/deleteHTTPDNSDomain"
+ HTTPDNSDomainService_UpdateHTTPDNSDomainStatus_FullMethodName = "/pb.HTTPDNSDomainService/updateHTTPDNSDomainStatus"
+ HTTPDNSDomainService_ListHTTPDNSDomainsWithAppId_FullMethodName = "/pb.HTTPDNSDomainService/listHTTPDNSDomainsWithAppId"
+)
+
+// HTTPDNSDomainServiceClient is the client API for HTTPDNSDomainService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type HTTPDNSDomainServiceClient interface {
+ CreateHTTPDNSDomain(ctx context.Context, in *CreateHTTPDNSDomainRequest, opts ...grpc.CallOption) (*CreateHTTPDNSDomainResponse, error)
+ DeleteHTTPDNSDomain(ctx context.Context, in *DeleteHTTPDNSDomainRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ UpdateHTTPDNSDomainStatus(ctx context.Context, in *UpdateHTTPDNSDomainStatusRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ ListHTTPDNSDomainsWithAppId(ctx context.Context, in *ListHTTPDNSDomainsWithAppIdRequest, opts ...grpc.CallOption) (*ListHTTPDNSDomainsWithAppIdResponse, error)
+}
+
+type hTTPDNSDomainServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewHTTPDNSDomainServiceClient(cc grpc.ClientConnInterface) HTTPDNSDomainServiceClient {
+ return &hTTPDNSDomainServiceClient{cc}
+}
+
+func (c *hTTPDNSDomainServiceClient) CreateHTTPDNSDomain(ctx context.Context, in *CreateHTTPDNSDomainRequest, opts ...grpc.CallOption) (*CreateHTTPDNSDomainResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(CreateHTTPDNSDomainResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSDomainService_CreateHTTPDNSDomain_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSDomainServiceClient) DeleteHTTPDNSDomain(ctx context.Context, in *DeleteHTTPDNSDomainRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSDomainService_DeleteHTTPDNSDomain_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSDomainServiceClient) UpdateHTTPDNSDomainStatus(ctx context.Context, in *UpdateHTTPDNSDomainStatusRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSDomainService_UpdateHTTPDNSDomainStatus_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSDomainServiceClient) ListHTTPDNSDomainsWithAppId(ctx context.Context, in *ListHTTPDNSDomainsWithAppIdRequest, opts ...grpc.CallOption) (*ListHTTPDNSDomainsWithAppIdResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(ListHTTPDNSDomainsWithAppIdResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSDomainService_ListHTTPDNSDomainsWithAppId_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// HTTPDNSDomainServiceServer is the server API for HTTPDNSDomainService service.
+// All implementations should embed UnimplementedHTTPDNSDomainServiceServer
+// for forward compatibility.
+type HTTPDNSDomainServiceServer interface {
+ CreateHTTPDNSDomain(context.Context, *CreateHTTPDNSDomainRequest) (*CreateHTTPDNSDomainResponse, error)
+ DeleteHTTPDNSDomain(context.Context, *DeleteHTTPDNSDomainRequest) (*RPCSuccess, error)
+ UpdateHTTPDNSDomainStatus(context.Context, *UpdateHTTPDNSDomainStatusRequest) (*RPCSuccess, error)
+ ListHTTPDNSDomainsWithAppId(context.Context, *ListHTTPDNSDomainsWithAppIdRequest) (*ListHTTPDNSDomainsWithAppIdResponse, error)
+}
+
+// UnimplementedHTTPDNSDomainServiceServer should be embedded to have
+// forward compatible implementations.
+//
+// NOTE: this should be embedded by value instead of pointer to avoid a nil
+// pointer dereference when methods are called.
+type UnimplementedHTTPDNSDomainServiceServer struct{}
+
+func (UnimplementedHTTPDNSDomainServiceServer) CreateHTTPDNSDomain(context.Context, *CreateHTTPDNSDomainRequest) (*CreateHTTPDNSDomainResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method CreateHTTPDNSDomain not implemented")
+}
+func (UnimplementedHTTPDNSDomainServiceServer) DeleteHTTPDNSDomain(context.Context, *DeleteHTTPDNSDomainRequest) (*RPCSuccess, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method DeleteHTTPDNSDomain not implemented")
+}
+func (UnimplementedHTTPDNSDomainServiceServer) UpdateHTTPDNSDomainStatus(context.Context, *UpdateHTTPDNSDomainStatusRequest) (*RPCSuccess, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UpdateHTTPDNSDomainStatus not implemented")
+}
+func (UnimplementedHTTPDNSDomainServiceServer) ListHTTPDNSDomainsWithAppId(context.Context, *ListHTTPDNSDomainsWithAppIdRequest) (*ListHTTPDNSDomainsWithAppIdResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method ListHTTPDNSDomainsWithAppId not implemented")
+}
+func (UnimplementedHTTPDNSDomainServiceServer) testEmbeddedByValue() {}
+
+// UnsafeHTTPDNSDomainServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to HTTPDNSDomainServiceServer will
+// result in compilation errors.
+type UnsafeHTTPDNSDomainServiceServer interface {
+ mustEmbedUnimplementedHTTPDNSDomainServiceServer()
+}
+
+func RegisterHTTPDNSDomainServiceServer(s grpc.ServiceRegistrar, srv HTTPDNSDomainServiceServer) {
+ // If the following call pancis, it indicates UnimplementedHTTPDNSDomainServiceServer was
+ // embedded by pointer and is nil. This will cause panics if an
+ // unimplemented method is ever invoked, so we test this at initialization
+ // time to prevent it from happening at runtime later due to I/O.
+ if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
+ t.testEmbeddedByValue()
+ }
+ s.RegisterService(&HTTPDNSDomainService_ServiceDesc, srv)
+}
+
+func _HTTPDNSDomainService_CreateHTTPDNSDomain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CreateHTTPDNSDomainRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSDomainServiceServer).CreateHTTPDNSDomain(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSDomainService_CreateHTTPDNSDomain_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSDomainServiceServer).CreateHTTPDNSDomain(ctx, req.(*CreateHTTPDNSDomainRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSDomainService_DeleteHTTPDNSDomain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(DeleteHTTPDNSDomainRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSDomainServiceServer).DeleteHTTPDNSDomain(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSDomainService_DeleteHTTPDNSDomain_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSDomainServiceServer).DeleteHTTPDNSDomain(ctx, req.(*DeleteHTTPDNSDomainRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSDomainService_UpdateHTTPDNSDomainStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpdateHTTPDNSDomainStatusRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSDomainServiceServer).UpdateHTTPDNSDomainStatus(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSDomainService_UpdateHTTPDNSDomainStatus_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSDomainServiceServer).UpdateHTTPDNSDomainStatus(ctx, req.(*UpdateHTTPDNSDomainStatusRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSDomainService_ListHTTPDNSDomainsWithAppId_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ListHTTPDNSDomainsWithAppIdRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSDomainServiceServer).ListHTTPDNSDomainsWithAppId(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSDomainService_ListHTTPDNSDomainsWithAppId_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSDomainServiceServer).ListHTTPDNSDomainsWithAppId(ctx, req.(*ListHTTPDNSDomainsWithAppIdRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// HTTPDNSDomainService_ServiceDesc is the grpc.ServiceDesc for HTTPDNSDomainService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var HTTPDNSDomainService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "pb.HTTPDNSDomainService",
+ HandlerType: (*HTTPDNSDomainServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "createHTTPDNSDomain",
+ Handler: _HTTPDNSDomainService_CreateHTTPDNSDomain_Handler,
+ },
+ {
+ MethodName: "deleteHTTPDNSDomain",
+ Handler: _HTTPDNSDomainService_DeleteHTTPDNSDomain_Handler,
+ },
+ {
+ MethodName: "updateHTTPDNSDomainStatus",
+ Handler: _HTTPDNSDomainService_UpdateHTTPDNSDomainStatus_Handler,
+ },
+ {
+ MethodName: "listHTTPDNSDomainsWithAppId",
+ Handler: _HTTPDNSDomainService_ListHTTPDNSDomainsWithAppId_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "service_httpdns_domain.proto",
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_node.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_node.pb.go
new file mode 100644
index 0000000..9e684be
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_node.pb.go
@@ -0,0 +1,970 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.36.11
+// protoc v3.21.12
+// source: service_httpdns_node.proto
+
+package pb
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+ unsafe "unsafe"
+)
+
+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 CreateHTTPDNSNodeRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+ Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+ InstallDir string `protobuf:"bytes,3,opt,name=installDir,proto3" json:"installDir,omitempty"`
+ IsOn bool `protobuf:"varint,4,opt,name=isOn,proto3" json:"isOn,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *CreateHTTPDNSNodeRequest) Reset() {
+ *x = CreateHTTPDNSNodeRequest{}
+ mi := &file_service_httpdns_node_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSNodeRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSNodeRequest) ProtoMessage() {}
+
+func (x *CreateHTTPDNSNodeRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSNodeRequest.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSNodeRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CreateHTTPDNSNodeRequest) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+func (x *CreateHTTPDNSNodeRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *CreateHTTPDNSNodeRequest) GetInstallDir() string {
+ if x != nil {
+ return x.InstallDir
+ }
+ return ""
+}
+
+func (x *CreateHTTPDNSNodeRequest) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+type CreateHTTPDNSNodeResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *CreateHTTPDNSNodeResponse) Reset() {
+ *x = CreateHTTPDNSNodeResponse{}
+ mi := &file_service_httpdns_node_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSNodeResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSNodeResponse) ProtoMessage() {}
+
+func (x *CreateHTTPDNSNodeResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[1]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSNodeResponse.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSNodeResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *CreateHTTPDNSNodeResponse) GetNodeId() int64 {
+ if x != nil {
+ return x.NodeId
+ }
+ return 0
+}
+
+type UpdateHTTPDNSNodeRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"`
+ Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+ InstallDir string `protobuf:"bytes,3,opt,name=installDir,proto3" json:"installDir,omitempty"`
+ IsOn bool `protobuf:"varint,4,opt,name=isOn,proto3" json:"isOn,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *UpdateHTTPDNSNodeRequest) Reset() {
+ *x = UpdateHTTPDNSNodeRequest{}
+ mi := &file_service_httpdns_node_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *UpdateHTTPDNSNodeRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateHTTPDNSNodeRequest) ProtoMessage() {}
+
+func (x *UpdateHTTPDNSNodeRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[2]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateHTTPDNSNodeRequest.ProtoReflect.Descriptor instead.
+func (*UpdateHTTPDNSNodeRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *UpdateHTTPDNSNodeRequest) GetNodeId() int64 {
+ if x != nil {
+ return x.NodeId
+ }
+ return 0
+}
+
+func (x *UpdateHTTPDNSNodeRequest) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *UpdateHTTPDNSNodeRequest) GetInstallDir() string {
+ if x != nil {
+ return x.InstallDir
+ }
+ return ""
+}
+
+func (x *UpdateHTTPDNSNodeRequest) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+type DeleteHTTPDNSNodeRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *DeleteHTTPDNSNodeRequest) Reset() {
+ *x = DeleteHTTPDNSNodeRequest{}
+ mi := &file_service_httpdns_node_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *DeleteHTTPDNSNodeRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DeleteHTTPDNSNodeRequest) ProtoMessage() {}
+
+func (x *DeleteHTTPDNSNodeRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[3]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use DeleteHTTPDNSNodeRequest.ProtoReflect.Descriptor instead.
+func (*DeleteHTTPDNSNodeRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *DeleteHTTPDNSNodeRequest) GetNodeId() int64 {
+ if x != nil {
+ return x.NodeId
+ }
+ return 0
+}
+
+type FindHTTPDNSNodeRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *FindHTTPDNSNodeRequest) Reset() {
+ *x = FindHTTPDNSNodeRequest{}
+ mi := &file_service_httpdns_node_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *FindHTTPDNSNodeRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FindHTTPDNSNodeRequest) ProtoMessage() {}
+
+func (x *FindHTTPDNSNodeRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[4]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FindHTTPDNSNodeRequest.ProtoReflect.Descriptor instead.
+func (*FindHTTPDNSNodeRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *FindHTTPDNSNodeRequest) GetNodeId() int64 {
+ if x != nil {
+ return x.NodeId
+ }
+ return 0
+}
+
+type FindHTTPDNSNodeResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Node *HTTPDNSNode `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *FindHTTPDNSNodeResponse) Reset() {
+ *x = FindHTTPDNSNodeResponse{}
+ mi := &file_service_httpdns_node_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *FindHTTPDNSNodeResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FindHTTPDNSNodeResponse) ProtoMessage() {}
+
+func (x *FindHTTPDNSNodeResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[5]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FindHTTPDNSNodeResponse.ProtoReflect.Descriptor instead.
+func (*FindHTTPDNSNodeResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *FindHTTPDNSNodeResponse) GetNode() *HTTPDNSNode {
+ if x != nil {
+ return x.Node
+ }
+ return nil
+}
+
+type ListHTTPDNSNodesRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *ListHTTPDNSNodesRequest) Reset() {
+ *x = ListHTTPDNSNodesRequest{}
+ mi := &file_service_httpdns_node_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSNodesRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSNodesRequest) ProtoMessage() {}
+
+func (x *ListHTTPDNSNodesRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[6]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSNodesRequest.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSNodesRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *ListHTTPDNSNodesRequest) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+type ListHTTPDNSNodesResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Nodes []*HTTPDNSNode `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *ListHTTPDNSNodesResponse) Reset() {
+ *x = ListHTTPDNSNodesResponse{}
+ mi := &file_service_httpdns_node_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSNodesResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSNodesResponse) ProtoMessage() {}
+
+func (x *ListHTTPDNSNodesResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[7]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSNodesResponse.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSNodesResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *ListHTTPDNSNodesResponse) GetNodes() []*HTTPDNSNode {
+ if x != nil {
+ return x.Nodes
+ }
+ return nil
+}
+
+type UpdateHTTPDNSNodeStatusRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"`
+ IsUp bool `protobuf:"varint,2,opt,name=isUp,proto3" json:"isUp,omitempty"`
+ IsInstalled bool `protobuf:"varint,3,opt,name=isInstalled,proto3" json:"isInstalled,omitempty"`
+ IsActive bool `protobuf:"varint,4,opt,name=isActive,proto3" json:"isActive,omitempty"`
+ StatusJSON []byte `protobuf:"bytes,5,opt,name=statusJSON,proto3" json:"statusJSON,omitempty"`
+ InstallStatusJSON []byte `protobuf:"bytes,6,opt,name=installStatusJSON,proto3" json:"installStatusJSON,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *UpdateHTTPDNSNodeStatusRequest) Reset() {
+ *x = UpdateHTTPDNSNodeStatusRequest{}
+ mi := &file_service_httpdns_node_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *UpdateHTTPDNSNodeStatusRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateHTTPDNSNodeStatusRequest) ProtoMessage() {}
+
+func (x *UpdateHTTPDNSNodeStatusRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[8]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateHTTPDNSNodeStatusRequest.ProtoReflect.Descriptor instead.
+func (*UpdateHTTPDNSNodeStatusRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *UpdateHTTPDNSNodeStatusRequest) GetNodeId() int64 {
+ if x != nil {
+ return x.NodeId
+ }
+ return 0
+}
+
+func (x *UpdateHTTPDNSNodeStatusRequest) GetIsUp() bool {
+ if x != nil {
+ return x.IsUp
+ }
+ return false
+}
+
+func (x *UpdateHTTPDNSNodeStatusRequest) GetIsInstalled() bool {
+ if x != nil {
+ return x.IsInstalled
+ }
+ return false
+}
+
+func (x *UpdateHTTPDNSNodeStatusRequest) GetIsActive() bool {
+ if x != nil {
+ return x.IsActive
+ }
+ return false
+}
+
+func (x *UpdateHTTPDNSNodeStatusRequest) GetStatusJSON() []byte {
+ if x != nil {
+ return x.StatusJSON
+ }
+ return nil
+}
+
+func (x *UpdateHTTPDNSNodeStatusRequest) GetInstallStatusJSON() []byte {
+ if x != nil {
+ return x.InstallStatusJSON
+ }
+ return nil
+}
+
+// 修改HTTPDNS节点登录信息
+type UpdateHTTPDNSNodeLoginRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"`
+ NodeLogin *NodeLogin `protobuf:"bytes,2,opt,name=nodeLogin,proto3" json:"nodeLogin,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *UpdateHTTPDNSNodeLoginRequest) Reset() {
+ *x = UpdateHTTPDNSNodeLoginRequest{}
+ mi := &file_service_httpdns_node_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *UpdateHTTPDNSNodeLoginRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateHTTPDNSNodeLoginRequest) ProtoMessage() {}
+
+func (x *UpdateHTTPDNSNodeLoginRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[9]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateHTTPDNSNodeLoginRequest.ProtoReflect.Descriptor instead.
+func (*UpdateHTTPDNSNodeLoginRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *UpdateHTTPDNSNodeLoginRequest) GetNodeId() int64 {
+ if x != nil {
+ return x.NodeId
+ }
+ return 0
+}
+
+func (x *UpdateHTTPDNSNodeLoginRequest) GetNodeLogin() *NodeLogin {
+ if x != nil {
+ return x.NodeLogin
+ }
+ return nil
+}
+
+// 检查HTTPDNS节点新版本
+type CheckHTTPDNSNodeLatestVersionRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Os string `protobuf:"bytes,1,opt,name=os,proto3" json:"os,omitempty"`
+ Arch string `protobuf:"bytes,2,opt,name=arch,proto3" json:"arch,omitempty"`
+ CurrentVersion string `protobuf:"bytes,3,opt,name=currentVersion,proto3" json:"currentVersion,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *CheckHTTPDNSNodeLatestVersionRequest) Reset() {
+ *x = CheckHTTPDNSNodeLatestVersionRequest{}
+ mi := &file_service_httpdns_node_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CheckHTTPDNSNodeLatestVersionRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CheckHTTPDNSNodeLatestVersionRequest) ProtoMessage() {}
+
+func (x *CheckHTTPDNSNodeLatestVersionRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[10]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CheckHTTPDNSNodeLatestVersionRequest.ProtoReflect.Descriptor instead.
+func (*CheckHTTPDNSNodeLatestVersionRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *CheckHTTPDNSNodeLatestVersionRequest) GetOs() string {
+ if x != nil {
+ return x.Os
+ }
+ return ""
+}
+
+func (x *CheckHTTPDNSNodeLatestVersionRequest) GetArch() string {
+ if x != nil {
+ return x.Arch
+ }
+ return ""
+}
+
+func (x *CheckHTTPDNSNodeLatestVersionRequest) GetCurrentVersion() string {
+ if x != nil {
+ return x.CurrentVersion
+ }
+ return ""
+}
+
+type CheckHTTPDNSNodeLatestVersionResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ HasNewVersion bool `protobuf:"varint,1,opt,name=hasNewVersion,proto3" json:"hasNewVersion,omitempty"`
+ NewVersion string `protobuf:"bytes,2,opt,name=newVersion,proto3" json:"newVersion,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *CheckHTTPDNSNodeLatestVersionResponse) Reset() {
+ *x = CheckHTTPDNSNodeLatestVersionResponse{}
+ mi := &file_service_httpdns_node_proto_msgTypes[11]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CheckHTTPDNSNodeLatestVersionResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CheckHTTPDNSNodeLatestVersionResponse) ProtoMessage() {}
+
+func (x *CheckHTTPDNSNodeLatestVersionResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[11]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CheckHTTPDNSNodeLatestVersionResponse.ProtoReflect.Descriptor instead.
+func (*CheckHTTPDNSNodeLatestVersionResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *CheckHTTPDNSNodeLatestVersionResponse) GetHasNewVersion() bool {
+ if x != nil {
+ return x.HasNewVersion
+ }
+ return false
+}
+
+func (x *CheckHTTPDNSNodeLatestVersionResponse) GetNewVersion() string {
+ if x != nil {
+ return x.NewVersion
+ }
+ return ""
+}
+
+// 下载最新HTTPDNS节点安装文件
+type DownloadHTTPDNSNodeInstallationFileRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Os string `protobuf:"bytes,1,opt,name=os,proto3" json:"os,omitempty"`
+ Arch string `protobuf:"bytes,2,opt,name=arch,proto3" json:"arch,omitempty"`
+ ChunkOffset int64 `protobuf:"varint,3,opt,name=chunkOffset,proto3" json:"chunkOffset,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *DownloadHTTPDNSNodeInstallationFileRequest) Reset() {
+ *x = DownloadHTTPDNSNodeInstallationFileRequest{}
+ mi := &file_service_httpdns_node_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *DownloadHTTPDNSNodeInstallationFileRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DownloadHTTPDNSNodeInstallationFileRequest) ProtoMessage() {}
+
+func (x *DownloadHTTPDNSNodeInstallationFileRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[12]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use DownloadHTTPDNSNodeInstallationFileRequest.ProtoReflect.Descriptor instead.
+func (*DownloadHTTPDNSNodeInstallationFileRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *DownloadHTTPDNSNodeInstallationFileRequest) GetOs() string {
+ if x != nil {
+ return x.Os
+ }
+ return ""
+}
+
+func (x *DownloadHTTPDNSNodeInstallationFileRequest) GetArch() string {
+ if x != nil {
+ return x.Arch
+ }
+ return ""
+}
+
+func (x *DownloadHTTPDNSNodeInstallationFileRequest) GetChunkOffset() int64 {
+ if x != nil {
+ return x.ChunkOffset
+ }
+ return 0
+}
+
+type DownloadHTTPDNSNodeInstallationFileResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ ChunkData []byte `protobuf:"bytes,1,opt,name=chunkData,proto3" json:"chunkData,omitempty"`
+ Sum string `protobuf:"bytes,2,opt,name=sum,proto3" json:"sum,omitempty"`
+ Offset int64 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"`
+ Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"`
+ Filename string `protobuf:"bytes,5,opt,name=filename,proto3" json:"filename,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *DownloadHTTPDNSNodeInstallationFileResponse) Reset() {
+ *x = DownloadHTTPDNSNodeInstallationFileResponse{}
+ mi := &file_service_httpdns_node_proto_msgTypes[13]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *DownloadHTTPDNSNodeInstallationFileResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DownloadHTTPDNSNodeInstallationFileResponse) ProtoMessage() {}
+
+func (x *DownloadHTTPDNSNodeInstallationFileResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_node_proto_msgTypes[13]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use DownloadHTTPDNSNodeInstallationFileResponse.ProtoReflect.Descriptor instead.
+func (*DownloadHTTPDNSNodeInstallationFileResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_node_proto_rawDescGZIP(), []int{13}
+}
+
+func (x *DownloadHTTPDNSNodeInstallationFileResponse) GetChunkData() []byte {
+ if x != nil {
+ return x.ChunkData
+ }
+ return nil
+}
+
+func (x *DownloadHTTPDNSNodeInstallationFileResponse) GetSum() string {
+ if x != nil {
+ return x.Sum
+ }
+ return ""
+}
+
+func (x *DownloadHTTPDNSNodeInstallationFileResponse) GetOffset() int64 {
+ if x != nil {
+ return x.Offset
+ }
+ return 0
+}
+
+func (x *DownloadHTTPDNSNodeInstallationFileResponse) GetVersion() string {
+ if x != nil {
+ return x.Version
+ }
+ return ""
+}
+
+func (x *DownloadHTTPDNSNodeInstallationFileResponse) GetFilename() string {
+ if x != nil {
+ return x.Filename
+ }
+ return ""
+}
+
+var File_service_httpdns_node_proto protoreflect.FileDescriptor
+
+const file_service_httpdns_node_proto_rawDesc = "" +
+ "\n" +
+ "\x1aservice_httpdns_node.proto\x12\x02pb\x1a\x1fmodels/model_httpdns_node.proto\x1a\x1dmodels/model_node_login.proto\x1a\x19models/rpc_messages.proto\"\x80\x01\n" +
+ "\x18CreateHTTPDNSNodeRequest\x12\x1c\n" +
+ "\tclusterId\x18\x01 \x01(\x03R\tclusterId\x12\x12\n" +
+ "\x04name\x18\x02 \x01(\tR\x04name\x12\x1e\n" +
+ "\n" +
+ "installDir\x18\x03 \x01(\tR\n" +
+ "installDir\x12\x12\n" +
+ "\x04isOn\x18\x04 \x01(\bR\x04isOn\"3\n" +
+ "\x19CreateHTTPDNSNodeResponse\x12\x16\n" +
+ "\x06nodeId\x18\x01 \x01(\x03R\x06nodeId\"z\n" +
+ "\x18UpdateHTTPDNSNodeRequest\x12\x16\n" +
+ "\x06nodeId\x18\x01 \x01(\x03R\x06nodeId\x12\x12\n" +
+ "\x04name\x18\x02 \x01(\tR\x04name\x12\x1e\n" +
+ "\n" +
+ "installDir\x18\x03 \x01(\tR\n" +
+ "installDir\x12\x12\n" +
+ "\x04isOn\x18\x04 \x01(\bR\x04isOn\"2\n" +
+ "\x18DeleteHTTPDNSNodeRequest\x12\x16\n" +
+ "\x06nodeId\x18\x01 \x01(\x03R\x06nodeId\"0\n" +
+ "\x16FindHTTPDNSNodeRequest\x12\x16\n" +
+ "\x06nodeId\x18\x01 \x01(\x03R\x06nodeId\">\n" +
+ "\x17FindHTTPDNSNodeResponse\x12#\n" +
+ "\x04node\x18\x01 \x01(\v2\x0f.pb.HTTPDNSNodeR\x04node\"7\n" +
+ "\x17ListHTTPDNSNodesRequest\x12\x1c\n" +
+ "\tclusterId\x18\x01 \x01(\x03R\tclusterId\"A\n" +
+ "\x18ListHTTPDNSNodesResponse\x12%\n" +
+ "\x05nodes\x18\x01 \x03(\v2\x0f.pb.HTTPDNSNodeR\x05nodes\"\xd8\x01\n" +
+ "\x1eUpdateHTTPDNSNodeStatusRequest\x12\x16\n" +
+ "\x06nodeId\x18\x01 \x01(\x03R\x06nodeId\x12\x12\n" +
+ "\x04isUp\x18\x02 \x01(\bR\x04isUp\x12 \n" +
+ "\visInstalled\x18\x03 \x01(\bR\visInstalled\x12\x1a\n" +
+ "\bisActive\x18\x04 \x01(\bR\bisActive\x12\x1e\n" +
+ "\n" +
+ "statusJSON\x18\x05 \x01(\fR\n" +
+ "statusJSON\x12,\n" +
+ "\x11installStatusJSON\x18\x06 \x01(\fR\x11installStatusJSON\"d\n" +
+ "\x1dUpdateHTTPDNSNodeLoginRequest\x12\x16\n" +
+ "\x06nodeId\x18\x01 \x01(\x03R\x06nodeId\x12+\n" +
+ "\tnodeLogin\x18\x02 \x01(\v2\r.pb.NodeLoginR\tnodeLogin\"r\n" +
+ "$CheckHTTPDNSNodeLatestVersionRequest\x12\x0e\n" +
+ "\x02os\x18\x01 \x01(\tR\x02os\x12\x12\n" +
+ "\x04arch\x18\x02 \x01(\tR\x04arch\x12&\n" +
+ "\x0ecurrentVersion\x18\x03 \x01(\tR\x0ecurrentVersion\"m\n" +
+ "%CheckHTTPDNSNodeLatestVersionResponse\x12$\n" +
+ "\rhasNewVersion\x18\x01 \x01(\bR\rhasNewVersion\x12\x1e\n" +
+ "\n" +
+ "newVersion\x18\x02 \x01(\tR\n" +
+ "newVersion\"r\n" +
+ "*DownloadHTTPDNSNodeInstallationFileRequest\x12\x0e\n" +
+ "\x02os\x18\x01 \x01(\tR\x02os\x12\x12\n" +
+ "\x04arch\x18\x02 \x01(\tR\x04arch\x12 \n" +
+ "\vchunkOffset\x18\x03 \x01(\x03R\vchunkOffset\"\xab\x01\n" +
+ "+DownloadHTTPDNSNodeInstallationFileResponse\x12\x1c\n" +
+ "\tchunkData\x18\x01 \x01(\fR\tchunkData\x12\x10\n" +
+ "\x03sum\x18\x02 \x01(\tR\x03sum\x12\x16\n" +
+ "\x06offset\x18\x03 \x01(\x03R\x06offset\x12\x18\n" +
+ "\aversion\x18\x04 \x01(\tR\aversion\x12\x1a\n" +
+ "\bfilename\x18\x05 \x01(\tR\bfilename2\xa2\x06\n" +
+ "\x12HTTPDNSNodeService\x12P\n" +
+ "\x11createHTTPDNSNode\x12\x1c.pb.CreateHTTPDNSNodeRequest\x1a\x1d.pb.CreateHTTPDNSNodeResponse\x12A\n" +
+ "\x11updateHTTPDNSNode\x12\x1c.pb.UpdateHTTPDNSNodeRequest\x1a\x0e.pb.RPCSuccess\x12A\n" +
+ "\x11deleteHTTPDNSNode\x12\x1c.pb.DeleteHTTPDNSNodeRequest\x1a\x0e.pb.RPCSuccess\x12J\n" +
+ "\x0ffindHTTPDNSNode\x12\x1a.pb.FindHTTPDNSNodeRequest\x1a\x1b.pb.FindHTTPDNSNodeResponse\x12M\n" +
+ "\x10listHTTPDNSNodes\x12\x1b.pb.ListHTTPDNSNodesRequest\x1a\x1c.pb.ListHTTPDNSNodesResponse\x12M\n" +
+ "\x17updateHTTPDNSNodeStatus\x12\".pb.UpdateHTTPDNSNodeStatusRequest\x1a\x0e.pb.RPCSuccess\x12K\n" +
+ "\x16updateHTTPDNSNodeLogin\x12!.pb.UpdateHTTPDNSNodeLoginRequest\x1a\x0e.pb.RPCSuccess\x12t\n" +
+ "\x1dcheckHTTPDNSNodeLatestVersion\x12(.pb.CheckHTTPDNSNodeLatestVersionRequest\x1a).pb.CheckHTTPDNSNodeLatestVersionResponse\x12\x86\x01\n" +
+ "#downloadHTTPDNSNodeInstallationFile\x12..pb.DownloadHTTPDNSNodeInstallationFileRequest\x1a/.pb.DownloadHTTPDNSNodeInstallationFileResponseB\x06Z\x04./pbb\x06proto3"
+
+var (
+ file_service_httpdns_node_proto_rawDescOnce sync.Once
+ file_service_httpdns_node_proto_rawDescData []byte
+)
+
+func file_service_httpdns_node_proto_rawDescGZIP() []byte {
+ file_service_httpdns_node_proto_rawDescOnce.Do(func() {
+ file_service_httpdns_node_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_service_httpdns_node_proto_rawDesc), len(file_service_httpdns_node_proto_rawDesc)))
+ })
+ return file_service_httpdns_node_proto_rawDescData
+}
+
+var file_service_httpdns_node_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
+var file_service_httpdns_node_proto_goTypes = []any{
+ (*CreateHTTPDNSNodeRequest)(nil), // 0: pb.CreateHTTPDNSNodeRequest
+ (*CreateHTTPDNSNodeResponse)(nil), // 1: pb.CreateHTTPDNSNodeResponse
+ (*UpdateHTTPDNSNodeRequest)(nil), // 2: pb.UpdateHTTPDNSNodeRequest
+ (*DeleteHTTPDNSNodeRequest)(nil), // 3: pb.DeleteHTTPDNSNodeRequest
+ (*FindHTTPDNSNodeRequest)(nil), // 4: pb.FindHTTPDNSNodeRequest
+ (*FindHTTPDNSNodeResponse)(nil), // 5: pb.FindHTTPDNSNodeResponse
+ (*ListHTTPDNSNodesRequest)(nil), // 6: pb.ListHTTPDNSNodesRequest
+ (*ListHTTPDNSNodesResponse)(nil), // 7: pb.ListHTTPDNSNodesResponse
+ (*UpdateHTTPDNSNodeStatusRequest)(nil), // 8: pb.UpdateHTTPDNSNodeStatusRequest
+ (*UpdateHTTPDNSNodeLoginRequest)(nil), // 9: pb.UpdateHTTPDNSNodeLoginRequest
+ (*CheckHTTPDNSNodeLatestVersionRequest)(nil), // 10: pb.CheckHTTPDNSNodeLatestVersionRequest
+ (*CheckHTTPDNSNodeLatestVersionResponse)(nil), // 11: pb.CheckHTTPDNSNodeLatestVersionResponse
+ (*DownloadHTTPDNSNodeInstallationFileRequest)(nil), // 12: pb.DownloadHTTPDNSNodeInstallationFileRequest
+ (*DownloadHTTPDNSNodeInstallationFileResponse)(nil), // 13: pb.DownloadHTTPDNSNodeInstallationFileResponse
+ (*HTTPDNSNode)(nil), // 14: pb.HTTPDNSNode
+ (*NodeLogin)(nil), // 15: pb.NodeLogin
+ (*RPCSuccess)(nil), // 16: pb.RPCSuccess
+}
+var file_service_httpdns_node_proto_depIdxs = []int32{
+ 14, // 0: pb.FindHTTPDNSNodeResponse.node:type_name -> pb.HTTPDNSNode
+ 14, // 1: pb.ListHTTPDNSNodesResponse.nodes:type_name -> pb.HTTPDNSNode
+ 15, // 2: pb.UpdateHTTPDNSNodeLoginRequest.nodeLogin:type_name -> pb.NodeLogin
+ 0, // 3: pb.HTTPDNSNodeService.createHTTPDNSNode:input_type -> pb.CreateHTTPDNSNodeRequest
+ 2, // 4: pb.HTTPDNSNodeService.updateHTTPDNSNode:input_type -> pb.UpdateHTTPDNSNodeRequest
+ 3, // 5: pb.HTTPDNSNodeService.deleteHTTPDNSNode:input_type -> pb.DeleteHTTPDNSNodeRequest
+ 4, // 6: pb.HTTPDNSNodeService.findHTTPDNSNode:input_type -> pb.FindHTTPDNSNodeRequest
+ 6, // 7: pb.HTTPDNSNodeService.listHTTPDNSNodes:input_type -> pb.ListHTTPDNSNodesRequest
+ 8, // 8: pb.HTTPDNSNodeService.updateHTTPDNSNodeStatus:input_type -> pb.UpdateHTTPDNSNodeStatusRequest
+ 9, // 9: pb.HTTPDNSNodeService.updateHTTPDNSNodeLogin:input_type -> pb.UpdateHTTPDNSNodeLoginRequest
+ 10, // 10: pb.HTTPDNSNodeService.checkHTTPDNSNodeLatestVersion:input_type -> pb.CheckHTTPDNSNodeLatestVersionRequest
+ 12, // 11: pb.HTTPDNSNodeService.downloadHTTPDNSNodeInstallationFile:input_type -> pb.DownloadHTTPDNSNodeInstallationFileRequest
+ 1, // 12: pb.HTTPDNSNodeService.createHTTPDNSNode:output_type -> pb.CreateHTTPDNSNodeResponse
+ 16, // 13: pb.HTTPDNSNodeService.updateHTTPDNSNode:output_type -> pb.RPCSuccess
+ 16, // 14: pb.HTTPDNSNodeService.deleteHTTPDNSNode:output_type -> pb.RPCSuccess
+ 5, // 15: pb.HTTPDNSNodeService.findHTTPDNSNode:output_type -> pb.FindHTTPDNSNodeResponse
+ 7, // 16: pb.HTTPDNSNodeService.listHTTPDNSNodes:output_type -> pb.ListHTTPDNSNodesResponse
+ 16, // 17: pb.HTTPDNSNodeService.updateHTTPDNSNodeStatus:output_type -> pb.RPCSuccess
+ 16, // 18: pb.HTTPDNSNodeService.updateHTTPDNSNodeLogin:output_type -> pb.RPCSuccess
+ 11, // 19: pb.HTTPDNSNodeService.checkHTTPDNSNodeLatestVersion:output_type -> pb.CheckHTTPDNSNodeLatestVersionResponse
+ 13, // 20: pb.HTTPDNSNodeService.downloadHTTPDNSNodeInstallationFile:output_type -> pb.DownloadHTTPDNSNodeInstallationFileResponse
+ 12, // [12:21] is the sub-list for method output_type
+ 3, // [3:12] is the sub-list for method input_type
+ 3, // [3:3] is the sub-list for extension type_name
+ 3, // [3:3] is the sub-list for extension extendee
+ 0, // [0:3] is the sub-list for field type_name
+}
+
+func init() { file_service_httpdns_node_proto_init() }
+func file_service_httpdns_node_proto_init() {
+ if File_service_httpdns_node_proto != nil {
+ return
+ }
+ file_models_model_httpdns_node_proto_init()
+ file_models_model_node_login_proto_init()
+ file_models_rpc_messages_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_service_httpdns_node_proto_rawDesc), len(file_service_httpdns_node_proto_rawDesc)),
+ NumEnums: 0,
+ NumMessages: 14,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_service_httpdns_node_proto_goTypes,
+ DependencyIndexes: file_service_httpdns_node_proto_depIdxs,
+ MessageInfos: file_service_httpdns_node_proto_msgTypes,
+ }.Build()
+ File_service_httpdns_node_proto = out.File
+ file_service_httpdns_node_proto_goTypes = nil
+ file_service_httpdns_node_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_node_grpc.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_node_grpc.pb.go
new file mode 100644
index 0000000..3f40be0
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_node_grpc.pb.go
@@ -0,0 +1,551 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.6.1
+// - protoc v3.21.12
+// source: service_httpdns_node.proto
+
+package pb
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.64.0 or later.
+const _ = grpc.SupportPackageIsVersion9
+
+const (
+ HTTPDNSNodeService_CreateHTTPDNSNode_FullMethodName = "/pb.HTTPDNSNodeService/createHTTPDNSNode"
+ HTTPDNSNodeService_UpdateHTTPDNSNode_FullMethodName = "/pb.HTTPDNSNodeService/updateHTTPDNSNode"
+ HTTPDNSNodeService_DeleteHTTPDNSNode_FullMethodName = "/pb.HTTPDNSNodeService/deleteHTTPDNSNode"
+ HTTPDNSNodeService_FindHTTPDNSNode_FullMethodName = "/pb.HTTPDNSNodeService/findHTTPDNSNode"
+ HTTPDNSNodeService_ListHTTPDNSNodes_FullMethodName = "/pb.HTTPDNSNodeService/listHTTPDNSNodes"
+ HTTPDNSNodeService_UpdateHTTPDNSNodeStatus_FullMethodName = "/pb.HTTPDNSNodeService/updateHTTPDNSNodeStatus"
+ HTTPDNSNodeService_UpdateHTTPDNSNodeLogin_FullMethodName = "/pb.HTTPDNSNodeService/updateHTTPDNSNodeLogin"
+ HTTPDNSNodeService_CheckHTTPDNSNodeLatestVersion_FullMethodName = "/pb.HTTPDNSNodeService/checkHTTPDNSNodeLatestVersion"
+ HTTPDNSNodeService_DownloadHTTPDNSNodeInstallationFile_FullMethodName = "/pb.HTTPDNSNodeService/downloadHTTPDNSNodeInstallationFile"
+ HTTPDNSNodeService_CountAllUpgradeHTTPDNSNodesWithClusterId_FullMethodName = "/pb.HTTPDNSNodeService/countAllUpgradeHTTPDNSNodesWithClusterId"
+ HTTPDNSNodeService_FindAllUpgradeHTTPDNSNodesWithClusterId_FullMethodName = "/pb.HTTPDNSNodeService/findAllUpgradeHTTPDNSNodesWithClusterId"
+ HTTPDNSNodeService_UpgradeHTTPDNSNode_FullMethodName = "/pb.HTTPDNSNodeService/upgradeHTTPDNSNode"
+)
+
+// HTTPDNSNodeServiceClient is the client API for HTTPDNSNodeService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type HTTPDNSNodeServiceClient interface {
+ CreateHTTPDNSNode(ctx context.Context, in *CreateHTTPDNSNodeRequest, opts ...grpc.CallOption) (*CreateHTTPDNSNodeResponse, error)
+ UpdateHTTPDNSNode(ctx context.Context, in *UpdateHTTPDNSNodeRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ DeleteHTTPDNSNode(ctx context.Context, in *DeleteHTTPDNSNodeRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ FindHTTPDNSNode(ctx context.Context, in *FindHTTPDNSNodeRequest, opts ...grpc.CallOption) (*FindHTTPDNSNodeResponse, error)
+ ListHTTPDNSNodes(ctx context.Context, in *ListHTTPDNSNodesRequest, opts ...grpc.CallOption) (*ListHTTPDNSNodesResponse, error)
+ UpdateHTTPDNSNodeStatus(ctx context.Context, in *UpdateHTTPDNSNodeStatusRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ // 修改HTTPDNS节点登录信息
+ UpdateHTTPDNSNodeLogin(ctx context.Context, in *UpdateHTTPDNSNodeLoginRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ // 检查HTTPDNS节点新版本
+ CheckHTTPDNSNodeLatestVersion(ctx context.Context, in *CheckHTTPDNSNodeLatestVersionRequest, opts ...grpc.CallOption) (*CheckHTTPDNSNodeLatestVersionResponse, error)
+ // 下载最新HTTPDNS节点安装文件
+ DownloadHTTPDNSNodeInstallationFile(ctx context.Context, in *DownloadHTTPDNSNodeInstallationFileRequest, opts ...grpc.CallOption) (*DownloadHTTPDNSNodeInstallationFileResponse, error)
+ // 计算需要升级的HTTPDNS节点数量
+ CountAllUpgradeHTTPDNSNodesWithClusterId(ctx context.Context, in *CountAllUpgradeHTTPDNSNodesWithClusterIdRequest, opts ...grpc.CallOption) (*RPCCountResponse, error)
+ // 列出所有需要升级的HTTPDNS节点
+ FindAllUpgradeHTTPDNSNodesWithClusterId(ctx context.Context, in *FindAllUpgradeHTTPDNSNodesWithClusterIdRequest, opts ...grpc.CallOption) (*FindAllUpgradeHTTPDNSNodesWithClusterIdResponse, error)
+ // 升级单个HTTPDNS节点
+ UpgradeHTTPDNSNode(ctx context.Context, in *UpgradeHTTPDNSNodeRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+}
+
+type hTTPDNSNodeServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewHTTPDNSNodeServiceClient(cc grpc.ClientConnInterface) HTTPDNSNodeServiceClient {
+ return &hTTPDNSNodeServiceClient{cc}
+}
+
+func (c *hTTPDNSNodeServiceClient) CreateHTTPDNSNode(ctx context.Context, in *CreateHTTPDNSNodeRequest, opts ...grpc.CallOption) (*CreateHTTPDNSNodeResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(CreateHTTPDNSNodeResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSNodeService_CreateHTTPDNSNode_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSNodeServiceClient) UpdateHTTPDNSNode(ctx context.Context, in *UpdateHTTPDNSNodeRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSNodeService_UpdateHTTPDNSNode_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSNodeServiceClient) DeleteHTTPDNSNode(ctx context.Context, in *DeleteHTTPDNSNodeRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSNodeService_DeleteHTTPDNSNode_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSNodeServiceClient) FindHTTPDNSNode(ctx context.Context, in *FindHTTPDNSNodeRequest, opts ...grpc.CallOption) (*FindHTTPDNSNodeResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(FindHTTPDNSNodeResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSNodeService_FindHTTPDNSNode_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSNodeServiceClient) ListHTTPDNSNodes(ctx context.Context, in *ListHTTPDNSNodesRequest, opts ...grpc.CallOption) (*ListHTTPDNSNodesResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(ListHTTPDNSNodesResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSNodeService_ListHTTPDNSNodes_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSNodeServiceClient) UpdateHTTPDNSNodeStatus(ctx context.Context, in *UpdateHTTPDNSNodeStatusRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSNodeService_UpdateHTTPDNSNodeStatus_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSNodeServiceClient) UpdateHTTPDNSNodeLogin(ctx context.Context, in *UpdateHTTPDNSNodeLoginRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSNodeService_UpdateHTTPDNSNodeLogin_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSNodeServiceClient) CheckHTTPDNSNodeLatestVersion(ctx context.Context, in *CheckHTTPDNSNodeLatestVersionRequest, opts ...grpc.CallOption) (*CheckHTTPDNSNodeLatestVersionResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(CheckHTTPDNSNodeLatestVersionResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSNodeService_CheckHTTPDNSNodeLatestVersion_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSNodeServiceClient) DownloadHTTPDNSNodeInstallationFile(ctx context.Context, in *DownloadHTTPDNSNodeInstallationFileRequest, opts ...grpc.CallOption) (*DownloadHTTPDNSNodeInstallationFileResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(DownloadHTTPDNSNodeInstallationFileResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSNodeService_DownloadHTTPDNSNodeInstallationFile_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSNodeServiceClient) CountAllUpgradeHTTPDNSNodesWithClusterId(ctx context.Context, in *CountAllUpgradeHTTPDNSNodesWithClusterIdRequest, opts ...grpc.CallOption) (*RPCCountResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCCountResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSNodeService_CountAllUpgradeHTTPDNSNodesWithClusterId_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSNodeServiceClient) FindAllUpgradeHTTPDNSNodesWithClusterId(ctx context.Context, in *FindAllUpgradeHTTPDNSNodesWithClusterIdRequest, opts ...grpc.CallOption) (*FindAllUpgradeHTTPDNSNodesWithClusterIdResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(FindAllUpgradeHTTPDNSNodesWithClusterIdResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSNodeService_FindAllUpgradeHTTPDNSNodesWithClusterId_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSNodeServiceClient) UpgradeHTTPDNSNode(ctx context.Context, in *UpgradeHTTPDNSNodeRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSNodeService_UpgradeHTTPDNSNode_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// HTTPDNSNodeServiceServer is the server API for HTTPDNSNodeService service.
+// All implementations must embed UnimplementedHTTPDNSNodeServiceServer
+// for forward compatibility.
+type HTTPDNSNodeServiceServer interface {
+ CreateHTTPDNSNode(context.Context, *CreateHTTPDNSNodeRequest) (*CreateHTTPDNSNodeResponse, error)
+ UpdateHTTPDNSNode(context.Context, *UpdateHTTPDNSNodeRequest) (*RPCSuccess, error)
+ DeleteHTTPDNSNode(context.Context, *DeleteHTTPDNSNodeRequest) (*RPCSuccess, error)
+ FindHTTPDNSNode(context.Context, *FindHTTPDNSNodeRequest) (*FindHTTPDNSNodeResponse, error)
+ ListHTTPDNSNodes(context.Context, *ListHTTPDNSNodesRequest) (*ListHTTPDNSNodesResponse, error)
+ UpdateHTTPDNSNodeStatus(context.Context, *UpdateHTTPDNSNodeStatusRequest) (*RPCSuccess, error)
+ // 修改HTTPDNS节点登录信息
+ UpdateHTTPDNSNodeLogin(context.Context, *UpdateHTTPDNSNodeLoginRequest) (*RPCSuccess, error)
+ // 检查HTTPDNS节点新版本
+ CheckHTTPDNSNodeLatestVersion(context.Context, *CheckHTTPDNSNodeLatestVersionRequest) (*CheckHTTPDNSNodeLatestVersionResponse, error)
+ // 下载最新HTTPDNS节点安装文件
+ DownloadHTTPDNSNodeInstallationFile(context.Context, *DownloadHTTPDNSNodeInstallationFileRequest) (*DownloadHTTPDNSNodeInstallationFileResponse, error)
+ // 计算需要升级的HTTPDNS节点数量
+ CountAllUpgradeHTTPDNSNodesWithClusterId(context.Context, *CountAllUpgradeHTTPDNSNodesWithClusterIdRequest) (*RPCCountResponse, error)
+ // 列出所有需要升级的HTTPDNS节点
+ FindAllUpgradeHTTPDNSNodesWithClusterId(context.Context, *FindAllUpgradeHTTPDNSNodesWithClusterIdRequest) (*FindAllUpgradeHTTPDNSNodesWithClusterIdResponse, error)
+ // 升级单个HTTPDNS节点
+ UpgradeHTTPDNSNode(context.Context, *UpgradeHTTPDNSNodeRequest) (*RPCSuccess, error)
+ mustEmbedUnimplementedHTTPDNSNodeServiceServer()
+}
+
+// UnimplementedHTTPDNSNodeServiceServer must be embedded to have
+// forward compatible implementations.
+//
+// NOTE: this should be embedded by value instead of pointer to avoid a nil
+// pointer dereference when methods are called.
+type UnimplementedHTTPDNSNodeServiceServer struct{}
+
+func (UnimplementedHTTPDNSNodeServiceServer) CreateHTTPDNSNode(context.Context, *CreateHTTPDNSNodeRequest) (*CreateHTTPDNSNodeResponse, error) {
+ return nil, status.Error(codes.Unimplemented, "method CreateHTTPDNSNode not implemented")
+}
+func (UnimplementedHTTPDNSNodeServiceServer) UpdateHTTPDNSNode(context.Context, *UpdateHTTPDNSNodeRequest) (*RPCSuccess, error) {
+ return nil, status.Error(codes.Unimplemented, "method UpdateHTTPDNSNode not implemented")
+}
+func (UnimplementedHTTPDNSNodeServiceServer) DeleteHTTPDNSNode(context.Context, *DeleteHTTPDNSNodeRequest) (*RPCSuccess, error) {
+ return nil, status.Error(codes.Unimplemented, "method DeleteHTTPDNSNode not implemented")
+}
+func (UnimplementedHTTPDNSNodeServiceServer) FindHTTPDNSNode(context.Context, *FindHTTPDNSNodeRequest) (*FindHTTPDNSNodeResponse, error) {
+ return nil, status.Error(codes.Unimplemented, "method FindHTTPDNSNode not implemented")
+}
+func (UnimplementedHTTPDNSNodeServiceServer) ListHTTPDNSNodes(context.Context, *ListHTTPDNSNodesRequest) (*ListHTTPDNSNodesResponse, error) {
+ return nil, status.Error(codes.Unimplemented, "method ListHTTPDNSNodes not implemented")
+}
+func (UnimplementedHTTPDNSNodeServiceServer) UpdateHTTPDNSNodeStatus(context.Context, *UpdateHTTPDNSNodeStatusRequest) (*RPCSuccess, error) {
+ return nil, status.Error(codes.Unimplemented, "method UpdateHTTPDNSNodeStatus not implemented")
+}
+func (UnimplementedHTTPDNSNodeServiceServer) UpdateHTTPDNSNodeLogin(context.Context, *UpdateHTTPDNSNodeLoginRequest) (*RPCSuccess, error) {
+ return nil, status.Error(codes.Unimplemented, "method UpdateHTTPDNSNodeLogin not implemented")
+}
+func (UnimplementedHTTPDNSNodeServiceServer) CheckHTTPDNSNodeLatestVersion(context.Context, *CheckHTTPDNSNodeLatestVersionRequest) (*CheckHTTPDNSNodeLatestVersionResponse, error) {
+ return nil, status.Error(codes.Unimplemented, "method CheckHTTPDNSNodeLatestVersion not implemented")
+}
+func (UnimplementedHTTPDNSNodeServiceServer) DownloadHTTPDNSNodeInstallationFile(context.Context, *DownloadHTTPDNSNodeInstallationFileRequest) (*DownloadHTTPDNSNodeInstallationFileResponse, error) {
+ return nil, status.Error(codes.Unimplemented, "method DownloadHTTPDNSNodeInstallationFile not implemented")
+}
+func (UnimplementedHTTPDNSNodeServiceServer) CountAllUpgradeHTTPDNSNodesWithClusterId(context.Context, *CountAllUpgradeHTTPDNSNodesWithClusterIdRequest) (*RPCCountResponse, error) {
+ return nil, status.Error(codes.Unimplemented, "method CountAllUpgradeHTTPDNSNodesWithClusterId not implemented")
+}
+func (UnimplementedHTTPDNSNodeServiceServer) FindAllUpgradeHTTPDNSNodesWithClusterId(context.Context, *FindAllUpgradeHTTPDNSNodesWithClusterIdRequest) (*FindAllUpgradeHTTPDNSNodesWithClusterIdResponse, error) {
+ return nil, status.Error(codes.Unimplemented, "method FindAllUpgradeHTTPDNSNodesWithClusterId not implemented")
+}
+func (UnimplementedHTTPDNSNodeServiceServer) UpgradeHTTPDNSNode(context.Context, *UpgradeHTTPDNSNodeRequest) (*RPCSuccess, error) {
+ return nil, status.Error(codes.Unimplemented, "method UpgradeHTTPDNSNode not implemented")
+}
+func (UnimplementedHTTPDNSNodeServiceServer) mustEmbedUnimplementedHTTPDNSNodeServiceServer() {}
+func (UnimplementedHTTPDNSNodeServiceServer) testEmbeddedByValue() {}
+
+// UnsafeHTTPDNSNodeServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to HTTPDNSNodeServiceServer will
+// result in compilation errors.
+type UnsafeHTTPDNSNodeServiceServer interface {
+ mustEmbedUnimplementedHTTPDNSNodeServiceServer()
+}
+
+func RegisterHTTPDNSNodeServiceServer(s grpc.ServiceRegistrar, srv HTTPDNSNodeServiceServer) {
+ // If the following call panics, it indicates UnimplementedHTTPDNSNodeServiceServer was
+ // embedded by pointer and is nil. This will cause panics if an
+ // unimplemented method is ever invoked, so we test this at initialization
+ // time to prevent it from happening at runtime later due to I/O.
+ if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
+ t.testEmbeddedByValue()
+ }
+ s.RegisterService(&HTTPDNSNodeService_ServiceDesc, srv)
+}
+
+func _HTTPDNSNodeService_CreateHTTPDNSNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CreateHTTPDNSNodeRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSNodeServiceServer).CreateHTTPDNSNode(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSNodeService_CreateHTTPDNSNode_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSNodeServiceServer).CreateHTTPDNSNode(ctx, req.(*CreateHTTPDNSNodeRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSNodeService_UpdateHTTPDNSNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpdateHTTPDNSNodeRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSNodeServiceServer).UpdateHTTPDNSNode(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSNodeService_UpdateHTTPDNSNode_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSNodeServiceServer).UpdateHTTPDNSNode(ctx, req.(*UpdateHTTPDNSNodeRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSNodeService_DeleteHTTPDNSNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(DeleteHTTPDNSNodeRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSNodeServiceServer).DeleteHTTPDNSNode(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSNodeService_DeleteHTTPDNSNode_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSNodeServiceServer).DeleteHTTPDNSNode(ctx, req.(*DeleteHTTPDNSNodeRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSNodeService_FindHTTPDNSNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(FindHTTPDNSNodeRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSNodeServiceServer).FindHTTPDNSNode(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSNodeService_FindHTTPDNSNode_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSNodeServiceServer).FindHTTPDNSNode(ctx, req.(*FindHTTPDNSNodeRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSNodeService_ListHTTPDNSNodes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ListHTTPDNSNodesRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSNodeServiceServer).ListHTTPDNSNodes(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSNodeService_ListHTTPDNSNodes_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSNodeServiceServer).ListHTTPDNSNodes(ctx, req.(*ListHTTPDNSNodesRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSNodeService_UpdateHTTPDNSNodeStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpdateHTTPDNSNodeStatusRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSNodeServiceServer).UpdateHTTPDNSNodeStatus(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSNodeService_UpdateHTTPDNSNodeStatus_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSNodeServiceServer).UpdateHTTPDNSNodeStatus(ctx, req.(*UpdateHTTPDNSNodeStatusRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSNodeService_UpdateHTTPDNSNodeLogin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpdateHTTPDNSNodeLoginRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSNodeServiceServer).UpdateHTTPDNSNodeLogin(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSNodeService_UpdateHTTPDNSNodeLogin_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSNodeServiceServer).UpdateHTTPDNSNodeLogin(ctx, req.(*UpdateHTTPDNSNodeLoginRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSNodeService_CheckHTTPDNSNodeLatestVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CheckHTTPDNSNodeLatestVersionRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSNodeServiceServer).CheckHTTPDNSNodeLatestVersion(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSNodeService_CheckHTTPDNSNodeLatestVersion_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSNodeServiceServer).CheckHTTPDNSNodeLatestVersion(ctx, req.(*CheckHTTPDNSNodeLatestVersionRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSNodeService_DownloadHTTPDNSNodeInstallationFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(DownloadHTTPDNSNodeInstallationFileRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSNodeServiceServer).DownloadHTTPDNSNodeInstallationFile(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSNodeService_DownloadHTTPDNSNodeInstallationFile_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSNodeServiceServer).DownloadHTTPDNSNodeInstallationFile(ctx, req.(*DownloadHTTPDNSNodeInstallationFileRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSNodeService_CountAllUpgradeHTTPDNSNodesWithClusterId_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CountAllUpgradeHTTPDNSNodesWithClusterIdRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSNodeServiceServer).CountAllUpgradeHTTPDNSNodesWithClusterId(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSNodeService_CountAllUpgradeHTTPDNSNodesWithClusterId_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSNodeServiceServer).CountAllUpgradeHTTPDNSNodesWithClusterId(ctx, req.(*CountAllUpgradeHTTPDNSNodesWithClusterIdRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSNodeService_FindAllUpgradeHTTPDNSNodesWithClusterId_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(FindAllUpgradeHTTPDNSNodesWithClusterIdRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSNodeServiceServer).FindAllUpgradeHTTPDNSNodesWithClusterId(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSNodeService_FindAllUpgradeHTTPDNSNodesWithClusterId_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSNodeServiceServer).FindAllUpgradeHTTPDNSNodesWithClusterId(ctx, req.(*FindAllUpgradeHTTPDNSNodesWithClusterIdRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSNodeService_UpgradeHTTPDNSNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpgradeHTTPDNSNodeRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSNodeServiceServer).UpgradeHTTPDNSNode(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSNodeService_UpgradeHTTPDNSNode_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSNodeServiceServer).UpgradeHTTPDNSNode(ctx, req.(*UpgradeHTTPDNSNodeRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// HTTPDNSNodeService_ServiceDesc is the grpc.ServiceDesc for HTTPDNSNodeService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var HTTPDNSNodeService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "pb.HTTPDNSNodeService",
+ HandlerType: (*HTTPDNSNodeServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "createHTTPDNSNode",
+ Handler: _HTTPDNSNodeService_CreateHTTPDNSNode_Handler,
+ },
+ {
+ MethodName: "updateHTTPDNSNode",
+ Handler: _HTTPDNSNodeService_UpdateHTTPDNSNode_Handler,
+ },
+ {
+ MethodName: "deleteHTTPDNSNode",
+ Handler: _HTTPDNSNodeService_DeleteHTTPDNSNode_Handler,
+ },
+ {
+ MethodName: "findHTTPDNSNode",
+ Handler: _HTTPDNSNodeService_FindHTTPDNSNode_Handler,
+ },
+ {
+ MethodName: "listHTTPDNSNodes",
+ Handler: _HTTPDNSNodeService_ListHTTPDNSNodes_Handler,
+ },
+ {
+ MethodName: "updateHTTPDNSNodeStatus",
+ Handler: _HTTPDNSNodeService_UpdateHTTPDNSNodeStatus_Handler,
+ },
+ {
+ MethodName: "updateHTTPDNSNodeLogin",
+ Handler: _HTTPDNSNodeService_UpdateHTTPDNSNodeLogin_Handler,
+ },
+ {
+ MethodName: "checkHTTPDNSNodeLatestVersion",
+ Handler: _HTTPDNSNodeService_CheckHTTPDNSNodeLatestVersion_Handler,
+ },
+ {
+ MethodName: "downloadHTTPDNSNodeInstallationFile",
+ Handler: _HTTPDNSNodeService_DownloadHTTPDNSNodeInstallationFile_Handler,
+ },
+ {
+ MethodName: "countAllUpgradeHTTPDNSNodesWithClusterId",
+ Handler: _HTTPDNSNodeService_CountAllUpgradeHTTPDNSNodesWithClusterId_Handler,
+ },
+ {
+ MethodName: "findAllUpgradeHTTPDNSNodesWithClusterId",
+ Handler: _HTTPDNSNodeService_FindAllUpgradeHTTPDNSNodesWithClusterId_Handler,
+ },
+ {
+ MethodName: "upgradeHTTPDNSNode",
+ Handler: _HTTPDNSNodeService_UpgradeHTTPDNSNode_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "service_httpdns_node.proto",
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_node_upgrade.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_node_upgrade.go
new file mode 100644
index 0000000..2736957
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_node_upgrade.go
@@ -0,0 +1,345 @@
+package pb
+
+import (
+ "fmt"
+
+ "google.golang.org/protobuf/encoding/protowire"
+ "google.golang.org/protobuf/proto"
+)
+
+// CountAllUpgradeHTTPDNSNodesWithClusterIdRequest 计算需要升级的HTTPDNS节点数量
+type CountAllUpgradeHTTPDNSNodesWithClusterIdRequest struct {
+ ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+}
+
+func (x *CountAllUpgradeHTTPDNSNodesWithClusterIdRequest) Reset() { *x = CountAllUpgradeHTTPDNSNodesWithClusterIdRequest{} }
+func (x *CountAllUpgradeHTTPDNSNodesWithClusterIdRequest) String() string { return fmt.Sprintf("%+v", *x) }
+func (x *CountAllUpgradeHTTPDNSNodesWithClusterIdRequest) ProtoMessage() {}
+
+func (x *CountAllUpgradeHTTPDNSNodesWithClusterIdRequest) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+func (x *CountAllUpgradeHTTPDNSNodesWithClusterIdRequest) Marshal() ([]byte, error) {
+ var b []byte
+ if x.ClusterId != 0 {
+ b = protowire.AppendTag(b, 1, protowire.VarintType)
+ b = protowire.AppendVarint(b, uint64(x.ClusterId))
+ }
+ return b, nil
+}
+
+func (x *CountAllUpgradeHTTPDNSNodesWithClusterIdRequest) Unmarshal(data []byte) error {
+ for len(data) > 0 {
+ num, typ, n := protowire.ConsumeTag(data)
+ if n < 0 {
+ return fmt.Errorf("invalid tag")
+ }
+ data = data[n:]
+ switch num {
+ case 1:
+ if typ == protowire.VarintType {
+ v, n := protowire.ConsumeVarint(data)
+ if n < 0 {
+ return fmt.Errorf("invalid varint")
+ }
+ x.ClusterId = int64(v)
+ data = data[n:]
+ }
+ default:
+ n := protowire.ConsumeFieldValue(num, typ, data)
+ if n < 0 {
+ return fmt.Errorf("invalid field value")
+ }
+ data = data[n:]
+ }
+ }
+ return nil
+}
+
+// FindAllUpgradeHTTPDNSNodesWithClusterIdRequest 列出所有需要升级的HTTPDNS节点
+type FindAllUpgradeHTTPDNSNodesWithClusterIdRequest struct {
+ ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+}
+
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdRequest) Reset() { *x = FindAllUpgradeHTTPDNSNodesWithClusterIdRequest{} }
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdRequest) String() string { return fmt.Sprintf("%+v", *x) }
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdRequest) ProtoMessage() {}
+
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdRequest) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdRequest) Marshal() ([]byte, error) {
+ var b []byte
+ if x.ClusterId != 0 {
+ b = protowire.AppendTag(b, 1, protowire.VarintType)
+ b = protowire.AppendVarint(b, uint64(x.ClusterId))
+ }
+ return b, nil
+}
+
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdRequest) Unmarshal(data []byte) error {
+ for len(data) > 0 {
+ num, typ, n := protowire.ConsumeTag(data)
+ if n < 0 {
+ return fmt.Errorf("invalid tag")
+ }
+ data = data[n:]
+ switch num {
+ case 1:
+ if typ == protowire.VarintType {
+ v, n := protowire.ConsumeVarint(data)
+ if n < 0 {
+ return fmt.Errorf("invalid varint")
+ }
+ x.ClusterId = int64(v)
+ data = data[n:]
+ }
+ default:
+ n := protowire.ConsumeFieldValue(num, typ, data)
+ if n < 0 {
+ return fmt.Errorf("invalid field value")
+ }
+ data = data[n:]
+ }
+ }
+ return nil
+}
+
+// FindAllUpgradeHTTPDNSNodesWithClusterIdResponse_HTTPDNSNodeUpgrade 单个待升级节点信息
+type FindAllUpgradeHTTPDNSNodesWithClusterIdResponse_HTTPDNSNodeUpgrade struct {
+ Node *HTTPDNSNode `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
+ Os string `protobuf:"bytes,2,opt,name=os,proto3" json:"os,omitempty"`
+ Arch string `protobuf:"bytes,3,opt,name=arch,proto3" json:"arch,omitempty"`
+ OldVersion string `protobuf:"bytes,4,opt,name=oldVersion,proto3" json:"oldVersion,omitempty"`
+ NewVersion string `protobuf:"bytes,5,opt,name=newVersion,proto3" json:"newVersion,omitempty"`
+}
+
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdResponse_HTTPDNSNodeUpgrade) Reset() {
+ *x = FindAllUpgradeHTTPDNSNodesWithClusterIdResponse_HTTPDNSNodeUpgrade{}
+}
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdResponse_HTTPDNSNodeUpgrade) String() string {
+ return fmt.Sprintf("%+v", *x)
+}
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdResponse_HTTPDNSNodeUpgrade) ProtoMessage() {}
+
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdResponse_HTTPDNSNodeUpgrade) Marshal() ([]byte, error) {
+ var b []byte
+ if x.Node != nil {
+ nodeData, err := proto.Marshal(x.Node)
+ if err != nil {
+ return nil, err
+ }
+ b = protowire.AppendTag(b, 1, protowire.BytesType)
+ b = protowire.AppendBytes(b, nodeData)
+ }
+ if x.Os != "" {
+ b = protowire.AppendTag(b, 2, protowire.BytesType)
+ b = protowire.AppendString(b, x.Os)
+ }
+ if x.Arch != "" {
+ b = protowire.AppendTag(b, 3, protowire.BytesType)
+ b = protowire.AppendString(b, x.Arch)
+ }
+ if x.OldVersion != "" {
+ b = protowire.AppendTag(b, 4, protowire.BytesType)
+ b = protowire.AppendString(b, x.OldVersion)
+ }
+ if x.NewVersion != "" {
+ b = protowire.AppendTag(b, 5, protowire.BytesType)
+ b = protowire.AppendString(b, x.NewVersion)
+ }
+ return b, nil
+}
+
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdResponse_HTTPDNSNodeUpgrade) Unmarshal(data []byte) error {
+ for len(data) > 0 {
+ num, typ, n := protowire.ConsumeTag(data)
+ if n < 0 {
+ return fmt.Errorf("invalid tag")
+ }
+ data = data[n:]
+ switch num {
+ case 1:
+ if typ == protowire.BytesType {
+ v, n := protowire.ConsumeBytes(data)
+ if n < 0 {
+ return fmt.Errorf("invalid bytes")
+ }
+ x.Node = &HTTPDNSNode{}
+ if err := proto.Unmarshal(v, x.Node); err != nil {
+ return err
+ }
+ data = data[n:]
+ }
+ case 2:
+ if typ == protowire.BytesType {
+ v, n := protowire.ConsumeString(data)
+ if n < 0 {
+ return fmt.Errorf("invalid string")
+ }
+ x.Os = v
+ data = data[n:]
+ }
+ case 3:
+ if typ == protowire.BytesType {
+ v, n := protowire.ConsumeString(data)
+ if n < 0 {
+ return fmt.Errorf("invalid string")
+ }
+ x.Arch = v
+ data = data[n:]
+ }
+ case 4:
+ if typ == protowire.BytesType {
+ v, n := protowire.ConsumeString(data)
+ if n < 0 {
+ return fmt.Errorf("invalid string")
+ }
+ x.OldVersion = v
+ data = data[n:]
+ }
+ case 5:
+ if typ == protowire.BytesType {
+ v, n := protowire.ConsumeString(data)
+ if n < 0 {
+ return fmt.Errorf("invalid string")
+ }
+ x.NewVersion = v
+ data = data[n:]
+ }
+ default:
+ n := protowire.ConsumeFieldValue(num, typ, data)
+ if n < 0 {
+ return fmt.Errorf("invalid field value")
+ }
+ data = data[n:]
+ }
+ }
+ return nil
+}
+
+// FindAllUpgradeHTTPDNSNodesWithClusterIdResponse 列出所有需要升级的HTTPDNS节点
+type FindAllUpgradeHTTPDNSNodesWithClusterIdResponse struct {
+ Nodes []*FindAllUpgradeHTTPDNSNodesWithClusterIdResponse_HTTPDNSNodeUpgrade `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
+}
+
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdResponse) Reset() {
+ *x = FindAllUpgradeHTTPDNSNodesWithClusterIdResponse{}
+}
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdResponse) String() string {
+ return fmt.Sprintf("%+v", *x)
+}
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdResponse) ProtoMessage() {}
+
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdResponse) GetNodes() []*FindAllUpgradeHTTPDNSNodesWithClusterIdResponse_HTTPDNSNodeUpgrade {
+ if x != nil {
+ return x.Nodes
+ }
+ return nil
+}
+
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdResponse) Marshal() ([]byte, error) {
+ var b []byte
+ for _, node := range x.Nodes {
+ nodeData, err := node.Marshal()
+ if err != nil {
+ return nil, err
+ }
+ b = protowire.AppendTag(b, 1, protowire.BytesType)
+ b = protowire.AppendBytes(b, nodeData)
+ }
+ return b, nil
+}
+
+func (x *FindAllUpgradeHTTPDNSNodesWithClusterIdResponse) Unmarshal(data []byte) error {
+ for len(data) > 0 {
+ num, typ, n := protowire.ConsumeTag(data)
+ if n < 0 {
+ return fmt.Errorf("invalid tag")
+ }
+ data = data[n:]
+ switch num {
+ case 1:
+ if typ == protowire.BytesType {
+ v, n := protowire.ConsumeBytes(data)
+ if n < 0 {
+ return fmt.Errorf("invalid bytes")
+ }
+ node := &FindAllUpgradeHTTPDNSNodesWithClusterIdResponse_HTTPDNSNodeUpgrade{}
+ if err := node.Unmarshal(v); err != nil {
+ return err
+ }
+ x.Nodes = append(x.Nodes, node)
+ data = data[n:]
+ }
+ default:
+ n := protowire.ConsumeFieldValue(num, typ, data)
+ if n < 0 {
+ return fmt.Errorf("invalid field value")
+ }
+ data = data[n:]
+ }
+ }
+ return nil
+}
+
+// UpgradeHTTPDNSNodeRequest 升级单个HTTPDNS节点
+type UpgradeHTTPDNSNodeRequest struct {
+ NodeId int64 `protobuf:"varint,1,opt,name=nodeId,proto3" json:"nodeId,omitempty"`
+}
+
+func (x *UpgradeHTTPDNSNodeRequest) Reset() { *x = UpgradeHTTPDNSNodeRequest{} }
+func (x *UpgradeHTTPDNSNodeRequest) String() string { return fmt.Sprintf("%+v", *x) }
+func (x *UpgradeHTTPDNSNodeRequest) ProtoMessage() {}
+
+func (x *UpgradeHTTPDNSNodeRequest) GetNodeId() int64 {
+ if x != nil {
+ return x.NodeId
+ }
+ return 0
+}
+
+func (x *UpgradeHTTPDNSNodeRequest) Marshal() ([]byte, error) {
+ var b []byte
+ if x.NodeId != 0 {
+ b = protowire.AppendTag(b, 1, protowire.VarintType)
+ b = protowire.AppendVarint(b, uint64(x.NodeId))
+ }
+ return b, nil
+}
+
+func (x *UpgradeHTTPDNSNodeRequest) Unmarshal(data []byte) error {
+ for len(data) > 0 {
+ num, typ, n := protowire.ConsumeTag(data)
+ if n < 0 {
+ return fmt.Errorf("invalid tag")
+ }
+ data = data[n:]
+ switch num {
+ case 1:
+ if typ == protowire.VarintType {
+ v, n := protowire.ConsumeVarint(data)
+ if n < 0 {
+ return fmt.Errorf("invalid varint")
+ }
+ x.NodeId = int64(v)
+ data = data[n:]
+ }
+ default:
+ n := protowire.ConsumeFieldValue(num, typ, data)
+ if n < 0 {
+ return fmt.Errorf("invalid field value")
+ }
+ data = data[n:]
+ }
+ }
+ return nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_rule.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_rule.pb.go
new file mode 100644
index 0000000..1ac612c
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_rule.pb.go
@@ -0,0 +1,492 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.35.1
+// protoc v3.21.12
+// source: service_httpdns_rule.proto
+
+package pb
+
+import (
+ 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 CreateHTTPDNSCustomRuleRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Rule *HTTPDNSCustomRule `protobuf:"bytes,1,opt,name=rule,proto3" json:"rule,omitempty"`
+}
+
+func (x *CreateHTTPDNSCustomRuleRequest) Reset() {
+ *x = CreateHTTPDNSCustomRuleRequest{}
+ mi := &file_service_httpdns_rule_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSCustomRuleRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSCustomRuleRequest) ProtoMessage() {}
+
+func (x *CreateHTTPDNSCustomRuleRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_rule_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSCustomRuleRequest.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSCustomRuleRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_rule_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CreateHTTPDNSCustomRuleRequest) GetRule() *HTTPDNSCustomRule {
+ if x != nil {
+ return x.Rule
+ }
+ return nil
+}
+
+type CreateHTTPDNSCustomRuleResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RuleId int64 `protobuf:"varint,1,opt,name=ruleId,proto3" json:"ruleId,omitempty"`
+}
+
+func (x *CreateHTTPDNSCustomRuleResponse) Reset() {
+ *x = CreateHTTPDNSCustomRuleResponse{}
+ mi := &file_service_httpdns_rule_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSCustomRuleResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSCustomRuleResponse) ProtoMessage() {}
+
+func (x *CreateHTTPDNSCustomRuleResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_rule_proto_msgTypes[1]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSCustomRuleResponse.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSCustomRuleResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_rule_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *CreateHTTPDNSCustomRuleResponse) GetRuleId() int64 {
+ if x != nil {
+ return x.RuleId
+ }
+ return 0
+}
+
+type UpdateHTTPDNSCustomRuleRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Rule *HTTPDNSCustomRule `protobuf:"bytes,1,opt,name=rule,proto3" json:"rule,omitempty"`
+}
+
+func (x *UpdateHTTPDNSCustomRuleRequest) Reset() {
+ *x = UpdateHTTPDNSCustomRuleRequest{}
+ mi := &file_service_httpdns_rule_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *UpdateHTTPDNSCustomRuleRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateHTTPDNSCustomRuleRequest) ProtoMessage() {}
+
+func (x *UpdateHTTPDNSCustomRuleRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_rule_proto_msgTypes[2]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateHTTPDNSCustomRuleRequest.ProtoReflect.Descriptor instead.
+func (*UpdateHTTPDNSCustomRuleRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_rule_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *UpdateHTTPDNSCustomRuleRequest) GetRule() *HTTPDNSCustomRule {
+ if x != nil {
+ return x.Rule
+ }
+ return nil
+}
+
+type DeleteHTTPDNSCustomRuleRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RuleId int64 `protobuf:"varint,1,opt,name=ruleId,proto3" json:"ruleId,omitempty"`
+}
+
+func (x *DeleteHTTPDNSCustomRuleRequest) Reset() {
+ *x = DeleteHTTPDNSCustomRuleRequest{}
+ mi := &file_service_httpdns_rule_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *DeleteHTTPDNSCustomRuleRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DeleteHTTPDNSCustomRuleRequest) ProtoMessage() {}
+
+func (x *DeleteHTTPDNSCustomRuleRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_rule_proto_msgTypes[3]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use DeleteHTTPDNSCustomRuleRequest.ProtoReflect.Descriptor instead.
+func (*DeleteHTTPDNSCustomRuleRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_rule_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *DeleteHTTPDNSCustomRuleRequest) GetRuleId() int64 {
+ if x != nil {
+ return x.RuleId
+ }
+ return 0
+}
+
+type UpdateHTTPDNSCustomRuleStatusRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ RuleId int64 `protobuf:"varint,1,opt,name=ruleId,proto3" json:"ruleId,omitempty"`
+ IsOn bool `protobuf:"varint,2,opt,name=isOn,proto3" json:"isOn,omitempty"`
+}
+
+func (x *UpdateHTTPDNSCustomRuleStatusRequest) Reset() {
+ *x = UpdateHTTPDNSCustomRuleStatusRequest{}
+ mi := &file_service_httpdns_rule_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *UpdateHTTPDNSCustomRuleStatusRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateHTTPDNSCustomRuleStatusRequest) ProtoMessage() {}
+
+func (x *UpdateHTTPDNSCustomRuleStatusRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_rule_proto_msgTypes[4]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateHTTPDNSCustomRuleStatusRequest.ProtoReflect.Descriptor instead.
+func (*UpdateHTTPDNSCustomRuleStatusRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_rule_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *UpdateHTTPDNSCustomRuleStatusRequest) GetRuleId() int64 {
+ if x != nil {
+ return x.RuleId
+ }
+ return 0
+}
+
+func (x *UpdateHTTPDNSCustomRuleStatusRequest) GetIsOn() bool {
+ if x != nil {
+ return x.IsOn
+ }
+ return false
+}
+
+type ListHTTPDNSCustomRulesWithDomainIdRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ DomainId int64 `protobuf:"varint,1,opt,name=domainId,proto3" json:"domainId,omitempty"`
+}
+
+func (x *ListHTTPDNSCustomRulesWithDomainIdRequest) Reset() {
+ *x = ListHTTPDNSCustomRulesWithDomainIdRequest{}
+ mi := &file_service_httpdns_rule_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSCustomRulesWithDomainIdRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSCustomRulesWithDomainIdRequest) ProtoMessage() {}
+
+func (x *ListHTTPDNSCustomRulesWithDomainIdRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_rule_proto_msgTypes[5]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSCustomRulesWithDomainIdRequest.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSCustomRulesWithDomainIdRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_rule_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *ListHTTPDNSCustomRulesWithDomainIdRequest) GetDomainId() int64 {
+ if x != nil {
+ return x.DomainId
+ }
+ return 0
+}
+
+type ListHTTPDNSCustomRulesWithDomainIdResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Rules []*HTTPDNSCustomRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"`
+}
+
+func (x *ListHTTPDNSCustomRulesWithDomainIdResponse) Reset() {
+ *x = ListHTTPDNSCustomRulesWithDomainIdResponse{}
+ mi := &file_service_httpdns_rule_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSCustomRulesWithDomainIdResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSCustomRulesWithDomainIdResponse) ProtoMessage() {}
+
+func (x *ListHTTPDNSCustomRulesWithDomainIdResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_rule_proto_msgTypes[6]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSCustomRulesWithDomainIdResponse.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSCustomRulesWithDomainIdResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_rule_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *ListHTTPDNSCustomRulesWithDomainIdResponse) GetRules() []*HTTPDNSCustomRule {
+ if x != nil {
+ return x.Rules
+ }
+ return nil
+}
+
+var File_service_httpdns_rule_proto protoreflect.FileDescriptor
+
+var file_service_httpdns_rule_proto_rawDesc = []byte{
+ 0x0a, 0x1a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x64, 0x6e,
+ 0x73, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62,
+ 0x1a, 0x1f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x68,
+ 0x74, 0x74, 0x70, 0x64, 0x6e, 0x73, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x1a, 0x19, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4b, 0x0a, 0x1e,
+ 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73,
+ 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29,
+ 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70,
+ 0x62, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52,
+ 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x22, 0x39, 0x0a, 0x1f, 0x43, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d,
+ 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06,
+ 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x72, 0x75,
+ 0x6c, 0x65, 0x49, 0x64, 0x22, 0x4b, 0x0a, 0x1e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x54,
+ 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e,
+ 0x53, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c,
+ 0x65, 0x22, 0x38, 0x0a, 0x1e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44,
+ 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x22, 0x52, 0x0a, 0x24, 0x55,
+ 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74,
+ 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x69,
+ 0x73, 0x4f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x22,
+ 0x47, 0x0a, 0x29, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75,
+ 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x44, 0x6f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08,
+ 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08,
+ 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x59, 0x0a, 0x2a, 0x4c, 0x69, 0x73, 0x74,
+ 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c,
+ 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18,
+ 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x44,
+ 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75,
+ 0x6c, 0x65, 0x73, 0x32, 0xf7, 0x03, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52,
+ 0x75, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x62, 0x0a, 0x17, 0x63, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74, 0x6f,
+ 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
+ 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75,
+ 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x62, 0x2e, 0x43,
+ 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74,
+ 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d,
+ 0x0a, 0x17, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43,
+ 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x70, 0x62, 0x2e, 0x55,
+ 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74,
+ 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e,
+ 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x4d, 0x0a,
+ 0x17, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75,
+ 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65,
+ 0x6c, 0x65, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74, 0x6f,
+ 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70,
+ 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x59, 0x0a, 0x1d,
+ 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73,
+ 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e,
+ 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53,
+ 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43,
+ 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x83, 0x01, 0x0a, 0x22, 0x6c, 0x69, 0x73, 0x74,
+ 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c,
+ 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x2d,
+ 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43,
+ 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x44, 0x6f,
+ 0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e,
+ 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x43, 0x75,
+ 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x44, 0x6f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x06, 0x5a,
+ 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_service_httpdns_rule_proto_rawDescOnce sync.Once
+ file_service_httpdns_rule_proto_rawDescData = file_service_httpdns_rule_proto_rawDesc
+)
+
+func file_service_httpdns_rule_proto_rawDescGZIP() []byte {
+ file_service_httpdns_rule_proto_rawDescOnce.Do(func() {
+ file_service_httpdns_rule_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_httpdns_rule_proto_rawDescData)
+ })
+ return file_service_httpdns_rule_proto_rawDescData
+}
+
+var file_service_httpdns_rule_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
+var file_service_httpdns_rule_proto_goTypes = []any{
+ (*CreateHTTPDNSCustomRuleRequest)(nil), // 0: pb.CreateHTTPDNSCustomRuleRequest
+ (*CreateHTTPDNSCustomRuleResponse)(nil), // 1: pb.CreateHTTPDNSCustomRuleResponse
+ (*UpdateHTTPDNSCustomRuleRequest)(nil), // 2: pb.UpdateHTTPDNSCustomRuleRequest
+ (*DeleteHTTPDNSCustomRuleRequest)(nil), // 3: pb.DeleteHTTPDNSCustomRuleRequest
+ (*UpdateHTTPDNSCustomRuleStatusRequest)(nil), // 4: pb.UpdateHTTPDNSCustomRuleStatusRequest
+ (*ListHTTPDNSCustomRulesWithDomainIdRequest)(nil), // 5: pb.ListHTTPDNSCustomRulesWithDomainIdRequest
+ (*ListHTTPDNSCustomRulesWithDomainIdResponse)(nil), // 6: pb.ListHTTPDNSCustomRulesWithDomainIdResponse
+ (*HTTPDNSCustomRule)(nil), // 7: pb.HTTPDNSCustomRule
+ (*RPCSuccess)(nil), // 8: pb.RPCSuccess
+}
+var file_service_httpdns_rule_proto_depIdxs = []int32{
+ 7, // 0: pb.CreateHTTPDNSCustomRuleRequest.rule:type_name -> pb.HTTPDNSCustomRule
+ 7, // 1: pb.UpdateHTTPDNSCustomRuleRequest.rule:type_name -> pb.HTTPDNSCustomRule
+ 7, // 2: pb.ListHTTPDNSCustomRulesWithDomainIdResponse.rules:type_name -> pb.HTTPDNSCustomRule
+ 0, // 3: pb.HTTPDNSRuleService.createHTTPDNSCustomRule:input_type -> pb.CreateHTTPDNSCustomRuleRequest
+ 2, // 4: pb.HTTPDNSRuleService.updateHTTPDNSCustomRule:input_type -> pb.UpdateHTTPDNSCustomRuleRequest
+ 3, // 5: pb.HTTPDNSRuleService.deleteHTTPDNSCustomRule:input_type -> pb.DeleteHTTPDNSCustomRuleRequest
+ 4, // 6: pb.HTTPDNSRuleService.updateHTTPDNSCustomRuleStatus:input_type -> pb.UpdateHTTPDNSCustomRuleStatusRequest
+ 5, // 7: pb.HTTPDNSRuleService.listHTTPDNSCustomRulesWithDomainId:input_type -> pb.ListHTTPDNSCustomRulesWithDomainIdRequest
+ 1, // 8: pb.HTTPDNSRuleService.createHTTPDNSCustomRule:output_type -> pb.CreateHTTPDNSCustomRuleResponse
+ 8, // 9: pb.HTTPDNSRuleService.updateHTTPDNSCustomRule:output_type -> pb.RPCSuccess
+ 8, // 10: pb.HTTPDNSRuleService.deleteHTTPDNSCustomRule:output_type -> pb.RPCSuccess
+ 8, // 11: pb.HTTPDNSRuleService.updateHTTPDNSCustomRuleStatus:output_type -> pb.RPCSuccess
+ 6, // 12: pb.HTTPDNSRuleService.listHTTPDNSCustomRulesWithDomainId:output_type -> pb.ListHTTPDNSCustomRulesWithDomainIdResponse
+ 8, // [8:13] is the sub-list for method output_type
+ 3, // [3:8] is the sub-list for method input_type
+ 3, // [3:3] is the sub-list for extension type_name
+ 3, // [3:3] is the sub-list for extension extendee
+ 0, // [0:3] is the sub-list for field type_name
+}
+
+func init() { file_service_httpdns_rule_proto_init() }
+func file_service_httpdns_rule_proto_init() {
+ if File_service_httpdns_rule_proto != nil {
+ return
+ }
+ file_models_model_httpdns_rule_proto_init()
+ file_models_rpc_messages_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_service_httpdns_rule_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 7,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_service_httpdns_rule_proto_goTypes,
+ DependencyIndexes: file_service_httpdns_rule_proto_depIdxs,
+ MessageInfos: file_service_httpdns_rule_proto_msgTypes,
+ }.Build()
+ File_service_httpdns_rule_proto = out.File
+ file_service_httpdns_rule_proto_rawDesc = nil
+ file_service_httpdns_rule_proto_goTypes = nil
+ file_service_httpdns_rule_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_rule_grpc.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_rule_grpc.pb.go
new file mode 100644
index 0000000..3f8125f
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_rule_grpc.pb.go
@@ -0,0 +1,271 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.5.1
+// - protoc v3.21.12
+// source: service_httpdns_rule.proto
+
+package pb
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.64.0 or later.
+const _ = grpc.SupportPackageIsVersion9
+
+const (
+ HTTPDNSRuleService_CreateHTTPDNSCustomRule_FullMethodName = "/pb.HTTPDNSRuleService/createHTTPDNSCustomRule"
+ HTTPDNSRuleService_UpdateHTTPDNSCustomRule_FullMethodName = "/pb.HTTPDNSRuleService/updateHTTPDNSCustomRule"
+ HTTPDNSRuleService_DeleteHTTPDNSCustomRule_FullMethodName = "/pb.HTTPDNSRuleService/deleteHTTPDNSCustomRule"
+ HTTPDNSRuleService_UpdateHTTPDNSCustomRuleStatus_FullMethodName = "/pb.HTTPDNSRuleService/updateHTTPDNSCustomRuleStatus"
+ HTTPDNSRuleService_ListHTTPDNSCustomRulesWithDomainId_FullMethodName = "/pb.HTTPDNSRuleService/listHTTPDNSCustomRulesWithDomainId"
+)
+
+// HTTPDNSRuleServiceClient is the client API for HTTPDNSRuleService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type HTTPDNSRuleServiceClient interface {
+ CreateHTTPDNSCustomRule(ctx context.Context, in *CreateHTTPDNSCustomRuleRequest, opts ...grpc.CallOption) (*CreateHTTPDNSCustomRuleResponse, error)
+ UpdateHTTPDNSCustomRule(ctx context.Context, in *UpdateHTTPDNSCustomRuleRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ DeleteHTTPDNSCustomRule(ctx context.Context, in *DeleteHTTPDNSCustomRuleRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ UpdateHTTPDNSCustomRuleStatus(ctx context.Context, in *UpdateHTTPDNSCustomRuleStatusRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ ListHTTPDNSCustomRulesWithDomainId(ctx context.Context, in *ListHTTPDNSCustomRulesWithDomainIdRequest, opts ...grpc.CallOption) (*ListHTTPDNSCustomRulesWithDomainIdResponse, error)
+}
+
+type hTTPDNSRuleServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewHTTPDNSRuleServiceClient(cc grpc.ClientConnInterface) HTTPDNSRuleServiceClient {
+ return &hTTPDNSRuleServiceClient{cc}
+}
+
+func (c *hTTPDNSRuleServiceClient) CreateHTTPDNSCustomRule(ctx context.Context, in *CreateHTTPDNSCustomRuleRequest, opts ...grpc.CallOption) (*CreateHTTPDNSCustomRuleResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(CreateHTTPDNSCustomRuleResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSRuleService_CreateHTTPDNSCustomRule_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSRuleServiceClient) UpdateHTTPDNSCustomRule(ctx context.Context, in *UpdateHTTPDNSCustomRuleRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSRuleService_UpdateHTTPDNSCustomRule_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSRuleServiceClient) DeleteHTTPDNSCustomRule(ctx context.Context, in *DeleteHTTPDNSCustomRuleRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSRuleService_DeleteHTTPDNSCustomRule_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSRuleServiceClient) UpdateHTTPDNSCustomRuleStatus(ctx context.Context, in *UpdateHTTPDNSCustomRuleStatusRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, HTTPDNSRuleService_UpdateHTTPDNSCustomRuleStatus_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSRuleServiceClient) ListHTTPDNSCustomRulesWithDomainId(ctx context.Context, in *ListHTTPDNSCustomRulesWithDomainIdRequest, opts ...grpc.CallOption) (*ListHTTPDNSCustomRulesWithDomainIdResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(ListHTTPDNSCustomRulesWithDomainIdResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSRuleService_ListHTTPDNSCustomRulesWithDomainId_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// HTTPDNSRuleServiceServer is the server API for HTTPDNSRuleService service.
+// All implementations should embed UnimplementedHTTPDNSRuleServiceServer
+// for forward compatibility.
+type HTTPDNSRuleServiceServer interface {
+ CreateHTTPDNSCustomRule(context.Context, *CreateHTTPDNSCustomRuleRequest) (*CreateHTTPDNSCustomRuleResponse, error)
+ UpdateHTTPDNSCustomRule(context.Context, *UpdateHTTPDNSCustomRuleRequest) (*RPCSuccess, error)
+ DeleteHTTPDNSCustomRule(context.Context, *DeleteHTTPDNSCustomRuleRequest) (*RPCSuccess, error)
+ UpdateHTTPDNSCustomRuleStatus(context.Context, *UpdateHTTPDNSCustomRuleStatusRequest) (*RPCSuccess, error)
+ ListHTTPDNSCustomRulesWithDomainId(context.Context, *ListHTTPDNSCustomRulesWithDomainIdRequest) (*ListHTTPDNSCustomRulesWithDomainIdResponse, error)
+}
+
+// UnimplementedHTTPDNSRuleServiceServer should be embedded to have
+// forward compatible implementations.
+//
+// NOTE: this should be embedded by value instead of pointer to avoid a nil
+// pointer dereference when methods are called.
+type UnimplementedHTTPDNSRuleServiceServer struct{}
+
+func (UnimplementedHTTPDNSRuleServiceServer) CreateHTTPDNSCustomRule(context.Context, *CreateHTTPDNSCustomRuleRequest) (*CreateHTTPDNSCustomRuleResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method CreateHTTPDNSCustomRule not implemented")
+}
+func (UnimplementedHTTPDNSRuleServiceServer) UpdateHTTPDNSCustomRule(context.Context, *UpdateHTTPDNSCustomRuleRequest) (*RPCSuccess, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UpdateHTTPDNSCustomRule not implemented")
+}
+func (UnimplementedHTTPDNSRuleServiceServer) DeleteHTTPDNSCustomRule(context.Context, *DeleteHTTPDNSCustomRuleRequest) (*RPCSuccess, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method DeleteHTTPDNSCustomRule not implemented")
+}
+func (UnimplementedHTTPDNSRuleServiceServer) UpdateHTTPDNSCustomRuleStatus(context.Context, *UpdateHTTPDNSCustomRuleStatusRequest) (*RPCSuccess, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UpdateHTTPDNSCustomRuleStatus not implemented")
+}
+func (UnimplementedHTTPDNSRuleServiceServer) ListHTTPDNSCustomRulesWithDomainId(context.Context, *ListHTTPDNSCustomRulesWithDomainIdRequest) (*ListHTTPDNSCustomRulesWithDomainIdResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method ListHTTPDNSCustomRulesWithDomainId not implemented")
+}
+func (UnimplementedHTTPDNSRuleServiceServer) testEmbeddedByValue() {}
+
+// UnsafeHTTPDNSRuleServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to HTTPDNSRuleServiceServer will
+// result in compilation errors.
+type UnsafeHTTPDNSRuleServiceServer interface {
+ mustEmbedUnimplementedHTTPDNSRuleServiceServer()
+}
+
+func RegisterHTTPDNSRuleServiceServer(s grpc.ServiceRegistrar, srv HTTPDNSRuleServiceServer) {
+ // If the following call pancis, it indicates UnimplementedHTTPDNSRuleServiceServer was
+ // embedded by pointer and is nil. This will cause panics if an
+ // unimplemented method is ever invoked, so we test this at initialization
+ // time to prevent it from happening at runtime later due to I/O.
+ if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
+ t.testEmbeddedByValue()
+ }
+ s.RegisterService(&HTTPDNSRuleService_ServiceDesc, srv)
+}
+
+func _HTTPDNSRuleService_CreateHTTPDNSCustomRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CreateHTTPDNSCustomRuleRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSRuleServiceServer).CreateHTTPDNSCustomRule(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSRuleService_CreateHTTPDNSCustomRule_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSRuleServiceServer).CreateHTTPDNSCustomRule(ctx, req.(*CreateHTTPDNSCustomRuleRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSRuleService_UpdateHTTPDNSCustomRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpdateHTTPDNSCustomRuleRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSRuleServiceServer).UpdateHTTPDNSCustomRule(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSRuleService_UpdateHTTPDNSCustomRule_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSRuleServiceServer).UpdateHTTPDNSCustomRule(ctx, req.(*UpdateHTTPDNSCustomRuleRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSRuleService_DeleteHTTPDNSCustomRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(DeleteHTTPDNSCustomRuleRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSRuleServiceServer).DeleteHTTPDNSCustomRule(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSRuleService_DeleteHTTPDNSCustomRule_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSRuleServiceServer).DeleteHTTPDNSCustomRule(ctx, req.(*DeleteHTTPDNSCustomRuleRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSRuleService_UpdateHTTPDNSCustomRuleStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpdateHTTPDNSCustomRuleStatusRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSRuleServiceServer).UpdateHTTPDNSCustomRuleStatus(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSRuleService_UpdateHTTPDNSCustomRuleStatus_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSRuleServiceServer).UpdateHTTPDNSCustomRuleStatus(ctx, req.(*UpdateHTTPDNSCustomRuleStatusRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSRuleService_ListHTTPDNSCustomRulesWithDomainId_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ListHTTPDNSCustomRulesWithDomainIdRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSRuleServiceServer).ListHTTPDNSCustomRulesWithDomainId(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSRuleService_ListHTTPDNSCustomRulesWithDomainId_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSRuleServiceServer).ListHTTPDNSCustomRulesWithDomainId(ctx, req.(*ListHTTPDNSCustomRulesWithDomainIdRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// HTTPDNSRuleService_ServiceDesc is the grpc.ServiceDesc for HTTPDNSRuleService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var HTTPDNSRuleService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "pb.HTTPDNSRuleService",
+ HandlerType: (*HTTPDNSRuleServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "createHTTPDNSCustomRule",
+ Handler: _HTTPDNSRuleService_CreateHTTPDNSCustomRule_Handler,
+ },
+ {
+ MethodName: "updateHTTPDNSCustomRule",
+ Handler: _HTTPDNSRuleService_UpdateHTTPDNSCustomRule_Handler,
+ },
+ {
+ MethodName: "deleteHTTPDNSCustomRule",
+ Handler: _HTTPDNSRuleService_DeleteHTTPDNSCustomRule_Handler,
+ },
+ {
+ MethodName: "updateHTTPDNSCustomRuleStatus",
+ Handler: _HTTPDNSRuleService_UpdateHTTPDNSCustomRuleStatus_Handler,
+ },
+ {
+ MethodName: "listHTTPDNSCustomRulesWithDomainId",
+ Handler: _HTTPDNSRuleService_ListHTTPDNSCustomRulesWithDomainId_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "service_httpdns_rule.proto",
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_runtime_log.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_runtime_log.pb.go
new file mode 100644
index 0000000..745b604
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_runtime_log.pb.go
@@ -0,0 +1,359 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.35.1
+// protoc v3.21.12
+// source: service_httpdns_runtime_log.proto
+
+package pb
+
+import (
+ 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 CreateHTTPDNSRuntimeLogsRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Logs []*HTTPDNSRuntimeLog `protobuf:"bytes,1,rep,name=logs,proto3" json:"logs,omitempty"`
+}
+
+func (x *CreateHTTPDNSRuntimeLogsRequest) Reset() {
+ *x = CreateHTTPDNSRuntimeLogsRequest{}
+ mi := &file_service_httpdns_runtime_log_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSRuntimeLogsRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSRuntimeLogsRequest) ProtoMessage() {}
+
+func (x *CreateHTTPDNSRuntimeLogsRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_runtime_log_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSRuntimeLogsRequest.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSRuntimeLogsRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_runtime_log_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CreateHTTPDNSRuntimeLogsRequest) GetLogs() []*HTTPDNSRuntimeLog {
+ if x != nil {
+ return x.Logs
+ }
+ return nil
+}
+
+type CreateHTTPDNSRuntimeLogsResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *CreateHTTPDNSRuntimeLogsResponse) Reset() {
+ *x = CreateHTTPDNSRuntimeLogsResponse{}
+ mi := &file_service_httpdns_runtime_log_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *CreateHTTPDNSRuntimeLogsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreateHTTPDNSRuntimeLogsResponse) ProtoMessage() {}
+
+func (x *CreateHTTPDNSRuntimeLogsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_runtime_log_proto_msgTypes[1]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreateHTTPDNSRuntimeLogsResponse.ProtoReflect.Descriptor instead.
+func (*CreateHTTPDNSRuntimeLogsResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_runtime_log_proto_rawDescGZIP(), []int{1}
+}
+
+type ListHTTPDNSRuntimeLogsRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Day string `protobuf:"bytes,1,opt,name=day,proto3" json:"day,omitempty"`
+ ClusterId int64 `protobuf:"varint,2,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+ NodeId int64 `protobuf:"varint,3,opt,name=nodeId,proto3" json:"nodeId,omitempty"`
+ Level string `protobuf:"bytes,4,opt,name=level,proto3" json:"level,omitempty"`
+ Keyword string `protobuf:"bytes,5,opt,name=keyword,proto3" json:"keyword,omitempty"`
+ Offset int64 `protobuf:"varint,6,opt,name=offset,proto3" json:"offset,omitempty"`
+ Size int64 `protobuf:"varint,7,opt,name=size,proto3" json:"size,omitempty"`
+}
+
+func (x *ListHTTPDNSRuntimeLogsRequest) Reset() {
+ *x = ListHTTPDNSRuntimeLogsRequest{}
+ mi := &file_service_httpdns_runtime_log_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSRuntimeLogsRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSRuntimeLogsRequest) ProtoMessage() {}
+
+func (x *ListHTTPDNSRuntimeLogsRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_runtime_log_proto_msgTypes[2]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSRuntimeLogsRequest.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSRuntimeLogsRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_runtime_log_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *ListHTTPDNSRuntimeLogsRequest) GetDay() string {
+ if x != nil {
+ return x.Day
+ }
+ return ""
+}
+
+func (x *ListHTTPDNSRuntimeLogsRequest) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+func (x *ListHTTPDNSRuntimeLogsRequest) GetNodeId() int64 {
+ if x != nil {
+ return x.NodeId
+ }
+ return 0
+}
+
+func (x *ListHTTPDNSRuntimeLogsRequest) GetLevel() string {
+ if x != nil {
+ return x.Level
+ }
+ return ""
+}
+
+func (x *ListHTTPDNSRuntimeLogsRequest) GetKeyword() string {
+ if x != nil {
+ return x.Keyword
+ }
+ return ""
+}
+
+func (x *ListHTTPDNSRuntimeLogsRequest) GetOffset() int64 {
+ if x != nil {
+ return x.Offset
+ }
+ return 0
+}
+
+func (x *ListHTTPDNSRuntimeLogsRequest) GetSize() int64 {
+ if x != nil {
+ return x.Size
+ }
+ return 0
+}
+
+type ListHTTPDNSRuntimeLogsResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Logs []*HTTPDNSRuntimeLog `protobuf:"bytes,1,rep,name=logs,proto3" json:"logs,omitempty"`
+ Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"`
+}
+
+func (x *ListHTTPDNSRuntimeLogsResponse) Reset() {
+ *x = ListHTTPDNSRuntimeLogsResponse{}
+ mi := &file_service_httpdns_runtime_log_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *ListHTTPDNSRuntimeLogsResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListHTTPDNSRuntimeLogsResponse) ProtoMessage() {}
+
+func (x *ListHTTPDNSRuntimeLogsResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_runtime_log_proto_msgTypes[3]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ListHTTPDNSRuntimeLogsResponse.ProtoReflect.Descriptor instead.
+func (*ListHTTPDNSRuntimeLogsResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_runtime_log_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *ListHTTPDNSRuntimeLogsResponse) GetLogs() []*HTTPDNSRuntimeLog {
+ if x != nil {
+ return x.Logs
+ }
+ return nil
+}
+
+func (x *ListHTTPDNSRuntimeLogsResponse) GetTotal() int64 {
+ if x != nil {
+ return x.Total
+ }
+ return 0
+}
+
+var File_service_httpdns_runtime_log_proto protoreflect.FileDescriptor
+
+var file_service_httpdns_runtime_log_proto_rawDesc = []byte{
+ 0x0a, 0x21, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x64, 0x6e,
+ 0x73, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x26, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f,
+ 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x64, 0x6e, 0x73, 0x5f, 0x72, 0x75,
+ 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
+ 0x4c, 0x0a, 0x1f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53,
+ 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x12, 0x29, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x75, 0x6e,
+ 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x22, 0x22, 0x0a,
+ 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x75,
+ 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x22, 0xc3, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e,
+ 0x53, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x03, 0x64, 0x61, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
+ 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65,
+ 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c,
+ 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65,
+ 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6f,
+ 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, 0x66, 0x66,
+ 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x61, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x48,
+ 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x67,
+ 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x04, 0x6c, 0x6f, 0x67,
+ 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x54, 0x54,
+ 0x50, 0x44, 0x4e, 0x53, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x67, 0x52, 0x04,
+ 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x32, 0xe2, 0x01, 0x0a, 0x18, 0x48,
+ 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x67,
+ 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x65, 0x0a, 0x18, 0x63, 0x72, 0x65, 0x61, 0x74,
+ 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4c,
+ 0x6f, 0x67, 0x73, 0x12, 0x23, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48,
+ 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x67,
+ 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x75, 0x6e, 0x74, 0x69,
+ 0x6d, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f,
+ 0x0a, 0x16, 0x6c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x75, 0x6e,
+ 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x21, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69,
+ 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65,
+ 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x70, 0x62,
+ 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x75, 0x6e, 0x74,
+ 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42,
+ 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_service_httpdns_runtime_log_proto_rawDescOnce sync.Once
+ file_service_httpdns_runtime_log_proto_rawDescData = file_service_httpdns_runtime_log_proto_rawDesc
+)
+
+func file_service_httpdns_runtime_log_proto_rawDescGZIP() []byte {
+ file_service_httpdns_runtime_log_proto_rawDescOnce.Do(func() {
+ file_service_httpdns_runtime_log_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_httpdns_runtime_log_proto_rawDescData)
+ })
+ return file_service_httpdns_runtime_log_proto_rawDescData
+}
+
+var file_service_httpdns_runtime_log_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_service_httpdns_runtime_log_proto_goTypes = []any{
+ (*CreateHTTPDNSRuntimeLogsRequest)(nil), // 0: pb.CreateHTTPDNSRuntimeLogsRequest
+ (*CreateHTTPDNSRuntimeLogsResponse)(nil), // 1: pb.CreateHTTPDNSRuntimeLogsResponse
+ (*ListHTTPDNSRuntimeLogsRequest)(nil), // 2: pb.ListHTTPDNSRuntimeLogsRequest
+ (*ListHTTPDNSRuntimeLogsResponse)(nil), // 3: pb.ListHTTPDNSRuntimeLogsResponse
+ (*HTTPDNSRuntimeLog)(nil), // 4: pb.HTTPDNSRuntimeLog
+}
+var file_service_httpdns_runtime_log_proto_depIdxs = []int32{
+ 4, // 0: pb.CreateHTTPDNSRuntimeLogsRequest.logs:type_name -> pb.HTTPDNSRuntimeLog
+ 4, // 1: pb.ListHTTPDNSRuntimeLogsResponse.logs:type_name -> pb.HTTPDNSRuntimeLog
+ 0, // 2: pb.HTTPDNSRuntimeLogService.createHTTPDNSRuntimeLogs:input_type -> pb.CreateHTTPDNSRuntimeLogsRequest
+ 2, // 3: pb.HTTPDNSRuntimeLogService.listHTTPDNSRuntimeLogs:input_type -> pb.ListHTTPDNSRuntimeLogsRequest
+ 1, // 4: pb.HTTPDNSRuntimeLogService.createHTTPDNSRuntimeLogs:output_type -> pb.CreateHTTPDNSRuntimeLogsResponse
+ 3, // 5: pb.HTTPDNSRuntimeLogService.listHTTPDNSRuntimeLogs:output_type -> pb.ListHTTPDNSRuntimeLogsResponse
+ 4, // [4:6] is the sub-list for method output_type
+ 2, // [2:4] is the sub-list for method input_type
+ 2, // [2:2] is the sub-list for extension type_name
+ 2, // [2:2] is the sub-list for extension extendee
+ 0, // [0:2] is the sub-list for field type_name
+}
+
+func init() { file_service_httpdns_runtime_log_proto_init() }
+func file_service_httpdns_runtime_log_proto_init() {
+ if File_service_httpdns_runtime_log_proto != nil {
+ return
+ }
+ file_models_model_httpdns_runtime_log_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_service_httpdns_runtime_log_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 4,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_service_httpdns_runtime_log_proto_goTypes,
+ DependencyIndexes: file_service_httpdns_runtime_log_proto_depIdxs,
+ MessageInfos: file_service_httpdns_runtime_log_proto_msgTypes,
+ }.Build()
+ File_service_httpdns_runtime_log_proto = out.File
+ file_service_httpdns_runtime_log_proto_rawDesc = nil
+ file_service_httpdns_runtime_log_proto_goTypes = nil
+ file_service_httpdns_runtime_log_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_runtime_log_grpc.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_runtime_log_grpc.pb.go
new file mode 100644
index 0000000..ad2e296
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_runtime_log_grpc.pb.go
@@ -0,0 +1,157 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.5.1
+// - protoc v3.21.12
+// source: service_httpdns_runtime_log.proto
+
+package pb
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.64.0 or later.
+const _ = grpc.SupportPackageIsVersion9
+
+const (
+ HTTPDNSRuntimeLogService_CreateHTTPDNSRuntimeLogs_FullMethodName = "/pb.HTTPDNSRuntimeLogService/createHTTPDNSRuntimeLogs"
+ HTTPDNSRuntimeLogService_ListHTTPDNSRuntimeLogs_FullMethodName = "/pb.HTTPDNSRuntimeLogService/listHTTPDNSRuntimeLogs"
+)
+
+// HTTPDNSRuntimeLogServiceClient is the client API for HTTPDNSRuntimeLogService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type HTTPDNSRuntimeLogServiceClient interface {
+ CreateHTTPDNSRuntimeLogs(ctx context.Context, in *CreateHTTPDNSRuntimeLogsRequest, opts ...grpc.CallOption) (*CreateHTTPDNSRuntimeLogsResponse, error)
+ ListHTTPDNSRuntimeLogs(ctx context.Context, in *ListHTTPDNSRuntimeLogsRequest, opts ...grpc.CallOption) (*ListHTTPDNSRuntimeLogsResponse, error)
+}
+
+type hTTPDNSRuntimeLogServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewHTTPDNSRuntimeLogServiceClient(cc grpc.ClientConnInterface) HTTPDNSRuntimeLogServiceClient {
+ return &hTTPDNSRuntimeLogServiceClient{cc}
+}
+
+func (c *hTTPDNSRuntimeLogServiceClient) CreateHTTPDNSRuntimeLogs(ctx context.Context, in *CreateHTTPDNSRuntimeLogsRequest, opts ...grpc.CallOption) (*CreateHTTPDNSRuntimeLogsResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(CreateHTTPDNSRuntimeLogsResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSRuntimeLogService_CreateHTTPDNSRuntimeLogs_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *hTTPDNSRuntimeLogServiceClient) ListHTTPDNSRuntimeLogs(ctx context.Context, in *ListHTTPDNSRuntimeLogsRequest, opts ...grpc.CallOption) (*ListHTTPDNSRuntimeLogsResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(ListHTTPDNSRuntimeLogsResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSRuntimeLogService_ListHTTPDNSRuntimeLogs_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// HTTPDNSRuntimeLogServiceServer is the server API for HTTPDNSRuntimeLogService service.
+// All implementations should embed UnimplementedHTTPDNSRuntimeLogServiceServer
+// for forward compatibility.
+type HTTPDNSRuntimeLogServiceServer interface {
+ CreateHTTPDNSRuntimeLogs(context.Context, *CreateHTTPDNSRuntimeLogsRequest) (*CreateHTTPDNSRuntimeLogsResponse, error)
+ ListHTTPDNSRuntimeLogs(context.Context, *ListHTTPDNSRuntimeLogsRequest) (*ListHTTPDNSRuntimeLogsResponse, error)
+}
+
+// UnimplementedHTTPDNSRuntimeLogServiceServer should be embedded to have
+// forward compatible implementations.
+//
+// NOTE: this should be embedded by value instead of pointer to avoid a nil
+// pointer dereference when methods are called.
+type UnimplementedHTTPDNSRuntimeLogServiceServer struct{}
+
+func (UnimplementedHTTPDNSRuntimeLogServiceServer) CreateHTTPDNSRuntimeLogs(context.Context, *CreateHTTPDNSRuntimeLogsRequest) (*CreateHTTPDNSRuntimeLogsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method CreateHTTPDNSRuntimeLogs not implemented")
+}
+func (UnimplementedHTTPDNSRuntimeLogServiceServer) ListHTTPDNSRuntimeLogs(context.Context, *ListHTTPDNSRuntimeLogsRequest) (*ListHTTPDNSRuntimeLogsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method ListHTTPDNSRuntimeLogs not implemented")
+}
+func (UnimplementedHTTPDNSRuntimeLogServiceServer) testEmbeddedByValue() {}
+
+// UnsafeHTTPDNSRuntimeLogServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to HTTPDNSRuntimeLogServiceServer will
+// result in compilation errors.
+type UnsafeHTTPDNSRuntimeLogServiceServer interface {
+ mustEmbedUnimplementedHTTPDNSRuntimeLogServiceServer()
+}
+
+func RegisterHTTPDNSRuntimeLogServiceServer(s grpc.ServiceRegistrar, srv HTTPDNSRuntimeLogServiceServer) {
+ // If the following call pancis, it indicates UnimplementedHTTPDNSRuntimeLogServiceServer was
+ // embedded by pointer and is nil. This will cause panics if an
+ // unimplemented method is ever invoked, so we test this at initialization
+ // time to prevent it from happening at runtime later due to I/O.
+ if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
+ t.testEmbeddedByValue()
+ }
+ s.RegisterService(&HTTPDNSRuntimeLogService_ServiceDesc, srv)
+}
+
+func _HTTPDNSRuntimeLogService_CreateHTTPDNSRuntimeLogs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CreateHTTPDNSRuntimeLogsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSRuntimeLogServiceServer).CreateHTTPDNSRuntimeLogs(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSRuntimeLogService_CreateHTTPDNSRuntimeLogs_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSRuntimeLogServiceServer).CreateHTTPDNSRuntimeLogs(ctx, req.(*CreateHTTPDNSRuntimeLogsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _HTTPDNSRuntimeLogService_ListHTTPDNSRuntimeLogs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(ListHTTPDNSRuntimeLogsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSRuntimeLogServiceServer).ListHTTPDNSRuntimeLogs(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSRuntimeLogService_ListHTTPDNSRuntimeLogs_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSRuntimeLogServiceServer).ListHTTPDNSRuntimeLogs(ctx, req.(*ListHTTPDNSRuntimeLogsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// HTTPDNSRuntimeLogService_ServiceDesc is the grpc.ServiceDesc for HTTPDNSRuntimeLogService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var HTTPDNSRuntimeLogService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "pb.HTTPDNSRuntimeLogService",
+ HandlerType: (*HTTPDNSRuntimeLogServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "createHTTPDNSRuntimeLogs",
+ Handler: _HTTPDNSRuntimeLogService_CreateHTTPDNSRuntimeLogs_Handler,
+ },
+ {
+ MethodName: "listHTTPDNSRuntimeLogs",
+ Handler: _HTTPDNSRuntimeLogService_ListHTTPDNSRuntimeLogs_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "service_httpdns_runtime_log.proto",
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_sandbox.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_sandbox.pb.go
new file mode 100644
index 0000000..6b4be37
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_sandbox.pb.go
@@ -0,0 +1,460 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.35.1
+// protoc v3.21.12
+// source: service_httpdns_sandbox.proto
+
+package pb
+
+import (
+ 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 TestHTTPDNSResolveRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ ClusterId int64 `protobuf:"varint,1,opt,name=clusterId,proto3" json:"clusterId,omitempty"`
+ AppId string `protobuf:"bytes,2,opt,name=appId,proto3" json:"appId,omitempty"`
+ Domain string `protobuf:"bytes,3,opt,name=domain,proto3" json:"domain,omitempty"`
+ Qtype string `protobuf:"bytes,4,opt,name=qtype,proto3" json:"qtype,omitempty"`
+ ClientIP string `protobuf:"bytes,5,opt,name=clientIP,proto3" json:"clientIP,omitempty"`
+ Sid string `protobuf:"bytes,6,opt,name=sid,proto3" json:"sid,omitempty"`
+ SdkVersion string `protobuf:"bytes,7,opt,name=sdkVersion,proto3" json:"sdkVersion,omitempty"`
+ Os string `protobuf:"bytes,8,opt,name=os,proto3" json:"os,omitempty"`
+}
+
+func (x *TestHTTPDNSResolveRequest) Reset() {
+ *x = TestHTTPDNSResolveRequest{}
+ mi := &file_service_httpdns_sandbox_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *TestHTTPDNSResolveRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TestHTTPDNSResolveRequest) ProtoMessage() {}
+
+func (x *TestHTTPDNSResolveRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_sandbox_proto_msgTypes[0]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use TestHTTPDNSResolveRequest.ProtoReflect.Descriptor instead.
+func (*TestHTTPDNSResolveRequest) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_sandbox_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *TestHTTPDNSResolveRequest) GetClusterId() int64 {
+ if x != nil {
+ return x.ClusterId
+ }
+ return 0
+}
+
+func (x *TestHTTPDNSResolveRequest) GetAppId() string {
+ if x != nil {
+ return x.AppId
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveRequest) GetDomain() string {
+ if x != nil {
+ return x.Domain
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveRequest) GetQtype() string {
+ if x != nil {
+ return x.Qtype
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveRequest) GetClientIP() string {
+ if x != nil {
+ return x.ClientIP
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveRequest) GetSid() string {
+ if x != nil {
+ return x.Sid
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveRequest) GetSdkVersion() string {
+ if x != nil {
+ return x.SdkVersion
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveRequest) GetOs() string {
+ if x != nil {
+ return x.Os
+ }
+ return ""
+}
+
+type HTTPDNSResolveRecord struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
+ Ip string `protobuf:"bytes,2,opt,name=ip,proto3" json:"ip,omitempty"`
+ Ttl int32 `protobuf:"varint,3,opt,name=ttl,proto3" json:"ttl,omitempty"`
+ Weight int32 `protobuf:"varint,4,opt,name=weight,proto3" json:"weight,omitempty"`
+ Line string `protobuf:"bytes,5,opt,name=line,proto3" json:"line,omitempty"`
+ Region string `protobuf:"bytes,6,opt,name=region,proto3" json:"region,omitempty"`
+}
+
+func (x *HTTPDNSResolveRecord) Reset() {
+ *x = HTTPDNSResolveRecord{}
+ mi := &file_service_httpdns_sandbox_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *HTTPDNSResolveRecord) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HTTPDNSResolveRecord) ProtoMessage() {}
+
+func (x *HTTPDNSResolveRecord) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_sandbox_proto_msgTypes[1]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HTTPDNSResolveRecord.ProtoReflect.Descriptor instead.
+func (*HTTPDNSResolveRecord) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_sandbox_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *HTTPDNSResolveRecord) GetType() string {
+ if x != nil {
+ return x.Type
+ }
+ return ""
+}
+
+func (x *HTTPDNSResolveRecord) GetIp() string {
+ if x != nil {
+ return x.Ip
+ }
+ return ""
+}
+
+func (x *HTTPDNSResolveRecord) GetTtl() int32 {
+ if x != nil {
+ return x.Ttl
+ }
+ return 0
+}
+
+func (x *HTTPDNSResolveRecord) GetWeight() int32 {
+ if x != nil {
+ return x.Weight
+ }
+ return 0
+}
+
+func (x *HTTPDNSResolveRecord) GetLine() string {
+ if x != nil {
+ return x.Line
+ }
+ return ""
+}
+
+func (x *HTTPDNSResolveRecord) GetRegion() string {
+ if x != nil {
+ return x.Region
+ }
+ return ""
+}
+
+type TestHTTPDNSResolveResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
+ Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
+ RequestId string `protobuf:"bytes,3,opt,name=requestId,proto3" json:"requestId,omitempty"`
+ Domain string `protobuf:"bytes,4,opt,name=domain,proto3" json:"domain,omitempty"`
+ Qtype string `protobuf:"bytes,5,opt,name=qtype,proto3" json:"qtype,omitempty"`
+ Ttl int32 `protobuf:"varint,6,opt,name=ttl,proto3" json:"ttl,omitempty"`
+ Records []*HTTPDNSResolveRecord `protobuf:"bytes,7,rep,name=records,proto3" json:"records,omitempty"`
+ ClientIP string `protobuf:"bytes,8,opt,name=clientIP,proto3" json:"clientIP,omitempty"`
+ ClientRegion string `protobuf:"bytes,9,opt,name=clientRegion,proto3" json:"clientRegion,omitempty"`
+ ClientCarrier string `protobuf:"bytes,10,opt,name=clientCarrier,proto3" json:"clientCarrier,omitempty"`
+ ClientCountry string `protobuf:"bytes,11,opt,name=clientCountry,proto3" json:"clientCountry,omitempty"`
+ Summary string `protobuf:"bytes,12,opt,name=summary,proto3" json:"summary,omitempty"`
+}
+
+func (x *TestHTTPDNSResolveResponse) Reset() {
+ *x = TestHTTPDNSResolveResponse{}
+ mi := &file_service_httpdns_sandbox_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *TestHTTPDNSResolveResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TestHTTPDNSResolveResponse) ProtoMessage() {}
+
+func (x *TestHTTPDNSResolveResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_service_httpdns_sandbox_proto_msgTypes[2]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use TestHTTPDNSResolveResponse.ProtoReflect.Descriptor instead.
+func (*TestHTTPDNSResolveResponse) Descriptor() ([]byte, []int) {
+ return file_service_httpdns_sandbox_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *TestHTTPDNSResolveResponse) GetCode() string {
+ if x != nil {
+ return x.Code
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveResponse) GetMessage() string {
+ if x != nil {
+ return x.Message
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveResponse) GetRequestId() string {
+ if x != nil {
+ return x.RequestId
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveResponse) GetDomain() string {
+ if x != nil {
+ return x.Domain
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveResponse) GetQtype() string {
+ if x != nil {
+ return x.Qtype
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveResponse) GetTtl() int32 {
+ if x != nil {
+ return x.Ttl
+ }
+ return 0
+}
+
+func (x *TestHTTPDNSResolveResponse) GetRecords() []*HTTPDNSResolveRecord {
+ if x != nil {
+ return x.Records
+ }
+ return nil
+}
+
+func (x *TestHTTPDNSResolveResponse) GetClientIP() string {
+ if x != nil {
+ return x.ClientIP
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveResponse) GetClientRegion() string {
+ if x != nil {
+ return x.ClientRegion
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveResponse) GetClientCarrier() string {
+ if x != nil {
+ return x.ClientCarrier
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveResponse) GetClientCountry() string {
+ if x != nil {
+ return x.ClientCountry
+ }
+ return ""
+}
+
+func (x *TestHTTPDNSResolveResponse) GetSummary() string {
+ if x != nil {
+ return x.Summary
+ }
+ return ""
+}
+
+var File_service_httpdns_sandbox_proto protoreflect.FileDescriptor
+
+var file_service_httpdns_sandbox_proto_rawDesc = []byte{
+ 0x0a, 0x1d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x64, 0x6e,
+ 0x73, 0x5f, 0x73, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+ 0x02, 0x70, 0x62, 0x1a, 0x19, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x72, 0x70, 0x63, 0x5f,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdb,
+ 0x01, 0x0a, 0x19, 0x54, 0x65, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x65,
+ 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09,
+ 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x70,
+ 0x70, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x49, 0x64,
+ 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x74, 0x79, 0x70,
+ 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a,
+ 0x0a, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69,
+ 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x0a,
+ 0x73, 0x64, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0a, 0x73, 0x64, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02,
+ 0x6f, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x73, 0x22, 0x90, 0x01, 0x0a,
+ 0x14, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52,
+ 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x74, 0x6c,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x77,
+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x77, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f,
+ 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x22,
+ 0x82, 0x03, 0x0a, 0x1a, 0x54, 0x65, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52,
+ 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12,
+ 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f,
+ 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f,
+ 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61,
+ 0x69, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x05, 0x71, 0x74, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x12, 0x32, 0x0a, 0x07, 0x72, 0x65,
+ 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x62,
+ 0x2e, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52,
+ 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x1a,
+ 0x0a, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x24,
+ 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18,
+ 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x72,
+ 0x72, 0x69, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f,
+ 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x69,
+ 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75,
+ 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x6d,
+ 0x6d, 0x61, 0x72, 0x79, 0x32, 0x6c, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x53,
+ 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x53, 0x0a,
+ 0x12, 0x74, 0x65, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50, 0x44, 0x4e, 0x53, 0x52, 0x65, 0x73, 0x6f,
+ 0x6c, 0x76, 0x65, 0x12, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x48, 0x54, 0x54,
+ 0x50, 0x44, 0x4e, 0x53, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x48, 0x54, 0x54, 0x50,
+ 0x44, 0x4e, 0x53, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x33,
+}
+
+var (
+ file_service_httpdns_sandbox_proto_rawDescOnce sync.Once
+ file_service_httpdns_sandbox_proto_rawDescData = file_service_httpdns_sandbox_proto_rawDesc
+)
+
+func file_service_httpdns_sandbox_proto_rawDescGZIP() []byte {
+ file_service_httpdns_sandbox_proto_rawDescOnce.Do(func() {
+ file_service_httpdns_sandbox_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_httpdns_sandbox_proto_rawDescData)
+ })
+ return file_service_httpdns_sandbox_proto_rawDescData
+}
+
+var file_service_httpdns_sandbox_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
+var file_service_httpdns_sandbox_proto_goTypes = []any{
+ (*TestHTTPDNSResolveRequest)(nil), // 0: pb.TestHTTPDNSResolveRequest
+ (*HTTPDNSResolveRecord)(nil), // 1: pb.HTTPDNSResolveRecord
+ (*TestHTTPDNSResolveResponse)(nil), // 2: pb.TestHTTPDNSResolveResponse
+}
+var file_service_httpdns_sandbox_proto_depIdxs = []int32{
+ 1, // 0: pb.TestHTTPDNSResolveResponse.records:type_name -> pb.HTTPDNSResolveRecord
+ 0, // 1: pb.HTTPDNSSandboxService.testHTTPDNSResolve:input_type -> pb.TestHTTPDNSResolveRequest
+ 2, // 2: pb.HTTPDNSSandboxService.testHTTPDNSResolve:output_type -> pb.TestHTTPDNSResolveResponse
+ 2, // [2:3] is the sub-list for method output_type
+ 1, // [1:2] 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_service_httpdns_sandbox_proto_init() }
+func file_service_httpdns_sandbox_proto_init() {
+ if File_service_httpdns_sandbox_proto != nil {
+ return
+ }
+ file_models_rpc_messages_proto_init()
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_service_httpdns_sandbox_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 3,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_service_httpdns_sandbox_proto_goTypes,
+ DependencyIndexes: file_service_httpdns_sandbox_proto_depIdxs,
+ MessageInfos: file_service_httpdns_sandbox_proto_msgTypes,
+ }.Build()
+ File_service_httpdns_sandbox_proto = out.File
+ file_service_httpdns_sandbox_proto_rawDesc = nil
+ file_service_httpdns_sandbox_proto_goTypes = nil
+ file_service_httpdns_sandbox_proto_depIdxs = nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_httpdns_sandbox_grpc.pb.go b/EdgeCommon/pkg/rpc/pb/service_httpdns_sandbox_grpc.pb.go
new file mode 100644
index 0000000..e7b9daa
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_httpdns_sandbox_grpc.pb.go
@@ -0,0 +1,119 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.5.1
+// - protoc v3.21.12
+// source: service_httpdns_sandbox.proto
+
+package pb
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.64.0 or later.
+const _ = grpc.SupportPackageIsVersion9
+
+const (
+ HTTPDNSSandboxService_TestHTTPDNSResolve_FullMethodName = "/pb.HTTPDNSSandboxService/testHTTPDNSResolve"
+)
+
+// HTTPDNSSandboxServiceClient is the client API for HTTPDNSSandboxService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type HTTPDNSSandboxServiceClient interface {
+ TestHTTPDNSResolve(ctx context.Context, in *TestHTTPDNSResolveRequest, opts ...grpc.CallOption) (*TestHTTPDNSResolveResponse, error)
+}
+
+type hTTPDNSSandboxServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewHTTPDNSSandboxServiceClient(cc grpc.ClientConnInterface) HTTPDNSSandboxServiceClient {
+ return &hTTPDNSSandboxServiceClient{cc}
+}
+
+func (c *hTTPDNSSandboxServiceClient) TestHTTPDNSResolve(ctx context.Context, in *TestHTTPDNSResolveRequest, opts ...grpc.CallOption) (*TestHTTPDNSResolveResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(TestHTTPDNSResolveResponse)
+ err := c.cc.Invoke(ctx, HTTPDNSSandboxService_TestHTTPDNSResolve_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// HTTPDNSSandboxServiceServer is the server API for HTTPDNSSandboxService service.
+// All implementations should embed UnimplementedHTTPDNSSandboxServiceServer
+// for forward compatibility.
+type HTTPDNSSandboxServiceServer interface {
+ TestHTTPDNSResolve(context.Context, *TestHTTPDNSResolveRequest) (*TestHTTPDNSResolveResponse, error)
+}
+
+// UnimplementedHTTPDNSSandboxServiceServer should be embedded to have
+// forward compatible implementations.
+//
+// NOTE: this should be embedded by value instead of pointer to avoid a nil
+// pointer dereference when methods are called.
+type UnimplementedHTTPDNSSandboxServiceServer struct{}
+
+func (UnimplementedHTTPDNSSandboxServiceServer) TestHTTPDNSResolve(context.Context, *TestHTTPDNSResolveRequest) (*TestHTTPDNSResolveResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method TestHTTPDNSResolve not implemented")
+}
+func (UnimplementedHTTPDNSSandboxServiceServer) testEmbeddedByValue() {}
+
+// UnsafeHTTPDNSSandboxServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to HTTPDNSSandboxServiceServer will
+// result in compilation errors.
+type UnsafeHTTPDNSSandboxServiceServer interface {
+ mustEmbedUnimplementedHTTPDNSSandboxServiceServer()
+}
+
+func RegisterHTTPDNSSandboxServiceServer(s grpc.ServiceRegistrar, srv HTTPDNSSandboxServiceServer) {
+ // If the following call pancis, it indicates UnimplementedHTTPDNSSandboxServiceServer was
+ // embedded by pointer and is nil. This will cause panics if an
+ // unimplemented method is ever invoked, so we test this at initialization
+ // time to prevent it from happening at runtime later due to I/O.
+ if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
+ t.testEmbeddedByValue()
+ }
+ s.RegisterService(&HTTPDNSSandboxService_ServiceDesc, srv)
+}
+
+func _HTTPDNSSandboxService_TestHTTPDNSResolve_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(TestHTTPDNSResolveRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(HTTPDNSSandboxServiceServer).TestHTTPDNSResolve(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: HTTPDNSSandboxService_TestHTTPDNSResolve_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(HTTPDNSSandboxServiceServer).TestHTTPDNSResolve(ctx, req.(*TestHTTPDNSResolveRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// HTTPDNSSandboxService_ServiceDesc is the grpc.ServiceDesc for HTTPDNSSandboxService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var HTTPDNSSandboxService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "pb.HTTPDNSSandboxService",
+ HandlerType: (*HTTPDNSSandboxServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "testHTTPDNSResolve",
+ Handler: _HTTPDNSSandboxService_TestHTTPDNSResolve_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "service_httpdns_sandbox.proto",
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_ns_node_grpc.pb.go b/EdgeCommon/pkg/rpc/pb/service_ns_node_grpc.pb.go
index 97acd0d..faf19a1 100644
--- a/EdgeCommon/pkg/rpc/pb/service_ns_node_grpc.pb.go
+++ b/EdgeCommon/pkg/rpc/pb/service_ns_node_grpc.pb.go
@@ -46,6 +46,8 @@ const (
NSNodeService_UpdateNSNodeDDoSProtection_FullMethodName = "/pb.NSNodeService/updateNSNodeDDoSProtection"
NSNodeService_FindNSNodeAPIConfig_FullMethodName = "/pb.NSNodeService/findNSNodeAPIConfig"
NSNodeService_UpdateNSNodeAPIConfig_FullMethodName = "/pb.NSNodeService/updateNSNodeAPIConfig"
+ NSNodeService_FindAllUpgradeNSNodesWithNSClusterId_FullMethodName = "/pb.NSNodeService/findAllUpgradeNSNodesWithNSClusterId"
+ NSNodeService_UpgradeNSNode_FullMethodName = "/pb.NSNodeService/upgradeNSNode"
)
// NSNodeServiceClient is the client API for NSNodeService service.
@@ -108,6 +110,10 @@ type NSNodeServiceClient interface {
FindNSNodeAPIConfig(ctx context.Context, in *FindNSNodeAPIConfigRequest, opts ...grpc.CallOption) (*FindNSNodeAPIConfigResponse, error)
// 修改某个节点的API相关配置
UpdateNSNodeAPIConfig(ctx context.Context, in *UpdateNSNodeAPIConfigRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
+ // 列出所有需要升级的NS节点
+ FindAllUpgradeNSNodesWithNSClusterId(ctx context.Context, in *FindAllUpgradeNSNodesWithNSClusterIdRequest, opts ...grpc.CallOption) (*FindAllUpgradeNSNodesWithNSClusterIdResponse, error)
+ // 升级单个NS节点
+ UpgradeNSNode(ctx context.Context, in *UpgradeNSNodeRequest, opts ...grpc.CallOption) (*RPCSuccess, error)
}
type nSNodeServiceClient struct {
@@ -391,6 +397,26 @@ func (c *nSNodeServiceClient) UpdateNSNodeAPIConfig(ctx context.Context, in *Upd
return out, nil
}
+func (c *nSNodeServiceClient) FindAllUpgradeNSNodesWithNSClusterId(ctx context.Context, in *FindAllUpgradeNSNodesWithNSClusterIdRequest, opts ...grpc.CallOption) (*FindAllUpgradeNSNodesWithNSClusterIdResponse, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(FindAllUpgradeNSNodesWithNSClusterIdResponse)
+ err := c.cc.Invoke(ctx, NSNodeService_FindAllUpgradeNSNodesWithNSClusterId_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *nSNodeServiceClient) UpgradeNSNode(ctx context.Context, in *UpgradeNSNodeRequest, opts ...grpc.CallOption) (*RPCSuccess, error) {
+ cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+ out := new(RPCSuccess)
+ err := c.cc.Invoke(ctx, NSNodeService_UpgradeNSNode_FullMethodName, in, out, cOpts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
// NSNodeServiceServer is the server API for NSNodeService service.
// All implementations should embed UnimplementedNSNodeServiceServer
// for forward compatibility.
@@ -451,6 +477,10 @@ type NSNodeServiceServer interface {
FindNSNodeAPIConfig(context.Context, *FindNSNodeAPIConfigRequest) (*FindNSNodeAPIConfigResponse, error)
// 修改某个节点的API相关配置
UpdateNSNodeAPIConfig(context.Context, *UpdateNSNodeAPIConfigRequest) (*RPCSuccess, error)
+ // 列出所有需要升级的NS节点
+ FindAllUpgradeNSNodesWithNSClusterId(context.Context, *FindAllUpgradeNSNodesWithNSClusterIdRequest) (*FindAllUpgradeNSNodesWithNSClusterIdResponse, error)
+ // 升级单个NS节点
+ UpgradeNSNode(context.Context, *UpgradeNSNodeRequest) (*RPCSuccess, error)
}
// UnimplementedNSNodeServiceServer should be embedded to have
@@ -541,6 +571,12 @@ func (UnimplementedNSNodeServiceServer) FindNSNodeAPIConfig(context.Context, *Fi
func (UnimplementedNSNodeServiceServer) UpdateNSNodeAPIConfig(context.Context, *UpdateNSNodeAPIConfigRequest) (*RPCSuccess, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateNSNodeAPIConfig not implemented")
}
+func (UnimplementedNSNodeServiceServer) FindAllUpgradeNSNodesWithNSClusterId(context.Context, *FindAllUpgradeNSNodesWithNSClusterIdRequest) (*FindAllUpgradeNSNodesWithNSClusterIdResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method FindAllUpgradeNSNodesWithNSClusterId not implemented")
+}
+func (UnimplementedNSNodeServiceServer) UpgradeNSNode(context.Context, *UpgradeNSNodeRequest) (*RPCSuccess, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UpgradeNSNode not implemented")
+}
func (UnimplementedNSNodeServiceServer) testEmbeddedByValue() {}
// UnsafeNSNodeServiceServer may be embedded to opt out of forward compatibility for this service.
@@ -1036,6 +1072,42 @@ func _NSNodeService_UpdateNSNodeAPIConfig_Handler(srv interface{}, ctx context.C
return interceptor(ctx, in, info, handler)
}
+func _NSNodeService_FindAllUpgradeNSNodesWithNSClusterId_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(FindAllUpgradeNSNodesWithNSClusterIdRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(NSNodeServiceServer).FindAllUpgradeNSNodesWithNSClusterId(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: NSNodeService_FindAllUpgradeNSNodesWithNSClusterId_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(NSNodeServiceServer).FindAllUpgradeNSNodesWithNSClusterId(ctx, req.(*FindAllUpgradeNSNodesWithNSClusterIdRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _NSNodeService_UpgradeNSNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpgradeNSNodeRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(NSNodeServiceServer).UpgradeNSNode(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: NSNodeService_UpgradeNSNode_FullMethodName,
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(NSNodeServiceServer).UpgradeNSNode(ctx, req.(*UpgradeNSNodeRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
// NSNodeService_ServiceDesc is the grpc.ServiceDesc for NSNodeService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -1147,6 +1219,14 @@ var NSNodeService_ServiceDesc = grpc.ServiceDesc{
MethodName: "updateNSNodeAPIConfig",
Handler: _NSNodeService_UpdateNSNodeAPIConfig_Handler,
},
+ {
+ MethodName: "findAllUpgradeNSNodesWithNSClusterId",
+ Handler: _NSNodeService_FindAllUpgradeNSNodesWithNSClusterId_Handler,
+ },
+ {
+ MethodName: "upgradeNSNode",
+ Handler: _NSNodeService_UpgradeNSNode_Handler,
+ },
},
Streams: []grpc.StreamDesc{
{
diff --git a/EdgeCommon/pkg/rpc/pb/service_ns_node_upgrade.go b/EdgeCommon/pkg/rpc/pb/service_ns_node_upgrade.go
new file mode 100644
index 0000000..baf3f88
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/pb/service_ns_node_upgrade.go
@@ -0,0 +1,274 @@
+package pb
+
+import (
+ "fmt"
+
+ "google.golang.org/protobuf/encoding/protowire"
+ "google.golang.org/protobuf/proto"
+)
+
+// FindAllUpgradeNSNodesWithNSClusterIdRequest 列出所有需要升级的NS节点
+type FindAllUpgradeNSNodesWithNSClusterIdRequest struct {
+ NsClusterId int64 `protobuf:"varint,1,opt,name=nsClusterId,proto3" json:"nsClusterId,omitempty"`
+}
+
+func (x *FindAllUpgradeNSNodesWithNSClusterIdRequest) Reset() { *x = FindAllUpgradeNSNodesWithNSClusterIdRequest{} }
+func (x *FindAllUpgradeNSNodesWithNSClusterIdRequest) String() string { return fmt.Sprintf("%+v", *x) }
+func (x *FindAllUpgradeNSNodesWithNSClusterIdRequest) ProtoMessage() {}
+
+func (x *FindAllUpgradeNSNodesWithNSClusterIdRequest) GetNsClusterId() int64 {
+ if x != nil {
+ return x.NsClusterId
+ }
+ return 0
+}
+
+func (x *FindAllUpgradeNSNodesWithNSClusterIdRequest) Marshal() ([]byte, error) {
+ var b []byte
+ if x.NsClusterId != 0 {
+ b = protowire.AppendTag(b, 1, protowire.VarintType)
+ b = protowire.AppendVarint(b, uint64(x.NsClusterId))
+ }
+ return b, nil
+}
+
+func (x *FindAllUpgradeNSNodesWithNSClusterIdRequest) Unmarshal(data []byte) error {
+ for len(data) > 0 {
+ num, typ, n := protowire.ConsumeTag(data)
+ if n < 0 {
+ return fmt.Errorf("invalid tag")
+ }
+ data = data[n:]
+ switch num {
+ case 1:
+ if typ == protowire.VarintType {
+ v, n := protowire.ConsumeVarint(data)
+ if n < 0 {
+ return fmt.Errorf("invalid varint")
+ }
+ x.NsClusterId = int64(v)
+ data = data[n:]
+ }
+ default:
+ n := protowire.ConsumeFieldValue(num, typ, data)
+ if n < 0 {
+ return fmt.Errorf("invalid field value")
+ }
+ data = data[n:]
+ }
+ }
+ return nil
+}
+
+// FindAllUpgradeNSNodesWithNSClusterIdResponse_NSNodeUpgrade 单个待升级NS节点信息
+type FindAllUpgradeNSNodesWithNSClusterIdResponse_NSNodeUpgrade struct {
+ NsNode *NSNode `protobuf:"bytes,1,opt,name=nsNode,proto3" json:"nsNode,omitempty"`
+ Os string `protobuf:"bytes,2,opt,name=os,proto3" json:"os,omitempty"`
+ Arch string `protobuf:"bytes,3,opt,name=arch,proto3" json:"arch,omitempty"`
+ OldVersion string `protobuf:"bytes,4,opt,name=oldVersion,proto3" json:"oldVersion,omitempty"`
+ NewVersion string `protobuf:"bytes,5,opt,name=newVersion,proto3" json:"newVersion,omitempty"`
+}
+
+func (x *FindAllUpgradeNSNodesWithNSClusterIdResponse_NSNodeUpgrade) Reset() {
+ *x = FindAllUpgradeNSNodesWithNSClusterIdResponse_NSNodeUpgrade{}
+}
+func (x *FindAllUpgradeNSNodesWithNSClusterIdResponse_NSNodeUpgrade) String() string {
+ return fmt.Sprintf("%+v", *x)
+}
+func (x *FindAllUpgradeNSNodesWithNSClusterIdResponse_NSNodeUpgrade) ProtoMessage() {}
+
+func (x *FindAllUpgradeNSNodesWithNSClusterIdResponse_NSNodeUpgrade) Marshal() ([]byte, error) {
+ var b []byte
+ if x.NsNode != nil {
+ nodeData, err := proto.Marshal(x.NsNode)
+ if err != nil {
+ return nil, err
+ }
+ b = protowire.AppendTag(b, 1, protowire.BytesType)
+ b = protowire.AppendBytes(b, nodeData)
+ }
+ if x.Os != "" {
+ b = protowire.AppendTag(b, 2, protowire.BytesType)
+ b = protowire.AppendString(b, x.Os)
+ }
+ if x.Arch != "" {
+ b = protowire.AppendTag(b, 3, protowire.BytesType)
+ b = protowire.AppendString(b, x.Arch)
+ }
+ if x.OldVersion != "" {
+ b = protowire.AppendTag(b, 4, protowire.BytesType)
+ b = protowire.AppendString(b, x.OldVersion)
+ }
+ if x.NewVersion != "" {
+ b = protowire.AppendTag(b, 5, protowire.BytesType)
+ b = protowire.AppendString(b, x.NewVersion)
+ }
+ return b, nil
+}
+
+func (x *FindAllUpgradeNSNodesWithNSClusterIdResponse_NSNodeUpgrade) Unmarshal(data []byte) error {
+ for len(data) > 0 {
+ num, typ, n := protowire.ConsumeTag(data)
+ if n < 0 {
+ return fmt.Errorf("invalid tag")
+ }
+ data = data[n:]
+ switch num {
+ case 1:
+ if typ == protowire.BytesType {
+ v, n := protowire.ConsumeBytes(data)
+ if n < 0 {
+ return fmt.Errorf("invalid bytes")
+ }
+ x.NsNode = &NSNode{}
+ if err := proto.Unmarshal(v, x.NsNode); err != nil {
+ return err
+ }
+ data = data[n:]
+ }
+ case 2, 3, 4, 5:
+ if typ == protowire.BytesType {
+ v, n := protowire.ConsumeString(data)
+ if n < 0 {
+ return fmt.Errorf("invalid string")
+ }
+ switch num {
+ case 2:
+ x.Os = v
+ case 3:
+ x.Arch = v
+ case 4:
+ x.OldVersion = v
+ case 5:
+ x.NewVersion = v
+ }
+ data = data[n:]
+ }
+ default:
+ n := protowire.ConsumeFieldValue(num, typ, data)
+ if n < 0 {
+ return fmt.Errorf("invalid field value")
+ }
+ data = data[n:]
+ }
+ }
+ return nil
+}
+
+// FindAllUpgradeNSNodesWithNSClusterIdResponse 列出所有需要升级的NS节点
+type FindAllUpgradeNSNodesWithNSClusterIdResponse struct {
+ Nodes []*FindAllUpgradeNSNodesWithNSClusterIdResponse_NSNodeUpgrade `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
+}
+
+func (x *FindAllUpgradeNSNodesWithNSClusterIdResponse) Reset() {
+ *x = FindAllUpgradeNSNodesWithNSClusterIdResponse{}
+}
+func (x *FindAllUpgradeNSNodesWithNSClusterIdResponse) String() string {
+ return fmt.Sprintf("%+v", *x)
+}
+func (x *FindAllUpgradeNSNodesWithNSClusterIdResponse) ProtoMessage() {}
+
+func (x *FindAllUpgradeNSNodesWithNSClusterIdResponse) GetNodes() []*FindAllUpgradeNSNodesWithNSClusterIdResponse_NSNodeUpgrade {
+ if x != nil {
+ return x.Nodes
+ }
+ return nil
+}
+
+func (x *FindAllUpgradeNSNodesWithNSClusterIdResponse) Marshal() ([]byte, error) {
+ var b []byte
+ for _, node := range x.Nodes {
+ nodeData, err := node.Marshal()
+ if err != nil {
+ return nil, err
+ }
+ b = protowire.AppendTag(b, 1, protowire.BytesType)
+ b = protowire.AppendBytes(b, nodeData)
+ }
+ return b, nil
+}
+
+func (x *FindAllUpgradeNSNodesWithNSClusterIdResponse) Unmarshal(data []byte) error {
+ for len(data) > 0 {
+ num, typ, n := protowire.ConsumeTag(data)
+ if n < 0 {
+ return fmt.Errorf("invalid tag")
+ }
+ data = data[n:]
+ switch num {
+ case 1:
+ if typ == protowire.BytesType {
+ v, n := protowire.ConsumeBytes(data)
+ if n < 0 {
+ return fmt.Errorf("invalid bytes")
+ }
+ node := &FindAllUpgradeNSNodesWithNSClusterIdResponse_NSNodeUpgrade{}
+ if err := node.Unmarshal(v); err != nil {
+ return err
+ }
+ x.Nodes = append(x.Nodes, node)
+ data = data[n:]
+ }
+ default:
+ n := protowire.ConsumeFieldValue(num, typ, data)
+ if n < 0 {
+ return fmt.Errorf("invalid field value")
+ }
+ data = data[n:]
+ }
+ }
+ return nil
+}
+
+// UpgradeNSNodeRequest 升级单个NS节点
+type UpgradeNSNodeRequest struct {
+ NsNodeId int64 `protobuf:"varint,1,opt,name=nsNodeId,proto3" json:"nsNodeId,omitempty"`
+}
+
+func (x *UpgradeNSNodeRequest) Reset() { *x = UpgradeNSNodeRequest{} }
+func (x *UpgradeNSNodeRequest) String() string { return fmt.Sprintf("%+v", *x) }
+func (x *UpgradeNSNodeRequest) ProtoMessage() {}
+
+func (x *UpgradeNSNodeRequest) GetNsNodeId() int64 {
+ if x != nil {
+ return x.NsNodeId
+ }
+ return 0
+}
+
+func (x *UpgradeNSNodeRequest) Marshal() ([]byte, error) {
+ var b []byte
+ if x.NsNodeId != 0 {
+ b = protowire.AppendTag(b, 1, protowire.VarintType)
+ b = protowire.AppendVarint(b, uint64(x.NsNodeId))
+ }
+ return b, nil
+}
+
+func (x *UpgradeNSNodeRequest) Unmarshal(data []byte) error {
+ for len(data) > 0 {
+ num, typ, n := protowire.ConsumeTag(data)
+ if n < 0 {
+ return fmt.Errorf("invalid tag")
+ }
+ data = data[n:]
+ switch num {
+ case 1:
+ if typ == protowire.VarintType {
+ v, n := protowire.ConsumeVarint(data)
+ if n < 0 {
+ return fmt.Errorf("invalid varint")
+ }
+ x.NsNodeId = int64(v)
+ data = data[n:]
+ }
+ default:
+ n := protowire.ConsumeFieldValue(num, typ, data)
+ if n < 0 {
+ return fmt.Errorf("invalid field value")
+ }
+ data = data[n:]
+ }
+ }
+ return nil
+}
diff --git a/EdgeCommon/pkg/rpc/pb/service_user.pb.go b/EdgeCommon/pkg/rpc/pb/service_user.pb.go
index 865cd1c..5940c43 100644
--- a/EdgeCommon/pkg/rpc/pb/service_user.pb.go
+++ b/EdgeCommon/pkg/rpc/pb/service_user.pb.go
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.36.0
-// protoc v6.33.2
+// protoc-gen-go v1.36.11
+// protoc v3.21.12
// source: service_user.proto
package pb
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
+ unsafe "unsafe"
)
const (
@@ -381,20 +382,21 @@ func (x *VerifyUserRequest) GetRejectReason() string {
// 修改用户
type UpdateUserRequest struct {
- state protoimpl.MessageState `protogen:"open.v1"`
- UserId int64 `protobuf:"varint,1,opt,name=userId,proto3" json:"userId,omitempty"`
- Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
- Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
- Fullname string `protobuf:"bytes,4,opt,name=fullname,proto3" json:"fullname,omitempty"`
- Mobile string `protobuf:"bytes,5,opt,name=mobile,proto3" json:"mobile,omitempty"`
- Tel string `protobuf:"bytes,6,opt,name=tel,proto3" json:"tel,omitempty"`
- Email string `protobuf:"bytes,7,opt,name=email,proto3" json:"email,omitempty"`
- Remark string `protobuf:"bytes,8,opt,name=remark,proto3" json:"remark,omitempty"`
- IsOn bool `protobuf:"varint,9,opt,name=isOn,proto3" json:"isOn,omitempty"`
- NodeClusterId int64 `protobuf:"varint,10,opt,name=nodeClusterId,proto3" json:"nodeClusterId,omitempty"`
- BandwidthAlgo string `protobuf:"bytes,11,opt,name=bandwidthAlgo,proto3" json:"bandwidthAlgo,omitempty"`
- unknownFields protoimpl.UnknownFields
- sizeCache protoimpl.SizeCache
+ state protoimpl.MessageState `protogen:"open.v1"`
+ UserId int64 `protobuf:"varint,1,opt,name=userId,proto3" json:"userId,omitempty"`
+ Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
+ Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
+ Fullname string `protobuf:"bytes,4,opt,name=fullname,proto3" json:"fullname,omitempty"`
+ Mobile string `protobuf:"bytes,5,opt,name=mobile,proto3" json:"mobile,omitempty"`
+ Tel string `protobuf:"bytes,6,opt,name=tel,proto3" json:"tel,omitempty"`
+ Email string `protobuf:"bytes,7,opt,name=email,proto3" json:"email,omitempty"`
+ Remark string `protobuf:"bytes,8,opt,name=remark,proto3" json:"remark,omitempty"`
+ IsOn bool `protobuf:"varint,9,opt,name=isOn,proto3" json:"isOn,omitempty"`
+ NodeClusterId int64 `protobuf:"varint,10,opt,name=nodeClusterId,proto3" json:"nodeClusterId,omitempty"`
+ BandwidthAlgo string `protobuf:"bytes,11,opt,name=bandwidthAlgo,proto3" json:"bandwidthAlgo,omitempty"`
+ HttpdnsClusterIdsJSON []byte `protobuf:"bytes,12,opt,name=httpdnsClusterIdsJSON,proto3" json:"httpdnsClusterIdsJSON,omitempty"` // HTTPDNS关联集群ID列表
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *UpdateUserRequest) Reset() {
@@ -504,6 +506,13 @@ func (x *UpdateUserRequest) GetBandwidthAlgo() string {
return ""
}
+func (x *UpdateUserRequest) GetHttpdnsClusterIdsJSON() []byte {
+ if x != nil {
+ return x.HttpdnsClusterIdsJSON
+ }
+ return nil
+}
+
// 删除用户
type DeleteUserRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
@@ -2842,511 +2851,235 @@ func (x *ComposeUserGlobalBoardResponse_TrafficStat) GetBytes() int64 {
var File_service_user_proto protoreflect.FileDescriptor
-var file_service_user_proto_rawDesc = []byte{
- 0x0a, 0x12, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x19, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73,
- 0x2f, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65,
- 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x6d, 0x6f,
- 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f,
- 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x6d,
- 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65,
- 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xfd, 0x01, 0x0a,
- 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a,
- 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x75,
- 0x6c, 0x6c, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x75,
- 0x6c, 0x6c, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x12, 0x10,
- 0x0a, 0x03, 0x74, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x65, 0x6c,
- 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x61, 0x72, 0x6b,
- 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x16,
- 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6c,
- 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6e,
- 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0x2c, 0x0a, 0x12,
- 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xbf, 0x01, 0x0a, 0x13, 0x52,
- 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a,
- 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f,
- 0x62, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x62, 0x69,
- 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x75, 0x6c, 0x6c,
- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x75, 0x6c, 0x6c,
- 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x02, 0x69, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x07,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x6a, 0x0a, 0x14,
- 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x18,
- 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x56, 0x65, 0x72, 0x69,
- 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18,
- 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x56, 0x65, 0x72, 0x69,
- 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6f, 0x0a, 0x11, 0x56, 0x65, 0x72, 0x69,
- 0x66, 0x79, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a,
- 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75,
- 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x52, 0x65, 0x6a, 0x65, 0x63,
- 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x52, 0x65, 0x6a,
- 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x52,
- 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x6a,
- 0x65, 0x63, 0x74, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xb7, 0x02, 0x0a, 0x11, 0x55, 0x70,
- 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
- 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e,
- 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e,
- 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12,
- 0x1a, 0x0a, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d,
- 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x62,
- 0x69, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x03, 0x74, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x72,
- 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6d,
- 0x61, 0x72, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x6e, 0x6f, 0x64, 0x65, 0x43,
- 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d,
- 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a,
- 0x0d, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x41, 0x6c, 0x67, 0x6f, 0x18, 0x0b,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x41,
- 0x6c, 0x67, 0x6f, 0x22, 0x2b, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65,
- 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72,
- 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64,
- 0x22, 0x85, 0x01, 0x0a, 0x1b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61,
- 0x62, 0x6c, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73,
- 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x0b, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x12, 0x2a, 0x0a, 0x10,
- 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x49, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x49, 0x73,
- 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x22, 0xad, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73,
- 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x20,
- 0x0a, 0x0b, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20,
- 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67,
- 0x12, 0x2a, 0x0a, 0x10, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x49, 0x73, 0x56, 0x65, 0x72, 0x69,
- 0x66, 0x69, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6d, 0x6f, 0x62, 0x69,
- 0x6c, 0x65, 0x49, 0x73, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06,
- 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, 0x66,
- 0x66, 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x3a, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74,
- 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75,
- 0x73, 0x65, 0x72, 0x73, 0x22, 0x30, 0x0a, 0x16, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62,
- 0x6c, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16,
- 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06,
- 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x37, 0x0a, 0x17, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e,
- 0x61, 0x62, 0x6c, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x12, 0x1c, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x08, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22,
- 0x4e, 0x0a, 0x18, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72,
- 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75,
- 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65,
- 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22,
- 0x33, 0x0a, 0x19, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72,
- 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06,
- 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x78,
- 0x69, 0x73, 0x74, 0x73, 0x22, 0x4a, 0x0a, 0x10, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, 0x65,
- 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72,
- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72,
- 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
- 0x22, 0x59, 0x0a, 0x11, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a,
- 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f,
- 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x79, 0x0a, 0x15, 0x55,
- 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08,
- 0x66, 0x75, 0x6c, 0x6c, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
- 0x66, 0x75, 0x6c, 0x6c, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x62, 0x69,
- 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65,
- 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x68, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
- 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72,
- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72,
- 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
- 0x22, 0x35, 0x0a, 0x1b, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x44,
- 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
- 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xa7, 0x07, 0x0a, 0x1c, 0x43, 0x6f, 0x6d, 0x70,
- 0x6f, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e,
- 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c,
- 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x30, 0x0a, 0x13,
- 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x42, 0x79,
- 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x6d, 0x6f, 0x6e, 0x74, 0x68,
- 0x6c, 0x79, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x3c,
- 0x0a, 0x19, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x50, 0x65, 0x65, 0x6b, 0x42, 0x61, 0x6e,
- 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x19, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x50, 0x65, 0x65, 0x6b, 0x42, 0x61,
- 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x11,
- 0x64, 0x61, 0x69, 0x6c, 0x79, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x42, 0x79, 0x74, 0x65,
- 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x54, 0x72,
- 0x61, 0x66, 0x66, 0x69, 0x63, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x64, 0x61,
- 0x69, 0x6c, 0x79, 0x50, 0x65, 0x65, 0x6b, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68,
- 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x64, 0x61, 0x69,
- 0x6c, 0x79, 0x50, 0x65, 0x65, 0x6b, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x42,
- 0x79, 0x74, 0x65, 0x73, 0x12, 0x5f, 0x0a, 0x11, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x54, 0x72, 0x61,
- 0x66, 0x66, 0x69, 0x63, 0x53, 0x74, 0x61, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x31, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72,
- 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x2e, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x53, 0x74,
- 0x61, 0x74, 0x52, 0x11, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63,
- 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x71, 0x0a, 0x17, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x50, 0x65,
- 0x65, 0x6b, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x73,
- 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x70,
- 0x6f, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x50, 0x65,
- 0x65, 0x6b, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x52,
- 0x17, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x50, 0x65, 0x65, 0x6b, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69,
- 0x64, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x30, 0x0a, 0x13, 0x62, 0x61, 0x6e, 0x64,
- 0x77, 0x69, 0x64, 0x74, 0x68, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x18,
- 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68,
- 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x12, 0x38, 0x0a, 0x17, 0x62, 0x61,
- 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x69, 0x6c,
- 0x65, 0x42, 0x69, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x62, 0x61, 0x6e,
- 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x69, 0x6c, 0x65,
- 0x42, 0x69, 0x74, 0x73, 0x1a, 0x88, 0x02, 0x0a, 0x10, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x54, 0x72,
- 0x61, 0x66, 0x66, 0x69, 0x63, 0x53, 0x74, 0x61, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x61, 0x79,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x61, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x62,
- 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65,
- 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x42, 0x79,
- 0x74, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x61, 0x63, 0x6b, 0x42, 0x79, 0x74,
- 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x61, 0x63, 0x6b,
- 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, 0x6f,
- 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x30, 0x0a, 0x13, 0x63,
- 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43,
- 0x61, 0x63, 0x68, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x30, 0x0a,
- 0x13, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x63, 0x6f, 0x75, 0x6e,
- 0x74, 0x41, 0x74, 0x74, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a,
- 0x40, 0x0a, 0x16, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x50, 0x65, 0x65, 0x6b, 0x42, 0x61, 0x6e, 0x64,
- 0x77, 0x69, 0x64, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x61, 0x79,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x61, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x62,
- 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65,
- 0x73, 0x22, 0x36, 0x0a, 0x1c, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x64,
- 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x45, 0x0a, 0x1d, 0x46, 0x69, 0x6e,
- 0x64, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
- 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x6e, 0x6f,
- 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x0d, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64,
- 0x22, 0x57, 0x0a, 0x19, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x46, 0x65,
- 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a,
- 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75,
- 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65,
- 0x43, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x65, 0x61,
- 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x61, 0x0a, 0x1d, 0x55, 0x70, 0x64,
- 0x61, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75,
- 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x66, 0x65,
- 0x61, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09,
- 0x52, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x1c,
- 0x0a, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, 0x31, 0x0a, 0x17,
- 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49,
- 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22,
- 0x47, 0x0a, 0x18, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x65, 0x61, 0x74, 0x75,
- 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x66,
- 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e,
- 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x08,
- 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x26, 0x0a, 0x24, 0x46, 0x69, 0x6e, 0x64,
- 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x44, 0x65,
- 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x22, 0x54, 0x0a, 0x25, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x46,
- 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e,
- 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x66, 0x65, 0x61,
- 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62,
- 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x08, 0x66, 0x65,
- 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x1f, 0x0a, 0x1d, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
- 0x65, 0x55, 0x73, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x6f, 0x61, 0x72, 0x64,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa9, 0x06, 0x0a, 0x1e, 0x43, 0x6f, 0x6d, 0x70,
- 0x6f, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x6f, 0x61,
- 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x6f,
- 0x74, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a,
- 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x63, 0x6f,
- 0x75, 0x6e, 0x74, 0x54, 0x6f, 0x64, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x6f, 0x64, 0x61, 0x79, 0x55,
- 0x73, 0x65, 0x72, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x57, 0x65, 0x65,
- 0x6b, 0x6c, 0x79, 0x55, 0x73, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10,
- 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x55, 0x73, 0x65, 0x72, 0x73,
- 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x64,
- 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55,
- 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x63, 0x6f, 0x75, 0x6e,
- 0x74, 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65,
- 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4f, 0x66,
- 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x30,
- 0x0a, 0x13, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67,
- 0x55, 0x73, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x63, 0x6f, 0x75,
- 0x6e, 0x74, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x72, 0x73,
- 0x12, 0x4c, 0x0a, 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x18, 0x1e,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
- 0x65, 0x55, 0x73, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x6f, 0x61, 0x72, 0x64,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x53, 0x74,
- 0x61, 0x74, 0x52, 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x33,
- 0x0a, 0x0d, 0x63, 0x70, 0x75, 0x4e, 0x6f, 0x64, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18,
- 0x1f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0d, 0x63, 0x70, 0x75, 0x4e, 0x6f, 0x64, 0x65, 0x56, 0x61, 0x6c,
- 0x75, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x10, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4e, 0x6f, 0x64,
- 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x20, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e,
- 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x10, 0x6d, 0x65,
- 0x6d, 0x6f, 0x72, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x35,
- 0x0a, 0x0e, 0x6c, 0x6f, 0x61, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73,
- 0x18, 0x21, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65,
- 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x6c, 0x6f, 0x61, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x0f, 0x74, 0x6f, 0x70, 0x54, 0x72, 0x61, 0x66,
- 0x66, 0x69, 0x63, 0x53, 0x74, 0x61, 0x74, 0x73, 0x18, 0x22, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e,
- 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x47,
- 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x53, 0x74, 0x61, 0x74, 0x52, 0x0f,
- 0x74, 0x6f, 0x70, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x53, 0x74, 0x61, 0x74, 0x73, 0x1a,
- 0x33, 0x0a, 0x09, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x74, 0x12, 0x10, 0x0a, 0x03,
- 0x64, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x61, 0x79, 0x12, 0x14,
- 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63,
- 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0x7d, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x53,
- 0x74, 0x61, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75,
- 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75,
- 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x75, 0x6e, 0x74,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d,
- 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x14, 0x0a,
- 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, 0x79,
- 0x74, 0x65, 0x73, 0x22, 0x3d, 0x0a, 0x1f, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72,
- 0x4f, 0x54, 0x50, 0x57, 0x69, 0x74, 0x68, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
- 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
- 0x6d, 0x65, 0x22, 0x42, 0x0a, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x4f,
- 0x54, 0x50, 0x57, 0x69, 0x74, 0x68, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,
- 0x65, 0x4f, 0x54, 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x65, 0x71, 0x75,
- 0x69, 0x72, 0x65, 0x4f, 0x54, 0x50, 0x22, 0x32, 0x0a, 0x18, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73,
- 0x65, 0x72, 0x50, 0x72, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x5b, 0x0a, 0x19, 0x46, 0x69,
- 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x69, 0x63, 0x65,
- 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x69, 0x63,
- 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x63, 0x65, 0x50, 0x65,
- 0x72, 0x69, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x69, 0x63,
- 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x22, 0x52, 0x0a, 0x1a, 0x55, 0x70, 0x64, 0x61, 0x74,
- 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1c, 0x0a,
- 0x09, 0x70, 0x72, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x09, 0x70, 0x72, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x58, 0x0a, 0x1c, 0x55,
- 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x69, 0x63, 0x65, 0x50, 0x65,
- 0x72, 0x69, 0x6f, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75,
- 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65,
- 0x72, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x63, 0x65, 0x50, 0x65, 0x72, 0x69,
- 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x69, 0x63, 0x65, 0x50,
- 0x65, 0x72, 0x69, 0x6f, 0x64, 0x22, 0x36, 0x0a, 0x1c, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73,
- 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x3d, 0x0a,
- 0x1d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
- 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c,
- 0x0a, 0x09, 0x69, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x09, 0x69, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x36, 0x0a, 0x1c,
- 0x52, 0x65, 0x6e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73,
- 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06,
- 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73,
- 0x65, 0x72, 0x49, 0x64, 0x22, 0x3d, 0x0a, 0x1d, 0x52, 0x65, 0x6e, 0x65, 0x77, 0x55, 0x73, 0x65,
- 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c,
- 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x45, 0x6e, 0x61, 0x62,
- 0x6c, 0x65, 0x64, 0x22, 0x2d, 0x0a, 0x15, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72,
- 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05,
- 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61,
- 0x69, 0x6c, 0x22, 0x30, 0x0a, 0x16, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x45,
- 0x6d, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06,
- 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x78,
- 0x69, 0x73, 0x74, 0x73, 0x22, 0x30, 0x0a, 0x16, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65,
- 0x72, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16,
- 0x0a, 0x06, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
- 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x22, 0x31, 0x0a, 0x17, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55,
- 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x06, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x22, 0x46, 0x0a, 0x28, 0x46, 0x69, 0x6e,
- 0x64, 0x55, 0x73, 0x65, 0x72, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x6d, 0x61,
- 0x69, 0x6c, 0x57, 0x69, 0x74, 0x68, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
- 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
- 0x65, 0x22, 0x41, 0x0a, 0x29, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x56, 0x65, 0x72,
- 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x57, 0x69, 0x74, 0x68, 0x55, 0x73,
- 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14,
- 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65,
- 0x6d, 0x61, 0x69, 0x6c, 0x32, 0xae, 0x11, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72,
- 0x76, 0x69, 0x63, 0x65, 0x12, 0x3b, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73,
- 0x65, 0x72, 0x12, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73,
- 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x62, 0x2e, 0x43,
- 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65,
- 0x72, 0x12, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55,
- 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x62, 0x2e,
- 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x55, 0x73,
- 0x65, 0x72, 0x12, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x55, 0x73,
- 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52,
- 0x50, 0x43, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x33, 0x0a, 0x0a, 0x75, 0x70, 0x64,
- 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64,
- 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e,
- 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x33,
- 0x0a, 0x0a, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x15, 0x2e, 0x70,
- 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63,
- 0x65, 0x73, 0x73, 0x12, 0x4d, 0x0a, 0x14, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45,
- 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x1f, 0x2e, 0x70, 0x62,
- 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
- 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70,
- 0x62, 0x2e, 0x52, 0x50, 0x43, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x10, 0x6c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65,
- 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74,
- 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x61,
- 0x62, 0x6c, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
- 0x55, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e,
- 0x61, 0x62, 0x6c, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x1a, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65,
- 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a,
- 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61,
- 0x6d, 0x65, 0x12, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65,
- 0x72, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x1a, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x55,
- 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
- 0x38, 0x0a, 0x09, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x14, 0x2e, 0x70,
- 0x62, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, 0x65,
- 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0e, 0x75, 0x70, 0x64,
- 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x2e, 0x70, 0x62,
- 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53,
- 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x3d, 0x0a, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
- 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x1a, 0x2e, 0x70, 0x62, 0x2e, 0x55,
- 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75,
- 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x59, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65,
- 0x55, 0x73, 0x65, 0x72, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x1f, 0x2e,
- 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x44, 0x61,
- 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20,
- 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x44,
- 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x12, 0x5c, 0x0a, 0x15, 0x66, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65,
- 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x46,
- 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74,
- 0x65, 0x72, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x62,
- 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75,
- 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43,
- 0x0a, 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x46, 0x65, 0x61, 0x74,
- 0x75, 0x72, 0x65, 0x73, 0x12, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
- 0x55, 0x73, 0x65, 0x72, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63,
- 0x65, 0x73, 0x73, 0x12, 0x4b, 0x0a, 0x16, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x6c, 0x6c,
- 0x55, 0x73, 0x65, 0x72, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x21, 0x2e,
- 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72,
- 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73,
- 0x12, 0x4d, 0x0a, 0x10, 0x66, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x65, 0x61, 0x74,
- 0x75, 0x72, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73,
- 0x65, 0x72, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46,
- 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
- 0x74, 0x0a, 0x1d, 0x66, 0x69, 0x6e, 0x64, 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x46, 0x65,
- 0x61, 0x74, 0x75, 0x72, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x12, 0x28, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65,
- 0x72, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69,
- 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x62, 0x2e,
- 0x46, 0x69, 0x6e, 0x64, 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x46, 0x65, 0x61, 0x74, 0x75,
- 0x72, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65,
- 0x55, 0x73, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x12,
- 0x21, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72,
- 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x55,
- 0x73, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x18, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x55,
- 0x73, 0x65, 0x72, 0x4f, 0x54, 0x50, 0x57, 0x69, 0x74, 0x68, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61,
- 0x6d, 0x65, 0x12, 0x23, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65,
- 0x72, 0x4f, 0x54, 0x50, 0x57, 0x69, 0x74, 0x68, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x65,
- 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x54, 0x50, 0x57, 0x69, 0x74, 0x68, 0x55, 0x73, 0x65,
- 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a,
- 0x11, 0x66, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x69, 0x63, 0x65, 0x49, 0x6e,
- 0x66, 0x6f, 0x12, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72,
- 0x50, 0x72, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x1a, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72,
- 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
- 0x45, 0x0a, 0x13, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x69,
- 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61,
- 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53,
- 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x49, 0x0a, 0x15, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
- 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x69, 0x63, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12,
- 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50,
- 0x72, 0x69, 0x63, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73,
- 0x73, 0x12, 0x5c, 0x0a, 0x15, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65,
- 0x72, 0x76, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x70, 0x62, 0x2e,
- 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73,
- 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70,
- 0x62, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65,
- 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
- 0x5c, 0x0a, 0x15, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76,
- 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65,
- 0x6e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x62, 0x2e,
- 0x52, 0x65, 0x6e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73,
- 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a,
- 0x0e, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12,
- 0x19, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x45, 0x6d,
- 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x62, 0x2e,
- 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x55,
- 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x62, 0x2e, 0x43,
- 0x68, 0x65, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b,
- 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x21, 0x66, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x56,
- 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x57, 0x69, 0x74, 0x68,
- 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2c, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69,
- 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x6d,
- 0x61, 0x69, 0x6c, 0x57, 0x69, 0x74, 0x68, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6e, 0x64,
- 0x55, 0x73, 0x65, 0x72, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x6d, 0x61, 0x69,
- 0x6c, 0x57, 0x69, 0x74, 0x68, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+const file_service_user_proto_rawDesc = "" +
+ "\n" +
+ "\x12service_user.proto\x12\x02pb\x1a\x19models/rpc_messages.proto\x1a\x17models/model_user.proto\x1a\x1fmodels/model_user_feature.proto\x1a\x1dmodels/model_node_value.proto\"\xfd\x01\n" +
+ "\x11CreateUserRequest\x12\x1a\n" +
+ "\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" +
+ "\bpassword\x18\x02 \x01(\tR\bpassword\x12\x1a\n" +
+ "\bfullname\x18\x03 \x01(\tR\bfullname\x12\x16\n" +
+ "\x06mobile\x18\x04 \x01(\tR\x06mobile\x12\x10\n" +
+ "\x03tel\x18\x05 \x01(\tR\x03tel\x12\x14\n" +
+ "\x05email\x18\x06 \x01(\tR\x05email\x12\x16\n" +
+ "\x06remark\x18\a \x01(\tR\x06remark\x12\x16\n" +
+ "\x06source\x18\b \x01(\tR\x06source\x12$\n" +
+ "\rnodeClusterId\x18\t \x01(\x03R\rnodeClusterId\",\n" +
+ "\x12CreateUserResponse\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\"\xbf\x01\n" +
+ "\x13RegisterUserRequest\x12\x1a\n" +
+ "\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" +
+ "\bpassword\x18\x02 \x01(\tR\bpassword\x12\x16\n" +
+ "\x06mobile\x18\x03 \x01(\tR\x06mobile\x12\x14\n" +
+ "\x05email\x18\x04 \x01(\tR\x05email\x12\x1a\n" +
+ "\bfullname\x18\x05 \x01(\tR\bfullname\x12\x0e\n" +
+ "\x02ip\x18\x06 \x01(\tR\x02ip\x12\x16\n" +
+ "\x06source\x18\a \x01(\tR\x06source\"j\n" +
+ "\x14RegisterUserResponse\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\x12:\n" +
+ "\x18requireEmailVerification\x18\x02 \x01(\bR\x18requireEmailVerification\"o\n" +
+ "\x11VerifyUserRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\x12\x1e\n" +
+ "\n" +
+ "isRejected\x18\x02 \x01(\bR\n" +
+ "isRejected\x12\"\n" +
+ "\frejectReason\x18\x03 \x01(\tR\frejectReason\"\xed\x02\n" +
+ "\x11UpdateUserRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
+ "\busername\x18\x02 \x01(\tR\busername\x12\x1a\n" +
+ "\bpassword\x18\x03 \x01(\tR\bpassword\x12\x1a\n" +
+ "\bfullname\x18\x04 \x01(\tR\bfullname\x12\x16\n" +
+ "\x06mobile\x18\x05 \x01(\tR\x06mobile\x12\x10\n" +
+ "\x03tel\x18\x06 \x01(\tR\x03tel\x12\x14\n" +
+ "\x05email\x18\a \x01(\tR\x05email\x12\x16\n" +
+ "\x06remark\x18\b \x01(\tR\x06remark\x12\x12\n" +
+ "\x04isOn\x18\t \x01(\bR\x04isOn\x12$\n" +
+ "\rnodeClusterId\x18\n" +
+ " \x01(\x03R\rnodeClusterId\x12$\n" +
+ "\rbandwidthAlgo\x18\v \x01(\tR\rbandwidthAlgo\x124\n" +
+ "\x15httpdnsClusterIdsJSON\x18\f \x01(\fR\x15httpdnsClusterIdsJSON\"+\n" +
+ "\x11DeleteUserRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\"\x85\x01\n" +
+ "\x1bCountAllEnabledUsersRequest\x12\x18\n" +
+ "\akeyword\x18\x01 \x01(\tR\akeyword\x12 \n" +
+ "\visVerifying\x18\x02 \x01(\bR\visVerifying\x12*\n" +
+ "\x10mobileIsVerified\x18\x03 \x01(\x05R\x10mobileIsVerified\"\xad\x01\n" +
+ "\x17ListEnabledUsersRequest\x12\x18\n" +
+ "\akeyword\x18\x01 \x01(\tR\akeyword\x12 \n" +
+ "\visVerifying\x18\x04 \x01(\bR\visVerifying\x12*\n" +
+ "\x10mobileIsVerified\x18\x05 \x01(\x05R\x10mobileIsVerified\x12\x16\n" +
+ "\x06offset\x18\x02 \x01(\x03R\x06offset\x12\x12\n" +
+ "\x04size\x18\x03 \x01(\x03R\x04size\":\n" +
+ "\x18ListEnabledUsersResponse\x12\x1e\n" +
+ "\x05users\x18\x01 \x03(\v2\b.pb.UserR\x05users\"0\n" +
+ "\x16FindEnabledUserRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\"7\n" +
+ "\x17FindEnabledUserResponse\x12\x1c\n" +
+ "\x04user\x18\x01 \x01(\v2\b.pb.UserR\x04user\"N\n" +
+ "\x18CheckUserUsernameRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
+ "\busername\x18\x02 \x01(\tR\busername\"3\n" +
+ "\x19CheckUserUsernameResponse\x12\x16\n" +
+ "\x06exists\x18\x01 \x01(\bR\x06exists\"J\n" +
+ "\x10LoginUserRequest\x12\x1a\n" +
+ "\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" +
+ "\bpassword\x18\x02 \x01(\tR\bpassword\"Y\n" +
+ "\x11LoginUserResponse\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\x12\x12\n" +
+ "\x04isOk\x18\x02 \x01(\bR\x04isOk\x12\x18\n" +
+ "\amessage\x18\x03 \x01(\tR\amessage\"y\n" +
+ "\x15UpdateUserInfoRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
+ "\bfullname\x18\x02 \x01(\tR\bfullname\x12\x16\n" +
+ "\x06mobile\x18\x03 \x01(\tR\x06mobile\x12\x14\n" +
+ "\x05email\x18\x04 \x01(\tR\x05email\"h\n" +
+ "\x16UpdateUserLoginRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
+ "\busername\x18\x02 \x01(\tR\busername\x12\x1a\n" +
+ "\bpassword\x18\x03 \x01(\tR\bpassword\"5\n" +
+ "\x1bComposeUserDashboardRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\"\xa7\a\n" +
+ "\x1cComposeUserDashboardResponse\x12\"\n" +
+ "\fcountServers\x18\x01 \x01(\x03R\fcountServers\x120\n" +
+ "\x13monthlyTrafficBytes\x18\x02 \x01(\x03R\x13monthlyTrafficBytes\x12<\n" +
+ "\x19monthlyPeekBandwidthBytes\x18\x03 \x01(\x03R\x19monthlyPeekBandwidthBytes\x12,\n" +
+ "\x11dailyTrafficBytes\x18\x04 \x01(\x03R\x11dailyTrafficBytes\x128\n" +
+ "\x17dailyPeekBandwidthBytes\x18\x05 \x01(\x03R\x17dailyPeekBandwidthBytes\x12_\n" +
+ "\x11dailyTrafficStats\x18\x06 \x03(\v21.pb.ComposeUserDashboardResponse.DailyTrafficStatR\x11dailyTrafficStats\x12q\n" +
+ "\x17dailyPeekBandwidthStats\x18\a \x03(\v27.pb.ComposeUserDashboardResponse.DailyPeekBandwidthStatR\x17dailyPeekBandwidthStats\x120\n" +
+ "\x13bandwidthPercentile\x18\b \x01(\x05R\x13bandwidthPercentile\x128\n" +
+ "\x17bandwidthPercentileBits\x18\t \x01(\x03R\x17bandwidthPercentileBits\x1a\x88\x02\n" +
+ "\x10DailyTrafficStat\x12\x10\n" +
+ "\x03day\x18\x01 \x01(\tR\x03day\x12\x14\n" +
+ "\x05bytes\x18\x02 \x01(\x03R\x05bytes\x12 \n" +
+ "\vcachedBytes\x18\x03 \x01(\x03R\vcachedBytes\x12 \n" +
+ "\vattackBytes\x18\x04 \x01(\x03R\vattackBytes\x12$\n" +
+ "\rcountRequests\x18\x05 \x01(\x03R\rcountRequests\x120\n" +
+ "\x13countCachedRequests\x18\x06 \x01(\x03R\x13countCachedRequests\x120\n" +
+ "\x13countAttackRequests\x18\a \x01(\x03R\x13countAttackRequests\x1a@\n" +
+ "\x16DailyPeekBandwidthStat\x12\x10\n" +
+ "\x03day\x18\x01 \x01(\tR\x03day\x12\x14\n" +
+ "\x05bytes\x18\x02 \x01(\x03R\x05bytes\"6\n" +
+ "\x1cFindUserNodeClusterIdRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\"E\n" +
+ "\x1dFindUserNodeClusterIdResponse\x12$\n" +
+ "\rnodeClusterId\x18\x01 \x01(\x03R\rnodeClusterId\"W\n" +
+ "\x19UpdateUserFeaturesRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\x12\"\n" +
+ "\ffeatureCodes\x18\x02 \x03(\tR\ffeatureCodes\"a\n" +
+ "\x1dUpdateAllUsersFeaturesRequest\x12\"\n" +
+ "\ffeatureCodes\x18\x01 \x03(\tR\ffeatureCodes\x12\x1c\n" +
+ "\toverwrite\x18\x02 \x01(\bR\toverwrite\"1\n" +
+ "\x17FindUserFeaturesRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\"G\n" +
+ "\x18FindUserFeaturesResponse\x12+\n" +
+ "\bfeatures\x18\x01 \x03(\v2\x0f.pb.UserFeatureR\bfeatures\"&\n" +
+ "$FindAllUserFeatureDefinitionsRequest\"T\n" +
+ "%FindAllUserFeatureDefinitionsResponse\x12+\n" +
+ "\bfeatures\x18\x01 \x03(\v2\x0f.pb.UserFeatureR\bfeatures\"\x1f\n" +
+ "\x1dComposeUserGlobalBoardRequest\"\xa9\x06\n" +
+ "\x1eComposeUserGlobalBoardResponse\x12\x1e\n" +
+ "\n" +
+ "totalUsers\x18\x01 \x01(\x03R\n" +
+ "totalUsers\x12(\n" +
+ "\x0fcountTodayUsers\x18\x02 \x01(\x03R\x0fcountTodayUsers\x12*\n" +
+ "\x10countWeeklyUsers\x18\x03 \x01(\x03R\x10countWeeklyUsers\x12&\n" +
+ "\x0ecountUserNodes\x18\x04 \x01(\x03R\x0ecountUserNodes\x124\n" +
+ "\x15countOfflineUserNodes\x18\x05 \x01(\x03R\x15countOfflineUserNodes\x120\n" +
+ "\x13countVerifyingUsers\x18\x06 \x01(\x03R\x13countVerifyingUsers\x12L\n" +
+ "\n" +
+ "dailyStats\x18\x1e \x03(\v2,.pb.ComposeUserGlobalBoardResponse.DailyStatR\n" +
+ "dailyStats\x123\n" +
+ "\rcpuNodeValues\x18\x1f \x03(\v2\r.pb.NodeValueR\rcpuNodeValues\x129\n" +
+ "\x10memoryNodeValues\x18 \x03(\v2\r.pb.NodeValueR\x10memoryNodeValues\x125\n" +
+ "\x0eloadNodeValues\x18! \x03(\v2\r.pb.NodeValueR\x0eloadNodeValues\x12X\n" +
+ "\x0ftopTrafficStats\x18\" \x03(\v2..pb.ComposeUserGlobalBoardResponse.TrafficStatR\x0ftopTrafficStats\x1a3\n" +
+ "\tDailyStat\x12\x10\n" +
+ "\x03day\x18\x01 \x01(\tR\x03day\x12\x14\n" +
+ "\x05count\x18\x02 \x01(\x03R\x05count\x1a}\n" +
+ "\vTrafficStat\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" +
+ "\buserName\x18\x02 \x01(\tR\buserName\x12$\n" +
+ "\rcountRequests\x18\x03 \x01(\x03R\rcountRequests\x12\x14\n" +
+ "\x05bytes\x18\x04 \x01(\x03R\x05bytes\"=\n" +
+ "\x1fCheckUserOTPWithUsernameRequest\x12\x1a\n" +
+ "\busername\x18\x01 \x01(\tR\busername\"B\n" +
+ " CheckUserOTPWithUsernameResponse\x12\x1e\n" +
+ "\n" +
+ "requireOTP\x18\x01 \x01(\bR\n" +
+ "requireOTP\"2\n" +
+ "\x18FindUserPriceInfoRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\"[\n" +
+ "\x19FindUserPriceInfoResponse\x12\x1c\n" +
+ "\tpriceType\x18\x01 \x01(\tR\tpriceType\x12 \n" +
+ "\vpricePeriod\x18\x02 \x01(\tR\vpricePeriod\"R\n" +
+ "\x1aUpdateUserPriceTypeRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\x12\x1c\n" +
+ "\tpriceType\x18\x02 \x01(\tR\tpriceType\"X\n" +
+ "\x1cUpdateUserPricePeriodRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\x12 \n" +
+ "\vpricePeriod\x18\x02 \x01(\tR\vpricePeriod\"6\n" +
+ "\x1cCheckUserServersStateRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\"=\n" +
+ "\x1dCheckUserServersStateResponse\x12\x1c\n" +
+ "\tisEnabled\x18\x01 \x01(\bR\tisEnabled\"6\n" +
+ "\x1cRenewUserServersStateRequest\x12\x16\n" +
+ "\x06userId\x18\x01 \x01(\x03R\x06userId\"=\n" +
+ "\x1dRenewUserServersStateResponse\x12\x1c\n" +
+ "\tisEnabled\x18\x01 \x01(\bR\tisEnabled\"-\n" +
+ "\x15CheckUserEmailRequest\x12\x14\n" +
+ "\x05email\x18\x01 \x01(\tR\x05email\"0\n" +
+ "\x16CheckUserEmailResponse\x12\x16\n" +
+ "\x06exists\x18\x01 \x01(\bR\x06exists\"0\n" +
+ "\x16CheckUserMobileRequest\x12\x16\n" +
+ "\x06mobile\x18\x01 \x01(\tR\x06mobile\"1\n" +
+ "\x17CheckUserMobileResponse\x12\x16\n" +
+ "\x06exists\x18\x01 \x01(\bR\x06exists\"F\n" +
+ "(FindUserVerifiedEmailWithUsernameRequest\x12\x1a\n" +
+ "\busername\x18\x01 \x01(\tR\busername\"A\n" +
+ ")FindUserVerifiedEmailWithUsernameResponse\x12\x14\n" +
+ "\x05email\x18\x01 \x01(\tR\x05email2\xae\x11\n" +
+ "\vUserService\x12;\n" +
+ "\n" +
+ "createUser\x12\x15.pb.CreateUserRequest\x1a\x16.pb.CreateUserResponse\x12A\n" +
+ "\fregisterUser\x12\x17.pb.RegisterUserRequest\x1a\x18.pb.RegisterUserResponse\x123\n" +
+ "\n" +
+ "verifyUser\x12\x15.pb.VerifyUserRequest\x1a\x0e.pb.RPCSuccess\x123\n" +
+ "\n" +
+ "updateUser\x12\x15.pb.UpdateUserRequest\x1a\x0e.pb.RPCSuccess\x123\n" +
+ "\n" +
+ "deleteUser\x12\x15.pb.DeleteUserRequest\x1a\x0e.pb.RPCSuccess\x12M\n" +
+ "\x14countAllEnabledUsers\x12\x1f.pb.CountAllEnabledUsersRequest\x1a\x14.pb.RPCCountResponse\x12M\n" +
+ "\x10listEnabledUsers\x12\x1b.pb.ListEnabledUsersRequest\x1a\x1c.pb.ListEnabledUsersResponse\x12J\n" +
+ "\x0ffindEnabledUser\x12\x1a.pb.FindEnabledUserRequest\x1a\x1b.pb.FindEnabledUserResponse\x12P\n" +
+ "\x11checkUserUsername\x12\x1c.pb.CheckUserUsernameRequest\x1a\x1d.pb.CheckUserUsernameResponse\x128\n" +
+ "\tloginUser\x12\x14.pb.LoginUserRequest\x1a\x15.pb.LoginUserResponse\x12;\n" +
+ "\x0eupdateUserInfo\x12\x19.pb.UpdateUserInfoRequest\x1a\x0e.pb.RPCSuccess\x12=\n" +
+ "\x0fupdateUserLogin\x12\x1a.pb.UpdateUserLoginRequest\x1a\x0e.pb.RPCSuccess\x12Y\n" +
+ "\x14composeUserDashboard\x12\x1f.pb.ComposeUserDashboardRequest\x1a .pb.ComposeUserDashboardResponse\x12\\\n" +
+ "\x15findUserNodeClusterId\x12 .pb.FindUserNodeClusterIdRequest\x1a!.pb.FindUserNodeClusterIdResponse\x12C\n" +
+ "\x12updateUserFeatures\x12\x1d.pb.UpdateUserFeaturesRequest\x1a\x0e.pb.RPCSuccess\x12K\n" +
+ "\x16updateAllUsersFeatures\x12!.pb.UpdateAllUsersFeaturesRequest\x1a\x0e.pb.RPCSuccess\x12M\n" +
+ "\x10findUserFeatures\x12\x1b.pb.FindUserFeaturesRequest\x1a\x1c.pb.FindUserFeaturesResponse\x12t\n" +
+ "\x1dfindAllUserFeatureDefinitions\x12(.pb.FindAllUserFeatureDefinitionsRequest\x1a).pb.FindAllUserFeatureDefinitionsResponse\x12_\n" +
+ "\x16composeUserGlobalBoard\x12!.pb.ComposeUserGlobalBoardRequest\x1a\".pb.ComposeUserGlobalBoardResponse\x12e\n" +
+ "\x18checkUserOTPWithUsername\x12#.pb.CheckUserOTPWithUsernameRequest\x1a$.pb.CheckUserOTPWithUsernameResponse\x12P\n" +
+ "\x11findUserPriceInfo\x12\x1c.pb.FindUserPriceInfoRequest\x1a\x1d.pb.FindUserPriceInfoResponse\x12E\n" +
+ "\x13updateUserPriceType\x12\x1e.pb.UpdateUserPriceTypeRequest\x1a\x0e.pb.RPCSuccess\x12I\n" +
+ "\x15updateUserPricePeriod\x12 .pb.UpdateUserPricePeriodRequest\x1a\x0e.pb.RPCSuccess\x12\\\n" +
+ "\x15checkUserServersState\x12 .pb.CheckUserServersStateRequest\x1a!.pb.CheckUserServersStateResponse\x12\\\n" +
+ "\x15renewUserServersState\x12 .pb.RenewUserServersStateRequest\x1a!.pb.RenewUserServersStateResponse\x12G\n" +
+ "\x0echeckUserEmail\x12\x19.pb.CheckUserEmailRequest\x1a\x1a.pb.CheckUserEmailResponse\x12J\n" +
+ "\x0fcheckUserMobile\x12\x1a.pb.CheckUserMobileRequest\x1a\x1b.pb.CheckUserMobileResponse\x12\x80\x01\n" +
+ "!findUserVerifiedEmailWithUsername\x12,.pb.FindUserVerifiedEmailWithUsernameRequest\x1a-.pb.FindUserVerifiedEmailWithUsernameResponseB\x06Z\x04./pbb\x06proto3"
var (
file_service_user_proto_rawDescOnce sync.Once
- file_service_user_proto_rawDescData = file_service_user_proto_rawDesc
+ file_service_user_proto_rawDescData []byte
)
func file_service_user_proto_rawDescGZIP() []byte {
file_service_user_proto_rawDescOnce.Do(func() {
- file_service_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_user_proto_rawDescData)
+ file_service_user_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_service_user_proto_rawDesc), len(file_service_user_proto_rawDesc)))
})
return file_service_user_proto_rawDescData
}
@@ -3497,7 +3230,7 @@ func file_service_user_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_service_user_proto_rawDesc,
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_service_user_proto_rawDesc), len(file_service_user_proto_rawDesc)),
NumEnums: 0,
NumMessages: 50,
NumExtensions: 0,
@@ -3508,7 +3241,6 @@ func file_service_user_proto_init() {
MessageInfos: file_service_user_proto_msgTypes,
}.Build()
File_service_user_proto = out.File
- file_service_user_proto_rawDesc = nil
file_service_user_proto_goTypes = nil
file_service_user_proto_depIdxs = nil
}
diff --git a/EdgeCommon/pkg/rpc/pb/service_user_grpc.pb.go b/EdgeCommon/pkg/rpc/pb/service_user_grpc.pb.go
index 97d95f4..8d24141 100644
--- a/EdgeCommon/pkg/rpc/pb/service_user_grpc.pb.go
+++ b/EdgeCommon/pkg/rpc/pb/service_user_grpc.pb.go
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
-// - protoc-gen-go-grpc v1.5.1
-// - protoc v6.33.2
+// - protoc-gen-go-grpc v1.6.1
+// - protoc v3.21.12
// source: service_user.proto
package pb
@@ -473,88 +473,88 @@ type UserServiceServer interface {
type UnimplementedUserServiceServer struct{}
func (UnimplementedUserServiceServer) CreateUser(context.Context, *CreateUserRequest) (*CreateUserResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method CreateUser not implemented")
+ return nil, status.Error(codes.Unimplemented, "method CreateUser not implemented")
}
func (UnimplementedUserServiceServer) RegisterUser(context.Context, *RegisterUserRequest) (*RegisterUserResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method RegisterUser not implemented")
+ return nil, status.Error(codes.Unimplemented, "method RegisterUser not implemented")
}
func (UnimplementedUserServiceServer) VerifyUser(context.Context, *VerifyUserRequest) (*RPCSuccess, error) {
- return nil, status.Errorf(codes.Unimplemented, "method VerifyUser not implemented")
+ return nil, status.Error(codes.Unimplemented, "method VerifyUser not implemented")
}
func (UnimplementedUserServiceServer) UpdateUser(context.Context, *UpdateUserRequest) (*RPCSuccess, error) {
- return nil, status.Errorf(codes.Unimplemented, "method UpdateUser not implemented")
+ return nil, status.Error(codes.Unimplemented, "method UpdateUser not implemented")
}
func (UnimplementedUserServiceServer) DeleteUser(context.Context, *DeleteUserRequest) (*RPCSuccess, error) {
- return nil, status.Errorf(codes.Unimplemented, "method DeleteUser not implemented")
+ return nil, status.Error(codes.Unimplemented, "method DeleteUser not implemented")
}
func (UnimplementedUserServiceServer) CountAllEnabledUsers(context.Context, *CountAllEnabledUsersRequest) (*RPCCountResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method CountAllEnabledUsers not implemented")
+ return nil, status.Error(codes.Unimplemented, "method CountAllEnabledUsers not implemented")
}
func (UnimplementedUserServiceServer) ListEnabledUsers(context.Context, *ListEnabledUsersRequest) (*ListEnabledUsersResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method ListEnabledUsers not implemented")
+ return nil, status.Error(codes.Unimplemented, "method ListEnabledUsers not implemented")
}
func (UnimplementedUserServiceServer) FindEnabledUser(context.Context, *FindEnabledUserRequest) (*FindEnabledUserResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method FindEnabledUser not implemented")
+ return nil, status.Error(codes.Unimplemented, "method FindEnabledUser not implemented")
}
func (UnimplementedUserServiceServer) CheckUserUsername(context.Context, *CheckUserUsernameRequest) (*CheckUserUsernameResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method CheckUserUsername not implemented")
+ return nil, status.Error(codes.Unimplemented, "method CheckUserUsername not implemented")
}
func (UnimplementedUserServiceServer) LoginUser(context.Context, *LoginUserRequest) (*LoginUserResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method LoginUser not implemented")
+ return nil, status.Error(codes.Unimplemented, "method LoginUser not implemented")
}
func (UnimplementedUserServiceServer) UpdateUserInfo(context.Context, *UpdateUserInfoRequest) (*RPCSuccess, error) {
- return nil, status.Errorf(codes.Unimplemented, "method UpdateUserInfo not implemented")
+ return nil, status.Error(codes.Unimplemented, "method UpdateUserInfo not implemented")
}
func (UnimplementedUserServiceServer) UpdateUserLogin(context.Context, *UpdateUserLoginRequest) (*RPCSuccess, error) {
- return nil, status.Errorf(codes.Unimplemented, "method UpdateUserLogin not implemented")
+ return nil, status.Error(codes.Unimplemented, "method UpdateUserLogin not implemented")
}
func (UnimplementedUserServiceServer) ComposeUserDashboard(context.Context, *ComposeUserDashboardRequest) (*ComposeUserDashboardResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method ComposeUserDashboard not implemented")
+ return nil, status.Error(codes.Unimplemented, "method ComposeUserDashboard not implemented")
}
func (UnimplementedUserServiceServer) FindUserNodeClusterId(context.Context, *FindUserNodeClusterIdRequest) (*FindUserNodeClusterIdResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method FindUserNodeClusterId not implemented")
+ return nil, status.Error(codes.Unimplemented, "method FindUserNodeClusterId not implemented")
}
func (UnimplementedUserServiceServer) UpdateUserFeatures(context.Context, *UpdateUserFeaturesRequest) (*RPCSuccess, error) {
- return nil, status.Errorf(codes.Unimplemented, "method UpdateUserFeatures not implemented")
+ return nil, status.Error(codes.Unimplemented, "method UpdateUserFeatures not implemented")
}
func (UnimplementedUserServiceServer) UpdateAllUsersFeatures(context.Context, *UpdateAllUsersFeaturesRequest) (*RPCSuccess, error) {
- return nil, status.Errorf(codes.Unimplemented, "method UpdateAllUsersFeatures not implemented")
+ return nil, status.Error(codes.Unimplemented, "method UpdateAllUsersFeatures not implemented")
}
func (UnimplementedUserServiceServer) FindUserFeatures(context.Context, *FindUserFeaturesRequest) (*FindUserFeaturesResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method FindUserFeatures not implemented")
+ return nil, status.Error(codes.Unimplemented, "method FindUserFeatures not implemented")
}
func (UnimplementedUserServiceServer) FindAllUserFeatureDefinitions(context.Context, *FindAllUserFeatureDefinitionsRequest) (*FindAllUserFeatureDefinitionsResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method FindAllUserFeatureDefinitions not implemented")
+ return nil, status.Error(codes.Unimplemented, "method FindAllUserFeatureDefinitions not implemented")
}
func (UnimplementedUserServiceServer) ComposeUserGlobalBoard(context.Context, *ComposeUserGlobalBoardRequest) (*ComposeUserGlobalBoardResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method ComposeUserGlobalBoard not implemented")
+ return nil, status.Error(codes.Unimplemented, "method ComposeUserGlobalBoard not implemented")
}
func (UnimplementedUserServiceServer) CheckUserOTPWithUsername(context.Context, *CheckUserOTPWithUsernameRequest) (*CheckUserOTPWithUsernameResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method CheckUserOTPWithUsername not implemented")
+ return nil, status.Error(codes.Unimplemented, "method CheckUserOTPWithUsername not implemented")
}
func (UnimplementedUserServiceServer) FindUserPriceInfo(context.Context, *FindUserPriceInfoRequest) (*FindUserPriceInfoResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method FindUserPriceInfo not implemented")
+ return nil, status.Error(codes.Unimplemented, "method FindUserPriceInfo not implemented")
}
func (UnimplementedUserServiceServer) UpdateUserPriceType(context.Context, *UpdateUserPriceTypeRequest) (*RPCSuccess, error) {
- return nil, status.Errorf(codes.Unimplemented, "method UpdateUserPriceType not implemented")
+ return nil, status.Error(codes.Unimplemented, "method UpdateUserPriceType not implemented")
}
func (UnimplementedUserServiceServer) UpdateUserPricePeriod(context.Context, *UpdateUserPricePeriodRequest) (*RPCSuccess, error) {
- return nil, status.Errorf(codes.Unimplemented, "method UpdateUserPricePeriod not implemented")
+ return nil, status.Error(codes.Unimplemented, "method UpdateUserPricePeriod not implemented")
}
func (UnimplementedUserServiceServer) CheckUserServersState(context.Context, *CheckUserServersStateRequest) (*CheckUserServersStateResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method CheckUserServersState not implemented")
+ return nil, status.Error(codes.Unimplemented, "method CheckUserServersState not implemented")
}
func (UnimplementedUserServiceServer) RenewUserServersState(context.Context, *RenewUserServersStateRequest) (*RenewUserServersStateResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method RenewUserServersState not implemented")
+ return nil, status.Error(codes.Unimplemented, "method RenewUserServersState not implemented")
}
func (UnimplementedUserServiceServer) CheckUserEmail(context.Context, *CheckUserEmailRequest) (*CheckUserEmailResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method CheckUserEmail not implemented")
+ return nil, status.Error(codes.Unimplemented, "method CheckUserEmail not implemented")
}
func (UnimplementedUserServiceServer) CheckUserMobile(context.Context, *CheckUserMobileRequest) (*CheckUserMobileResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method CheckUserMobile not implemented")
+ return nil, status.Error(codes.Unimplemented, "method CheckUserMobile not implemented")
}
func (UnimplementedUserServiceServer) FindUserVerifiedEmailWithUsername(context.Context, *FindUserVerifiedEmailWithUsernameRequest) (*FindUserVerifiedEmailWithUsernameResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method FindUserVerifiedEmailWithUsername not implemented")
+ return nil, status.Error(codes.Unimplemented, "method FindUserVerifiedEmailWithUsername not implemented")
}
func (UnimplementedUserServiceServer) testEmbeddedByValue() {}
@@ -566,7 +566,7 @@ type UnsafeUserServiceServer interface {
}
func RegisterUserServiceServer(s grpc.ServiceRegistrar, srv UserServiceServer) {
- // If the following call pancis, it indicates UnimplementedUserServiceServer was
+ // If the following call panics, it indicates UnimplementedUserServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
diff --git a/EdgeCommon/pkg/rpc/protos/models/model_httpdns_access_log.proto b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_access_log.proto
new file mode 100644
index 0000000..fe23460
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_access_log.proto
@@ -0,0 +1,29 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+message HTTPDNSAccessLog {
+ int64 id = 1;
+ string requestId = 2;
+ int64 clusterId = 3;
+ int64 nodeId = 4;
+ string appId = 5;
+ string appName = 6;
+ string domain = 7;
+ string qtype = 8;
+ string clientIP = 9;
+ string clientRegion = 10;
+ string carrier = 11;
+ string sdkVersion = 12;
+ string os = 13;
+ string resultIPs = 14;
+ string status = 15;
+ string errorCode = 16;
+ int32 costMs = 17;
+ int64 createdAt = 18;
+ string day = 19;
+ string summary = 20;
+ string nodeName = 21;
+ string clusterName = 22;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/models/model_httpdns_app.proto b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_app.proto
new file mode 100644
index 0000000..553ca89
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_app.proto
@@ -0,0 +1,20 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+message HTTPDNSApp {
+ int64 id = 1;
+ string name = 2;
+ string appId = 3;
+ bool isOn = 4;
+ reserved 5, 6; // removed: primaryClusterId, backupClusterId
+ string sniMode = 7;
+ bool signEnabled = 8;
+ string signSecret = 9;
+ int64 signUpdatedAt = 10;
+ int64 createdAt = 11;
+ int64 updatedAt = 12;
+ int64 userId = 13;
+ bytes clusterIdsJSON = 14;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/models/model_httpdns_cluster.proto b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_cluster.proto
new file mode 100644
index 0000000..3f38b02
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_cluster.proto
@@ -0,0 +1,21 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+message HTTPDNSCluster {
+ int64 id = 1;
+ bool isOn = 2;
+ bool isDefault = 3;
+ string name = 4;
+ string serviceDomain = 5;
+ int32 defaultTTL = 6;
+ int32 fallbackTimeoutMs = 7;
+ string installDir = 8;
+ bytes tlsPolicyJSON = 9;
+ int64 createdAt = 10;
+ int64 updatedAt = 11;
+ bool autoRemoteStart = 12;
+ bool accessLogIsOn = 13;
+ string timeZone = 14;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/models/model_httpdns_domain.proto b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_domain.proto
new file mode 100644
index 0000000..5b7f3f0
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_domain.proto
@@ -0,0 +1,14 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+message HTTPDNSDomain {
+ int64 id = 1;
+ int64 appId = 2;
+ string domain = 3;
+ bool isOn = 4;
+ int64 createdAt = 5;
+ int64 updatedAt = 6;
+ int64 ruleCount = 7;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/models/model_httpdns_node.proto b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_node.proto
new file mode 100644
index 0000000..ecfbe5f
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_node.proto
@@ -0,0 +1,24 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+import "models/model_node_login.proto";
+
+message HTTPDNSNode {
+ int64 id = 1;
+ int64 clusterId = 2;
+ string name = 3;
+ bool isOn = 4;
+ bool isUp = 5;
+ bool isInstalled = 6;
+ bool isActive = 7;
+ string uniqueId = 8;
+ string secret = 9;
+ string installDir = 10;
+ bytes statusJSON = 11;
+ bytes installStatusJSON = 12;
+ int64 createdAt = 13;
+ int64 updatedAt = 14;
+ NodeLogin nodeLogin = 15;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/models/model_httpdns_rule.proto b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_rule.proto
new file mode 100644
index 0000000..7141520
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_rule.proto
@@ -0,0 +1,31 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+message HTTPDNSRuleRecord {
+ int64 id = 1;
+ int64 ruleId = 2;
+ string recordType = 3;
+ string recordValue = 4;
+ int32 weight = 5;
+ int32 sort = 6;
+}
+
+message HTTPDNSCustomRule {
+ int64 id = 1;
+ int64 appId = 2;
+ int64 domainId = 3;
+ string ruleName = 4;
+ string lineScope = 5;
+ string lineCarrier = 6;
+ string lineRegion = 7;
+ string lineProvince = 8;
+ string lineContinent = 9;
+ string lineCountry = 10;
+ int32 ttl = 11;
+ bool isOn = 12;
+ int32 priority = 13;
+ int64 updatedAt = 14;
+ repeated HTTPDNSRuleRecord records = 15;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/models/model_httpdns_runtime_log.proto b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_runtime_log.proto
new file mode 100644
index 0000000..73e7069
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/models/model_httpdns_runtime_log.proto
@@ -0,0 +1,20 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+message HTTPDNSRuntimeLog {
+ int64 id = 1;
+ int64 clusterId = 2;
+ int64 nodeId = 3;
+ string level = 4;
+ string type = 5;
+ string module = 6;
+ string description = 7;
+ int64 count = 8;
+ string requestId = 9;
+ int64 createdAt = 10;
+ string day = 11;
+ string clusterName = 12;
+ string nodeName = 13;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/models/model_user.proto b/EdgeCommon/pkg/rpc/protos/models/model_user.proto
index 16d729d..ac09565 100644
--- a/EdgeCommon/pkg/rpc/protos/models/model_user.proto
+++ b/EdgeCommon/pkg/rpc/protos/models/model_user.proto
@@ -28,6 +28,7 @@ message User {
bool isEnterpriseIdentified = 18; // 是否已通过企业验证
string bandwidthAlgo = 21; // 带宽算法
string lang = 22; // 语言代号
+ bytes httpdnsClusterIdsJSON = 24; // HTTPDNS关联集群ID列表
Login otpLogin = 19; // OTP认证
diff --git a/EdgeCommon/pkg/rpc/protos/service_httpdns_access_log.proto b/EdgeCommon/pkg/rpc/protos/service_httpdns_access_log.proto
new file mode 100644
index 0000000..766eb64
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/service_httpdns_access_log.proto
@@ -0,0 +1,35 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+import "models/model_httpdns_access_log.proto";
+
+service HTTPDNSAccessLogService {
+ rpc createHTTPDNSAccessLogs (CreateHTTPDNSAccessLogsRequest) returns (CreateHTTPDNSAccessLogsResponse);
+ rpc listHTTPDNSAccessLogs (ListHTTPDNSAccessLogsRequest) returns (ListHTTPDNSAccessLogsResponse);
+}
+
+message CreateHTTPDNSAccessLogsRequest {
+ repeated HTTPDNSAccessLog logs = 1;
+}
+
+message CreateHTTPDNSAccessLogsResponse {
+}
+
+message ListHTTPDNSAccessLogsRequest {
+ string day = 1;
+ int64 clusterId = 2;
+ int64 nodeId = 3;
+ string appId = 4;
+ string domain = 5;
+ string status = 6;
+ string keyword = 7;
+ int64 offset = 8;
+ int64 size = 9;
+}
+
+message ListHTTPDNSAccessLogsResponse {
+ repeated HTTPDNSAccessLog logs = 1;
+ int64 total = 2;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/service_httpdns_app.proto b/EdgeCommon/pkg/rpc/protos/service_httpdns_app.proto
new file mode 100644
index 0000000..da8b9f9
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/service_httpdns_app.proto
@@ -0,0 +1,84 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+import "models/model_httpdns_app.proto";
+import "models/rpc_messages.proto";
+
+service HTTPDNSAppService {
+ rpc createHTTPDNSApp (CreateHTTPDNSAppRequest) returns (CreateHTTPDNSAppResponse);
+ rpc updateHTTPDNSApp (UpdateHTTPDNSAppRequest) returns (RPCSuccess);
+ rpc deleteHTTPDNSApp (DeleteHTTPDNSAppRequest) returns (RPCSuccess);
+ rpc findHTTPDNSApp (FindHTTPDNSAppRequest) returns (FindHTTPDNSAppResponse);
+ rpc listHTTPDNSApps (ListHTTPDNSAppsRequest) returns (ListHTTPDNSAppsResponse);
+ rpc findAllHTTPDNSApps (FindAllHTTPDNSAppsRequest) returns (FindAllHTTPDNSAppsResponse);
+ rpc updateHTTPDNSAppSignEnabled (UpdateHTTPDNSAppSignEnabledRequest) returns (RPCSuccess);
+ rpc resetHTTPDNSAppSignSecret (ResetHTTPDNSAppSignSecretRequest) returns (ResetHTTPDNSAppSignSecretResponse);
+}
+
+message CreateHTTPDNSAppRequest {
+ string name = 1;
+ string appId = 2;
+ reserved 3, 4; // removed: primaryClusterId, backupClusterId
+ bool isOn = 5;
+ bool signEnabled = 6;
+ int64 userId = 7;
+ bytes clusterIdsJSON = 8;
+}
+
+message CreateHTTPDNSAppResponse {
+ int64 appDbId = 1;
+}
+
+message UpdateHTTPDNSAppRequest {
+ int64 appDbId = 1;
+ string name = 2;
+ reserved 3, 4; // removed: primaryClusterId, backupClusterId
+ bool isOn = 5;
+ int64 userId = 6;
+ bytes clusterIdsJSON = 7;
+}
+
+message DeleteHTTPDNSAppRequest {
+ int64 appDbId = 1;
+}
+
+message FindHTTPDNSAppRequest {
+ int64 appDbId = 1;
+}
+
+message FindHTTPDNSAppResponse {
+ HTTPDNSApp app = 1;
+}
+
+message ListHTTPDNSAppsRequest {
+ int64 offset = 1;
+ int64 size = 2;
+ string keyword = 3;
+}
+
+message ListHTTPDNSAppsResponse {
+ repeated HTTPDNSApp apps = 1;
+}
+
+message FindAllHTTPDNSAppsRequest {
+}
+
+message FindAllHTTPDNSAppsResponse {
+ repeated HTTPDNSApp apps = 1;
+}
+
+message UpdateHTTPDNSAppSignEnabledRequest {
+ int64 appDbId = 1;
+ bool signEnabled = 2;
+}
+
+message ResetHTTPDNSAppSignSecretRequest {
+ int64 appDbId = 1;
+}
+
+message ResetHTTPDNSAppSignSecretResponse {
+ string signSecret = 1;
+ int64 updatedAt = 2;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/service_httpdns_cluster.proto b/EdgeCommon/pkg/rpc/protos/service_httpdns_cluster.proto
new file mode 100644
index 0000000..9167467
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/service_httpdns_cluster.proto
@@ -0,0 +1,93 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+import "models/model_httpdns_cluster.proto";
+import "models/model_httpdns_node.proto";
+import "models/rpc_messages.proto";
+
+service HTTPDNSClusterService {
+ rpc createHTTPDNSCluster (CreateHTTPDNSClusterRequest) returns (CreateHTTPDNSClusterResponse);
+ rpc updateHTTPDNSCluster (UpdateHTTPDNSClusterRequest) returns (RPCSuccess);
+ rpc deleteHTTPDNSCluster (DeleteHTTPDNSClusterRequest) returns (RPCSuccess);
+ rpc findHTTPDNSCluster (FindHTTPDNSClusterRequest) returns (FindHTTPDNSClusterResponse);
+ rpc listHTTPDNSClusters (ListHTTPDNSClustersRequest) returns (ListHTTPDNSClustersResponse);
+ rpc findAllHTTPDNSClusters (FindAllHTTPDNSClustersRequest) returns (FindAllHTTPDNSClustersResponse);
+ rpc updateHTTPDNSClusterDefault (UpdateHTTPDNSClusterDefaultRequest) returns (RPCSuccess);
+ rpc listHTTPDNSNodesWithClusterId (ListHTTPDNSNodesWithClusterIdRequest) returns (ListHTTPDNSNodesWithClusterIdResponse);
+}
+
+message CreateHTTPDNSClusterRequest {
+ string name = 1;
+ string serviceDomain = 2;
+ int32 defaultTTL = 3;
+ int32 fallbackTimeoutMs = 4;
+ string installDir = 5;
+ bytes tlsPolicyJSON = 6;
+ bool isOn = 7;
+ bool isDefault = 8;
+ bool autoRemoteStart = 9;
+ bool accessLogIsOn = 10;
+ string timeZone = 11;
+}
+
+message CreateHTTPDNSClusterResponse {
+ int64 clusterId = 1;
+}
+
+message UpdateHTTPDNSClusterRequest {
+ int64 clusterId = 1;
+ string name = 2;
+ string serviceDomain = 3;
+ int32 defaultTTL = 4;
+ int32 fallbackTimeoutMs = 5;
+ string installDir = 6;
+ bytes tlsPolicyJSON = 7;
+ bool isOn = 8;
+ bool isDefault = 9;
+ bool autoRemoteStart = 10;
+ bool accessLogIsOn = 11;
+ string timeZone = 12;
+}
+
+message DeleteHTTPDNSClusterRequest {
+ int64 clusterId = 1;
+}
+
+message FindHTTPDNSClusterRequest {
+ int64 clusterId = 1;
+}
+
+message FindHTTPDNSClusterResponse {
+ HTTPDNSCluster cluster = 1;
+}
+
+message ListHTTPDNSClustersRequest {
+ int64 offset = 1;
+ int64 size = 2;
+ string keyword = 3;
+}
+
+message ListHTTPDNSClustersResponse {
+ repeated HTTPDNSCluster clusters = 1;
+}
+
+message FindAllHTTPDNSClustersRequest {
+}
+
+message FindAllHTTPDNSClustersResponse {
+ repeated HTTPDNSCluster clusters = 1;
+}
+
+message UpdateHTTPDNSClusterDefaultRequest {
+ int64 clusterId = 1;
+}
+
+message ListHTTPDNSNodesWithClusterIdRequest {
+ int64 clusterId = 1;
+}
+
+message ListHTTPDNSNodesWithClusterIdResponse {
+ repeated HTTPDNSNode nodes = 1;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/service_httpdns_domain.proto b/EdgeCommon/pkg/rpc/protos/service_httpdns_domain.proto
new file mode 100644
index 0000000..21171b9
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/service_httpdns_domain.proto
@@ -0,0 +1,42 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+import "models/model_httpdns_domain.proto";
+import "models/rpc_messages.proto";
+
+service HTTPDNSDomainService {
+ rpc createHTTPDNSDomain (CreateHTTPDNSDomainRequest) returns (CreateHTTPDNSDomainResponse);
+ rpc deleteHTTPDNSDomain (DeleteHTTPDNSDomainRequest) returns (RPCSuccess);
+ rpc updateHTTPDNSDomainStatus (UpdateHTTPDNSDomainStatusRequest) returns (RPCSuccess);
+ rpc listHTTPDNSDomainsWithAppId (ListHTTPDNSDomainsWithAppIdRequest) returns (ListHTTPDNSDomainsWithAppIdResponse);
+}
+
+message CreateHTTPDNSDomainRequest {
+ int64 appDbId = 1;
+ string domain = 2;
+ bool isOn = 3;
+}
+
+message CreateHTTPDNSDomainResponse {
+ int64 domainId = 1;
+}
+
+message DeleteHTTPDNSDomainRequest {
+ int64 domainId = 1;
+}
+
+message UpdateHTTPDNSDomainStatusRequest {
+ int64 domainId = 1;
+ bool isOn = 2;
+}
+
+message ListHTTPDNSDomainsWithAppIdRequest {
+ int64 appDbId = 1;
+ string keyword = 2;
+}
+
+message ListHTTPDNSDomainsWithAppIdResponse {
+ repeated HTTPDNSDomain domains = 1;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/service_httpdns_node.proto b/EdgeCommon/pkg/rpc/protos/service_httpdns_node.proto
new file mode 100644
index 0000000..052a6f7
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/service_httpdns_node.proto
@@ -0,0 +1,141 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+import "models/model_httpdns_node.proto";
+import "models/model_node_login.proto";
+import "models/rpc_messages.proto";
+
+service HTTPDNSNodeService {
+ rpc createHTTPDNSNode (CreateHTTPDNSNodeRequest) returns (CreateHTTPDNSNodeResponse);
+ rpc updateHTTPDNSNode (UpdateHTTPDNSNodeRequest) returns (RPCSuccess);
+ rpc deleteHTTPDNSNode (DeleteHTTPDNSNodeRequest) returns (RPCSuccess);
+ rpc findHTTPDNSNode (FindHTTPDNSNodeRequest) returns (FindHTTPDNSNodeResponse);
+ rpc listHTTPDNSNodes (ListHTTPDNSNodesRequest) returns (ListHTTPDNSNodesResponse);
+ rpc updateHTTPDNSNodeStatus (UpdateHTTPDNSNodeStatusRequest) returns (RPCSuccess);
+ // 修改HTTPDNS节点登录信息
+ rpc updateHTTPDNSNodeLogin (UpdateHTTPDNSNodeLoginRequest) returns (RPCSuccess);
+
+ // 检查HTTPDNS节点新版本
+ rpc checkHTTPDNSNodeLatestVersion (CheckHTTPDNSNodeLatestVersionRequest) returns (CheckHTTPDNSNodeLatestVersionResponse);
+
+ // 下载最新HTTPDNS节点安装文件
+ rpc downloadHTTPDNSNodeInstallationFile (DownloadHTTPDNSNodeInstallationFileRequest) returns (DownloadHTTPDNSNodeInstallationFileResponse);
+
+ // 计算需要升级的HTTPDNS节点数量
+ rpc countAllUpgradeHTTPDNSNodesWithClusterId (CountAllUpgradeHTTPDNSNodesWithClusterIdRequest) returns (RPCCountResponse);
+
+ // 列出所有需要升级的HTTPDNS节点
+ rpc findAllUpgradeHTTPDNSNodesWithClusterId (FindAllUpgradeHTTPDNSNodesWithClusterIdRequest) returns (FindAllUpgradeHTTPDNSNodesWithClusterIdResponse);
+
+ // 升级单个HTTPDNS节点
+ rpc upgradeHTTPDNSNode (UpgradeHTTPDNSNodeRequest) returns (RPCSuccess);
+}
+
+message CreateHTTPDNSNodeRequest {
+ int64 clusterId = 1;
+ string name = 2;
+ string installDir = 3;
+ bool isOn = 4;
+}
+
+message CreateHTTPDNSNodeResponse {
+ int64 nodeId = 1;
+}
+
+message UpdateHTTPDNSNodeRequest {
+ int64 nodeId = 1;
+ string name = 2;
+ string installDir = 3;
+ bool isOn = 4;
+}
+
+message DeleteHTTPDNSNodeRequest {
+ int64 nodeId = 1;
+}
+
+message FindHTTPDNSNodeRequest {
+ int64 nodeId = 1;
+}
+
+message FindHTTPDNSNodeResponse {
+ HTTPDNSNode node = 1;
+}
+
+message ListHTTPDNSNodesRequest {
+ int64 clusterId = 1;
+}
+
+message ListHTTPDNSNodesResponse {
+ repeated HTTPDNSNode nodes = 1;
+}
+
+message UpdateHTTPDNSNodeStatusRequest {
+ int64 nodeId = 1;
+ bool isUp = 2;
+ bool isInstalled = 3;
+ bool isActive = 4;
+ bytes statusJSON = 5;
+ bytes installStatusJSON = 6;
+}
+
+// 修改HTTPDNS节点登录信息
+message UpdateHTTPDNSNodeLoginRequest {
+ int64 nodeId = 1;
+ NodeLogin nodeLogin = 2;
+}
+
+// 检查HTTPDNS节点新版本
+message CheckHTTPDNSNodeLatestVersionRequest {
+ string os = 1;
+ string arch = 2;
+ string currentVersion = 3;
+}
+
+message CheckHTTPDNSNodeLatestVersionResponse {
+ bool hasNewVersion = 1;
+ string newVersion = 2;
+}
+
+// 下载最新HTTPDNS节点安装文件
+message DownloadHTTPDNSNodeInstallationFileRequest {
+ string os = 1;
+ string arch = 2;
+ int64 chunkOffset = 3;
+}
+
+message DownloadHTTPDNSNodeInstallationFileResponse {
+ bytes chunkData = 1;
+ string sum = 2;
+ int64 offset = 3;
+ string version = 4;
+ string filename = 5;
+}
+
+// 计算需要升级的HTTPDNS节点数量
+message CountAllUpgradeHTTPDNSNodesWithClusterIdRequest {
+ int64 clusterId = 1;
+}
+
+// 列出所有需要升级的HTTPDNS节点
+message FindAllUpgradeHTTPDNSNodesWithClusterIdRequest {
+ int64 clusterId = 1;
+}
+
+message FindAllUpgradeHTTPDNSNodesWithClusterIdResponse {
+ repeated HTTPDNSNodeUpgrade nodes = 1;
+
+ message HTTPDNSNodeUpgrade {
+ HTTPDNSNode node = 1;
+ string os = 2;
+ string arch = 3;
+ string oldVersion = 4;
+ string newVersion = 5;
+ }
+}
+
+// 升级单个HTTPDNS节点
+message UpgradeHTTPDNSNodeRequest {
+ int64 nodeId = 1;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/service_httpdns_rule.proto b/EdgeCommon/pkg/rpc/protos/service_httpdns_rule.proto
new file mode 100644
index 0000000..2d23b5f
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/service_httpdns_rule.proto
@@ -0,0 +1,44 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+import "models/model_httpdns_rule.proto";
+import "models/rpc_messages.proto";
+
+service HTTPDNSRuleService {
+ rpc createHTTPDNSCustomRule (CreateHTTPDNSCustomRuleRequest) returns (CreateHTTPDNSCustomRuleResponse);
+ rpc updateHTTPDNSCustomRule (UpdateHTTPDNSCustomRuleRequest) returns (RPCSuccess);
+ rpc deleteHTTPDNSCustomRule (DeleteHTTPDNSCustomRuleRequest) returns (RPCSuccess);
+ rpc updateHTTPDNSCustomRuleStatus (UpdateHTTPDNSCustomRuleStatusRequest) returns (RPCSuccess);
+ rpc listHTTPDNSCustomRulesWithDomainId (ListHTTPDNSCustomRulesWithDomainIdRequest) returns (ListHTTPDNSCustomRulesWithDomainIdResponse);
+}
+
+message CreateHTTPDNSCustomRuleRequest {
+ HTTPDNSCustomRule rule = 1;
+}
+
+message CreateHTTPDNSCustomRuleResponse {
+ int64 ruleId = 1;
+}
+
+message UpdateHTTPDNSCustomRuleRequest {
+ HTTPDNSCustomRule rule = 1;
+}
+
+message DeleteHTTPDNSCustomRuleRequest {
+ int64 ruleId = 1;
+}
+
+message UpdateHTTPDNSCustomRuleStatusRequest {
+ int64 ruleId = 1;
+ bool isOn = 2;
+}
+
+message ListHTTPDNSCustomRulesWithDomainIdRequest {
+ int64 domainId = 1;
+}
+
+message ListHTTPDNSCustomRulesWithDomainIdResponse {
+ repeated HTTPDNSCustomRule rules = 1;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/service_httpdns_runtime_log.proto b/EdgeCommon/pkg/rpc/protos/service_httpdns_runtime_log.proto
new file mode 100644
index 0000000..7aff93a
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/service_httpdns_runtime_log.proto
@@ -0,0 +1,33 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+import "models/model_httpdns_runtime_log.proto";
+
+service HTTPDNSRuntimeLogService {
+ rpc createHTTPDNSRuntimeLogs (CreateHTTPDNSRuntimeLogsRequest) returns (CreateHTTPDNSRuntimeLogsResponse);
+ rpc listHTTPDNSRuntimeLogs (ListHTTPDNSRuntimeLogsRequest) returns (ListHTTPDNSRuntimeLogsResponse);
+}
+
+message CreateHTTPDNSRuntimeLogsRequest {
+ repeated HTTPDNSRuntimeLog logs = 1;
+}
+
+message CreateHTTPDNSRuntimeLogsResponse {
+}
+
+message ListHTTPDNSRuntimeLogsRequest {
+ string day = 1;
+ int64 clusterId = 2;
+ int64 nodeId = 3;
+ string level = 4;
+ string keyword = 5;
+ int64 offset = 6;
+ int64 size = 7;
+}
+
+message ListHTTPDNSRuntimeLogsResponse {
+ repeated HTTPDNSRuntimeLog logs = 1;
+ int64 total = 2;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/service_httpdns_sandbox.proto b/EdgeCommon/pkg/rpc/protos/service_httpdns_sandbox.proto
new file mode 100644
index 0000000..5a95fbe
--- /dev/null
+++ b/EdgeCommon/pkg/rpc/protos/service_httpdns_sandbox.proto
@@ -0,0 +1,45 @@
+syntax = "proto3";
+option go_package = "./pb";
+
+package pb;
+
+import "models/rpc_messages.proto";
+
+service HTTPDNSSandboxService {
+ rpc testHTTPDNSResolve (TestHTTPDNSResolveRequest) returns (TestHTTPDNSResolveResponse);
+}
+
+message TestHTTPDNSResolveRequest {
+ int64 clusterId = 1;
+ string appId = 2;
+ string domain = 3;
+ string qtype = 4;
+ string clientIP = 5;
+ string sid = 6;
+ string sdkVersion = 7;
+ string os = 8;
+}
+
+message HTTPDNSResolveRecord {
+ string type = 1;
+ string ip = 2;
+ int32 ttl = 3;
+ int32 weight = 4;
+ string line = 5;
+ string region = 6;
+}
+
+message TestHTTPDNSResolveResponse {
+ string code = 1;
+ string message = 2;
+ string requestId = 3;
+ string domain = 4;
+ string qtype = 5;
+ int32 ttl = 6;
+ repeated HTTPDNSResolveRecord records = 7;
+ string clientIP = 8;
+ string clientRegion = 9;
+ string clientCarrier = 10;
+ string clientCountry = 11;
+ string summary = 12;
+}
diff --git a/EdgeCommon/pkg/rpc/protos/service_ns_node.proto b/EdgeCommon/pkg/rpc/protos/service_ns_node.proto
index 0bed186..2546c88 100644
--- a/EdgeCommon/pkg/rpc/protos/service_ns_node.proto
+++ b/EdgeCommon/pkg/rpc/protos/service_ns_node.proto
@@ -25,6 +25,12 @@ service NSNodeService {
// 计算需要升级的NS节点数量
rpc countAllUpgradeNSNodesWithNSClusterId (CountAllUpgradeNSNodesWithNSClusterIdRequest) returns (RPCCountResponse);
+ // 列出所有需要升级的NS节点
+ rpc findAllUpgradeNSNodesWithNSClusterId (FindAllUpgradeNSNodesWithNSClusterIdRequest) returns (FindAllUpgradeNSNodesWithNSClusterIdResponse);
+
+ // 升级单个NS节点
+ rpc upgradeNSNode (UpgradeNSNodeRequest) returns (RPCSuccess);
+
// 创建NS节点
rpc createNSNode (CreateNSNodeRequest) returns (CreateNSNodeResponse);
@@ -316,4 +322,26 @@ message FindNSNodeAPIConfigResponse {
message UpdateNSNodeAPIConfigRequest {
int64 nsNodeId = 1;
bytes apiNodeAddrsJSON = 2;
+}
+
+// 列出所有需要升级的NS节点
+message FindAllUpgradeNSNodesWithNSClusterIdRequest {
+ int64 nsClusterId = 1;
+}
+
+message FindAllUpgradeNSNodesWithNSClusterIdResponse {
+ repeated NSNodeUpgrade nodes = 1;
+
+ message NSNodeUpgrade {
+ NSNode nsNode = 1;
+ string os = 2;
+ string arch = 3;
+ string oldVersion = 4;
+ string newVersion = 5;
+ }
+}
+
+// 升级单个NS节点
+message UpgradeNSNodeRequest {
+ int64 nsNodeId = 1;
}
\ No newline at end of file
diff --git a/EdgeCommon/pkg/rpc/protos/service_user.proto b/EdgeCommon/pkg/rpc/protos/service_user.proto
index 940acac..a490de1 100644
--- a/EdgeCommon/pkg/rpc/protos/service_user.proto
+++ b/EdgeCommon/pkg/rpc/protos/service_user.proto
@@ -148,6 +148,7 @@ message UpdateUserRequest {
bool isOn = 9;
int64 nodeClusterId = 10;
string bandwidthAlgo = 11;
+ bytes httpdnsClusterIdsJSON = 12; // HTTPDNS关联集群ID列表
}
// 删除用户
diff --git a/EdgeCommon/pkg/systemconfigs/settings.go b/EdgeCommon/pkg/systemconfigs/settings.go
index 45224fd..26f3f7a 100644
--- a/EdgeCommon/pkg/systemconfigs/settings.go
+++ b/EdgeCommon/pkg/systemconfigs/settings.go
@@ -3,18 +3,19 @@ package systemconfigs
type SettingCode = string
const (
- SettingCodeNodeMonitor SettingCode = "nodeMonitor" // 监控节点状态
- SettingCodeClusterHealthCheck SettingCode = "clusterHealthCheck" // 集群健康检查
- SettingCodeIPListVersion SettingCode = "ipListVersion" // IP名单的版本号
- SettingCodeAdminSecurityConfig SettingCode = "adminSecurityConfig" // 管理员安全设置
- SettingCodeAdminUIConfig SettingCode = "adminUIConfig" // 管理员界面设置
- SettingCodeDatabaseConfigSetting SettingCode = "databaseConfig" // 数据库相关配置
- SettingCodeAccessLogQueue SettingCode = "accessLogQueue" // 访问日志队列
- SettingCodeCheckUpdates SettingCode = "checkUpdates" // 检查自动更新配置
+ SettingCodeNodeMonitor SettingCode = "nodeMonitor" // 监控节点状态
+ SettingCodeClusterHealthCheck SettingCode = "clusterHealthCheck" // 集群健康检查
+ SettingCodeIPListVersion SettingCode = "ipListVersion" // IP名单版本号
+ SettingCodeAdminSecurityConfig SettingCode = "adminSecurityConfig" // 管理端安全设置
+ SettingCodeAdminUIConfig SettingCode = "adminUIConfig" // 管理端界面设置
+ SettingCodeDatabaseConfigSetting SettingCode = "databaseConfig" // 数据库配置
+ SettingCodeAccessLogQueue SettingCode = "accessLogQueue" // 访问日志队列
+ SettingCodeCheckUpdates SettingCode = "checkUpdates" // 自动更新配置
+ SettingCodeUserServerConfig SettingCode = "userServerConfig" // 用户服务设置
+ SettingCodeUserRegisterConfig SettingCode = "userRegisterConfig" // 用户注册配置
+ SettingCodeUserUIConfig SettingCode = "userUIConfig" // 用户界面配置
+ SettingCodeStandaloneInstanceInitialized SettingCode = "standaloneInstanceInitialized" // 单体实例初始化状态
- SettingCodeUserServerConfig SettingCode = "userServerConfig" // 用户服务设置
- SettingCodeUserRegisterConfig SettingCode = "userRegisterConfig" // 用户注册配置
- SettingCodeUserUIConfig SettingCode = "userUIConfig" // 用户界面配置
-
- SettingCodeStandaloneInstanceInitialized SettingCode = "standaloneInstanceInitialized" // 单体实例是否已经被初始化:0 未被初始化, 1 已经成功初始化
+ SettingCodeHTTPDNSDefaultBackupClusterId SettingCode = "httpdnsDefaultBackupClusterId" // HTTPDNS默认备用集群ID
+ SettingCodeUpgradeConfig SettingCode = "upgradeConfig" // 升级设置
)
diff --git a/EdgeCommon/pkg/systemconfigs/upgrade_config.go b/EdgeCommon/pkg/systemconfigs/upgrade_config.go
new file mode 100644
index 0000000..e511cd3
--- /dev/null
+++ b/EdgeCommon/pkg/systemconfigs/upgrade_config.go
@@ -0,0 +1,12 @@
+package systemconfigs
+
+// UpgradeConfig 升级设置
+type UpgradeConfig struct {
+ AutoUpgrade bool `json:"autoUpgrade"` // 是否开启自动升级(控制EdgeNode、EdgeDNS、EdgeHTTPDNS三个模块)
+}
+
+func NewUpgradeConfig() *UpgradeConfig {
+ return &UpgradeConfig{
+ AutoUpgrade: false,
+ }
+}
diff --git a/EdgeCommon/pkg/userconfigs/user_features.go b/EdgeCommon/pkg/userconfigs/user_features.go
index 2df5b35..84a3fb9 100644
--- a/EdgeCommon/pkg/userconfigs/user_features.go
+++ b/EdgeCommon/pkg/userconfigs/user_features.go
@@ -9,6 +9,7 @@ type UserFeatureCode = string
const (
UserFeatureCodePlan UserFeatureCode = "plan"
+ UserFeatureCodeHTTPDNS UserFeatureCode = "httpdns"
UserFeatureCodeServerTCP UserFeatureCode = "server.tcp"
UserFeatureCodeServerTCPPort UserFeatureCode = "server.tcp.port"
@@ -57,7 +58,7 @@ func (this *UserFeature) ToPB() *pb.UserFeature {
func FindAllUserFeatures() []*UserFeature {
return []*UserFeature{
{
- Name: "记录访问日志",
+ Name: "访问日志记录",
Code: UserFeatureCodeServerAccessLog,
Description: "用户可以开启服务的访问日志。",
SupportPlan: true,
@@ -105,7 +106,7 @@ func FindAllUserFeatures() []*UserFeature {
SupportPlan: false,
},
{
- Name: "开启WAF",
+ Name: "WAF",
Code: UserFeatureCodeServerWAF,
Description: "用户可以开启WAF功能并可以设置黑白名单等。",
SupportPlan: true,
@@ -135,7 +136,7 @@ func FindAllUserFeatures() []*UserFeature {
SupportPlan: true,
},
{
- Name: "页面优化",
+ Name: "页面动态加密",
Code: UserFeatureCodeServerOptimization,
Description: "用户可以开启页面优化功能。",
SupportPlan: true,
@@ -212,6 +213,7 @@ func FindAllUserFeatures() []*UserFeature {
Description: "用户可以购买和管理套餐。",
SupportPlan: false,
},
+ // HTTPDNS 功能已改为通过用户设置页面全局开关控制,不再作为单独的功能选项
}
}
diff --git a/EdgeCommon/pkg/userconfigs/user_register_config.go b/EdgeCommon/pkg/userconfigs/user_register_config.go
index 175009e..862c732 100644
--- a/EdgeCommon/pkg/userconfigs/user_register_config.go
+++ b/EdgeCommon/pkg/userconfigs/user_register_config.go
@@ -52,6 +52,9 @@ type UserRegisterConfig struct {
// 开通DNS服务
NSIsOn bool `json:"nsIsOn"` // 是否开启智能DNS服务
+ // 开通HTTPDNS服务
+ HTTPDNSIsOn bool `json:"httpdnsIsOn"` // 是否开启用户端HTTPDNS服务
+ HTTPDNSDefaultClusterIds []int64 `json:"httpdnsDefaultClusterIds"` // HTTPDNS默认集群ID列表
// 开通高防服务
ADIsOn bool `json:"adIsOn"` // 是否开启高防服务
@@ -63,6 +66,7 @@ func DefaultUserRegisterConfig() *UserRegisterConfig {
ComplexPassword: true,
CDNIsOn: true,
NSIsOn: false,
+ HTTPDNSIsOn: false,
Features: []string{
UserFeatureCodeServerAccessLog,
UserFeatureCodeServerViewAccessLog,
diff --git a/EdgeDNS/internal/const/const.go b/EdgeDNS/internal/const/const.go
index 6eea4be..1770316 100644
--- a/EdgeDNS/internal/const/const.go
+++ b/EdgeDNS/internal/const/const.go
@@ -1,7 +1,7 @@
package teaconst
const (
- Version = "1.4.7" //1.3.8.2
+ Version = "1.4.9" //1.3.8.2
ProductName = "Edge DNS"
ProcessName = "edge-dns"
diff --git a/EdgeDNS/internal/firewalls/ddos_protection.go b/EdgeDNS/internal/firewalls/ddos_protection.go
index c852a08..45b38fa 100644
--- a/EdgeDNS/internal/firewalls/ddos_protection.go
+++ b/EdgeDNS/internal/firewalls/ddos_protection.go
@@ -173,6 +173,10 @@ func (this *DDoSProtectionManager) addTCPRules(tcpConfig *ddosconfigs.TCPConfig)
var ports = []int32{}
for _, portConfig := range tcpConfig.Ports {
+ // 校验端口范围
+ if portConfig.Port <= 0 || portConfig.Port > 65535 {
+ continue
+ }
if !lists.ContainsInt32(ports, portConfig.Port) {
ports = append(ports, portConfig.Port)
}
@@ -367,7 +371,19 @@ func (this *DDoSProtectionManager) encodeUserData(attrs []string) string {
return ""
}
- return "ZZ" + strings.Join(attrs, "_") + "ZZ"
+ // 清洗每个属性值,只保留字母、数字和横杠
+ var safeAttrs = make([]string, len(attrs))
+ for i, attr := range attrs {
+ var safe strings.Builder
+ for _, c := range attr {
+ if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' {
+ safe.WriteRune(c)
+ }
+ }
+ safeAttrs[i] = safe.String()
+ }
+
+ return "ZZ" + strings.Join(safeAttrs, "_") + "ZZ"
}
// 解码user data
diff --git a/EdgeDNS/internal/nodes/dns_node.go b/EdgeDNS/internal/nodes/dns_node.go
index 5c5d15c..a2c7d11 100644
--- a/EdgeDNS/internal/nodes/dns_node.go
+++ b/EdgeDNS/internal/nodes/dns_node.go
@@ -31,6 +31,7 @@ import (
"os"
"os/exec"
"os/signal"
+ "regexp"
"runtime"
"runtime/debug"
"syscall"
@@ -328,6 +329,13 @@ func (this *DNSNode) start() {
apiConfig.NumberId = config.Id
}
+ // 验证 NodeId 防止路径遍历
+ var nodeIdRegexp = regexp.MustCompile(`^[a-zA-Z0-9_\-]+$`)
+ if !nodeIdRegexp.MatchString(config.NodeId) {
+ remotelogs.Error("NODE", "invalid NodeId: contains illegal characters")
+ return
+ }
+
var db = dbs.NewDB(Tea.Root + "/data/data-" + types.String(config.Id) + "-" + config.NodeId + "-v0.1.0.db")
err = db.Init()
if err != nil {
diff --git a/EdgeDNS/internal/nodes/server.go b/EdgeDNS/internal/nodes/server.go
index 2ebab02..e4f3630 100644
--- a/EdgeDNS/internal/nodes/server.go
+++ b/EdgeDNS/internal/nodes/server.go
@@ -247,6 +247,15 @@ func (this *Server) parseAction(questionName string, remoteAddr *string) (string
return "", errors.New("decode question option failed: " + err.Error())
} else {
var ip = m.GetString("ip")
+ // 验证 IP 地址合法性,防止 IP 欺骗
+ parsedIP := net.ParseIP(ip)
+ if parsedIP == nil {
+ return "", errors.New("invalid IP address in setRemoteAddr: " + ip)
+ }
+ // 拒绝回环地址和未指定地址
+ if parsedIP.IsLoopback() || parsedIP.IsUnspecified() {
+ return "", errors.New("disallowed IP address in setRemoteAddr: " + ip)
+ }
*remoteAddr = ip
}
}
diff --git a/EdgeHttpDNS/.gitignore b/EdgeHttpDNS/.gitignore
new file mode 100644
index 0000000..419bf8d
--- /dev/null
+++ b/EdgeHttpDNS/.gitignore
@@ -0,0 +1,4 @@
+*.zip
+edge-dns
+logs/
+data/
diff --git a/EdgeHttpDNS/bin/edge-httpdns b/EdgeHttpDNS/bin/edge-httpdns
new file mode 100644
index 0000000..6ce2729
Binary files /dev/null and b/EdgeHttpDNS/bin/edge-httpdns differ
diff --git a/EdgeHttpDNS/bin/edge-httpdns.exe b/EdgeHttpDNS/bin/edge-httpdns.exe
new file mode 100644
index 0000000..d41c3e3
Binary files /dev/null and b/EdgeHttpDNS/bin/edge-httpdns.exe differ
diff --git a/EdgeHttpDNS/build/build-all.sh b/EdgeHttpDNS/build/build-all.sh
new file mode 100644
index 0000000..119d58b
--- /dev/null
+++ b/EdgeHttpDNS/build/build-all.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+./build.sh linux amd64
+# ./build.sh linux arm64
+# ./build.sh darwin amd64
+# ./build.sh darwin arm64
diff --git a/EdgeHttpDNS/build/build.sh b/EdgeHttpDNS/build/build.sh
new file mode 100644
index 0000000..adc3efb
--- /dev/null
+++ b/EdgeHttpDNS/build/build.sh
@@ -0,0 +1,150 @@
+#!/usr/bin/env bash
+set -e
+
+function build() {
+ ROOT=$(dirname "$0")
+ NAME="edge-httpdns"
+ VERSION=$(lookup-version "$ROOT"/../internal/const/const.go)
+ DIST=$ROOT/"../dist/${NAME}"
+ OS=${1}
+ ARCH=${2}
+
+ if [ -z "$OS" ]; then
+ echo "usage: build.sh OS ARCH"
+ exit 1
+ fi
+ if [ -z "$ARCH" ]; then
+ echo "usage: build.sh OS ARCH"
+ exit 1
+ fi
+
+ ZIP_PATH=$(which zip)
+ if [ -z "$ZIP_PATH" ]; then
+ echo "we need 'zip' command to compress files"
+ exit 1
+ fi
+
+ echo "building v${VERSION}/${OS}/${ARCH} ..."
+ ZIP="${NAME}-${OS}-${ARCH}-v${VERSION}.zip"
+
+ rm -rf "$DIST"
+ mkdir -p "$DIST"/bin
+ mkdir -p "$DIST"/configs
+ mkdir -p "$DIST"/logs
+ mkdir -p "$DIST"/data
+
+ cp "$ROOT"/configs/api_httpdns.template.yaml "$DIST"/configs
+ copy_fluent_bit_assets "$ROOT" "$DIST" "$OS" "$ARCH" || exit 1
+
+ env GOOS="${OS}" GOARCH="${ARCH}" CGO_ENABLED=1 \
+ go build -trimpath -o "$DIST"/bin/${NAME} -ldflags="-s -w" "$ROOT"/../cmd/edge-httpdns/main.go
+
+ if [ ! -f "$DIST"/bin/${NAME} ]; then
+ echo "build failed!"
+ exit 1
+ fi
+
+ # delete hidden files
+ find "$DIST" -name ".DS_Store" -delete
+ find "$DIST" -name ".gitignore" -delete
+
+ echo "zip files ..."
+ cd "${DIST}/../" || exit 1
+ if [ -f "${ZIP}" ]; then
+ rm -f "${ZIP}"
+ fi
+ zip -r -X -q "${ZIP}" ${NAME}/
+ rm -rf "${NAME}"
+ cd - || exit 1
+
+ echo "OK"
+}
+
+function copy_fluent_bit_assets() {
+ ROOT=$1
+ DIST=$2
+ OS=$3
+ ARCH=$4
+ FLUENT_ROOT="$ROOT/../../deploy/fluent-bit"
+ FLUENT_DIST="$DIST/deploy/fluent-bit"
+
+ if [ ! -d "$FLUENT_ROOT" ]; then
+ echo "[error] fluent-bit source directory not found: $FLUENT_ROOT"
+ return 1
+ fi
+ verify_fluent_bit_package_matrix "$FLUENT_ROOT" "$ARCH" || return 1
+
+ rm -rf "$FLUENT_DIST"
+ mkdir -p "$FLUENT_DIST"
+
+ for file in fluent-bit.conf fluent-bit-dns.conf fluent-bit-https.conf fluent-bit-dns-https.conf fluent-bit-windows.conf fluent-bit-windows-https.conf parsers.conf clickhouse-upstream.conf clickhouse-upstream-windows.conf README.md; do
+ if [ -f "$FLUENT_ROOT/$file" ]; then
+ cp "$FLUENT_ROOT/$file" "$FLUENT_DIST/"
+ fi
+ done
+
+ if [ "$OS" = "linux" ]; then
+ PACKAGE_SRC="$FLUENT_ROOT/packages/linux-$ARCH"
+ PACKAGE_DST="$FLUENT_DIST/packages/linux-$ARCH"
+ if [ -d "$PACKAGE_SRC" ]; then
+ mkdir -p "$PACKAGE_DST"
+ cp -R "$PACKAGE_SRC/." "$PACKAGE_DST/"
+ else
+ echo "[error] fluent-bit package directory not found: $PACKAGE_SRC"
+ return 1
+ fi
+ fi
+
+ rm -f "$FLUENT_DIST/.gitignore"
+ rm -f "$FLUENT_DIST"/logs.db*
+ rm -rf "$FLUENT_DIST/storage"
+
+ return 0
+}
+
+function verify_fluent_bit_package_matrix() {
+ FLUENT_ROOT=$1
+ ARCH=$2
+ REQUIRED_FILES=()
+ if [ "$ARCH" = "amd64" ]; then
+ REQUIRED_FILES=(
+ "packages/linux-amd64/fluent-bit_4.2.2_amd64.deb"
+ "packages/linux-amd64/fluent-bit-4.2.2-1.x86_64.rpm"
+ )
+ elif [ "$ARCH" = "arm64" ]; then
+ REQUIRED_FILES=(
+ "packages/linux-arm64/fluent-bit_4.2.2_arm64.deb"
+ "packages/linux-arm64/fluent-bit-4.2.2-1.aarch64.rpm"
+ )
+ else
+ echo "[error] unsupported arch for fluent-bit package validation: $ARCH"
+ return 1
+ fi
+
+ MISSING=0
+ for FILE in "${REQUIRED_FILES[@]}"; do
+ if [ ! -f "$FLUENT_ROOT/$FILE" ]; then
+ echo "[error] fluent-bit matrix package missing: $FLUENT_ROOT/$FILE"
+ MISSING=1
+ fi
+ done
+
+ if [ "$MISSING" -ne 0 ]; then
+ return 1
+ fi
+ return 0
+}
+
+function lookup-version() {
+ FILE=$1
+ VERSION_DATA=$(cat "$FILE")
+ re="Version[ ]+=[ ]+\"([0-9.]+)\""
+ if [[ $VERSION_DATA =~ $re ]]; then
+ echo "${BASH_REMATCH[1]}"
+ else
+ echo "could not match version"
+ exit 1
+ fi
+}
+
+build "$1" "$2"
diff --git a/EdgeHttpDNS/cmd/edge-httpdns/main.go b/EdgeHttpDNS/cmd/edge-httpdns/main.go
new file mode 100644
index 0000000..f85e62e
--- /dev/null
+++ b/EdgeHttpDNS/cmd/edge-httpdns/main.go
@@ -0,0 +1,43 @@
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/apps"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/configs"
+ teaconst "github.com/TeaOSLab/EdgeHttpDNS/internal/const"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/nodes"
+)
+
+func main() {
+ app := apps.NewAppCmd().
+ Version(teaconst.Version).
+ Product(teaconst.ProductName).
+ Usage(teaconst.ProcessName + " [-v|start|stop|restart|status|service|daemon]")
+
+ app.On("start:before", func() {
+ _, err := configs.LoadAPIConfig()
+ if err != nil {
+ fmt.Println("[ERROR]start failed: load config from '" + configs.ConfigFileName + "' failed: " + err.Error())
+ os.Exit(1)
+ }
+ })
+
+ app.On("daemon", func() {
+ nodes.NewHTTPDNSNode().Daemon()
+ })
+
+ app.On("service", func() {
+ err := nodes.NewHTTPDNSNode().InstallSystemService()
+ if err != nil {
+ fmt.Println("[ERROR]install failed: " + err.Error())
+ return
+ }
+ fmt.Println("done")
+ })
+
+ app.Run(func() {
+ nodes.NewHTTPDNSNode().Run()
+ })
+}
diff --git a/EdgeHttpDNS/edge-httpdns.exe b/EdgeHttpDNS/edge-httpdns.exe
new file mode 100644
index 0000000..0311351
Binary files /dev/null and b/EdgeHttpDNS/edge-httpdns.exe differ
diff --git a/EdgeHttpDNS/go.mod b/EdgeHttpDNS/go.mod
new file mode 100644
index 0000000..fec8371
--- /dev/null
+++ b/EdgeHttpDNS/go.mod
@@ -0,0 +1,28 @@
+module github.com/TeaOSLab/EdgeHttpDNS
+
+go 1.25
+
+replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
+
+require (
+ github.com/TeaOSLab/EdgeCommon v0.0.0-00010101000000-000000000000
+ github.com/iwind/TeaGo v0.0.0-20240411075713-6c1fc9aca7b6
+ github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4
+ google.golang.org/grpc v1.78.0
+ gopkg.in/yaml.v3 v3.0.1
+)
+
+require (
+ github.com/miekg/dns v1.1.72 // indirect
+ github.com/oschwald/geoip2-golang v1.13.0 // indirect
+ github.com/oschwald/maxminddb-golang v1.13.0 // indirect
+ golang.org/x/mod v0.31.0 // indirect
+ golang.org/x/net v0.48.0 // indirect
+ golang.org/x/sync v0.19.0 // indirect
+ golang.org/x/sys v0.39.0 // indirect
+ golang.org/x/text v0.32.0 // indirect
+ golang.org/x/tools v0.40.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda // indirect
+ google.golang.org/protobuf v1.36.10 // indirect
+ gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
+)
diff --git a/EdgeHttpDNS/go.sum b/EdgeHttpDNS/go.sum
new file mode 100644
index 0000000..fe5cf68
--- /dev/null
+++ b/EdgeHttpDNS/go.sum
@@ -0,0 +1,69 @@
+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/iwind/TeaGo v0.0.0-20240411075713-6c1fc9aca7b6 h1:dS3pTxrLlDQxdoxSUcHkHnr3LHpsBIXv8v2/xw65RN8=
+github.com/iwind/TeaGo v0.0.0-20240411075713-6c1fc9aca7b6/go.mod h1:SfqVbWyIPdVflyA6lMgicZzsoGS8pyeLiTRe8/CIpGI=
+github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4 h1:VWGsCqTzObdlbf7UUE3oceIpcEKi4C/YBUszQXk118A=
+github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI=
+github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
+github.com/oschwald/geoip2-golang v1.13.0 h1:Q44/Ldc703pasJeP5V9+aFSZFmBN7DKHbNsSFzQATJI=
+github.com/oschwald/geoip2-golang v1.13.0/go.mod h1:P9zG+54KPEFOliZ29i7SeYZ/GM6tfEL+rgSn03hYuUo=
+github.com/oschwald/maxminddb-golang v1.13.0 h1:R8xBorY71s84yO06NgTmQvqvTvlS/bnYZrrWX1MElnU=
+github.com/oschwald/maxminddb-golang v1.13.0/go.mod h1:BU0z8BfFVhi1LQaonTwwGQlsHUEu9pWNdMfmq4ztm0o=
+go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
+go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
+go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
+go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
+go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
+go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
+go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
+go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
+go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
+go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
+go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
+go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
+golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
+golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
+golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
+golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
+golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
+golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
+golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
+golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
+golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
+golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
+golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
+golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
+golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
+golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
+golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
+golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda h1:i/Q+bfisr7gq6feoJnS/DlpdwEL4ihp41fvRiM3Ork0=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
+google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
+google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
+google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
+google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/EdgeHttpDNS/internal/accesslogs/httpdns_file_writer.go b/EdgeHttpDNS/internal/accesslogs/httpdns_file_writer.go
new file mode 100644
index 0000000..a6c66dd
--- /dev/null
+++ b/EdgeHttpDNS/internal/accesslogs/httpdns_file_writer.go
@@ -0,0 +1,172 @@
+package accesslogs
+
+import (
+ "encoding/json"
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
+ "gopkg.in/natefinch/lumberjack.v2"
+)
+
+const (
+ defaultHTTPDNSLogDir = "/var/log/edge/edge-httpdns"
+ envHTTPDNSLogDir = "EDGE_HTTPDNS_LOG_DIR"
+)
+
+var (
+ sharedHTTPDNSFileWriter *HTTPDNSFileWriter
+ sharedHTTPDNSFileWriterOnce sync.Once
+)
+
+// SharedHTTPDNSFileWriter 返回 HTTPDNS 本地日志写入器(单例).
+func SharedHTTPDNSFileWriter() *HTTPDNSFileWriter {
+ sharedHTTPDNSFileWriterOnce.Do(func() {
+ sharedHTTPDNSFileWriter = NewHTTPDNSFileWriter()
+ })
+ return sharedHTTPDNSFileWriter
+}
+
+// HTTPDNSFileWriter 将 HTTPDNS 访问日志以 JSON Lines 写入本地文件,供 Fluent Bit 采集。
+type HTTPDNSFileWriter struct {
+ dir string
+ mu sync.Mutex
+ file *lumberjack.Logger
+ rotateConfig *serverconfigs.AccessLogRotateConfig
+ inited bool
+}
+
+// NewHTTPDNSFileWriter 创建 HTTPDNS 本地日志写入器.
+func NewHTTPDNSFileWriter() *HTTPDNSFileWriter {
+ logDir := resolveDefaultHTTPDNSLogDir()
+ return &HTTPDNSFileWriter{
+ dir: logDir,
+ rotateConfig: serverconfigs.NewDefaultAccessLogRotateConfig(),
+ }
+}
+
+func resolveDefaultHTTPDNSLogDir() string {
+ logDir := strings.TrimSpace(os.Getenv(envHTTPDNSLogDir))
+ if logDir == "" {
+ return defaultHTTPDNSLogDir
+ }
+ return logDir
+}
+
+// SetDir 更新日志目录并重置文件句柄。
+func (w *HTTPDNSFileWriter) SetDir(dir string) {
+ if strings.TrimSpace(dir) == "" {
+ dir = resolveDefaultHTTPDNSLogDir()
+ }
+
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ if dir == w.dir {
+ return
+ }
+
+ if w.file != nil {
+ _ = w.file.Close()
+ w.file = nil
+ }
+ w.inited = false
+ w.dir = dir
+}
+
+// Dir 返回当前日志目录.
+func (w *HTTPDNSFileWriter) Dir() string {
+ return w.dir
+}
+
+// EnsureInit 在启动时预创建目录与 access.log.
+func (w *HTTPDNSFileWriter) EnsureInit() error {
+ if w.dir == "" {
+ return nil
+ }
+ return w.init()
+}
+
+func (w *HTTPDNSFileWriter) init() error {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ if w.inited && w.file != nil {
+ return nil
+ }
+
+ if w.dir == "" {
+ return nil
+ }
+
+ if err := os.MkdirAll(w.dir, 0755); err != nil {
+ log.Println("[HTTPDNS_ACCESS_LOG]mkdir log dir failed:", err.Error())
+ return err
+ }
+
+ rotateConfig := w.rotateConfig.Normalize()
+ w.file = &lumberjack.Logger{
+ Filename: filepath.Join(w.dir, "access.log"),
+ MaxSize: rotateConfig.MaxSizeMB,
+ MaxBackups: rotateConfig.MaxBackups,
+ MaxAge: rotateConfig.MaxAgeDays,
+ Compress: *rotateConfig.Compress,
+ LocalTime: *rotateConfig.LocalTime,
+ }
+
+ w.inited = true
+ return nil
+}
+
+// WriteBatch 批量写入 HTTPDNS 访问日志.
+func (w *HTTPDNSFileWriter) WriteBatch(logs []*pb.HTTPDNSAccessLog) {
+ if len(logs) == 0 || w.dir == "" {
+ return
+ }
+ if err := w.init(); err != nil {
+ return
+ }
+
+ w.mu.Lock()
+ file := w.file
+ w.mu.Unlock()
+ if file == nil {
+ return
+ }
+
+ for _, logItem := range logs {
+ ingestLog := FromPBAccessLog(logItem)
+ if ingestLog == nil {
+ continue
+ }
+ line, err := json.Marshal(ingestLog)
+ if err != nil {
+ continue
+ }
+ _, _ = file.Write(append(line, '\n'))
+ }
+}
+
+// Close 关闭日志文件.
+func (w *HTTPDNSFileWriter) Close() error {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ if w.file == nil {
+ return nil
+ }
+
+ err := w.file.Close()
+ w.file = nil
+ w.inited = false
+ if err != nil {
+ log.Println(fmt.Sprintf("[HTTPDNS_ACCESS_LOG]close access.log failed: %v", err))
+ return err
+ }
+ return nil
+}
diff --git a/EdgeHttpDNS/internal/accesslogs/httpdns_ingest_log.go b/EdgeHttpDNS/internal/accesslogs/httpdns_ingest_log.go
new file mode 100644
index 0000000..60ad141
--- /dev/null
+++ b/EdgeHttpDNS/internal/accesslogs/httpdns_ingest_log.go
@@ -0,0 +1,57 @@
+package accesslogs
+
+import "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+
+// HTTPDNSIngestLog HTTPDNS 访问日志单行结构(JSONEachRow),字段与
+// ClickHouse httpdns_access_logs_ingest 表一一对应。
+type HTTPDNSIngestLog struct {
+ Timestamp int64 `json:"timestamp"`
+ RequestId string `json:"request_id"`
+ ClusterId int64 `json:"cluster_id"`
+ NodeId int64 `json:"node_id"`
+ AppId string `json:"app_id"`
+ AppName string `json:"app_name"`
+ Domain string `json:"domain"`
+ QType string `json:"qtype"`
+ ClientIP string `json:"client_ip"`
+ ClientRegion string `json:"client_region"`
+ Carrier string `json:"carrier"`
+ SDKVersion string `json:"sdk_version"`
+ OS string `json:"os"`
+ ResultIPs string `json:"result_ips"`
+ Status string `json:"status"`
+ ErrorCode string `json:"error_code"`
+ CostMs int32 `json:"cost_ms"`
+ CreatedAt int64 `json:"created_at"`
+ Day string `json:"day"`
+ Summary string `json:"summary"`
+}
+
+// FromPBAccessLog 将 pb.HTTPDNSAccessLog 转为本地 ingest 结构。
+func FromPBAccessLog(log *pb.HTTPDNSAccessLog) *HTTPDNSIngestLog {
+ if log == nil {
+ return nil
+ }
+ return &HTTPDNSIngestLog{
+ Timestamp: log.GetCreatedAt(),
+ RequestId: log.GetRequestId(),
+ ClusterId: log.GetClusterId(),
+ NodeId: log.GetNodeId(),
+ AppId: log.GetAppId(),
+ AppName: log.GetAppName(),
+ Domain: log.GetDomain(),
+ QType: log.GetQtype(),
+ ClientIP: log.GetClientIP(),
+ ClientRegion: log.GetClientRegion(),
+ Carrier: log.GetCarrier(),
+ SDKVersion: log.GetSdkVersion(),
+ OS: log.GetOs(),
+ ResultIPs: log.GetResultIPs(),
+ Status: log.GetStatus(),
+ ErrorCode: log.GetErrorCode(),
+ CostMs: log.GetCostMs(),
+ CreatedAt: log.GetCreatedAt(),
+ Day: log.GetDay(),
+ Summary: log.GetSummary(),
+ }
+}
diff --git a/EdgeHttpDNS/internal/apps/app_cmd.go b/EdgeHttpDNS/internal/apps/app_cmd.go
new file mode 100644
index 0000000..d7db2f8
--- /dev/null
+++ b/EdgeHttpDNS/internal/apps/app_cmd.go
@@ -0,0 +1,153 @@
+package apps
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "runtime"
+ "time"
+
+ teaconst "github.com/TeaOSLab/EdgeHttpDNS/internal/const"
+ "github.com/iwind/TeaGo/maps"
+ "github.com/iwind/gosock/pkg/gosock"
+)
+
+type AppCmd struct {
+ product string
+ version string
+ usage string
+ directives map[string]func()
+ sock *gosock.Sock
+}
+
+func NewAppCmd() *AppCmd {
+ return &AppCmd{
+ directives: map[string]func(){},
+ sock: gosock.NewTmpSock(teaconst.ProcessName),
+ }
+}
+
+func (a *AppCmd) Product(product string) *AppCmd {
+ a.product = product
+ return a
+}
+
+func (a *AppCmd) Version(version string) *AppCmd {
+ a.version = version
+ return a
+}
+
+func (a *AppCmd) Usage(usage string) *AppCmd {
+ a.usage = usage
+ return a
+}
+
+func (a *AppCmd) On(arg string, callback func()) {
+ a.directives[arg] = callback
+}
+
+func (a *AppCmd) Run(main func()) {
+ args := os.Args[1:]
+ if len(args) == 0 {
+ main()
+ return
+ }
+
+ switch args[0] {
+ case "-v", "version", "-version", "--version":
+ fmt.Println(a.product+" v"+a.version, "(build:", runtimeString()+")")
+ return
+ case "help", "-h", "--help":
+ fmt.Println(a.product + " v" + a.version)
+ fmt.Println("Usage:")
+ fmt.Println(" " + a.usage)
+ return
+ case "start":
+ a.runDirective("start:before")
+ a.runStart()
+ return
+ case "stop":
+ a.runStop()
+ return
+ case "restart":
+ a.runStop()
+ time.Sleep(1 * time.Second)
+ a.runDirective("start:before")
+ a.runStart()
+ return
+ case "status":
+ a.runStatus()
+ return
+ default:
+ if callback, ok := a.directives[args[0]]; ok {
+ callback()
+ return
+ }
+ fmt.Println("unknown command '" + args[0] + "'")
+ }
+}
+
+func (a *AppCmd) runStart() {
+ pid := a.getPID()
+ if pid > 0 {
+ fmt.Println(a.product+" already started, pid:", pid)
+ return
+ }
+
+ exe, _ := os.Executable()
+ if len(exe) == 0 {
+ exe = os.Args[0]
+ }
+ cmd := exec.Command(exe)
+ cmd.Env = append(os.Environ(), "EdgeBackground=on")
+ err := cmd.Start()
+ if err != nil {
+ fmt.Println(a.product+" start failed:", err.Error())
+ return
+ }
+
+ fmt.Println(a.product+" started, pid:", cmd.Process.Pid)
+}
+
+func (a *AppCmd) runStop() {
+ pid := a.getPID()
+ if pid == 0 {
+ fmt.Println(a.product + " not started")
+ return
+ }
+
+ _, _ = a.sock.Send(&gosock.Command{Code: "stop"})
+ fmt.Println(a.product+" stopped, pid:", pid)
+}
+
+func (a *AppCmd) runStatus() {
+ pid := a.getPID()
+ if pid == 0 {
+ fmt.Println(a.product + " not started")
+ return
+ }
+ fmt.Println(a.product+" is running, pid:", pid)
+}
+
+func (a *AppCmd) runDirective(name string) {
+ if callback, ok := a.directives[name]; ok && callback != nil {
+ callback()
+ }
+}
+
+func (a *AppCmd) getPID() int {
+ if !a.sock.IsListening() {
+ return 0
+ }
+
+ reply, err := a.sock.Send(&gosock.Command{Code: "pid"})
+ if err != nil {
+ return 0
+ }
+
+ return maps.NewMap(reply.Params).GetInt("pid")
+}
+
+func runtimeString() string {
+ return runtime.GOOS + "/" + runtime.GOARCH
+}
diff --git a/EdgeHttpDNS/internal/configs/api_config.go b/EdgeHttpDNS/internal/configs/api_config.go
new file mode 100644
index 0000000..05e0739
--- /dev/null
+++ b/EdgeHttpDNS/internal/configs/api_config.go
@@ -0,0 +1,171 @@
+package configs
+
+import (
+ "errors"
+ "os"
+ "path/filepath"
+
+ "github.com/iwind/TeaGo/Tea"
+ "gopkg.in/yaml.v3"
+)
+
+const ConfigFileName = "api_httpdns.yaml"
+const oldConfigFileName = "api.yaml"
+
+var sharedAPIConfig *APIConfig
+
+type APIConfig struct {
+ OldRPC struct {
+ Endpoints []string `yaml:"endpoints"`
+ DisableUpdate bool `yaml:"disableUpdate"`
+ } `yaml:"rpc,omitempty"`
+
+ RPCEndpoints []string `yaml:"rpc.endpoints,flow" json:"rpc.endpoints"`
+ RPCDisableUpdate bool `yaml:"rpc.disableUpdate" json:"rpc.disableUpdate"`
+
+ NodeId string `yaml:"nodeId"`
+ Secret string `yaml:"secret"`
+
+ ListenAddr string `yaml:"listenAddr"`
+
+ HTTPSListenAddr string `yaml:"https.listenAddr" json:"https.listenAddr"`
+ HTTPSCert string `yaml:"https.cert" json:"https.cert"`
+ HTTPSKey string `yaml:"https.key" json:"https.key"`
+
+ LogDir string `yaml:"logDir" json:"logDir"`
+}
+
+func SharedAPIConfig() (*APIConfig, error) {
+ if sharedAPIConfig != nil {
+ return sharedAPIConfig, nil
+ }
+
+ config, err := LoadAPIConfig()
+ if err != nil {
+ return nil, err
+ }
+ sharedAPIConfig = config
+ return config, nil
+}
+
+func LoadAPIConfig() (*APIConfig, error) {
+ for _, filename := range []string{ConfigFileName, oldConfigFileName} {
+ var loadedData []byte
+ var loadedPath string
+ for _, candidate := range findConfigCandidates(filename) {
+ data, err := os.ReadFile(candidate)
+ if err != nil {
+ if os.IsNotExist(err) {
+ continue
+ }
+ return nil, err
+ }
+ loadedData = data
+ loadedPath = candidate
+ break
+ }
+
+ if len(loadedData) == 0 {
+ if filename == oldConfigFileName {
+ continue
+ }
+ return nil, errors.New("no config file '" + ConfigFileName + "' found")
+ }
+
+ config := &APIConfig{}
+ err := yaml.Unmarshal(loadedData, config)
+ if err != nil {
+ return nil, err
+ }
+
+ err = config.Init()
+ if err != nil {
+ return nil, err
+ }
+
+ if filename == oldConfigFileName {
+ config.OldRPC.Endpoints = nil
+ // 优先写回当前旧配置所在目录,避免依赖启动时工作目录
+ _ = config.WriteFile(filepath.Join(filepath.Dir(loadedPath), ConfigFileName))
+ }
+
+ return config, nil
+ }
+ return nil, errors.New("no config file '" + ConfigFileName + "' found")
+}
+
+func (c *APIConfig) Init() error {
+ if len(c.RPCEndpoints) == 0 && len(c.OldRPC.Endpoints) > 0 {
+ c.RPCEndpoints = c.OldRPC.Endpoints
+ c.RPCDisableUpdate = c.OldRPC.DisableUpdate
+ }
+
+ if len(c.RPCEndpoints) == 0 {
+ return errors.New("no valid 'rpc.endpoints'")
+ }
+
+ if len(c.NodeId) == 0 {
+ return errors.New("'nodeId' required")
+ }
+ if len(c.Secret) == 0 {
+ return errors.New("'secret' required")
+ }
+
+ // 兼容旧配置中的 listenAddr
+ if len(c.HTTPSListenAddr) == 0 {
+ if len(c.ListenAddr) > 0 {
+ c.HTTPSListenAddr = c.ListenAddr
+ } else {
+ c.HTTPSListenAddr = ":8443"
+ }
+ }
+
+ if len(c.HTTPSCert) == 0 {
+ // return errors.New("'https.cert' required")
+ }
+ if len(c.HTTPSKey) == 0 {
+ // return errors.New("'https.key' required")
+ }
+ return nil
+}
+
+func (c *APIConfig) WriteFile(path string) error {
+ data, err := yaml.Marshal(c)
+ if err != nil {
+ return err
+ }
+ return os.WriteFile(path, data, 0666)
+}
+
+func findConfigCandidates(filename string) []string {
+ candidates := []string{
+ Tea.ConfigFile(filename),
+ Tea.ConfigFile(filepath.Join("configs", filename)),
+ filename,
+ filepath.Join("configs", filename),
+ }
+
+ if exePath, err := os.Executable(); err == nil {
+ exeDir := filepath.Dir(exePath)
+ candidates = append(candidates,
+ filepath.Join(exeDir, filename),
+ filepath.Join(exeDir, "configs", filename),
+ filepath.Join(exeDir, "..", "configs", filename),
+ )
+ }
+
+ uniq := map[string]struct{}{}
+ result := make([]string, 0, len(candidates))
+ for _, candidate := range candidates {
+ candidate = filepath.Clean(candidate)
+ if len(candidate) == 0 {
+ continue
+ }
+ if _, ok := uniq[candidate]; ok {
+ continue
+ }
+ uniq[candidate] = struct{}{}
+ result = append(result, candidate)
+ }
+ return result
+}
diff --git a/EdgeHttpDNS/internal/const/const.go b/EdgeHttpDNS/internal/const/const.go
new file mode 100644
index 0000000..f254982
--- /dev/null
+++ b/EdgeHttpDNS/internal/const/const.go
@@ -0,0 +1,23 @@
+package teaconst
+
+const (
+ Version = "1.4.9"
+
+ ProductName = "Edge HTTPDNS"
+ ProcessName = "edge-httpdns"
+ ProductNameZH = "Edge HTTPDNS"
+
+ Role = "httpdns"
+
+ EncryptKey = "8f983f4d69b83aaa0d74b21a212f6967"
+ EncryptMethod = "aes-256-cfb"
+
+ SystemdServiceName = "edge-httpdns"
+
+ // HTTPDNS node tasks from API.
+ TaskTypeHTTPDNSConfigChanged = "httpdnsConfigChanged"
+ TaskTypeHTTPDNSAppChanged = "httpdnsAppChanged"
+ TaskTypeHTTPDNSDomainChanged = "httpdnsDomainChanged"
+ TaskTypeHTTPDNSRuleChanged = "httpdnsRuleChanged"
+ TaskTypeHTTPDNSTLSChanged = "httpdnsTLSChanged"
+)
diff --git a/EdgeHttpDNS/internal/encrypt/method.go b/EdgeHttpDNS/internal/encrypt/method.go
new file mode 100644
index 0000000..a297e7f
--- /dev/null
+++ b/EdgeHttpDNS/internal/encrypt/method.go
@@ -0,0 +1,7 @@
+package encrypt
+
+type MethodInterface interface {
+ Init(key []byte, iv []byte) error
+ Encrypt(src []byte) (dst []byte, err error)
+ Decrypt(dst []byte) (src []byte, err error)
+}
diff --git a/EdgeHttpDNS/internal/encrypt/method_aes_256_cfb.go b/EdgeHttpDNS/internal/encrypt/method_aes_256_cfb.go
new file mode 100644
index 0000000..3c3435f
--- /dev/null
+++ b/EdgeHttpDNS/internal/encrypt/method_aes_256_cfb.go
@@ -0,0 +1,64 @@
+package encrypt
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+)
+
+type AES256CFBMethod struct {
+ block cipher.Block
+ iv []byte
+}
+
+func (m *AES256CFBMethod) Init(key, iv []byte) error {
+ keyLen := len(key)
+ if keyLen > 32 {
+ key = key[:32]
+ } else if keyLen < 32 {
+ key = append(key, bytes.Repeat([]byte{' '}, 32-keyLen)...)
+ }
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return err
+ }
+ m.block = block
+
+ ivLen := len(iv)
+ if ivLen > aes.BlockSize {
+ iv = iv[:aes.BlockSize]
+ } else if ivLen < aes.BlockSize {
+ iv = append(iv, bytes.Repeat([]byte{' '}, aes.BlockSize-ivLen)...)
+ }
+ m.iv = iv
+ return nil
+}
+
+func (m *AES256CFBMethod) Encrypt(src []byte) (dst []byte, err error) {
+ if len(src) == 0 {
+ return
+ }
+
+ defer func() {
+ err = RecoverMethodPanic(recover())
+ }()
+
+ dst = make([]byte, len(src))
+ cipher.NewCFBEncrypter(m.block, m.iv).XORKeyStream(dst, src)
+ return
+}
+
+func (m *AES256CFBMethod) Decrypt(dst []byte) (src []byte, err error) {
+ if len(dst) == 0 {
+ return
+ }
+
+ defer func() {
+ err = RecoverMethodPanic(recover())
+ }()
+
+ src = make([]byte, len(dst))
+ cipher.NewCFBDecrypter(m.block, m.iv).XORKeyStream(src, dst)
+ return
+}
diff --git a/EdgeHttpDNS/internal/encrypt/method_raw.go b/EdgeHttpDNS/internal/encrypt/method_raw.go
new file mode 100644
index 0000000..a823cc3
--- /dev/null
+++ b/EdgeHttpDNS/internal/encrypt/method_raw.go
@@ -0,0 +1,15 @@
+package encrypt
+
+type RawMethod struct{}
+
+func (m *RawMethod) Init(key []byte, iv []byte) error {
+ return nil
+}
+
+func (m *RawMethod) Encrypt(src []byte) (dst []byte, err error) {
+ return src, nil
+}
+
+func (m *RawMethod) Decrypt(dst []byte) (src []byte, err error) {
+ return dst, nil
+}
diff --git a/EdgeHttpDNS/internal/encrypt/method_utils.go b/EdgeHttpDNS/internal/encrypt/method_utils.go
new file mode 100644
index 0000000..7c4077b
--- /dev/null
+++ b/EdgeHttpDNS/internal/encrypt/method_utils.go
@@ -0,0 +1,40 @@
+package encrypt
+
+import (
+ "errors"
+ "reflect"
+)
+
+var methods = map[string]reflect.Type{
+ "raw": reflect.TypeOf(new(RawMethod)).Elem(),
+ "aes-256-cfb": reflect.TypeOf(new(AES256CFBMethod)).Elem(),
+}
+
+func NewMethodInstance(method string, key string, iv string) (MethodInterface, error) {
+ valueType, ok := methods[method]
+ if !ok {
+ return nil, errors.New("method '" + method + "' not found")
+ }
+
+ instance, ok := reflect.New(valueType).Interface().(MethodInterface)
+ if !ok {
+ return nil, errors.New("method '" + method + "' must implement MethodInterface")
+ }
+
+ err := instance.Init([]byte(key), []byte(iv))
+ return instance, err
+}
+
+func RecoverMethodPanic(err interface{}) error {
+ if err == nil {
+ return nil
+ }
+
+ if s, ok := err.(string); ok {
+ return errors.New(s)
+ }
+ if e, ok := err.(error); ok {
+ return e
+ }
+ return errors.New("unknown error")
+}
diff --git a/EdgeHttpDNS/internal/nodes/httpdns_node.go b/EdgeHttpDNS/internal/nodes/httpdns_node.go
new file mode 100644
index 0000000..322da60
--- /dev/null
+++ b/EdgeHttpDNS/internal/nodes/httpdns_node.go
@@ -0,0 +1,168 @@
+package nodes
+
+import (
+ "errors"
+ "log"
+ "net"
+ "os"
+ "os/exec"
+ "runtime"
+ "sync"
+ "time"
+
+ teaconst "github.com/TeaOSLab/EdgeHttpDNS/internal/const"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/utils"
+ "github.com/iwind/TeaGo/maps"
+ "github.com/iwind/gosock/pkg/gosock"
+)
+
+var DaemonIsOn = false
+var DaemonPid = 0
+
+type HTTPDNSNode struct {
+ sock *gosock.Sock
+
+ quitOnce sync.Once
+ quitCh chan struct{}
+}
+
+func NewHTTPDNSNode() *HTTPDNSNode {
+ return &HTTPDNSNode{
+ sock: gosock.NewTmpSock(teaconst.ProcessName),
+ quitCh: make(chan struct{}),
+ }
+}
+
+func (n *HTTPDNSNode) Run() {
+ _, ok := os.LookupEnv("EdgeDaemon")
+ if ok {
+ DaemonIsOn = true
+ DaemonPid = os.Getppid()
+ }
+
+ err := n.listenSock()
+ if err != nil {
+ log.Println("[HTTPDNS_NODE]" + err.Error())
+ return
+ }
+
+ go n.start()
+ select {}
+}
+
+func (n *HTTPDNSNode) Daemon() {
+ path := os.TempDir() + "/" + teaconst.ProcessName + ".sock"
+ for {
+ conn, err := net.DialTimeout("unix", path, 1*time.Second)
+ if err != nil {
+ exe, exeErr := os.Executable()
+ if exeErr != nil {
+ log.Println("[DAEMON]", exeErr)
+ time.Sleep(1 * time.Second)
+ continue
+ }
+
+ cmd := exec.Command(exe)
+ cmd.Env = append(os.Environ(), "EdgeBackground=on", "EdgeDaemon=on")
+ if runtime.GOOS != "windows" {
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ }
+ startErr := cmd.Start()
+ if startErr != nil {
+ log.Println("[DAEMON]", startErr)
+ time.Sleep(1 * time.Second)
+ continue
+ }
+ _ = cmd.Wait()
+ time.Sleep(5 * time.Second)
+ continue
+ }
+
+ _ = conn.Close()
+ time.Sleep(5 * time.Second)
+ }
+}
+
+func (n *HTTPDNSNode) InstallSystemService() error {
+ exe, err := os.Executable()
+ if err != nil {
+ return err
+ }
+
+ manager := utils.NewServiceManager(teaconst.SystemdServiceName, teaconst.ProductName)
+ return manager.Install(exe, []string{})
+}
+
+func (n *HTTPDNSNode) listenSock() error {
+ if runtime.GOOS == "windows" {
+ return nil
+ }
+
+ if n.sock.IsListening() {
+ reply, err := n.sock.Send(&gosock.Command{Code: "pid"})
+ if err == nil {
+ return errors.New("the process is already running, pid: " + maps.NewMap(reply.Params).GetString("pid"))
+ }
+ return errors.New("the process is already running")
+ }
+
+ go func() {
+ n.sock.OnCommand(func(cmd *gosock.Command) {
+ switch cmd.Code {
+ case "pid":
+ _ = cmd.Reply(&gosock.Command{
+ Code: "pid",
+ Params: map[string]interface{}{
+ "pid": os.Getpid(),
+ },
+ })
+ case "info":
+ exePath, _ := os.Executable()
+ _ = cmd.Reply(&gosock.Command{
+ Code: "info",
+ Params: map[string]interface{}{
+ "pid": os.Getpid(),
+ "version": teaconst.Version,
+ "path": exePath,
+ },
+ })
+ case "stop":
+ _ = cmd.ReplyOk()
+ n.stop()
+ time.Sleep(100 * time.Millisecond)
+ os.Exit(0)
+ }
+ })
+
+ err := n.sock.Listen()
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][sock]", err.Error())
+ }
+ }()
+
+ return nil
+}
+
+func (n *HTTPDNSNode) start() {
+ log.Println("[HTTPDNS_NODE]started")
+
+ snapshotManager := NewSnapshotManager(n.quitCh)
+ statusManager := NewStatusManager(n.quitCh)
+ taskManager := NewTaskManager(n.quitCh, snapshotManager)
+ resolveServer := NewResolveServer(n.quitCh, snapshotManager)
+
+ go snapshotManager.Start()
+ go statusManager.Start()
+ go taskManager.Start()
+ go resolveServer.Start()
+
+ go NewUpgradeManager().Loop()
+}
+
+func (n *HTTPDNSNode) stop() {
+ n.quitOnce.Do(func() {
+ close(n.quitCh)
+ _ = n.sock.Close()
+ })
+}
diff --git a/EdgeHttpDNS/internal/nodes/resolve_server.go b/EdgeHttpDNS/internal/nodes/resolve_server.go
new file mode 100644
index 0000000..a4e4d12
--- /dev/null
+++ b/EdgeHttpDNS/internal/nodes/resolve_server.go
@@ -0,0 +1,1489 @@
+package nodes
+
+import (
+ "context"
+ "crypto/hmac"
+ "crypto/sha256"
+ "crypto/tls"
+ "encoding/hex"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "log"
+ "net"
+ "net/http"
+ "net/url"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
+ "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/accesslogs"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/configs"
+ "github.com/iwind/TeaGo/rands"
+ "github.com/miekg/dns"
+)
+
+// sharedRecursionDNSClient 共享的递归DNS客户端(对齐 EdgeDNS 实现)
+var sharedRecursionDNSClient = &dns.Client{
+ Timeout: 3 * time.Second,
+}
+
+const (
+ httpdnsCodeSuccess = "SUCCESS"
+ httpdnsCodeAppInvalid = "APP_NOT_FOUND_OR_DISABLED"
+ httpdnsCodeDomainNotBound = "DOMAIN_NOT_BOUND"
+ httpdnsCodeSignInvalid = "SIGN_INVALID"
+ httpdnsCodeNoRecords = "NO_RECORDS"
+ httpdnsCodeInternalError = "RESOLVE_TIMEOUT_OR_INTERNAL"
+ httpdnsCodeMethodNotAllow = "METHOD_NOT_ALLOWED"
+ httpdnsCodeInvalidArgument = "INVALID_ARGUMENT"
+)
+
+type resolveClientInfo struct {
+ IP string `json:"ip"`
+ Region string `json:"region"`
+ Carrier string `json:"carrier"`
+ Country string `json:"country"`
+}
+
+type resolveRecord struct {
+ Type string `json:"type"`
+ IP string `json:"ip"`
+ Weight int32 `json:"weight,omitempty"`
+ Line string `json:"line,omitempty"`
+ Region string `json:"region,omitempty"`
+}
+
+type resolveData struct {
+ Domain string `json:"domain"`
+ QType string `json:"qtype"`
+ TTL int32 `json:"ttl"`
+ Records []*resolveRecord `json:"records"`
+ Client *resolveClientInfo `json:"client"`
+ Summary string `json:"summary"`
+}
+
+type resolveResponse struct {
+ Code string `json:"code"`
+ Message string `json:"message"`
+ RequestID string `json:"requestId"`
+ Data *resolveData `json:"data,omitempty"`
+}
+
+type clientRouteProfile struct {
+ IP string
+ Country string
+ Province string
+ Carrier string
+ ProviderRaw string
+ Region string
+ Continent string
+ RegionText string
+}
+
+type tlsListener struct {
+ addr string // e.g. ":443"
+ listener net.Listener
+ server *http.Server
+}
+
+type ResolveServer struct {
+ quitCh <-chan struct{}
+ snapshotManager *SnapshotManager
+
+ // Local config fallback
+ fallbackAddr string
+ certFile string
+ keyFile string
+
+ handler http.Handler // shared mux
+ tlsConfig *tls.Config // shared TLS config (with GetCertificate)
+
+ logWriter *accesslogs.HTTPDNSFileWriter
+ logQueue chan *pb.HTTPDNSAccessLog
+
+ // TLS certificate hot-reload
+ certMu sync.RWMutex
+ currentCert *tls.Certificate
+ certSnapshotAt int64
+
+ // Listener hot-reload
+ listenerMu sync.Mutex
+ listeners map[string]*tlsListener // key: addr (e.g. ":443")
+}
+
+func NewResolveServer(quitCh <-chan struct{}, snapshotManager *SnapshotManager) *ResolveServer {
+ fallbackAddr := ":443"
+ certFile := ""
+ keyFile := ""
+ if apiConfig, err := configs.SharedAPIConfig(); err == nil && apiConfig != nil {
+ if len(apiConfig.HTTPSListenAddr) > 0 {
+ fallbackAddr = apiConfig.HTTPSListenAddr
+ }
+ certFile = apiConfig.HTTPSCert
+ keyFile = apiConfig.HTTPSKey
+ }
+
+ logWriter := accesslogs.SharedHTTPDNSFileWriter()
+ if apiConfig, err := configs.SharedAPIConfig(); err == nil && apiConfig != nil {
+ if len(strings.TrimSpace(apiConfig.LogDir)) > 0 {
+ logWriter.SetDir(strings.TrimSpace(apiConfig.LogDir))
+ }
+ }
+ if err := logWriter.EnsureInit(); err != nil {
+ log.Println("[HTTPDNS_NODE][resolve]init access log file writer failed:", err.Error())
+ }
+
+ instance := &ResolveServer{
+ quitCh: quitCh,
+ snapshotManager: snapshotManager,
+ fallbackAddr: fallbackAddr,
+ certFile: certFile,
+ keyFile: keyFile,
+ logWriter: logWriter,
+ logQueue: make(chan *pb.HTTPDNSAccessLog, 8192),
+ listeners: make(map[string]*tlsListener),
+ }
+
+ mux := http.NewServeMux()
+ mux.HandleFunc("/resolve", instance.handleResolve)
+ mux.HandleFunc("/healthz", instance.handleHealth)
+ instance.handler = mux
+
+ instance.tlsConfig = &tls.Config{
+ MinVersion: tls.VersionTLS11,
+ NextProtos: []string{"http/1.1"},
+ GetCertificate: instance.getCertificate,
+ }
+
+ return instance
+}
+
+func (s *ResolveServer) Start() {
+ go s.startAccessLogFlusher()
+
+ // 1. Load initial certificate from file (fallback)
+ if len(s.certFile) > 0 && len(s.keyFile) > 0 {
+ cert, err := tls.LoadX509KeyPair(s.certFile, s.keyFile)
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][resolve]load cert file failed:", err.Error())
+ } else {
+ s.currentCert = &cert
+ log.Println("[HTTPDNS_NODE][resolve]loaded initial TLS cert from file")
+ }
+ }
+
+ // 2. Try loading certificate from cluster snapshot (takes priority over file)
+ if snapshot := s.snapshotManager.Current(); snapshot != nil {
+ s.reloadCertFromSnapshot(snapshot)
+ }
+
+ if s.currentCert == nil {
+ log.Println("[HTTPDNS_NODE][resolve]WARNING: no TLS certificate available, HTTPS will fail")
+ }
+
+ // 3. Parse initial listen addresses and start listeners
+ if snapshot := s.snapshotManager.Current(); snapshot != nil {
+ addrs := s.desiredAddrs(snapshot)
+ s.syncListeners(addrs)
+ } else {
+ s.syncListeners([]string{s.fallbackAddr})
+ }
+
+ // 4. Watch for changes (blocks until quit)
+ s.watchLoop()
+}
+
+func (s *ResolveServer) getCertificate(_ *tls.ClientHelloInfo) (*tls.Certificate, error) {
+ s.certMu.RLock()
+ cert := s.currentCert
+ s.certMu.RUnlock()
+ if cert != nil {
+ return cert, nil
+ }
+ return nil, errors.New("no TLS certificate available")
+}
+
+type snapshotTLSConfig struct {
+ Listen []*serverconfigs.NetworkAddressConfig `json:"listen"`
+ SSLPolicy *sslconfigs.SSLPolicy `json:"sslPolicy"`
+}
+
+func (s *ResolveServer) parseTLSConfig(snapshot *LoadedSnapshot) *snapshotTLSConfig {
+ if snapshot.ClusterID <= 0 {
+ return nil
+ }
+ cluster := snapshot.Clusters[snapshot.ClusterID]
+ if cluster == nil {
+ return nil
+ }
+ raw := cluster.GetTlsPolicyJSON()
+ if len(raw) == 0 {
+ return nil
+ }
+
+ var cfg snapshotTLSConfig
+ if err := json.Unmarshal(raw, &cfg); err != nil {
+ log.Println("[HTTPDNS_NODE][resolve]parse tlsPolicyJSON failed:", err.Error())
+ return nil
+ }
+ return &cfg
+}
+
+func (s *ResolveServer) desiredAddrs(snapshot *LoadedSnapshot) []string {
+ cfg := s.parseTLSConfig(snapshot)
+ if cfg == nil || len(cfg.Listen) == 0 {
+ return []string{s.fallbackAddr}
+ }
+
+ seen := make(map[string]struct{})
+ var addrs []string
+ for _, listenCfg := range cfg.Listen {
+ if listenCfg == nil {
+ continue
+ }
+ if err := listenCfg.Init(); err != nil {
+ log.Println("[HTTPDNS_NODE][resolve]init listen config failed:", err.Error())
+ continue
+ }
+ for _, addr := range listenCfg.Addresses() {
+ if _, ok := seen[addr]; !ok {
+ seen[addr] = struct{}{}
+ addrs = append(addrs, addr)
+ }
+ }
+ }
+
+ if len(addrs) == 0 {
+ return []string{s.fallbackAddr}
+ }
+ sort.Strings(addrs)
+ return addrs
+}
+
+func (s *ResolveServer) reloadCertFromSnapshot(snapshot *LoadedSnapshot) {
+ cfg := s.parseTLSConfig(snapshot)
+ if cfg == nil || cfg.SSLPolicy == nil || len(cfg.SSLPolicy.Certs) == 0 {
+ // 没有TLS配置,标记已处理(不需要重试)
+ s.certMu.Lock()
+ s.certSnapshotAt = snapshot.LoadedAt
+ s.certMu.Unlock()
+ reportRuntimeLog("info", "tls", "resolve", "no TLS policy in cluster snapshot, skipped cert reload", fmt.Sprintf("cert-skip-%d", snapshot.LoadedAt))
+ return
+ }
+ if err := cfg.SSLPolicy.Init(context.Background()); err != nil {
+ log.Println("[HTTPDNS_NODE][resolve]init SSLPolicy failed:", err.Error())
+ reportRuntimeLog("error", "tls", "resolve", "init SSLPolicy failed: "+err.Error(), fmt.Sprintf("cert-err-%d", snapshot.LoadedAt))
+ // 不更新 certSnapshotAt,下次 watchLoop 会重试
+ return
+ }
+ cert := cfg.SSLPolicy.FirstCert()
+ if cert == nil {
+ log.Println("[HTTPDNS_NODE][resolve]SSLPolicy has no valid certificate after Init")
+ reportRuntimeLog("error", "tls", "resolve", "SSLPolicy has no valid certificate after Init", fmt.Sprintf("cert-err-%d", snapshot.LoadedAt))
+ // 不更新 certSnapshotAt,下次 watchLoop 会重试
+ return
+ }
+
+ s.certMu.Lock()
+ s.currentCert = cert
+ s.certSnapshotAt = snapshot.LoadedAt
+ s.certMu.Unlock()
+ log.Println("[HTTPDNS_NODE][resolve]TLS certificate reloaded from snapshot")
+ reportRuntimeLog("info", "tls", "resolve", "TLS certificate reloaded from snapshot successfully", fmt.Sprintf("cert-ok-%d", snapshot.LoadedAt))
+}
+
+func (s *ResolveServer) startListener(addr string) error {
+ ln, err := net.Listen("tcp", addr)
+ if err != nil {
+ return fmt.Errorf("listen on %s: %w", addr, err)
+ }
+ tlsLn := tls.NewListener(ln, s.tlsConfig)
+
+ srv := &http.Server{
+ Handler: s.handler,
+ ReadTimeout: 5 * time.Second,
+ ReadHeaderTimeout: 3 * time.Second,
+ WriteTimeout: 5 * time.Second,
+ IdleTimeout: 75 * time.Second,
+ MaxHeaderBytes: 8 * 1024,
+ TLSNextProto: map[string]func(*http.Server, *tls.Conn, http.Handler){},
+ }
+
+ s.listeners[addr] = &tlsListener{
+ addr: addr,
+ listener: tlsLn,
+ server: srv,
+ }
+
+ go func() {
+ if err := srv.Serve(tlsLn); err != nil && !errors.Is(err, http.ErrServerClosed) {
+ log.Println("[HTTPDNS_NODE][resolve]serve failed on", addr, ":", err.Error())
+ }
+ }()
+
+ log.Println("[HTTPDNS_NODE][resolve]listening HTTPS on", addr)
+ return nil
+}
+
+func (s *ResolveServer) stopListener(addr string) {
+ tl, ok := s.listeners[addr]
+ if !ok {
+ return
+ }
+ ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
+ defer cancel()
+ _ = tl.server.Shutdown(ctx)
+ delete(s.listeners, addr)
+ log.Println("[HTTPDNS_NODE][resolve]stopped listener on", addr)
+}
+
+func (s *ResolveServer) syncListeners(desired []string) {
+ s.listenerMu.Lock()
+ defer s.listenerMu.Unlock()
+
+ desiredSet := make(map[string]struct{}, len(desired))
+ for _, addr := range desired {
+ desiredSet[addr] = struct{}{}
+ }
+
+ // Stop listeners that are no longer desired
+ for addr := range s.listeners {
+ if _, ok := desiredSet[addr]; !ok {
+ s.stopListener(addr)
+ }
+ }
+
+ // Start new listeners
+ for _, addr := range desired {
+ if _, ok := s.listeners[addr]; !ok {
+ if err := s.startListener(addr); err != nil {
+ log.Println("[HTTPDNS_NODE][resolve]start listener failed:", err.Error())
+ }
+ }
+ }
+}
+
+func (s *ResolveServer) watchLoop() {
+ ticker := time.NewTicker(5 * time.Second)
+ defer ticker.Stop()
+ for {
+ select {
+ case <-ticker.C:
+ snapshot := s.snapshotManager.Current()
+ if snapshot == nil {
+ continue
+ }
+ s.certMu.RLock()
+ lastAt := s.certSnapshotAt
+ s.certMu.RUnlock()
+ if snapshot.LoadedAt == lastAt {
+ continue
+ }
+ // Snapshot changed — sync listeners and reload cert
+ addrs := s.desiredAddrs(snapshot)
+ s.syncListeners(addrs)
+ s.reloadCertFromSnapshot(snapshot)
+ case <-s.quitCh:
+ s.shutdownAll()
+ return
+ }
+ }
+}
+
+func (s *ResolveServer) shutdownAll() {
+ s.listenerMu.Lock()
+ defer s.listenerMu.Unlock()
+ for addr := range s.listeners {
+ s.stopListener(addr)
+ }
+}
+
+func (s *ResolveServer) handleHealth(writer http.ResponseWriter, _ *http.Request) {
+ writer.WriteHeader(http.StatusOK)
+ _, _ = writer.Write([]byte("ok"))
+}
+
+func (s *ResolveServer) handleResolve(writer http.ResponseWriter, request *http.Request) {
+ startAt := time.Now()
+ requestID := "rid-" + rands.HexString(16)
+
+ if request.Method != http.MethodGet {
+ s.writeResolveJSON(writer, http.StatusMethodNotAllowed, &resolveResponse{
+ Code: httpdnsCodeMethodNotAllow,
+ Message: "只允许使用 GET 方法",
+ RequestID: requestID,
+ })
+ return
+ }
+
+ query := request.URL.Query()
+ appID := strings.TrimSpace(query.Get("appId"))
+ domain := strings.TrimSuffix(strings.ToLower(strings.TrimSpace(query.Get("dn"))), ".")
+ qtype := strings.ToUpper(strings.TrimSpace(query.Get("qtype")))
+ if len(qtype) == 0 {
+ qtype = "A"
+ }
+ if qtype != "A" && qtype != "AAAA" {
+ s.writeResolveJSON(writer, http.StatusBadRequest, &resolveResponse{
+ Code: httpdnsCodeInvalidArgument,
+ Message: "qtype 参数仅支持 A 或 AAAA",
+ RequestID: requestID,
+ })
+ return
+ }
+
+ if len(appID) == 0 || len(domain) == 0 {
+ s.writeResolveJSON(writer, http.StatusBadRequest, &resolveResponse{
+ Code: httpdnsCodeInvalidArgument,
+ Message: "缺少必填参数: appId 和 dn",
+ RequestID: requestID,
+ })
+ return
+ }
+
+ snapshot := s.snapshotManager.Current()
+ if snapshot == nil {
+ s.writeResolveJSON(writer, http.StatusServiceUnavailable, &resolveResponse{
+ Code: httpdnsCodeInternalError,
+ Message: "服务节点尚未准备就绪,请稍后再试",
+ RequestID: requestID,
+ })
+ return
+ }
+
+ loadedApp := snapshot.Apps[strings.ToLower(appID)]
+ if loadedApp == nil || loadedApp.App == nil || !loadedApp.App.GetIsOn() {
+ s.writeFailedResolve(writer, requestID, snapshot, nil, domain, qtype, httpdnsCodeAppInvalid, "找不到指定的应用,或该应用已下线", startAt, request, query)
+ return
+ }
+
+ if snapshot.ClusterID > 0 {
+ var appClusterIds []int64
+ if len(loadedApp.App.GetClusterIdsJSON()) > 0 {
+ _ = json.Unmarshal(loadedApp.App.GetClusterIdsJSON(), &appClusterIds)
+ }
+ var clusterBound bool
+ for _, cid := range appClusterIds {
+ if cid == snapshot.ClusterID {
+ clusterBound = true
+ break
+ }
+ }
+ if !clusterBound {
+ s.writeFailedResolve(writer, requestID, snapshot, loadedApp.App, domain, qtype, httpdnsCodeAppInvalid, "当前应用未绑定到该解析集群", startAt, request, query)
+ return
+ }
+ }
+
+ loadedDomain := loadedApp.Domains[domain]
+ if loadedDomain == nil || loadedDomain.Domain == nil || !loadedDomain.Domain.GetIsOn() {
+ s.writeFailedResolve(writer, requestID, snapshot, loadedApp.App, domain, qtype, httpdnsCodeDomainNotBound, "应用尚未绑定该域名,或域名解析已暂停", startAt, request, query)
+ return
+ }
+
+ if loadedApp.App.GetSignEnabled() {
+ if !validateResolveSign(loadedApp.App.GetSignSecret(), loadedApp.App.GetAppId(), domain, qtype, query.Get("nonce"), query.Get("exp"), query.Get("sign")) {
+ s.writeFailedResolve(writer, requestID, snapshot, loadedApp.App, domain, qtype, httpdnsCodeSignInvalid, "请求鉴权失败:签名无效或已过期", startAt, request, query)
+ return
+ }
+ }
+
+ clientIP := detectClientIP(request, query.Get("cip"))
+ clientProfile := buildClientRouteProfile(clientIP)
+
+ clusterTTL := pickDefaultTTL(snapshot, loadedApp.App)
+ rule, records, ttl := pickRuleRecords(loadedDomain.Rules, qtype, clientProfile, clusterTTL)
+ if len(records) == 0 {
+ // Fallback:回源上游 DNS 查询真实记录
+ fallbackRecords, fallbackTTL, fallbackErr := fallbackResolve(domain, qtype)
+ if fallbackErr != nil || len(fallbackRecords) == 0 {
+ errMsg := "未找到解析记录"
+ if fallbackErr != nil {
+ errMsg = "未找到解析记录 (上游回源失败: " + fallbackErr.Error() + ")"
+ }
+ s.writeFailedResolve(writer, requestID, snapshot, loadedApp.App, domain, qtype, httpdnsCodeNoRecords, errMsg, startAt, request, query)
+ return
+ }
+ records = fallbackRecords
+ if fallbackTTL > 0 {
+ ttl = fallbackTTL
+ } else {
+ ttl = clusterTTL
+ }
+ }
+ if ttl <= 0 {
+ ttl = clusterTTL
+ }
+ if ttl <= 0 {
+ ttl = 30
+ }
+
+ resultIPs := make([]string, 0, len(records))
+ for _, record := range records {
+ resultIPs = append(resultIPs, record.IP)
+ }
+
+ summary := fmt.Sprintf("%s|%s(%s)|%s|%s %s -> %s|success|%dms",
+ time.Now().Format("2006-01-02 15:04:05"),
+ loadedApp.App.GetName(),
+ loadedApp.App.GetAppId(),
+ clientProfile.IP,
+ qtype,
+ domain,
+ strings.Join(resultIPs, ", "),
+ time.Since(startAt).Milliseconds(),
+ )
+ if rule != nil && len(strings.TrimSpace(rule.GetRuleName())) > 0 {
+ summary += "|rule:" + strings.TrimSpace(rule.GetRuleName())
+ }
+
+ s.writeResolveJSON(writer, http.StatusOK, &resolveResponse{
+ Code: httpdnsCodeSuccess,
+ Message: "ok",
+ RequestID: requestID,
+ Data: &resolveData{
+ Domain: domain,
+ QType: qtype,
+ TTL: ttl,
+ Records: records,
+ Client: &resolveClientInfo{
+ IP: clientProfile.IP,
+ Region: clientProfile.RegionText,
+ Carrier: clientProfile.Carrier,
+ Country: clientProfile.Country,
+ },
+ Summary: summary,
+ },
+ })
+
+ if s.isAccessLogEnabled(snapshot) {
+ s.enqueueAccessLog(&pb.HTTPDNSAccessLog{
+ RequestId: requestID,
+ ClusterId: snapshot.ClusterID,
+ NodeId: snapshot.NodeID,
+ AppId: loadedApp.App.GetAppId(),
+ AppName: loadedApp.App.GetName(),
+ Domain: domain,
+ Qtype: qtype,
+ ClientIP: clientProfile.IP,
+ ClientRegion: clientProfile.RegionText,
+ Carrier: clientProfile.Carrier,
+ SdkVersion: strings.TrimSpace(query.Get("sdk_version")),
+ Os: strings.TrimSpace(query.Get("os")),
+ ResultIPs: strings.Join(resultIPs, ","),
+ Status: "success",
+ ErrorCode: "none",
+ CostMs: int32(time.Since(startAt).Milliseconds()),
+ CreatedAt: time.Now().Unix(),
+ Day: time.Now().Format("20060102"),
+ Summary: summary,
+ })
+ }
+}
+
+func pickDefaultTTL(snapshot *LoadedSnapshot, app *pb.HTTPDNSApp) int32 {
+ if snapshot == nil {
+ return 30
+ }
+
+ if snapshot.ClusterID > 0 {
+ if cluster := snapshot.Clusters[snapshot.ClusterID]; cluster != nil && cluster.GetDefaultTTL() > 0 {
+ return cluster.GetDefaultTTL()
+ }
+ }
+ if app != nil {
+ var appClusterIds []int64
+ if len(app.GetClusterIdsJSON()) > 0 {
+ _ = json.Unmarshal(app.GetClusterIdsJSON(), &appClusterIds)
+ }
+ for _, cid := range appClusterIds {
+ if cluster := snapshot.Clusters[cid]; cluster != nil && cluster.GetDefaultTTL() > 0 {
+ return cluster.GetDefaultTTL()
+ }
+ }
+ }
+ return 30
+}
+
+func (s *ResolveServer) writeFailedResolve(
+ writer http.ResponseWriter,
+ requestID string,
+ snapshot *LoadedSnapshot,
+ app *pb.HTTPDNSApp,
+ domain string,
+ qtype string,
+ errorCode string,
+ message string,
+ startAt time.Time,
+ request *http.Request,
+ query url.Values,
+) {
+ clientIP := detectClientIP(request, query.Get("cip"))
+ clientProfile := buildClientRouteProfile(clientIP)
+
+ appID := ""
+ appName := ""
+ if app != nil {
+ appID = app.GetAppId()
+ appName = app.GetName()
+ }
+
+ summary := fmt.Sprintf("%s|%s(%s)|%s|%s %s -> [none]|failed(%s)|%dms",
+ time.Now().Format("2006-01-02 15:04:05"),
+ appName,
+ appID,
+ clientProfile.IP,
+ qtype,
+ domain,
+ errorCode,
+ time.Since(startAt).Milliseconds(),
+ )
+
+ s.writeResolveJSON(writer, http.StatusOK, &resolveResponse{
+ Code: errorCode,
+ Message: message,
+ RequestID: requestID,
+ })
+
+ clusterID := int64(0)
+ nodeID := int64(0)
+ if snapshot != nil {
+ clusterID = snapshot.ClusterID
+ nodeID = snapshot.NodeID
+ }
+
+ if s.isAccessLogEnabled(snapshot) {
+ s.enqueueAccessLog(&pb.HTTPDNSAccessLog{
+ RequestId: requestID,
+ ClusterId: clusterID,
+ NodeId: nodeID,
+ AppId: appID,
+ AppName: appName,
+ Domain: domain,
+ Qtype: qtype,
+ ClientIP: clientProfile.IP,
+ ClientRegion: clientProfile.RegionText,
+ Carrier: clientProfile.Carrier,
+ SdkVersion: strings.TrimSpace(query.Get("sdk_version")),
+ Os: strings.TrimSpace(query.Get("os")),
+ ResultIPs: "",
+ Status: "failed",
+ ErrorCode: errorCode,
+ CostMs: int32(time.Since(startAt).Milliseconds()),
+ CreatedAt: time.Now().Unix(),
+ Day: time.Now().Format("20060102"),
+ Summary: summary,
+ })
+ }
+}
+
+func (s *ResolveServer) writeResolveJSON(writer http.ResponseWriter, status int, resp *resolveResponse) {
+ writer.Header().Set("Content-Type", "application/json; charset=utf-8")
+ writer.WriteHeader(status)
+ data, err := json.Marshal(resp)
+ if err != nil {
+ _, _ = writer.Write([]byte(`{"code":"RESOLVE_TIMEOUT_OR_INTERNAL","message":"encode response failed"}`))
+ return
+ }
+ _, _ = writer.Write(data)
+}
+
+func detectClientIP(request *http.Request, cip string) string {
+ if candidate := normalizeIPCandidate(cip); len(candidate) > 0 {
+ return candidate
+ }
+
+ xff := strings.TrimSpace(request.Header.Get("X-Forwarded-For"))
+ if len(xff) > 0 {
+ for _, item := range strings.Split(xff, ",") {
+ if candidate := normalizeIPCandidate(item); len(candidate) > 0 {
+ return candidate
+ }
+ }
+ }
+
+ headerKeys := []string{"X-Real-IP", "X-Client-IP", "CF-Connecting-IP", "True-Client-IP"}
+ for _, key := range headerKeys {
+ if candidate := normalizeIPCandidate(request.Header.Get(key)); len(candidate) > 0 {
+ return candidate
+ }
+ }
+
+ return normalizeIPCandidate(request.RemoteAddr)
+}
+
+func validateResolveSign(signSecret string, appID string, domain string, qtype string, nonce string, exp string, sign string) bool {
+ signSecret = strings.TrimSpace(signSecret)
+ nonce = strings.TrimSpace(nonce)
+ exp = strings.TrimSpace(exp)
+ sign = strings.TrimSpace(sign)
+ if len(signSecret) == 0 || len(nonce) == 0 || len(exp) == 0 || len(sign) == 0 {
+ return false
+ }
+
+ expireAt, err := strconv.ParseInt(exp, 10, 64)
+ if err != nil {
+ return false
+ }
+ now := time.Now().Unix()
+ if expireAt <= now-30 || expireAt > now+86400 {
+ return false
+ }
+
+ raw := appID + "|" + strings.ToLower(domain) + "|" + strings.ToUpper(qtype) + "|" + exp + "|" + nonce
+ mac := hmac.New(sha256.New, []byte(signSecret))
+ _, _ = mac.Write([]byte(raw))
+ expected := hex.EncodeToString(mac.Sum(nil))
+ return strings.EqualFold(expected, sign)
+}
+
+func buildClientRouteProfile(ip string) *clientRouteProfile {
+ profile := &clientRouteProfile{
+ IP: normalizeIPCandidate(ip),
+ }
+ if net.ParseIP(profile.IP) == nil {
+ return profile
+ }
+
+ result := iplibrary.LookupIP(profile.IP)
+ if result == nil || !result.IsOk() {
+ return profile
+ }
+
+ profile.Country = normalizeCountryName(strings.TrimSpace(result.CountryName()))
+ profile.Province = normalizeProvinceName(strings.TrimSpace(result.ProvinceName()))
+ profile.ProviderRaw = strings.TrimSpace(result.ProviderName())
+ profile.Carrier = normalizeCarrier(profile.ProviderRaw, profile.Country)
+ if len(profile.Carrier) == 0 {
+ if isMainlandChinaCountry(profile.Country) {
+ profile.Carrier = "默认"
+ } else {
+ if len(profile.ProviderRaw) > 0 {
+ profile.Carrier = profile.ProviderRaw
+ } else {
+ profile.Carrier = "默认"
+ }
+ }
+ }
+ profile.Region = normalizeChinaRegion(profile.Province)
+ profile.Continent = normalizeContinent(profile.Country)
+ profile.RegionText = strings.TrimSpace(result.RegionSummary())
+ if len(profile.RegionText) == 0 {
+ pieces := make([]string, 0, 4)
+ if len(profile.Country) > 0 {
+ pieces = append(pieces, profile.Country)
+ }
+ if len(profile.Province) > 0 {
+ pieces = append(pieces, profile.Province)
+ }
+ if len(profile.Region) > 0 {
+ pieces = append(pieces, profile.Region)
+ }
+ if len(profile.Carrier) > 0 {
+ pieces = append(pieces, profile.Carrier)
+ }
+ profile.RegionText = strings.Join(pieces, " ")
+ }
+
+ return profile
+}
+
+func normalizeCarrier(provider string, country string) string {
+ value := strings.TrimSpace(provider)
+ if len(value) == 0 {
+ return ""
+ }
+ lower := strings.ToLower(value)
+ switch {
+ case strings.Contains(value, "电信"), strings.Contains(value, "天翼"),
+ strings.Contains(lower, "telecom"), strings.Contains(lower, "chinanet"),
+ strings.Contains(lower, "chinatelecom"), strings.Contains(lower, "ctnet"), strings.Contains(lower, "cn2"):
+ return "电信"
+ case strings.Contains(value, "联通"), strings.Contains(value, "网通"),
+ strings.Contains(lower, "unicom"), strings.Contains(lower, "chinaunicom"),
+ strings.Contains(lower, "cucc"), strings.Contains(lower, "china169"), strings.Contains(lower, "cnc"):
+ return "联通"
+ case strings.Contains(value, "移动"),
+ strings.Contains(lower, "mobile"), strings.Contains(lower, "chinamobile"),
+ strings.Contains(lower, "cmcc"), strings.Contains(lower, "cmnet"):
+ return "移动"
+ case strings.Contains(value, "教育"),
+ strings.Contains(lower, "cernet"), strings.Contains(lower, "edu"), strings.Contains(lower, "education"):
+ return "教育网"
+ case strings.Contains(value, "鹏博士"),
+ strings.Contains(lower, "drpeng"), strings.Contains(lower, "dr.peng"), strings.Contains(lower, "dr_peng"):
+ return "鹏博士"
+ case strings.Contains(value, "广电"),
+ strings.Contains(lower, "broadcast"), strings.Contains(lower, "cable"), strings.Contains(lower, "radio"):
+ return "广电"
+ default:
+ if isMainlandChinaCountry(country) {
+ return ""
+ }
+ return value
+ }
+}
+
+func normalizeChinaRegion(province string) string {
+ switch normalizeProvinceName(province) {
+ case "辽宁", "吉林", "黑龙江":
+ return "东北"
+ case "北京", "天津", "河北", "山西", "内蒙古":
+ return "华北"
+ case "上海", "江苏", "浙江", "安徽", "福建", "江西", "山东":
+ return "华东"
+ case "广东", "广西", "海南":
+ return "华南"
+ case "河南", "湖北", "湖南":
+ return "华中"
+ case "陕西", "甘肃", "青海", "宁夏", "新疆":
+ return "西北"
+ case "重庆", "四川", "贵州", "云南", "西藏":
+ return "西南"
+ default:
+ return ""
+ }
+}
+
+func normalizeContinent(country string) string {
+ switch normalizeCountryName(country) {
+ case "中国", "中国香港", "中国澳门", "中国台湾", "日本", "韩国", "新加坡", "印度", "泰国", "越南",
+ "印度尼西亚", "马来西亚", "菲律宾", "柬埔寨", "缅甸", "老挝", "斯里兰卡", "孟加拉国", "巴基斯坦", "尼泊尔",
+ "阿联酋", "沙特阿拉伯", "土耳其", "以色列", "伊朗", "伊拉克", "卡塔尔", "科威特", "蒙古":
+ return "亚洲"
+ case "美国", "加拿大", "墨西哥", "巴拿马", "哥斯达黎加", "古巴":
+ return "北美洲"
+ case "巴西", "阿根廷", "智利", "哥伦比亚", "秘鲁", "委内瑞拉", "厄瓜多尔":
+ return "南美洲"
+ case "德国", "英国", "法国", "荷兰", "西班牙", "意大利", "俄罗斯",
+ "波兰", "瑞典", "瑞士", "挪威", "芬兰", "丹麦", "葡萄牙", "爱尔兰", "比利时", "奥地利",
+ "乌克兰", "捷克", "罗马尼亚", "匈牙利", "希腊":
+ return "欧洲"
+ case "南非", "埃及", "尼日利亚", "肯尼亚", "摩洛哥", "阿尔及利亚", "坦桑尼亚", "埃塞俄比亚", "加纳", "突尼斯":
+ return "非洲"
+ case "澳大利亚", "新西兰":
+ return "大洋洲"
+ default:
+ return ""
+ }
+}
+func pickRuleRecords(rules []*pb.HTTPDNSCustomRule, qtype string, profile *clientRouteProfile, defaultTTL int32) (*pb.HTTPDNSCustomRule, []*resolveRecord, int32) {
+ bestScore := -1
+ var bestRule *pb.HTTPDNSCustomRule
+ var bestRecords []*resolveRecord
+ bestTTL := defaultTTL
+
+ for _, rule := range rules {
+ if rule == nil || !rule.GetIsOn() {
+ continue
+ }
+
+ score, ok := matchRuleLine(rule, profile)
+ if !ok {
+ continue
+ }
+
+ records := make([]*resolveRecord, 0)
+ for _, item := range rule.GetRecords() {
+ if item == nil {
+ continue
+ }
+ if strings.ToUpper(strings.TrimSpace(item.GetRecordType())) != qtype {
+ continue
+ }
+ value := strings.TrimSpace(item.GetRecordValue())
+ if len(value) == 0 {
+ continue
+ }
+ records = append(records, &resolveRecord{
+ Type: qtype,
+ IP: value,
+ Weight: item.GetWeight(),
+ Line: lookupIPLineLabel(value),
+ Region: lookupIPRegionSummary(value),
+ })
+ }
+ if len(records) == 0 {
+ continue
+ }
+
+ if score > bestScore {
+ bestScore = score
+ bestRule = rule
+ bestRecords = records
+ if rule.GetTtl() > 0 {
+ bestTTL = rule.GetTtl()
+ } else {
+ bestTTL = defaultTTL
+ }
+ }
+ }
+
+ return bestRule, bestRecords, bestTTL
+}
+
+// fallbackResolve 当无自定义规则命中时,回源上游 DNS 查询真实记录(对齐 EdgeDNS 做法)
+func fallbackResolve(domain string, qtype string) ([]*resolveRecord, int32, error) {
+ var dnsType uint16
+ switch qtype {
+ case "A":
+ dnsType = dns.TypeA
+ case "AAAA":
+ dnsType = dns.TypeAAAA
+ default:
+ return nil, 0, nil // 仅降级处理 A 和 AAAA
+ }
+
+ m := new(dns.Msg)
+ m.SetQuestion(dns.Fqdn(domain), dnsType)
+ m.RecursionDesired = true
+
+ // 优先使用本机 /etc/resolv.conf 中的 DNS 服务器(对齐 EdgeDNS)
+ var upstream = "223.5.5.5:53"
+ resolveConfig, confErr := dns.ClientConfigFromFile("/etc/resolv.conf")
+ if confErr == nil && len(resolveConfig.Servers) > 0 {
+ port := resolveConfig.Port
+ if len(port) == 0 {
+ port = "53"
+ }
+ server := resolveConfig.Servers[rands.Int(0, len(resolveConfig.Servers)-1)]
+ upstream = server + ":" + port
+ }
+
+ r, _, err := sharedRecursionDNSClient.Exchange(m, upstream)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ if r.Rcode != dns.RcodeSuccess {
+ return nil, 0, fmt.Errorf("upstream rcode: %d", r.Rcode)
+ }
+
+ var records []*resolveRecord
+ var responseTTL int32
+ for _, ans := range r.Answer {
+ switch t := ans.(type) {
+ case *dns.A:
+ if qtype == "A" {
+ if t.Hdr.Ttl > 0 {
+ ttl := int32(t.Hdr.Ttl)
+ if responseTTL == 0 || ttl < responseTTL {
+ responseTTL = ttl
+ }
+ }
+ ip := t.A.String()
+ records = append(records, &resolveRecord{
+ Type: "A",
+ IP: ip,
+ Line: lookupIPLineLabel(ip),
+ Region: lookupIPRegionSummary(ip),
+ })
+ }
+ case *dns.AAAA:
+ if qtype == "AAAA" {
+ if t.Hdr.Ttl > 0 {
+ ttl := int32(t.Hdr.Ttl)
+ if responseTTL == 0 || ttl < responseTTL {
+ responseTTL = ttl
+ }
+ }
+ ip := t.AAAA.String()
+ records = append(records, &resolveRecord{
+ Type: "AAAA",
+ IP: ip,
+ Line: lookupIPLineLabel(ip),
+ Region: lookupIPRegionSummary(ip),
+ })
+ }
+ }
+ }
+
+ return records, responseTTL, nil
+}
+
+func lookupIPRegionSummary(ip string) string {
+ address := strings.TrimSpace(ip)
+ if len(address) == 0 || net.ParseIP(address) == nil {
+ return ""
+ }
+
+ result := iplibrary.LookupIP(address)
+ if result == nil || !result.IsOk() {
+ return ""
+ }
+
+ return strings.TrimSpace(result.RegionSummary())
+}
+
+func lookupIPLineLabel(ip string) string {
+ address := strings.TrimSpace(ip)
+ if len(address) == 0 || net.ParseIP(address) == nil {
+ return "上游DNS"
+ }
+
+ result := iplibrary.LookupIP(address)
+ if result == nil || !result.IsOk() {
+ return "上游DNS"
+ }
+
+ provider := strings.TrimSpace(result.ProviderName())
+ country := normalizeCountryName(strings.TrimSpace(result.CountryName()))
+ carrier := strings.TrimSpace(normalizeCarrier(provider, country))
+ if isMainlandChinaCountry(country) {
+ if len(carrier) > 0 {
+ return carrier
+ }
+ return "默认"
+ }
+
+ if len(carrier) > 0 {
+ return carrier
+ }
+ if len(provider) > 0 {
+ return provider
+ }
+ return "上游DNS"
+}
+
+func isMainlandChinaCountry(country string) bool {
+ switch normalizeCountryName(country) {
+ case "中国":
+ return true
+ }
+ return false
+}
+
+func matchRuleLine(rule *pb.HTTPDNSCustomRule, profile *clientRouteProfile) (int, bool) {
+ scope := strings.ToLower(strings.TrimSpace(rule.GetLineScope()))
+ score := 0
+
+ if scope == "overseas" {
+ // 境外规则只匹配非中国大陆来源
+ if isMainlandChinaCountry(profile.Country) {
+ return 0, false
+ }
+
+ fieldScore, ok := matchRuleField(rule.GetLineContinent(), profile.Continent)
+ if !ok {
+ return 0, false
+ }
+ score += fieldScore
+
+ fieldScore, ok = matchRuleField(rule.GetLineCountry(), profile.Country)
+ if !ok {
+ return 0, false
+ }
+ score += fieldScore
+ return score, true
+ }
+
+ // 中国地区规则只匹配中国大陆来源
+ if !isMainlandChinaCountry(profile.Country) {
+ return 0, false
+ }
+
+ fieldScore, ok := matchRuleField(rule.GetLineCountry(), profile.Country)
+ if !ok {
+ return 0, false
+ }
+ score += fieldScore
+
+ fieldScore, ok = matchRuleField(rule.GetLineContinent(), profile.Continent)
+ if !ok {
+ return 0, false
+ }
+ score += fieldScore
+
+ fieldScore, ok = matchRuleField(rule.GetLineCarrier(), profile.Carrier, profile.ProviderRaw)
+ if !ok {
+ return 0, false
+ }
+ score += fieldScore
+
+ fieldScore, ok = matchRuleField(rule.GetLineRegion(), profile.Region)
+ if !ok {
+ return 0, false
+ }
+ score += fieldScore
+
+ fieldScore, ok = matchRuleField(rule.GetLineProvince(), profile.Province)
+ if !ok {
+ return 0, false
+ }
+ score += fieldScore
+
+ return score, true
+}
+
+func matchRuleField(ruleValue string, candidates ...string) (int, bool) {
+ if isDefaultLineValue(ruleValue) {
+ return 0, true
+ }
+
+ want := normalizeLineValue(ruleValue)
+ if len(want) == 0 {
+ return 0, true
+ }
+
+ for _, candidate := range candidates {
+ got := normalizeLineValue(candidate)
+ if len(got) == 0 {
+ // 如果规则设了具体值(want),但客户端信息(got)为空,则不能匹配
+ // 否则 strings.Contains("xxx", "") 永远为 true
+ continue
+ }
+ if want == got || strings.Contains(got, want) || strings.Contains(want, got) {
+ return 1, true
+ }
+ }
+ return 0, false
+}
+
+func isDefaultLineValue(value string) bool {
+ switch normalizeLineValue(value) {
+ case "", "default", "all", "*", "any", "默认", "全部", "不限":
+ return true
+ }
+ return false
+}
+
+func normalizeLineValue(value string) string {
+ v := strings.ToLower(strings.TrimSpace(value))
+ v = strings.ReplaceAll(v, " ", "")
+ v = strings.ReplaceAll(v, "-", "")
+ v = strings.ReplaceAll(v, "_", "")
+ v = strings.ReplaceAll(v, "/", "")
+ return v
+}
+
+func normalizeIPCandidate(ip string) string {
+ value := strings.TrimSpace(ip)
+ if len(value) == 0 {
+ return ""
+ }
+ if host, _, err := net.SplitHostPort(value); err == nil {
+ value = strings.TrimSpace(host)
+ }
+ if parsed := net.ParseIP(value); parsed != nil {
+ return parsed.String()
+ }
+ return ""
+}
+
+func normalizeCountryName(country string) string {
+ value := strings.TrimSpace(country)
+ if len(value) == 0 {
+ return ""
+ }
+
+ normalized := normalizeLineValue(value)
+ switch normalized {
+ case "中国香港", "香港", "hongkong":
+ return "中国香港"
+ case "中国澳门", "澳门", "macao", "macau":
+ return "中国澳门"
+ case "中国台湾", "台湾", "taiwan":
+ return "中国台湾"
+ }
+
+ switch normalized {
+ case "中国", "中国大陆", "中国内地", "中华人民共和国", "prc", "cn", "china", "mainlandchina", "peoplesrepublicofchina", "thepeoplesrepublicofchina":
+ return "中国"
+ case "美国", "usa", "unitedstates", "unitedstatesofamerica":
+ return "美国"
+ case "加拿大", "canada":
+ return "加拿大"
+ case "墨西哥", "mexico":
+ return "墨西哥"
+ case "日本", "japan":
+ return "日本"
+ case "韩国", "southkorea", "korea":
+ return "韩国"
+ case "新加坡", "singapore":
+ return "新加坡"
+ case "印度", "india":
+ return "印度"
+ case "泰国", "thailand":
+ return "泰国"
+ case "越南", "vietnam":
+ return "越南"
+ case "德国", "germany":
+ return "德国"
+ case "英国", "uk", "unitedkingdom", "greatbritain", "britain":
+ return "英国"
+ case "法国", "france":
+ return "法国"
+ case "荷兰", "netherlands":
+ return "荷兰"
+ case "西班牙", "spain":
+ return "西班牙"
+ case "意大利", "italy":
+ return "意大利"
+ case "俄罗斯", "russia":
+ return "俄罗斯"
+ case "巴西", "brazil":
+ return "巴西"
+ case "阿根廷", "argentina":
+ return "阿根廷"
+ case "智利", "chile":
+ return "智利"
+ case "哥伦比亚", "colombia":
+ return "哥伦比亚"
+ // --- 亚洲(新增)---
+ case "印度尼西亚", "indonesia":
+ return "印度尼西亚"
+ case "马来西亚", "malaysia":
+ return "马来西亚"
+ case "菲律宾", "philippines":
+ return "菲律宾"
+ case "柬埔寨", "cambodia":
+ return "柬埔寨"
+ case "缅甸", "myanmar", "burma":
+ return "缅甸"
+ case "老挝", "laos":
+ return "老挝"
+ case "斯里兰卡", "srilanka":
+ return "斯里兰卡"
+ case "孟加拉国", "孟加拉", "bangladesh":
+ return "孟加拉国"
+ case "巴基斯坦", "pakistan":
+ return "巴基斯坦"
+ case "尼泊尔", "nepal":
+ return "尼泊尔"
+ case "阿联酋", "阿拉伯联合酋长国", "uae", "unitedarabemirates":
+ return "阿联酋"
+ case "沙特阿拉伯", "沙特", "saudiarabia", "saudi":
+ return "沙特阿拉伯"
+ case "土耳其", "turkey", "türkiye", "turkiye":
+ return "土耳其"
+ case "以色列", "israel":
+ return "以色列"
+ case "伊朗", "iran":
+ return "伊朗"
+ case "伊拉克", "iraq":
+ return "伊拉克"
+ case "卡塔尔", "qatar":
+ return "卡塔尔"
+ case "科威特", "kuwait":
+ return "科威特"
+ case "蒙古", "mongolia":
+ return "蒙古"
+ // --- 欧洲(新增)---
+ case "波兰", "poland":
+ return "波兰"
+ case "瑞典", "sweden":
+ return "瑞典"
+ case "瑞士", "switzerland":
+ return "瑞士"
+ case "挪威", "norway":
+ return "挪威"
+ case "芬兰", "finland":
+ return "芬兰"
+ case "丹麦", "denmark":
+ return "丹麦"
+ case "葡萄牙", "portugal":
+ return "葡萄牙"
+ case "爱尔兰", "ireland":
+ return "爱尔兰"
+ case "比利时", "belgium":
+ return "比利时"
+ case "奥地利", "austria":
+ return "奥地利"
+ case "乌克兰", "ukraine":
+ return "乌克兰"
+ case "捷克", "czech", "czechrepublic", "czechia":
+ return "捷克"
+ case "罗马尼亚", "romania":
+ return "罗马尼亚"
+ case "匈牙利", "hungary":
+ return "匈牙利"
+ case "希腊", "greece":
+ return "希腊"
+ // --- 北美洲(新增)---
+ case "巴拿马", "panama":
+ return "巴拿马"
+ case "哥斯达黎加", "costarica":
+ return "哥斯达黎加"
+ case "古巴", "cuba":
+ return "古巴"
+ // --- 南美洲(新增)---
+ case "秘鲁", "peru":
+ return "秘鲁"
+ case "委内瑞拉", "venezuela":
+ return "委内瑞拉"
+ case "厄瓜多尔", "ecuador":
+ return "厄瓜多尔"
+ // --- 非洲 ---
+ case "南非", "southafrica":
+ return "南非"
+ case "埃及", "egypt":
+ return "埃及"
+ case "尼日利亚", "nigeria":
+ return "尼日利亚"
+ case "肯尼亚", "kenya":
+ return "肯尼亚"
+ case "摩洛哥", "morocco":
+ return "摩洛哥"
+ case "阿尔及利亚", "algeria":
+ return "阿尔及利亚"
+ case "坦桑尼亚", "tanzania":
+ return "坦桑尼亚"
+ case "埃塞俄比亚", "ethiopia":
+ return "埃塞俄比亚"
+ case "加纳", "ghana":
+ return "加纳"
+ case "突尼斯", "tunisia":
+ return "突尼斯"
+ // --- 大洋洲 ---
+ case "澳大利亚", "australia":
+ return "澳大利亚"
+ case "新西兰", "newzealand":
+ return "新西兰"
+ default:
+ return value
+ }
+}
+
+func normalizeProvinceName(province string) string {
+ value := strings.TrimSpace(province)
+ if len(value) == 0 {
+ return ""
+ }
+
+ switch value {
+ case "内蒙古自治区":
+ return "内蒙古"
+ case "广西壮族自治区":
+ return "广西"
+ case "宁夏回族自治区":
+ return "宁夏"
+ case "新疆维吾尔自治区":
+ return "新疆"
+ case "西藏自治区":
+ return "西藏"
+ case "香港特别行政区":
+ return "香港"
+ case "澳门特别行政区":
+ return "澳门"
+ }
+
+ for _, suffix := range []string{"维吾尔自治区", "回族自治区", "壮族自治区", "自治区", "特别行政区", "省", "市"} {
+ value = strings.TrimSuffix(value, suffix)
+ }
+
+ return value
+}
+
+func ruleLineSummary(rule *pb.HTTPDNSCustomRule) string {
+ if rule == nil {
+ return ""
+ }
+
+ scope := strings.ToLower(strings.TrimSpace(rule.GetLineScope()))
+ if scope == "overseas" {
+ pieces := make([]string, 0, 2)
+ if !isDefaultLineValue(rule.GetLineContinent()) {
+ pieces = append(pieces, strings.TrimSpace(rule.GetLineContinent()))
+ }
+ if !isDefaultLineValue(rule.GetLineCountry()) {
+ pieces = append(pieces, strings.TrimSpace(rule.GetLineCountry()))
+ }
+ return strings.Join(pieces, "/")
+ }
+
+ pieces := make([]string, 0, 3)
+ if !isDefaultLineValue(rule.GetLineCarrier()) {
+ pieces = append(pieces, strings.TrimSpace(rule.GetLineCarrier()))
+ }
+ if !isDefaultLineValue(rule.GetLineRegion()) {
+ pieces = append(pieces, strings.TrimSpace(rule.GetLineRegion()))
+ }
+ if !isDefaultLineValue(rule.GetLineProvince()) {
+ pieces = append(pieces, strings.TrimSpace(rule.GetLineProvince()))
+ }
+ return strings.Join(pieces, "/")
+}
+
+func ruleRegionSummary(rule *pb.HTTPDNSCustomRule) string {
+ if rule == nil {
+ return ""
+ }
+ if !isDefaultLineValue(rule.GetLineProvince()) {
+ return strings.TrimSpace(rule.GetLineProvince())
+ }
+ if !isDefaultLineValue(rule.GetLineCountry()) {
+ return strings.TrimSpace(rule.GetLineCountry())
+ }
+ if !isDefaultLineValue(rule.GetLineRegion()) {
+ return strings.TrimSpace(rule.GetLineRegion())
+ }
+ if !isDefaultLineValue(rule.GetLineContinent()) {
+ return strings.TrimSpace(rule.GetLineContinent())
+ }
+ return ""
+}
+
+func (s *ResolveServer) isAccessLogEnabled(snapshot *LoadedSnapshot) bool {
+ if snapshot == nil || snapshot.ClusterID <= 0 {
+ return true
+ }
+ cluster := snapshot.Clusters[snapshot.ClusterID]
+ if cluster == nil {
+ return true
+ }
+ return cluster.GetAccessLogIsOn()
+}
+
+func (s *ResolveServer) enqueueAccessLog(item *pb.HTTPDNSAccessLog) {
+ if item == nil {
+ return
+ }
+ select {
+ case s.logQueue <- item:
+ default:
+ log.Println("[HTTPDNS_NODE][resolve]access log queue is full, drop request:", item.GetRequestId())
+ }
+}
+
+func (s *ResolveServer) startAccessLogFlusher() {
+ ticker := time.NewTicker(1 * time.Second)
+ defer ticker.Stop()
+
+ batch := make([]*pb.HTTPDNSAccessLog, 0, 128)
+ flush := func() {
+ if len(batch) == 0 {
+ return
+ }
+ s.logWriter.WriteBatch(batch)
+ batch = batch[:0]
+ }
+
+ for {
+ select {
+ case item := <-s.logQueue:
+ if item != nil {
+ batch = append(batch, item)
+ }
+ if len(batch) > 4096 {
+ log.Println("[HTTPDNS_NODE][resolve]access log flush backlog too large, trim:", len(batch))
+ batch = batch[len(batch)-2048:]
+ }
+ if len(batch) >= 128 {
+ flush()
+ }
+ case <-ticker.C:
+ flush()
+ case <-s.quitCh:
+ flush()
+ _ = s.logWriter.Close()
+ return
+ }
+ }
+}
diff --git a/EdgeHttpDNS/internal/nodes/runtime_log.go b/EdgeHttpDNS/internal/nodes/runtime_log.go
new file mode 100644
index 0000000..ad6ca39
--- /dev/null
+++ b/EdgeHttpDNS/internal/nodes/runtime_log.go
@@ -0,0 +1,39 @@
+package nodes
+
+import (
+ "log"
+ "time"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/rpc"
+)
+
+func reportRuntimeLog(level string, logType string, module string, description string, requestID string) {
+ rpcClient, err := rpc.SharedRPC()
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][runtime-log]", err.Error())
+ return
+ }
+
+ nodeID := int64(0)
+
+ now := time.Now()
+ _, err = rpcClient.HTTPDNSRuntimeLogRPC.CreateHTTPDNSRuntimeLogs(rpcClient.Context(), &pb.CreateHTTPDNSRuntimeLogsRequest{
+ Logs: []*pb.HTTPDNSRuntimeLog{
+ {
+ NodeId: nodeID,
+ Level: level,
+ Type: logType,
+ Module: module,
+ Description: description,
+ Count: 1,
+ RequestId: requestID,
+ CreatedAt: now.Unix(),
+ Day: now.Format("20060102"),
+ },
+ },
+ })
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][runtime-log]", err.Error())
+ }
+}
diff --git a/EdgeHttpDNS/internal/nodes/snapshot_manager.go b/EdgeHttpDNS/internal/nodes/snapshot_manager.go
new file mode 100644
index 0000000..5c10860
--- /dev/null
+++ b/EdgeHttpDNS/internal/nodes/snapshot_manager.go
@@ -0,0 +1,193 @@
+package nodes
+
+import (
+ "fmt"
+ "log"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/rpc"
+)
+
+type LoadedDomain struct {
+ Domain *pb.HTTPDNSDomain
+ Rules []*pb.HTTPDNSCustomRule
+}
+
+type LoadedApp struct {
+ App *pb.HTTPDNSApp
+ Domains map[string]*LoadedDomain // key: lower(domain)
+}
+
+type LoadedSnapshot struct {
+ LoadedAt int64
+
+ NodeID int64
+ ClusterID int64
+
+ Clusters map[int64]*pb.HTTPDNSCluster
+ Apps map[string]*LoadedApp // key: lower(appId)
+}
+
+type SnapshotManager struct {
+ quitCh <-chan struct{}
+ ticker *time.Ticker
+
+ locker sync.RWMutex
+ snapshot *LoadedSnapshot
+
+ timezone string
+}
+
+func NewSnapshotManager(quitCh <-chan struct{}) *SnapshotManager {
+ return &SnapshotManager{
+ quitCh: quitCh,
+ ticker: time.NewTicker(30 * time.Second),
+ }
+}
+
+func (m *SnapshotManager) Start() {
+ defer m.ticker.Stop()
+
+ if err := m.RefreshNow("startup"); err != nil {
+ log.Println("[HTTPDNS_NODE][snapshot]initial refresh failed:", err.Error())
+ }
+
+ for {
+ select {
+ case <-m.ticker.C:
+ if err := m.RefreshNow("periodic"); err != nil {
+ log.Println("[HTTPDNS_NODE][snapshot]periodic refresh failed:", err.Error())
+ }
+ case <-m.quitCh:
+ return
+ }
+ }
+}
+
+func (m *SnapshotManager) Current() *LoadedSnapshot {
+ m.locker.RLock()
+ defer m.locker.RUnlock()
+ return m.snapshot
+}
+
+func (m *SnapshotManager) RefreshNow(reason string) error {
+ rpcClient, err := rpc.SharedRPC()
+ if err != nil {
+ return err
+ }
+
+ nodeResp, err := rpcClient.HTTPDNSNodeRPC.FindHTTPDNSNode(rpcClient.Context(), &pb.FindHTTPDNSNodeRequest{
+ NodeId: 0,
+ })
+ if err != nil {
+ return err
+ }
+ if nodeResp.GetNode() == nil {
+ return fmt.Errorf("httpdns node info not found")
+ }
+
+ clusterResp, err := rpcClient.HTTPDNSClusterRPC.FindAllHTTPDNSClusters(rpcClient.Context(), &pb.FindAllHTTPDNSClustersRequest{})
+ if err != nil {
+ return err
+ }
+ clusters := map[int64]*pb.HTTPDNSCluster{}
+ for _, cluster := range clusterResp.GetClusters() {
+ if cluster == nil || cluster.GetId() <= 0 {
+ continue
+ }
+ clusters[cluster.GetId()] = cluster
+ }
+
+ appResp, err := rpcClient.HTTPDNSAppRPC.FindAllHTTPDNSApps(rpcClient.Context(), &pb.FindAllHTTPDNSAppsRequest{})
+ if err != nil {
+ return err
+ }
+
+ apps := map[string]*LoadedApp{}
+ for _, app := range appResp.GetApps() {
+ if app == nil || app.GetId() <= 0 || len(app.GetAppId()) == 0 {
+ continue
+ }
+
+ domainResp, err := rpcClient.HTTPDNSDomainRPC.ListHTTPDNSDomainsWithAppId(rpcClient.Context(), &pb.ListHTTPDNSDomainsWithAppIdRequest{
+ AppDbId: app.GetId(),
+ })
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][snapshot]list domains failed, appId:", app.GetAppId(), "err:", err.Error())
+ continue
+ }
+
+ domains := map[string]*LoadedDomain{}
+ for _, domain := range domainResp.GetDomains() {
+ if domain == nil || domain.GetId() <= 0 || len(domain.GetDomain()) == 0 {
+ continue
+ }
+ ruleResp, err := rpcClient.HTTPDNSRuleRPC.ListHTTPDNSCustomRulesWithDomainId(rpcClient.Context(), &pb.ListHTTPDNSCustomRulesWithDomainIdRequest{
+ DomainId: domain.GetId(),
+ })
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][snapshot]list rules failed, domain:", domain.GetDomain(), "err:", err.Error())
+ continue
+ }
+
+ domains[strings.ToLower(strings.TrimSpace(domain.GetDomain()))] = &LoadedDomain{
+ Domain: domain,
+ Rules: ruleResp.GetRules(),
+ }
+ }
+
+ apps[strings.ToLower(strings.TrimSpace(app.GetAppId()))] = &LoadedApp{
+ App: app,
+ Domains: domains,
+ }
+ }
+
+ snapshot := &LoadedSnapshot{
+ LoadedAt: time.Now().UnixNano(),
+ NodeID: nodeResp.GetNode().GetId(),
+ ClusterID: nodeResp.GetNode().GetClusterId(),
+ Clusters: clusters,
+ Apps: apps,
+ }
+
+ m.locker.Lock()
+ m.snapshot = snapshot
+ m.locker.Unlock()
+
+ reportRuntimeLog("info", "config", "snapshot", "snapshot refreshed: "+reason, fmt.Sprintf("snapshot-%d", time.Now().UnixNano()))
+
+ // timezone sync - prefer current node's cluster timezone
+ var timeZone string
+ if snapshot.ClusterID > 0 {
+ if cluster := clusters[snapshot.ClusterID]; cluster != nil && len(cluster.GetTimeZone()) > 0 {
+ timeZone = cluster.GetTimeZone()
+ }
+ }
+ // fallback to any non-empty cluster timezone for compatibility
+ if len(timeZone) == 0 {
+ for _, cluster := range clusters {
+ if cluster != nil && len(cluster.GetTimeZone()) > 0 {
+ timeZone = cluster.GetTimeZone()
+ break
+ }
+ }
+ }
+ if len(timeZone) == 0 {
+ timeZone = "Asia/Shanghai"
+ }
+ if m.timezone != timeZone {
+ location, err := time.LoadLocation(timeZone)
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][TIMEZONE]change time zone failed:", err.Error())
+ } else {
+ log.Println("[HTTPDNS_NODE][TIMEZONE]change time zone to '" + timeZone + "'")
+ time.Local = location
+ m.timezone = timeZone
+ }
+ }
+
+ return nil
+}
diff --git a/EdgeHttpDNS/internal/nodes/status_manager.go b/EdgeHttpDNS/internal/nodes/status_manager.go
new file mode 100644
index 0000000..2a3c159
--- /dev/null
+++ b/EdgeHttpDNS/internal/nodes/status_manager.go
@@ -0,0 +1,144 @@
+package nodes
+
+import (
+ "encoding/json"
+ "log"
+ "os"
+ "runtime"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/configs"
+ teaconst "github.com/TeaOSLab/EdgeHttpDNS/internal/const"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/rpc"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/utils"
+)
+
+
+type StatusManager struct {
+ quitCh <-chan struct{}
+ ticker *time.Ticker
+}
+
+func NewStatusManager(quitCh <-chan struct{}) *StatusManager {
+ return &StatusManager{
+ quitCh: quitCh,
+ ticker: time.NewTicker(30 * time.Second),
+ }
+}
+
+func (m *StatusManager) Start() {
+ defer m.ticker.Stop()
+
+ m.update()
+ for {
+ select {
+ case <-m.ticker.C:
+ m.update()
+ case <-m.quitCh:
+ return
+ }
+ }
+}
+
+func (m *StatusManager) update() {
+ status := m.collectStatus()
+ statusJSON, err := json.Marshal(status)
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][status]marshal status failed:", err.Error())
+ return
+ }
+
+ rpcClient, err := rpc.SharedRPC()
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][status]rpc unavailable:", err.Error())
+ return
+ }
+
+ config, err := configs.SharedAPIConfig()
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][status]load config failed:", err.Error())
+ return
+ }
+ nodeId, _ := strconv.ParseInt(config.NodeId, 10, 64)
+
+ _, err = rpcClient.HTTPDNSNodeRPC.UpdateHTTPDNSNodeStatus(rpcClient.Context(), &pb.UpdateHTTPDNSNodeStatusRequest{
+ NodeId: nodeId,
+ IsUp: true,
+ IsInstalled: true,
+ IsActive: true,
+ StatusJSON: statusJSON,
+ })
+
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][status]update status failed:", err.Error())
+ }
+}
+
+func (m *StatusManager) collectStatus() *nodeconfigs.NodeStatus {
+ now := time.Now().Unix()
+
+ status := &nodeconfigs.NodeStatus{
+ BuildVersion: teaconst.Version,
+ BuildVersionCode: utils.VersionToLong(teaconst.Version),
+ ConfigVersion: 0,
+ OS: runtime.GOOS,
+ Arch: runtime.GOARCH,
+ CPULogicalCount: runtime.NumCPU(),
+ CPUPhysicalCount: runtime.NumCPU(),
+ IsActive: true,
+ ConnectionCount: 0,
+ UpdatedAt: now,
+ Timestamp: now,
+ }
+
+ rpcClient, err := rpc.SharedRPC()
+ if err == nil {
+ total, failed, avgCostSeconds := rpcClient.GetAndResetMetrics()
+ if total > 0 {
+ status.APISuccessPercent = float64(total-failed) * 100.0 / float64(total)
+ status.APIAvgCostSeconds = avgCostSeconds
+ }
+ }
+
+
+ hostname, _ := os.Hostname()
+ status.Hostname = hostname
+
+ exePath, _ := os.Executable()
+ status.ExePath = exePath
+
+ var memStats runtime.MemStats
+ runtime.ReadMemStats(&memStats)
+ status.MemoryTotal = memStats.Sys
+ if status.MemoryTotal > 0 {
+ status.MemoryUsage = float64(memStats.Alloc) / float64(status.MemoryTotal)
+ }
+
+ load1m, load5m, load15m := readLoadAvg()
+ status.Load1m = load1m
+ status.Load5m = load5m
+ status.Load15m = load15m
+
+ return status
+}
+
+func readLoadAvg() (float64, float64, float64) {
+ data, err := os.ReadFile("/proc/loadavg")
+ if err != nil {
+ return 0, 0, 0
+ }
+
+ parts := strings.Fields(strings.TrimSpace(string(data)))
+ if len(parts) < 3 {
+ return 0, 0, 0
+ }
+
+ load1m, _ := strconv.ParseFloat(parts[0], 64)
+ load5m, _ := strconv.ParseFloat(parts[1], 64)
+ load15m, _ := strconv.ParseFloat(parts[2], 64)
+ return load1m, load5m, load15m
+}
diff --git a/EdgeHttpDNS/internal/nodes/task_manager.go b/EdgeHttpDNS/internal/nodes/task_manager.go
new file mode 100644
index 0000000..f11a6af
--- /dev/null
+++ b/EdgeHttpDNS/internal/nodes/task_manager.go
@@ -0,0 +1,131 @@
+package nodes
+
+import (
+ "fmt"
+ "log"
+ "time"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ teaconst "github.com/TeaOSLab/EdgeHttpDNS/internal/const"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/rpc"
+)
+
+type TaskManager struct {
+ quitCh <-chan struct{}
+ ticker *time.Ticker
+ version int64
+
+ snapshotManager *SnapshotManager
+}
+
+func NewTaskManager(quitCh <-chan struct{}, snapshotManager *SnapshotManager) *TaskManager {
+ return &TaskManager{
+ quitCh: quitCh,
+ ticker: time.NewTicker(20 * time.Second),
+ version: 0,
+ snapshotManager: snapshotManager,
+ }
+}
+
+func (m *TaskManager) Start() {
+ defer m.ticker.Stop()
+
+ m.processTasks()
+ for {
+ select {
+ case <-m.ticker.C:
+ m.processTasks()
+ case <-m.quitCh:
+ return
+ }
+ }
+}
+
+func (m *TaskManager) processTasks() {
+ rpcClient, err := rpc.SharedRPC()
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][task]rpc unavailable:", err.Error())
+ return
+ }
+
+ resp, err := rpcClient.NodeTaskRPC.FindNodeTasks(rpcClient.Context(), &pb.FindNodeTasksRequest{
+ Version: m.version,
+ })
+ if err != nil {
+ log.Println("[HTTPDNS_NODE][task]fetch tasks failed:", err.Error())
+ return
+ }
+
+ for _, task := range resp.GetNodeTasks() {
+ ok, errorMessage := m.handleTask(task)
+
+ _, reportErr := rpcClient.NodeTaskRPC.ReportNodeTaskDone(rpcClient.Context(), &pb.ReportNodeTaskDoneRequest{
+ NodeTaskId: task.GetId(),
+ IsOk: ok,
+ Error: errorMessage,
+ })
+ if reportErr != nil {
+ log.Println("[HTTPDNS_NODE][task]report task result failed:", reportErr.Error())
+ }
+
+ if task.GetVersion() > m.version {
+ m.version = task.GetVersion()
+ }
+ }
+}
+
+func (m *TaskManager) handleTask(task *pb.NodeTask) (bool, string) {
+ taskType := task.GetType()
+ requestID := fmt.Sprintf("task-%d", task.GetId())
+
+ switch taskType {
+ case teaconst.TaskTypeHTTPDNSConfigChanged:
+ if m.snapshotManager != nil {
+ if err := m.snapshotManager.RefreshNow(taskType); err != nil {
+ reportRuntimeLog("error", "config", "task-manager", "refresh snapshot failed: "+err.Error(), requestID)
+ return false, err.Error()
+ }
+ }
+ reportRuntimeLog("info", "config", "task-manager", "HTTPDNS configuration updated", requestID)
+ return true, ""
+ case teaconst.TaskTypeHTTPDNSAppChanged:
+ if m.snapshotManager != nil {
+ if err := m.snapshotManager.RefreshNow(taskType); err != nil {
+ reportRuntimeLog("error", "app", "task-manager", "refresh snapshot failed: "+err.Error(), requestID)
+ return false, err.Error()
+ }
+ }
+ reportRuntimeLog("info", "app", "task-manager", "HTTPDNS app policy updated", requestID)
+ return true, ""
+ case teaconst.TaskTypeHTTPDNSDomainChanged:
+ if m.snapshotManager != nil {
+ if err := m.snapshotManager.RefreshNow(taskType); err != nil {
+ reportRuntimeLog("error", "domain", "task-manager", "refresh snapshot failed: "+err.Error(), requestID)
+ return false, err.Error()
+ }
+ }
+ reportRuntimeLog("info", "domain", "task-manager", "HTTPDNS domain binding updated", requestID)
+ return true, ""
+ case teaconst.TaskTypeHTTPDNSRuleChanged:
+ if m.snapshotManager != nil {
+ if err := m.snapshotManager.RefreshNow(taskType); err != nil {
+ reportRuntimeLog("error", "rule", "task-manager", "refresh snapshot failed: "+err.Error(), requestID)
+ return false, err.Error()
+ }
+ }
+ reportRuntimeLog("info", "rule", "task-manager", "HTTPDNS custom rule updated", requestID)
+ return true, ""
+ case teaconst.TaskTypeHTTPDNSTLSChanged:
+ if m.snapshotManager != nil {
+ if err := m.snapshotManager.RefreshNow(taskType); err != nil {
+ reportRuntimeLog("error", "tls", "task-manager", "refresh snapshot failed: "+err.Error(), requestID)
+ return false, err.Error()
+ }
+ }
+ reportRuntimeLog("info", "tls", "task-manager", "HTTPDNS TLS config updated", requestID)
+ return true, ""
+ default:
+ reportRuntimeLog("warning", "task", "task-manager", "unknown task type: "+taskType, requestID)
+ return true, ""
+ }
+}
diff --git a/EdgeHttpDNS/internal/nodes/upgrade_manager.go b/EdgeHttpDNS/internal/nodes/upgrade_manager.go
new file mode 100644
index 0000000..291ac2f
--- /dev/null
+++ b/EdgeHttpDNS/internal/nodes/upgrade_manager.go
@@ -0,0 +1,280 @@
+package nodes
+
+import (
+ "crypto/md5"
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "time"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ teaconst "github.com/TeaOSLab/EdgeHttpDNS/internal/const"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/rpc"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/utils"
+ "github.com/iwind/TeaGo/Tea"
+ stringutil "github.com/iwind/TeaGo/utils/string"
+ "github.com/iwind/gosock/pkg/gosock"
+)
+
+// UpgradeManager 节点升级管理器
+type UpgradeManager struct {
+ isInstalling bool
+ lastFile string
+ exe string
+}
+
+// NewUpgradeManager 获取新对象
+func NewUpgradeManager() *UpgradeManager {
+ return &UpgradeManager{}
+}
+
+// Loop 启动升级检查循环(每1分钟)
+func (this *UpgradeManager) Loop() {
+ rpcClient, err := rpc.SharedRPC()
+ if err != nil {
+ log.Println("[UPGRADE_MANAGER]" + err.Error())
+ return
+ }
+
+ var ticker = time.NewTicker(1 * time.Minute)
+ for range ticker.C {
+ resp, err := rpcClient.HTTPDNSNodeRPC.CheckHTTPDNSNodeLatestVersion(rpcClient.Context(), &pb.CheckHTTPDNSNodeLatestVersionRequest{
+ Os: runtime.GOOS,
+ Arch: runtime.GOARCH,
+ CurrentVersion: teaconst.Version,
+ })
+ if err != nil {
+ log.Println("[UPGRADE_MANAGER]check version failed: " + err.Error())
+ continue
+ }
+ if resp.HasNewVersion {
+ this.Start()
+ }
+ }
+}
+
+// Start 启动升级
+func (this *UpgradeManager) Start() {
+ // 必须放在文件解压之前读取可执行文件路径,防止解压之后,当前的可执行文件路径发生改变
+ exe, err := os.Executable()
+ if err != nil {
+ log.Println("[UPGRADE_MANAGER]can not find current executable file name")
+ return
+ }
+ this.exe = exe
+
+ // 测试环境下不更新
+ if Tea.IsTesting() {
+ return
+ }
+
+ if this.isInstalling {
+ return
+ }
+ this.isInstalling = true
+
+ // 还原安装状态
+ defer func() {
+ this.isInstalling = false
+ }()
+
+ log.Println("[UPGRADE_MANAGER]upgrading httpdns node ...")
+ err = this.install()
+ if err != nil {
+ log.Println("[UPGRADE_MANAGER]download failed: " + err.Error())
+ return
+ }
+
+ log.Println("[UPGRADE_MANAGER]upgrade successfully")
+
+ go func() {
+ err = this.restart()
+ if err != nil {
+ log.Println("[UPGRADE_MANAGER]" + err.Error())
+ }
+ }()
+}
+
+func (this *UpgradeManager) install() error {
+ // 检查是否有已下载但未安装成功的
+ if len(this.lastFile) > 0 {
+ _, err := os.Stat(this.lastFile)
+ if err == nil {
+ err = this.unzip(this.lastFile)
+ if err != nil {
+ return err
+ }
+ this.lastFile = ""
+ return nil
+ }
+ }
+
+ // 创建临时文件
+ dir := Tea.Root + "/tmp"
+ _, err := os.Stat(dir)
+ if err != nil {
+ if os.IsNotExist(err) {
+ err = os.Mkdir(dir, 0777)
+ if err != nil {
+ return err
+ }
+ } else {
+ return err
+ }
+ }
+
+ log.Println("[UPGRADE_MANAGER]downloading new node ...")
+
+ path := dir + "/" + teaconst.ProcessName + ".tmp"
+ fp, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0777)
+ if err != nil {
+ return err
+ }
+ isClosed := false
+ defer func() {
+ if !isClosed {
+ _ = fp.Close()
+ }
+ }()
+
+ client, err := rpc.SharedRPC()
+ if err != nil {
+ return err
+ }
+
+ var offset int64
+ var h = md5.New()
+ var sum = ""
+ var filename = ""
+ for {
+ resp, err := client.HTTPDNSNodeRPC.DownloadHTTPDNSNodeInstallationFile(client.Context(), &pb.DownloadHTTPDNSNodeInstallationFileRequest{
+ Os: runtime.GOOS,
+ Arch: runtime.GOARCH,
+ ChunkOffset: offset,
+ })
+ if err != nil {
+ return err
+ }
+ if len(resp.Sum) == 0 {
+ return nil
+ }
+ sum = resp.Sum
+ filename = resp.Filename
+ if stringutil.VersionCompare(resp.Version, teaconst.Version) <= 0 {
+ return nil
+ }
+ if len(resp.ChunkData) == 0 {
+ break
+ }
+
+ // 写入文件
+ _, err = fp.Write(resp.ChunkData)
+ if err != nil {
+ return err
+ }
+ _, err = h.Write(resp.ChunkData)
+ if err != nil {
+ return err
+ }
+
+ offset = resp.Offset
+ }
+
+ if len(filename) == 0 {
+ return nil
+ }
+
+ isClosed = true
+ err = fp.Close()
+ if err != nil {
+ return err
+ }
+
+ if fmt.Sprintf("%x", h.Sum(nil)) != sum {
+ _ = os.Remove(path)
+ return nil
+ }
+
+ // 改成zip
+ zipPath := dir + "/" + filename
+ err = os.Rename(path, zipPath)
+ if err != nil {
+ return err
+ }
+ this.lastFile = zipPath
+
+ // 解压
+ err = this.unzip(zipPath)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// 解压
+func (this *UpgradeManager) unzip(zipPath string) error {
+ var isOk = false
+ defer func() {
+ if isOk {
+ // 只有解压并覆盖成功后才会删除
+ _ = os.Remove(zipPath)
+ }
+ }()
+
+ // 解压
+ var target = Tea.Root
+ if Tea.IsTesting() {
+ // 测试环境下只解压在tmp目录
+ target = Tea.Root + "/tmp"
+ }
+
+ // 先改先前的可执行文件
+ err := os.Rename(target+"/bin/"+teaconst.ProcessName, target+"/bin/."+teaconst.ProcessName+".dist")
+ hasBackup := err == nil
+ defer func() {
+ if !isOk && hasBackup {
+ // 失败时还原
+ _ = os.Rename(target+"/bin/."+teaconst.ProcessName+".dist", target+"/bin/"+teaconst.ProcessName)
+ }
+ }()
+
+ unzip := utils.NewUnzip(zipPath, target, teaconst.ProcessName+"/")
+ err = unzip.Run()
+ if err != nil {
+ return err
+ }
+
+ isOk = true
+
+ return nil
+}
+
+// 重启
+func (this *UpgradeManager) restart() error {
+ // 关闭当前sock,防止无法重启
+ _ = gosock.NewTmpSock(teaconst.ProcessName).Close()
+
+ // 重新启动
+ if DaemonIsOn && DaemonPid == os.Getppid() {
+ os.Exit(0)
+ } else {
+ // 启动
+ var exe = filepath.Dir(this.exe) + "/" + teaconst.ProcessName
+
+ log.Println("[UPGRADE_MANAGER]restarting ...", exe)
+ cmd := exec.Command(exe, "start")
+ err := cmd.Start()
+ if err != nil {
+ return err
+ }
+
+ // 退出当前进程
+ time.Sleep(1 * time.Second)
+ os.Exit(0)
+ }
+ return nil
+}
diff --git a/EdgeHttpDNS/internal/rpc/rpc_client.go b/EdgeHttpDNS/internal/rpc/rpc_client.go
new file mode 100644
index 0000000..52d76c1
--- /dev/null
+++ b/EdgeHttpDNS/internal/rpc/rpc_client.go
@@ -0,0 +1,222 @@
+package rpc
+
+import (
+ "context"
+ "crypto/tls"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "net/url"
+ "sync"
+ "time"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/configs"
+ teaconst "github.com/TeaOSLab/EdgeHttpDNS/internal/const"
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/encrypt"
+ "github.com/iwind/TeaGo/maps"
+ "github.com/iwind/TeaGo/rands"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/connectivity"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/credentials/insecure"
+ "google.golang.org/grpc/encoding/gzip"
+ "google.golang.org/grpc/keepalive"
+ "google.golang.org/grpc/metadata"
+ "sync/atomic"
+)
+
+
+type RPCClient struct {
+ apiConfig *configs.APIConfig
+ conns []*grpc.ClientConn
+ locker sync.RWMutex
+
+ NodeTaskRPC pb.NodeTaskServiceClient
+ HTTPDNSNodeRPC pb.HTTPDNSNodeServiceClient
+ HTTPDNSClusterRPC pb.HTTPDNSClusterServiceClient
+ HTTPDNSAppRPC pb.HTTPDNSAppServiceClient
+ HTTPDNSDomainRPC pb.HTTPDNSDomainServiceClient
+ HTTPDNSRuleRPC pb.HTTPDNSRuleServiceClient
+ HTTPDNSRuntimeLogRPC pb.HTTPDNSRuntimeLogServiceClient
+ HTTPDNSAccessLogRPC pb.HTTPDNSAccessLogServiceClient
+ HTTPDNSSandboxRPC pb.HTTPDNSSandboxServiceClient
+
+ totalRequests int64
+ failedRequests int64
+ totalCostMs int64
+}
+
+
+func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) {
+ if apiConfig == nil {
+ return nil, errors.New("api config should not be nil")
+ }
+
+ client := &RPCClient{apiConfig: apiConfig}
+ client.NodeTaskRPC = pb.NewNodeTaskServiceClient(client)
+ client.HTTPDNSNodeRPC = pb.NewHTTPDNSNodeServiceClient(client)
+ client.HTTPDNSClusterRPC = pb.NewHTTPDNSClusterServiceClient(client)
+ client.HTTPDNSAppRPC = pb.NewHTTPDNSAppServiceClient(client)
+ client.HTTPDNSDomainRPC = pb.NewHTTPDNSDomainServiceClient(client)
+ client.HTTPDNSRuleRPC = pb.NewHTTPDNSRuleServiceClient(client)
+ client.HTTPDNSRuntimeLogRPC = pb.NewHTTPDNSRuntimeLogServiceClient(client)
+ client.HTTPDNSAccessLogRPC = pb.NewHTTPDNSAccessLogServiceClient(client)
+ client.HTTPDNSSandboxRPC = pb.NewHTTPDNSSandboxServiceClient(client)
+
+ err := client.init()
+ if err != nil {
+ return nil, err
+ }
+ return client, nil
+}
+
+func (c *RPCClient) Context() context.Context {
+ ctx := context.Background()
+ payload := maps.Map{
+ "timestamp": time.Now().Unix(),
+ "type": "httpdns",
+ "userId": 0,
+ }
+
+ method, err := encrypt.NewMethodInstance(teaconst.EncryptMethod, c.apiConfig.Secret, c.apiConfig.NodeId)
+ if err != nil {
+ return context.Background()
+ }
+ encrypted, err := method.Encrypt(payload.AsJSON())
+ if err != nil {
+ return context.Background()
+ }
+
+ token := base64.StdEncoding.EncodeToString(encrypted)
+ return metadata.AppendToOutgoingContext(ctx, "nodeId", c.apiConfig.NodeId, "token", token)
+}
+
+func (c *RPCClient) UpdateConfig(config *configs.APIConfig) error {
+ c.apiConfig = config
+ c.locker.Lock()
+ defer c.locker.Unlock()
+ return c.init()
+}
+
+func (c *RPCClient) init() error {
+ conns := []*grpc.ClientConn{}
+ for _, endpoint := range c.apiConfig.RPCEndpoints {
+ u, err := url.Parse(endpoint)
+ if err != nil {
+ return fmt.Errorf("parse endpoint failed: %w", err)
+ }
+
+ var conn *grpc.ClientConn
+ callOptions := grpc.WithDefaultCallOptions(
+ grpc.MaxCallRecvMsgSize(128<<20),
+ grpc.MaxCallSendMsgSize(128<<20),
+ grpc.UseCompressor(gzip.Name),
+ )
+ keepaliveParams := grpc.WithKeepaliveParams(keepalive.ClientParameters{
+ Time: 30 * time.Second,
+ })
+
+ if u.Scheme == "http" {
+ conn, err = grpc.Dial(u.Host, grpc.WithTransportCredentials(insecure.NewCredentials()), callOptions, keepaliveParams)
+ } else if u.Scheme == "https" {
+ conn, err = grpc.Dial(u.Host, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
+ InsecureSkipVerify: true,
+ })), callOptions, keepaliveParams)
+ } else {
+ return errors.New("invalid endpoint scheme '" + u.Scheme + "'")
+ }
+ if err != nil {
+ return err
+ }
+ conns = append(conns, conn)
+ }
+
+ if len(conns) == 0 {
+ return errors.New("no available rpc endpoints")
+ }
+
+ c.conns = conns
+ return nil
+}
+
+func (c *RPCClient) pickConn() *grpc.ClientConn {
+ c.locker.RLock()
+ defer c.locker.RUnlock()
+
+ countConns := len(c.conns)
+ if countConns == 0 {
+ return nil
+ }
+ if countConns == 1 {
+ return c.conns[0]
+ }
+
+ for _, state := range []connectivity.State{
+ connectivity.Ready,
+ connectivity.Idle,
+ connectivity.Connecting,
+ connectivity.TransientFailure,
+ } {
+ available := []*grpc.ClientConn{}
+ for _, conn := range c.conns {
+ if conn.GetState() == state {
+ available = append(available, conn)
+ }
+ }
+ if len(available) > 0 {
+ return c.randConn(available)
+ }
+ }
+
+ return c.randConn(c.conns)
+}
+
+func (c *RPCClient) randConn(conns []*grpc.ClientConn) *grpc.ClientConn {
+ l := len(conns)
+ if l == 0 {
+ return nil
+ }
+ if l == 1 {
+ return conns[0]
+ }
+ return conns[rands.Int(0, l-1)]
+}
+
+func (c *RPCClient) Invoke(ctx context.Context, method string, args interface{}, reply interface{}, opts ...grpc.CallOption) error {
+ conn := c.pickConn()
+ if conn == nil {
+ return errors.New("can not get available grpc connection")
+ }
+
+ atomic.AddInt64(&c.totalRequests, 1)
+ start := time.Now()
+ err := conn.Invoke(ctx, method, args, reply, opts...)
+ costMs := time.Since(start).Milliseconds()
+ atomic.AddInt64(&c.totalCostMs, costMs)
+
+ if err != nil {
+ atomic.AddInt64(&c.failedRequests, 1)
+ }
+ return err
+}
+
+func (c *RPCClient) GetAndResetMetrics() (total int64, failed int64, avgCostSeconds float64) {
+ total = atomic.SwapInt64(&c.totalRequests, 0)
+ failed = atomic.SwapInt64(&c.failedRequests, 0)
+ costMs := atomic.SwapInt64(&c.totalCostMs, 0)
+
+ if total > 0 {
+ avgCostSeconds = float64(costMs) / float64(total) / 1000.0
+ }
+ return
+}
+
+
+func (c *RPCClient) NewStream(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+ conn := c.pickConn()
+ if conn == nil {
+ return nil, errors.New("can not get available grpc connection")
+ }
+ return conn.NewStream(ctx, desc, method, opts...)
+}
diff --git a/EdgeHttpDNS/internal/rpc/shared.go b/EdgeHttpDNS/internal/rpc/shared.go
new file mode 100644
index 0000000..bff809e
--- /dev/null
+++ b/EdgeHttpDNS/internal/rpc/shared.go
@@ -0,0 +1,31 @@
+package rpc
+
+import (
+ "sync"
+
+ "github.com/TeaOSLab/EdgeHttpDNS/internal/configs"
+)
+
+var sharedRPCClient *RPCClient
+var sharedLocker sync.Mutex
+
+func SharedRPC() (*RPCClient, error) {
+ sharedLocker.Lock()
+ defer sharedLocker.Unlock()
+
+ config, err := configs.SharedAPIConfig()
+ if err != nil {
+ return nil, err
+ }
+
+ if sharedRPCClient == nil {
+ client, err := NewRPCClient(config)
+ if err != nil {
+ return nil, err
+ }
+ sharedRPCClient = client
+ return sharedRPCClient, nil
+ }
+
+ return sharedRPCClient, nil
+}
diff --git a/EdgeHttpDNS/internal/utils/exec/cmd.go b/EdgeHttpDNS/internal/utils/exec/cmd.go
new file mode 100644
index 0000000..f1a4178
--- /dev/null
+++ b/EdgeHttpDNS/internal/utils/exec/cmd.go
@@ -0,0 +1,160 @@
+package executils
+
+import (
+ "bytes"
+ "context"
+ "os"
+ "os/exec"
+ "strings"
+ "time"
+)
+
+type Cmd struct {
+ name string
+ args []string
+ env []string
+ dir string
+
+ ctx context.Context
+ timeout time.Duration
+ cancelFunc func()
+
+ captureStdout bool
+ captureStderr bool
+
+ stdout *bytes.Buffer
+ stderr *bytes.Buffer
+
+ rawCmd *exec.Cmd
+}
+
+func NewCmd(name string, args ...string) *Cmd {
+ return &Cmd{
+ name: name,
+ args: args,
+ }
+}
+
+func NewTimeoutCmd(timeout time.Duration, name string, args ...string) *Cmd {
+ return (&Cmd{
+ name: name,
+ args: args,
+ }).WithTimeout(timeout)
+}
+
+func (this *Cmd) WithTimeout(timeout time.Duration) *Cmd {
+ this.timeout = timeout
+
+ ctx, cancelFunc := context.WithTimeout(context.Background(), timeout)
+ this.ctx = ctx
+ this.cancelFunc = cancelFunc
+
+ return this
+}
+
+func (this *Cmd) WithStdout() *Cmd {
+ this.captureStdout = true
+ return this
+}
+
+func (this *Cmd) WithStderr() *Cmd {
+ this.captureStderr = true
+ return this
+}
+
+func (this *Cmd) WithEnv(env []string) *Cmd {
+ this.env = env
+ return this
+}
+
+func (this *Cmd) WithDir(dir string) *Cmd {
+ this.dir = dir
+ return this
+}
+
+func (this *Cmd) Start() error {
+ var cmd = this.compose()
+ return cmd.Start()
+}
+
+func (this *Cmd) Wait() error {
+ var cmd = this.compose()
+ return cmd.Wait()
+}
+
+func (this *Cmd) Run() error {
+ if this.cancelFunc != nil {
+ defer this.cancelFunc()
+ }
+
+ var cmd = this.compose()
+ return cmd.Run()
+}
+
+func (this *Cmd) RawStdout() string {
+ if this.stdout != nil {
+ return this.stdout.String()
+ }
+ return ""
+}
+
+func (this *Cmd) Stdout() string {
+ return strings.TrimSpace(this.RawStdout())
+}
+
+func (this *Cmd) RawStderr() string {
+ if this.stderr != nil {
+ return this.stderr.String()
+ }
+ return ""
+}
+
+func (this *Cmd) Stderr() string {
+ return strings.TrimSpace(this.RawStderr())
+}
+
+func (this *Cmd) String() string {
+ if this.rawCmd != nil {
+ return this.rawCmd.String()
+ }
+ var newCmd = exec.Command(this.name, this.args...)
+ return newCmd.String()
+}
+
+func (this *Cmd) Process() *os.Process {
+ if this.rawCmd != nil {
+ return this.rawCmd.Process
+ }
+ return nil
+}
+
+func (this *Cmd) compose() *exec.Cmd {
+ if this.rawCmd != nil {
+ return this.rawCmd
+ }
+
+ if this.ctx != nil {
+ this.rawCmd = exec.CommandContext(this.ctx, this.name, this.args...)
+ } else {
+ this.rawCmd = exec.Command(this.name, this.args...)
+ }
+
+ if this.env != nil {
+ this.rawCmd.Env = this.env
+ }
+
+ if len(this.dir) > 0 {
+ this.rawCmd.Dir = this.dir
+ }
+
+ if this.captureStdout {
+ this.stdout = &bytes.Buffer{}
+ this.rawCmd.Stdout = this.stdout
+ }
+ if this.captureStderr {
+ this.stderr = &bytes.Buffer{}
+ this.rawCmd.Stderr = this.stderr
+ }
+
+ return this.rawCmd
+}
diff --git a/EdgeHttpDNS/internal/utils/exec/look_linux.go b/EdgeHttpDNS/internal/utils/exec/look_linux.go
new file mode 100644
index 0000000..e65cb42
--- /dev/null
+++ b/EdgeHttpDNS/internal/utils/exec/look_linux.go
@@ -0,0 +1,57 @@
+//go:build linux
+
+package executils
+
+import (
+ "golang.org/x/sys/unix"
+ "io/fs"
+ "os"
+ "os/exec"
+ "syscall"
+)
+
+// LookPath customize our LookPath() function, to work in broken $PATH environment variable
+func LookPath(file string) (string, error) {
+ result, err := exec.LookPath(file)
+ if err == nil && len(result) > 0 {
+ return result, nil
+ }
+
+ // add common dirs contains executable files these may be excluded in $PATH environment variable
+ var binPaths = []string{
+ "/usr/sbin",
+ "/usr/bin",
+ "/usr/local/sbin",
+ "/usr/local/bin",
+ }
+
+ for _, binPath := range binPaths {
+ var fullPath = binPath + string(os.PathSeparator) + file
+
+ stat, err := os.Stat(fullPath)
+ if err != nil {
+ continue
+ }
+ if stat.IsDir() {
+ return "", syscall.EISDIR
+ }
+
+ var mode = stat.Mode()
+ if mode.IsDir() {
+ return "", syscall.EISDIR
+ }
+ err = syscall.Faccessat(unix.AT_FDCWD, fullPath, unix.X_OK, unix.AT_EACCESS)
+ if err == nil || (err != syscall.ENOSYS && err != syscall.EPERM) {
+ return fullPath, err
+ }
+ if mode&0111 != 0 {
+ return fullPath, nil
+ }
+ return "", fs.ErrPermission
+ }
+
+ return "", &exec.Error{
+ Name: file,
+ Err: exec.ErrNotFound,
+ }
+}
diff --git a/EdgeHttpDNS/internal/utils/exec/look_others.go b/EdgeHttpDNS/internal/utils/exec/look_others.go
new file mode 100644
index 0000000..17132a0
--- /dev/null
+++ b/EdgeHttpDNS/internal/utils/exec/look_others.go
@@ -0,0 +1,9 @@
+//go:build !linux
+
+package executils
+
+import "os/exec"
+
+func LookPath(file string) (string, error) {
+ return exec.LookPath(file)
+}
diff --git a/EdgeHttpDNS/internal/utils/ip.go b/EdgeHttpDNS/internal/utils/ip.go
new file mode 100644
index 0000000..88ea3c9
--- /dev/null
+++ b/EdgeHttpDNS/internal/utils/ip.go
@@ -0,0 +1,18 @@
+package utils
+
+import (
+ "encoding/binary"
+ "net"
+)
+
+func IP2Long(ip string) uint32 {
+ s := net.ParseIP(ip)
+ if s == nil {
+ return 0
+ }
+
+ if len(s) == 16 {
+ return binary.BigEndian.Uint32(s[12:16])
+ }
+ return binary.BigEndian.Uint32(s)
+}
diff --git a/EdgeHttpDNS/internal/utils/service.go b/EdgeHttpDNS/internal/utils/service.go
new file mode 100644
index 0000000..2435036
--- /dev/null
+++ b/EdgeHttpDNS/internal/utils/service.go
@@ -0,0 +1,46 @@
+package utils
+
+import (
+ "os"
+ "path/filepath"
+ "sync"
+
+ "github.com/iwind/TeaGo/Tea"
+)
+
+type ServiceManager struct {
+ Name string
+ Description string
+
+ onceLocker sync.Once
+}
+
+func NewServiceManager(name, description string) *ServiceManager {
+ manager := &ServiceManager{
+ Name: name,
+ Description: description,
+ }
+ manager.resetRoot()
+ return manager
+}
+
+func (m *ServiceManager) setup() {
+ m.onceLocker.Do(func() {})
+}
+
+func (m *ServiceManager) resetRoot() {
+ if !Tea.IsTesting() {
+ exePath, err := os.Executable()
+ if err != nil {
+ exePath = os.Args[0]
+ }
+ link, err := filepath.EvalSymlinks(exePath)
+ if err == nil {
+ exePath = link
+ }
+ fullPath, err := filepath.Abs(exePath)
+ if err == nil {
+ Tea.UpdateRoot(filepath.Dir(filepath.Dir(fullPath)))
+ }
+ }
+}
diff --git a/EdgeHttpDNS/internal/utils/service_linux.go b/EdgeHttpDNS/internal/utils/service_linux.go
new file mode 100644
index 0000000..3a392a4
--- /dev/null
+++ b/EdgeHttpDNS/internal/utils/service_linux.go
@@ -0,0 +1,215 @@
+//go:build linux
+// +build linux
+
+package utils
+
+import (
+ "errors"
+ "os"
+ "time"
+
+ teaconst "github.com/TeaOSLab/EdgeHttpDNS/internal/const"
+ executils "github.com/TeaOSLab/EdgeHttpDNS/internal/utils/exec"
+ "github.com/iwind/TeaGo/Tea"
+)
+
+var systemdServiceFile = "/etc/systemd/system/" + teaconst.SystemdServiceName + ".service"
+var initServiceFile = "/etc/init.d/" + teaconst.SystemdServiceName
+
+// Install 安装系统服务
+func (m *ServiceManager) Install(exePath string, args []string) error {
+ if os.Getgid() != 0 {
+ return errors.New("only root users can install the service")
+ }
+
+ systemd, err := executils.LookPath("systemctl")
+ if err != nil {
+ // systemd 不可用,降级到 init.d
+ return m.installInitService(exePath, args)
+ }
+
+ return m.installSystemdService(systemd, exePath, args)
+}
+
+// Start 启动服务
+func (m *ServiceManager) Start() error {
+ if os.Getgid() != 0 {
+ return errors.New("only root users can start the service")
+ }
+
+ // 优先检查 systemd
+ if fileExists(systemdServiceFile) {
+ systemd, err := executils.LookPath("systemctl")
+ if err != nil {
+ return err
+ }
+ return executils.NewTimeoutCmd(10*time.Second, systemd, "start", teaconst.SystemdServiceName+".service").Start()
+ }
+
+ // 降级到 init.d
+ if fileExists(initServiceFile) {
+ return executils.NewTimeoutCmd(10*time.Second, "service", teaconst.ProcessName, "start").Start()
+ }
+
+ return errors.New("no service file found, please install the service first")
+}
+
+// Uninstall 删除服务
+func (m *ServiceManager) Uninstall() error {
+ if os.Getgid() != 0 {
+ return errors.New("only root users can uninstall the service")
+ }
+
+ // systemd
+ if fileExists(systemdServiceFile) {
+ systemd, err := executils.LookPath("systemctl")
+ if err == nil {
+ _ = executils.NewTimeoutCmd(10*time.Second, systemd, "stop", teaconst.SystemdServiceName+".service").Run()
+ _ = executils.NewTimeoutCmd(10*time.Second, systemd, "disable", teaconst.SystemdServiceName+".service").Run()
+ _ = executils.NewTimeoutCmd(10*time.Second, systemd, "daemon-reload").Run()
+ }
+ return os.Remove(systemdServiceFile)
+ }
+
+ // init.d
+ if fileExists(initServiceFile) {
+ _ = executils.NewTimeoutCmd(10*time.Second, "service", teaconst.ProcessName, "stop").Run()
+ chkCmd, err := executils.LookPath("chkconfig")
+ if err == nil {
+ _ = executils.NewTimeoutCmd(10*time.Second, chkCmd, "--del", teaconst.ProcessName).Run()
+ }
+ return os.Remove(initServiceFile)
+ }
+
+ return nil
+}
+
+// installSystemdService 安装 systemd 服务
+func (m *ServiceManager) installSystemdService(systemd, exePath string, args []string) error {
+ shortName := teaconst.SystemdServiceName
+ longName := "GoEdge HTTPDNS"
+
+ // 用 bash 包装启动命令,兼容路径含空格的场景
+ var startCmd = exePath + " daemon"
+ bashPath, _ := executils.LookPath("bash")
+ if len(bashPath) > 0 {
+ startCmd = bashPath + " -c \"" + startCmd + "\""
+ }
+
+ desc := `### BEGIN INIT INFO
+# Provides: ` + shortName + `
+# Required-Start: $all
+# Required-Stop:
+# Default-Start: 2 3 4 5
+# Default-Stop:
+# Short-Description: ` + longName + ` Service
+### END INIT INFO
+
+[Unit]
+Description=` + longName + ` Node Service
+Before=shutdown.target
+After=network-online.target
+
+[Service]
+Type=simple
+Restart=always
+RestartSec=1s
+ExecStart=` + startCmd + `
+ExecStop=` + exePath + ` stop
+ExecReload=` + exePath + ` restart
+
+[Install]
+WantedBy=multi-user.target`
+
+ // 权限 0644,systemd 单元文件不需要执行权限
+ err := os.WriteFile(systemdServiceFile, []byte(desc), 0644)
+ if err != nil {
+ return err
+ }
+
+ // 停止已有服务
+ _ = executils.NewTimeoutCmd(10*time.Second, systemd, "stop", shortName+".service").Run()
+
+ // 重新加载
+ _ = executils.NewTimeoutCmd(10*time.Second, systemd, "daemon-reload").Run()
+
+ // 启用开机自启
+ return executils.NewTimeoutCmd(10*time.Second, systemd, "enable", shortName+".service").Run()
+}
+
+// installInitService 安装 init.d 服务(降级方案,适用于无 systemd 的旧系统)
+func (m *ServiceManager) installInitService(exePath string, args []string) error {
+ shortName := teaconst.SystemdServiceName
+ longName := "GoEdge HTTPDNS"
+
+ // 生成 init.d 脚本
+ script := `#!/bin/bash
+### BEGIN INIT INFO
+# Provides: ` + shortName + `
+# Required-Start: $all
+# Required-Stop:
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: ` + longName + ` Service
+### END INIT INFO
+
+INSTALL_DIR=` + Tea.Root + `
+
+case "$1" in
+start)
+ cd "${INSTALL_DIR}"
+ ` + exePath + ` daemon &
+ echo "` + longName + ` started"
+ ;;
+stop)
+ cd "${INSTALL_DIR}"
+ ` + exePath + ` stop
+ echo "` + longName + ` stopped"
+ ;;
+restart)
+ cd "${INSTALL_DIR}"
+ ` + exePath + ` stop
+ sleep 1
+ ` + exePath + ` daemon &
+ echo "` + longName + ` restarted"
+ ;;
+status)
+ cd "${INSTALL_DIR}"
+ ` + exePath + ` status
+ ;;
+*)
+ echo "Usage: $0 {start|stop|restart|status}"
+ exit 1
+ ;;
+esac
+exit 0
+`
+
+ // init.d 脚本需要执行权限
+ err := os.WriteFile(initServiceFile, []byte(script), 0755)
+ if err != nil {
+ return err
+ }
+
+ // 尝试用 chkconfig 注册(CentOS/RHEL)
+ chkCmd, err := executils.LookPath("chkconfig")
+ if err == nil {
+ _ = executils.NewTimeoutCmd(10*time.Second, chkCmd, "--add", teaconst.ProcessName).Run()
+ return nil
+ }
+
+ // 尝试用 update-rc.d 注册(Debian/Ubuntu)
+ updateRcCmd, err := executils.LookPath("update-rc.d")
+ if err == nil {
+ _ = executils.NewTimeoutCmd(10*time.Second, updateRcCmd, teaconst.ProcessName, "defaults").Run()
+ return nil
+ }
+
+ return nil
+}
+
+// fileExists 检查文件是否存在
+func fileExists(path string) bool {
+ _, err := os.Stat(path)
+ return err == nil
+}
diff --git a/EdgeHttpDNS/internal/utils/service_others.go b/EdgeHttpDNS/internal/utils/service_others.go
new file mode 100644
index 0000000..e42b43c
--- /dev/null
+++ b/EdgeHttpDNS/internal/utils/service_others.go
@@ -0,0 +1,14 @@
+//go:build !linux
+// +build !linux
+
+package utils
+
+import "errors"
+
+func (m *ServiceManager) Install(exePath string, args []string) error {
+ return errors.New("service install is only supported on linux in this version")
+}
+
+func (m *ServiceManager) Uninstall() error {
+ return errors.New("service uninstall is only supported on linux in this version")
+}
diff --git a/EdgeHttpDNS/internal/utils/unzip.go b/EdgeHttpDNS/internal/utils/unzip.go
new file mode 100644
index 0000000..95e4bdb
--- /dev/null
+++ b/EdgeHttpDNS/internal/utils/unzip.go
@@ -0,0 +1,98 @@
+package utils
+
+import (
+ "archive/zip"
+ "errors"
+ "io"
+ "os"
+ "strings"
+)
+
+type Unzip struct {
+ zipFile string
+ targetDir string
+ stripPrefix string
+}
+
+func NewUnzip(zipFile string, targetDir string, stripPrefix string) *Unzip {
+ return &Unzip{
+ zipFile: zipFile,
+ targetDir: targetDir,
+ stripPrefix: stripPrefix,
+ }
+}
+
+func (this *Unzip) Run() error {
+ if len(this.zipFile) == 0 {
+ return errors.New("zip file should not be empty")
+ }
+ if len(this.targetDir) == 0 {
+ return errors.New("target dir should not be empty")
+ }
+
+ reader, err := zip.OpenReader(this.zipFile)
+ if err != nil {
+ return err
+ }
+
+ defer func() {
+ _ = reader.Close()
+ }()
+
+ for _, file := range reader.File {
+ info := file.FileInfo()
+ filename := file.Name
+ if len(this.stripPrefix) > 0 {
+ filename = strings.TrimPrefix(filename, this.stripPrefix)
+ }
+ target := this.targetDir + "/" + filename
+
+ // 目录
+ if info.IsDir() {
+ stat, err := os.Stat(target)
+ if err != nil {
+ if !os.IsNotExist(err) {
+ return err
+ } else {
+ err = os.MkdirAll(target, info.Mode())
+ if err != nil {
+ return err
+ }
+ }
+ } else if !stat.IsDir() {
+ err = os.MkdirAll(target, info.Mode())
+ if err != nil {
+ return err
+ }
+ }
+ continue
+ }
+
+ // 文件
+ err := func(file *zip.File, target string) error {
+ fileReader, err := file.Open()
+ if err != nil {
+ return err
+ }
+ defer func() {
+ _ = fileReader.Close()
+ }()
+
+ fileWriter, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, file.FileInfo().Mode())
+ if err != nil {
+ return err
+ }
+ defer func() {
+ _ = fileWriter.Close()
+ }()
+
+ _, err = io.Copy(fileWriter, fileReader)
+ return err
+ }(file, target)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/EdgeHttpDNS/internal/utils/version.go b/EdgeHttpDNS/internal/utils/version.go
new file mode 100644
index 0000000..0e28897
--- /dev/null
+++ b/EdgeHttpDNS/internal/utils/version.go
@@ -0,0 +1,15 @@
+package utils
+
+import "strings"
+
+func VersionToLong(version string) uint32 {
+ countDots := strings.Count(version, ".")
+ if countDots == 2 {
+ version += ".0"
+ } else if countDots == 1 {
+ version += ".0.0"
+ } else if countDots == 0 {
+ version += ".0.0.0"
+ }
+ return IP2Long(version)
+}
diff --git a/EdgeNode/internal/const/const.go b/EdgeNode/internal/const/const.go
index 73081fb..ae07326 100644
--- a/EdgeNode/internal/const/const.go
+++ b/EdgeNode/internal/const/const.go
@@ -1,7 +1,7 @@
package teaconst
const (
- Version = "1.4.7" //1.3.8.2
+ Version = "1.4.9" //1.3.8.2
ProductName = "Edge Node"
ProcessName = "edge-node"
diff --git a/EdgePlus/pkg/utils/edition.go b/EdgePlus/pkg/utils/edition.go
index c3e540a..30a2819 100644
--- a/EdgePlus/pkg/utils/edition.go
+++ b/EdgePlus/pkg/utils/edition.go
@@ -17,7 +17,7 @@ func FindAllEditions() []*EditionDefinition {
MaxNodes: 20,
},
{
- Name: "专业版",
+ Name: "商业版",
Code: EditionPro,
MaxNodes: 100,
},
diff --git a/EdgeUser/internal/const/const.go b/EdgeUser/internal/const/const.go
index 9adfbef..d085702 100644
--- a/EdgeUser/internal/const/const.go
+++ b/EdgeUser/internal/const/const.go
@@ -1,7 +1,7 @@
package teaconst
const (
- Version = "1.4.7" //1.3.8.2
+ Version = "1.4.9" //1.3.8.2
ProductName = "Edge User"
ProcessName = "edge-user"
diff --git a/EdgeUser/internal/rpc/rpc_client.go b/EdgeUser/internal/rpc/rpc_client.go
index 2dfbdb4..028eea2 100644
--- a/EdgeUser/internal/rpc/rpc_client.go
+++ b/EdgeUser/internal/rpc/rpc_client.go
@@ -420,6 +420,34 @@ func (this *RPCClient) NSPlanRPC() pb.NSPlanServiceClient {
return pb.NewNSPlanServiceClient(this.pickConn())
}
+func (this *RPCClient) HTTPDNSClusterRPC() pb.HTTPDNSClusterServiceClient {
+ return pb.NewHTTPDNSClusterServiceClient(this.pickConn())
+}
+
+func (this *RPCClient) HTTPDNSNodeRPC() pb.HTTPDNSNodeServiceClient {
+ return pb.NewHTTPDNSNodeServiceClient(this.pickConn())
+}
+
+func (this *RPCClient) HTTPDNSAppRPC() pb.HTTPDNSAppServiceClient {
+ return pb.NewHTTPDNSAppServiceClient(this.pickConn())
+}
+
+func (this *RPCClient) HTTPDNSDomainRPC() pb.HTTPDNSDomainServiceClient {
+ return pb.NewHTTPDNSDomainServiceClient(this.pickConn())
+}
+
+func (this *RPCClient) HTTPDNSRuleRPC() pb.HTTPDNSRuleServiceClient {
+ return pb.NewHTTPDNSRuleServiceClient(this.pickConn())
+}
+
+func (this *RPCClient) HTTPDNSAccessLogRPC() pb.HTTPDNSAccessLogServiceClient {
+ return pb.NewHTTPDNSAccessLogServiceClient(this.pickConn())
+}
+
+func (this *RPCClient) HTTPDNSSandboxRPC() pb.HTTPDNSSandboxServiceClient {
+ return pb.NewHTTPDNSSandboxServiceClient(this.pickConn())
+}
+
func (this *RPCClient) ServerBandwidthStatRPC() pb.ServerBandwidthStatServiceClient {
return pb.NewServerBandwidthStatServiceClient(this.pickConn())
}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/addPortPopup.go b/EdgeUser/internal/web/actions/default/httpdns/addPortPopup.go
new file mode 100644
index 0000000..c533db3
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/addPortPopup.go
@@ -0,0 +1,123 @@
+package httpdns
+
+import (
+ "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/iwind/TeaGo/actions"
+ "github.com/iwind/TeaGo/maps"
+ "github.com/iwind/TeaGo/types"
+ "regexp"
+ "strings"
+)
+
+type AddPortPopupAction struct {
+ actionutils.ParentAction
+}
+
+func (this *AddPortPopupAction) Init() {
+ this.Nav("", "", "")
+}
+
+func (this *AddPortPopupAction) RunGet(params struct {
+ Protocol string
+ From string
+ SupportRange bool
+}) {
+ this.Data["from"] = params.From
+
+ var protocols = serverconfigs.FindAllServerProtocols()
+ if len(params.Protocol) > 0 {
+ result := []maps.Map{}
+ for _, p := range protocols {
+ if p.GetString("code") == params.Protocol {
+ result = append(result, p)
+ }
+ }
+ protocols = result
+ }
+ this.Data["protocols"] = protocols
+
+ this.Data["supportRange"] = params.SupportRange
+
+ this.Show()
+}
+
+func (this *AddPortPopupAction) RunPost(params struct {
+ SupportRange bool
+
+ Protocol string
+ Address string
+
+ Must *actions.Must
+}) {
+ // 鏍¢獙鍦板潃
+ var addr = maps.Map{
+ "protocol": params.Protocol,
+ "host": "",
+ "portRange": "",
+ "minPort": 0,
+ "maxPort": 0,
+ }
+
+ var portRegexp = regexp.MustCompile(`^\d+$`)
+ if portRegexp.MatchString(params.Address) { // 鍗曚釜绔彛
+ addr["portRange"] = this.checkPort(params.Address)
+ } else if params.SupportRange && regexp.MustCompile(`^\d+\s*-\s*\d+$`).MatchString(params.Address) { // Port1-Port2
+ addr["portRange"], addr["minPort"], addr["maxPort"] = this.checkPortRange(params.Address)
+ } else if strings.Contains(params.Address, ":") { // IP:Port
+ index := strings.LastIndex(params.Address, ":")
+ addr["host"] = strings.TrimSpace(params.Address[:index])
+ port := strings.TrimSpace(params.Address[index+1:])
+ if portRegexp.MatchString(port) {
+ addr["portRange"] = this.checkPort(port)
+ } else if params.SupportRange && regexp.MustCompile(`^\d+\s*-\s*\d+$`).MatchString(port) { // Port1-Port2
+ addr["portRange"], addr["minPort"], addr["maxPort"] = this.checkPortRange(port)
+ } else {
+ this.FailField("address", "璇疯緭鍏ユ纭殑绔彛鎴栬€呯綉缁滃湴鍧€")
+ }
+ } else {
+ this.FailField("address", "璇疯緭鍏ユ纭殑绔彛鎴栬€呯綉缁滃湴鍧€")
+ }
+
+ this.Data["address"] = addr
+ this.Success()
+}
+
+func (this *AddPortPopupAction) checkPort(port string) (portRange string) {
+ var intPort = types.Int(port)
+ if intPort < 1 {
+ this.FailField("address", "绔彛鍙蜂笉鑳藉皬浜?")
+ }
+ if intPort > 65535 {
+ this.FailField("address", "绔彛鍙蜂笉鑳藉ぇ浜?5535")
+ }
+ return port
+}
+
+func (this *AddPortPopupAction) checkPortRange(port string) (portRange string, minPort int, maxPort int) {
+ var pieces = strings.Split(port, "-")
+ var piece1 = strings.TrimSpace(pieces[0])
+ var piece2 = strings.TrimSpace(pieces[1])
+ var port1 = types.Int(piece1)
+ var port2 = types.Int(piece2)
+
+ if port1 < 1 {
+ this.FailField("address", "绔彛鍙蜂笉鑳藉皬浜?")
+ }
+ if port1 > 65535 {
+ this.FailField("address", "绔彛鍙蜂笉鑳藉ぇ浜?5535")
+ }
+
+ if port2 < 1 {
+ this.FailField("address", "绔彛鍙蜂笉鑳藉皬浜?")
+ }
+ if port2 > 65535 {
+ this.FailField("address", "绔彛鍙蜂笉鑳藉ぇ浜?5535")
+ }
+
+ if port1 > port2 {
+ port1, port2 = port2, port1
+ }
+
+ return types.String(port1) + "-" + types.String(port2), port1, port2
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/app.go b/EdgeUser/internal/web/actions/default/httpdns/apps/app.go
new file mode 100644
index 0000000..86bc071
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/app.go
@@ -0,0 +1,26 @@
+package apps
+
+import (
+ "strconv"
+
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+)
+
+type AppAction struct {
+ actionutils.ParentAction
+}
+
+func (this *AppAction) Init() {
+ this.Nav("httpdns", "app", "")
+}
+
+func (this *AppAction) RunGet(params struct {
+ AppId int64
+}) {
+ app, err := findAppMap(this.Parent(), params.AppId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ this.RedirectURL("/httpdns/apps/domains?appId=" + strconv.FormatInt(app.GetInt64("id"), 10))
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/appSettings.go b/EdgeUser/internal/web/actions/default/httpdns/apps/appSettings.go
new file mode 100644
index 0000000..3e30df7
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/appSettings.go
@@ -0,0 +1,156 @@
+package apps
+import (
+ "encoding/json"
+ "strconv"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/httpdns/httpdnsutils"
+ "github.com/iwind/TeaGo/actions"
+ "github.com/iwind/TeaGo/maps"
+)
+
+type AppSettingsAction struct {
+ actionutils.ParentAction
+}
+
+func (this *AppSettingsAction) Init() {
+ this.Nav("httpdns", "app", "settings")
+}
+
+func (this *AppSettingsAction) RunGet(params struct {
+ AppId int64
+ Section string
+}) {
+ httpdnsutils.AddLeftMenu(this.Parent())
+
+ app, err := findAppMap(this.Parent(), params.AppId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ httpdnsutils.AddAppTabbar(this.Parent(), app.GetString("name"), app.GetInt64("id"), "settings")
+
+ section := params.Section
+ if len(section) == 0 {
+ section = "basic"
+ }
+ this.Data["activeSection"] = section
+
+ appIDStr := strconv.FormatInt(app.GetInt64("id"), 10)
+ this.Data["leftMenuItems"] = []maps.Map{
+ {
+ "name": "基础配置",
+ "url": "/httpdns/apps/app/settings?appId=" + appIDStr + "§ion=basic",
+ "isActive": section == "basic",
+ },
+ {
+ "name": "认证与密钥",
+ "url": "/httpdns/apps/app/settings?appId=" + appIDStr + "§ion=auth",
+ "isActive": section == "auth",
+ },
+ }
+
+ clusterResp, err := this.RPC().HTTPDNSClusterRPC().FindAllHTTPDNSClusters(this.UserContext(), &pb.FindAllHTTPDNSClustersRequest{})
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ clusterApiAddressMap := map[int64]string{}
+ clusterNameMap := map[int64]string{}
+ for _, cluster := range clusterResp.GetClusters() {
+ port := "443"
+ if rawTLS := cluster.GetTlsPolicyJSON(); len(rawTLS) > 0 {
+ var tlsConfig map[string]interface{}
+ if err := json.Unmarshal(rawTLS, &tlsConfig); err == nil {
+ if listenRaw, ok := tlsConfig["listen"]; ok && listenRaw != nil {
+ if data, err := json.Marshal(listenRaw); err == nil {
+ var listenAddresses []map[string]interface{}
+ if err := json.Unmarshal(data, &listenAddresses); err == nil {
+ if len(listenAddresses) > 0 {
+ if portRange, ok := listenAddresses[0]["portRange"].(string); ok && len(portRange) > 0 {
+ port = portRange
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ apiAddress := "https://" + cluster.GetServiceDomain() + ":" + port
+ clusterApiAddressMap[cluster.GetId()] = apiAddress
+ clusterNameMap[cluster.GetId()] = cluster.GetName()
+ }
+
+ // 读取应用绑定的集群列表
+ var clusterIds []int64
+ if raw := app.Get("clusterIds"); raw != nil {
+ if ids, ok := raw.([]int64); ok {
+ clusterIds = ids
+ }
+ }
+
+ // 构建服务地址列表
+ serviceAddresses := make([]maps.Map, 0)
+ for _, cid := range clusterIds {
+ addr := clusterApiAddressMap[cid]
+ name := clusterNameMap[cid]
+ if len(addr) > 0 {
+ serviceAddresses = append(serviceAddresses, maps.Map{
+ "address": addr,
+ "clusterName": name,
+ })
+ }
+ }
+
+ settings := maps.Map{
+ "appId": app.GetString("appId"),
+ "appStatus": app.GetBool("isOn"),
+ "serviceAddresses": serviceAddresses,
+ "signEnabled": app.GetBool("signEnabled"),
+ "signSecretPlain": app.GetString("signSecretPlain"),
+ "signSecretMasked": app.GetString("signSecretMasked"),
+ "signSecretUpdatedAt": app.GetString("signSecretUpdated"),
+ }
+ this.Data["app"] = app
+ this.Data["settings"] = settings
+ this.Show()
+}
+
+func (this *AppSettingsAction) RunPost(params struct {
+ AppId int64
+
+ AppStatus bool
+
+ Must *actions.Must
+ CSRF *actionutils.CSRF
+}) {
+ params.Must.Field("appId", params.AppId).Gt(0, "请选择应用")
+
+ appResp, err := this.RPC().HTTPDNSAppRPC().FindHTTPDNSApp(this.UserContext(), &pb.FindHTTPDNSAppRequest{
+ AppDbId: params.AppId,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ if appResp.GetApp() == nil {
+ this.Fail("找不到对应的应用")
+ return
+ }
+
+ _, err = this.RPC().HTTPDNSAppRPC().UpdateHTTPDNSApp(this.UserContext(), &pb.UpdateHTTPDNSAppRequest{
+ AppDbId: params.AppId,
+ Name: appResp.GetApp().GetName(),
+ ClusterIdsJSON: appResp.GetApp().GetClusterIdsJSON(),
+ IsOn: params.AppStatus,
+ UserId: appResp.GetApp().GetUserId(),
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ this.Success()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/appSettingsResetSignSecret.go b/EdgeUser/internal/web/actions/default/httpdns/apps/appSettingsResetSignSecret.go
new file mode 100644
index 0000000..c8eade0
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/appSettingsResetSignSecret.go
@@ -0,0 +1,29 @@
+package apps
+
+import (
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/iwind/TeaGo/actions"
+)
+
+type AppSettingsResetSignSecretAction struct {
+ actionutils.ParentAction
+}
+
+func (this *AppSettingsResetSignSecretAction) RunPost(params struct {
+ AppId int64
+
+ Must *actions.Must
+}) {
+ params.Must.Field("appId", params.AppId).Gt(0, "请选择应用")
+
+ _, err := this.RPC().HTTPDNSAppRPC().ResetHTTPDNSAppSignSecret(this.UserContext(), &pb.ResetHTTPDNSAppSignSecretRequest{
+ AppDbId: params.AppId,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ this.Success()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/appSettingsToggleSignEnabled.go b/EdgeUser/internal/web/actions/default/httpdns/apps/appSettingsToggleSignEnabled.go
new file mode 100644
index 0000000..89cdbcb
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/appSettingsToggleSignEnabled.go
@@ -0,0 +1,31 @@
+package apps
+
+import (
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/iwind/TeaGo/actions"
+)
+
+type AppSettingsToggleSignEnabledAction struct {
+ actionutils.ParentAction
+}
+
+func (this *AppSettingsToggleSignEnabledAction) RunPost(params struct {
+ AppId int64
+ IsOn int
+
+ Must *actions.Must
+}) {
+ params.Must.Field("appId", params.AppId).Gt(0, "请选择应用")
+
+ _, err := this.RPC().HTTPDNSAppRPC().UpdateHTTPDNSAppSignEnabled(this.UserContext(), &pb.UpdateHTTPDNSAppSignEnabledRequest{
+ AppDbId: params.AppId,
+ SignEnabled: params.IsOn == 1,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ this.Success()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/create.go b/EdgeUser/internal/web/actions/default/httpdns/apps/create.go
new file mode 100644
index 0000000..5dfee04
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/create.go
@@ -0,0 +1,45 @@
+package apps
+
+import (
+ "strconv"
+ "time"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/iwind/TeaGo/actions"
+)
+
+type CreateAction struct {
+ actionutils.ParentAction
+}
+
+func (this *CreateAction) Init() {
+ this.Nav("", "", "create")
+}
+
+func (this *CreateAction) RunGet(params struct{}) {
+ this.Show()
+}
+
+func (this *CreateAction) RunPost(params struct {
+ Name string
+
+ Must *actions.Must
+ CSRF *actionutils.CSRF
+}) {
+ params.Must.Field("name", params.Name).Require("请输入应用名称")
+
+ createResp, err := this.RPC().HTTPDNSAppRPC().CreateHTTPDNSApp(this.UserContext(), &pb.CreateHTTPDNSAppRequest{
+ Name: params.Name,
+ AppId: "app" + strconv.FormatInt(time.Now().UnixNano()%1_000_000_000_000, 36),
+ IsOn: true,
+ SignEnabled: true,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ this.Data["appId"] = createResp.GetAppDbId()
+ this.Success()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/customRecords.go b/EdgeUser/internal/web/actions/default/httpdns/apps/customRecords.go
new file mode 100644
index 0000000..e9a5d67
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/customRecords.go
@@ -0,0 +1,55 @@
+package apps
+
+import (
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/httpdns/httpdnsutils"
+ "github.com/iwind/TeaGo/maps"
+)
+
+type CustomRecordsAction struct {
+ actionutils.ParentAction
+}
+
+func (this *CustomRecordsAction) Init() {
+ this.Nav("httpdns", "app", "")
+}
+
+func (this *CustomRecordsAction) RunGet(params struct {
+ AppId int64
+ DomainId int64
+}) {
+ httpdnsutils.AddLeftMenu(this.Parent())
+
+ app, err := findAppMap(this.Parent(), params.AppId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ httpdnsutils.AddAppTabbar(this.Parent(), app.GetString("name"), app.GetInt64("id"), "domains")
+
+ domains, err := listDomainMaps(this.Parent(), app.GetInt64("id"), "")
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ domain := findDomainMap(domains, params.DomainId)
+
+ records := make([]maps.Map, 0)
+ if domain.GetInt64("id") > 0 {
+ records, err = listCustomRuleMaps(this.Parent(), domain.GetInt64("id"))
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ for _, record := range records {
+ record["domain"] = domain.GetString("name")
+ record["lineText"] = buildLineText(record)
+ record["recordValueText"] = buildRecordValueText(record)
+ }
+ }
+
+ this.Data["app"] = app
+ this.Data["domain"] = domain
+ this.Data["records"] = records
+ this.Show()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/customRecordsCreatePopup.go b/EdgeUser/internal/web/actions/default/httpdns/apps/customRecordsCreatePopup.go
new file mode 100644
index 0000000..07fa372
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/customRecordsCreatePopup.go
@@ -0,0 +1,263 @@
+package apps
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/iwind/TeaGo/actions"
+ "github.com/iwind/TeaGo/maps"
+)
+
+type CustomRecordsCreatePopupAction struct {
+ actionutils.ParentAction
+}
+
+func (this *CustomRecordsCreatePopupAction) Init() {
+ this.Nav("", "", "")
+}
+
+func (this *CustomRecordsCreatePopupAction) RunGet(params struct {
+ AppId int64
+ DomainId int64
+ RecordId int64
+}) {
+ app, err := findAppMap(this.Parent(), params.AppId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ domains, err := listDomainMaps(this.Parent(), app.GetInt64("id"), "")
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ domain := findDomainMap(domains, params.DomainId)
+
+ record := maps.Map{
+ "id": int64(0),
+ "domain": domain.GetString("name"),
+ "lineScope": "china",
+ "lineCarrier": "默认",
+ "lineRegion": "默认",
+ "lineProvince": "默认",
+ "lineContinent": "默认",
+ "lineCountry": "默认",
+ "ruleName": "",
+ "weightEnabled": false,
+ "ttl": 60,
+ "isOn": true,
+ "recordItemsJson": `[{"type":"A","value":"","weight":100}]`,
+ }
+
+ if params.RecordId > 0 && domain.GetInt64("id") > 0 {
+ rules, err := listCustomRuleMaps(this.Parent(), domain.GetInt64("id"))
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ for _, rule := range rules {
+ if rule.GetInt64("id") != params.RecordId {
+ continue
+ }
+ record["id"] = rule.GetInt64("id")
+ record["domain"] = domain.GetString("name")
+ record["lineScope"] = rule.GetString("lineScope")
+ record["lineCarrier"] = defaultLineField(rule.GetString("lineCarrier"))
+ record["lineRegion"] = defaultLineField(rule.GetString("lineRegion"))
+ record["lineProvince"] = defaultLineField(rule.GetString("lineProvince"))
+ record["lineContinent"] = defaultLineField(rule.GetString("lineContinent"))
+ record["lineCountry"] = defaultLineField(rule.GetString("lineCountry"))
+ record["ruleName"] = rule.GetString("ruleName")
+ record["weightEnabled"] = rule.GetBool("weightEnabled")
+ record["ttl"] = rule.GetInt("ttl")
+ record["isOn"] = rule.GetBool("isOn")
+ record["recordItemsJson"] = marshalJSON(rule["recordValues"], "[]")
+ break
+ }
+ }
+
+ this.Data["app"] = app
+ this.Data["domain"] = domain
+ this.Data["record"] = record
+ this.Data["isEditing"] = params.RecordId > 0
+ this.Show()
+}
+
+func (this *CustomRecordsCreatePopupAction) RunPost(params struct {
+ AppId int64
+ DomainId int64
+
+ RecordId int64
+ Domain string
+ LineScope string
+
+ LineCarrier string
+ LineRegion string
+ LineProvince string
+ LineContinent string
+ LineCountry string
+
+ RuleName string
+ RecordItemsJSON string
+ WeightEnabled bool
+ Ttl int
+ IsOn bool
+
+ Must *actions.Must
+ CSRF *actionutils.CSRF
+}) {
+ params.Must.Field("appId", params.AppId).Gt(0, "请选择应用")
+ params.Must.Field("domainId", params.DomainId).Gt(0, "请选择所属域名")
+
+ params.LineScope = strings.ToLower(strings.TrimSpace(params.LineScope))
+ if params.LineScope != "china" && params.LineScope != "overseas" {
+ params.LineScope = "china"
+ }
+ params.RuleName = strings.TrimSpace(params.RuleName)
+ if len(params.RuleName) == 0 {
+ this.Fail("请输入规则名称")
+ return
+ }
+ if params.Ttl <= 0 || params.Ttl > 86400 {
+ this.Fail("TTL值必须在 1-86400 范围内")
+ return
+ }
+
+ recordValues, err := parseRecordItemsJSON(params.RecordItemsJSON, params.WeightEnabled)
+ if err != nil {
+ this.Fail(err.Error())
+ return
+ }
+ if len(recordValues) == 0 {
+ this.Fail("请输入解析记录值")
+ return
+ }
+ if len(recordValues) > 10 {
+ this.Fail("单个规则最多只能添加 10 条解析记录")
+ return
+ }
+
+ lineCarrier := strings.TrimSpace(params.LineCarrier)
+ lineRegion := strings.TrimSpace(params.LineRegion)
+ lineProvince := strings.TrimSpace(params.LineProvince)
+ lineContinent := strings.TrimSpace(params.LineContinent)
+ lineCountry := strings.TrimSpace(params.LineCountry)
+ if len(lineCarrier) == 0 {
+ lineCarrier = "默认"
+ }
+ if len(lineRegion) == 0 {
+ lineRegion = "默认"
+ }
+ if len(lineProvince) == 0 {
+ lineProvince = "默认"
+ }
+ if len(lineContinent) == 0 {
+ lineContinent = "默认"
+ }
+ if len(lineCountry) == 0 {
+ lineCountry = "默认"
+ }
+ if params.LineScope == "overseas" {
+ lineCarrier = ""
+ lineRegion = ""
+ lineProvince = ""
+ } else {
+ lineContinent = ""
+ lineCountry = ""
+ }
+
+ records := make([]*pb.HTTPDNSRuleRecord, 0, len(recordValues))
+ for i, item := range recordValues {
+ records = append(records, &pb.HTTPDNSRuleRecord{
+ Id: 0,
+ RuleId: 0,
+ RecordType: item.GetString("type"),
+ RecordValue: item.GetString("value"),
+ Weight: int32(item.GetInt("weight")),
+ Sort: int32(i + 1),
+ })
+ }
+
+ rule := &pb.HTTPDNSCustomRule{
+ Id: params.RecordId,
+ AppId: params.AppId,
+ DomainId: params.DomainId,
+ RuleName: params.RuleName,
+ LineScope: params.LineScope,
+ LineCarrier: lineCarrier,
+ LineRegion: lineRegion,
+ LineProvince: lineProvince,
+ LineContinent: lineContinent,
+ LineCountry: lineCountry,
+ Ttl: int32(params.Ttl),
+ IsOn: params.IsOn,
+ Priority: 100,
+ Records: records,
+ }
+
+ if params.RecordId > 0 {
+ err = updateCustomRule(this.Parent(), rule)
+ } else {
+ _, err = createCustomRule(this.Parent(), rule)
+ }
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ this.Success()
+}
+
+func parseRecordItemsJSON(raw string, weightEnabled bool) ([]maps.Map, error) {
+ raw = strings.TrimSpace(raw)
+ if len(raw) == 0 {
+ return []maps.Map{}, nil
+ }
+
+ list := []maps.Map{}
+ if err := json.Unmarshal([]byte(raw), &list); err != nil {
+ return nil, fmt.Errorf("解析记录格式不正确")
+ }
+
+ result := make([]maps.Map, 0, len(list))
+ for _, item := range list {
+ recordType := strings.ToUpper(strings.TrimSpace(item.GetString("type")))
+ recordValue := strings.TrimSpace(item.GetString("value"))
+ if len(recordType) == 0 && len(recordValue) == 0 {
+ continue
+ }
+ if recordType != "A" && recordType != "AAAA" {
+ return nil, fmt.Errorf("记录类型只能是 A 或 AAAA")
+ }
+ if len(recordValue) == 0 {
+ return nil, fmt.Errorf("记录值不能为空")
+ }
+
+ weight := item.GetInt("weight")
+ if !weightEnabled {
+ weight = 100
+ }
+ if weight < 1 || weight > 100 {
+ return nil, fmt.Errorf("权重值必须在 1-100 之间")
+ }
+
+ result = append(result, maps.Map{
+ "type": recordType,
+ "value": recordValue,
+ "weight": weight,
+ })
+ }
+ return result, nil
+}
+
+func marshalJSON(v interface{}, fallback string) string {
+ b, err := json.Marshal(v)
+ if err != nil {
+ return fallback
+ }
+ return string(b)
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/customRecordsDelete.go b/EdgeUser/internal/web/actions/default/httpdns/apps/customRecordsDelete.go
new file mode 100644
index 0000000..0673a1a
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/customRecordsDelete.go
@@ -0,0 +1,21 @@
+package apps
+
+import "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+
+type CustomRecordsDeleteAction struct {
+ actionutils.ParentAction
+}
+
+func (this *CustomRecordsDeleteAction) RunPost(params struct {
+ AppId int64
+ RecordId int64
+}) {
+ if params.RecordId > 0 {
+ err := deleteCustomRule(this.Parent(), params.RecordId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ }
+ this.Success()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/customRecordsToggle.go b/EdgeUser/internal/web/actions/default/httpdns/apps/customRecordsToggle.go
new file mode 100644
index 0000000..c55a70f
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/customRecordsToggle.go
@@ -0,0 +1,22 @@
+package apps
+
+import "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+
+type CustomRecordsToggleAction struct {
+ actionutils.ParentAction
+}
+
+func (this *CustomRecordsToggleAction) RunPost(params struct {
+ AppId int64
+ RecordId int64
+ IsOn bool
+}) {
+ if params.RecordId > 0 {
+ err := toggleCustomRule(this.Parent(), params.RecordId, params.IsOn)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ }
+ this.Success()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/delete.go b/EdgeUser/internal/web/actions/default/httpdns/apps/delete.go
new file mode 100644
index 0000000..001af1e
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/delete.go
@@ -0,0 +1,48 @@
+package apps
+
+import (
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/httpdns/httpdnsutils"
+)
+
+type DeleteAction struct {
+ actionutils.ParentAction
+}
+
+func (this *DeleteAction) Init() {
+ this.Nav("httpdns", "app", "delete")
+}
+
+func (this *DeleteAction) RunGet(params struct {
+ AppId int64
+}) {
+ httpdnsutils.AddLeftMenu(this.Parent())
+ app, err := findAppMap(this.Parent(), params.AppId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ httpdnsutils.AddAppTabbar(this.Parent(), app.GetString("name"), app.GetInt64("id"), "delete")
+ this.Data["app"] = app
+ domains, err := listDomainMaps(this.Parent(), app.GetInt64("id"), "")
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ this.Data["domainCount"] = len(domains)
+ this.Show()
+}
+
+func (this *DeleteAction) RunPost(params struct {
+ AppId int64
+}) {
+ if params.AppId > 0 {
+ err := deleteAppByID(this.Parent(), params.AppId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ }
+
+ this.Success()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/domains.go b/EdgeUser/internal/web/actions/default/httpdns/apps/domains.go
new file mode 100644
index 0000000..0894b2e
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/domains.go
@@ -0,0 +1,38 @@
+package apps
+
+import (
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/httpdns/httpdnsutils"
+)
+
+type DomainsAction struct {
+ actionutils.ParentAction
+}
+
+func (this *DomainsAction) Init() {
+ this.Nav("httpdns", "app", "domains")
+}
+
+func (this *DomainsAction) RunGet(params struct {
+ AppId int64
+}) {
+ httpdnsutils.AddLeftMenu(this.Parent())
+ app, err := findAppMap(this.Parent(), params.AppId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ httpdnsutils.AddAppTabbar(this.Parent(), app.GetString("name"), params.AppId, "domains")
+
+ domains, err := listDomainMaps(this.Parent(), app.GetInt64("id"), "")
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ this.Data["app"] = app
+ this.Data["domains"] = domains
+ this.Data["keyword"] = ""
+ this.Show()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/domainsCreatePopup.go b/EdgeUser/internal/web/actions/default/httpdns/apps/domainsCreatePopup.go
new file mode 100644
index 0000000..189bc87
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/domainsCreatePopup.go
@@ -0,0 +1,44 @@
+package apps
+
+import (
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/iwind/TeaGo/actions"
+)
+
+type DomainsCreatePopupAction struct {
+ actionutils.ParentAction
+}
+
+func (this *DomainsCreatePopupAction) Init() {
+ this.Nav("", "", "")
+}
+
+func (this *DomainsCreatePopupAction) RunGet(params struct {
+ AppId int64
+}) {
+ app, err := findAppMap(this.Parent(), params.AppId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ this.Data["app"] = app
+ this.Show()
+}
+
+func (this *DomainsCreatePopupAction) RunPost(params struct {
+ AppId int64
+ Domain string
+
+ Must *actions.Must
+ CSRF *actionutils.CSRF
+}) {
+ params.Must.Field("appId", params.AppId).Gt(0, "请选择应用")
+ params.Must.Field("domain", params.Domain).Require("请输入域名")
+
+ err := createDomain(this.Parent(), params.AppId, params.Domain)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ this.Success()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/domainsDelete.go b/EdgeUser/internal/web/actions/default/httpdns/apps/domainsDelete.go
new file mode 100644
index 0000000..1cad958
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/domainsDelete.go
@@ -0,0 +1,20 @@
+package apps
+
+import "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+
+type DomainsDeleteAction struct {
+ actionutils.ParentAction
+}
+
+func (this *DomainsDeleteAction) RunPost(params struct {
+ DomainId int64
+}) {
+ if params.DomainId > 0 {
+ err := deleteDomain(this.Parent(), params.DomainId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ }
+ this.Success()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/formatters.go b/EdgeUser/internal/web/actions/default/httpdns/apps/formatters.go
new file mode 100644
index 0000000..5c52256
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/formatters.go
@@ -0,0 +1,92 @@
+package apps
+
+import (
+ "strconv"
+ "strings"
+
+ "github.com/iwind/TeaGo/maps"
+)
+
+func maskSecret(secret string) string {
+ secret = strings.TrimSpace(secret)
+ if len(secret) < 4 {
+ return "******"
+ }
+
+ prefix := ""
+ for i := 0; i < len(secret); i++ {
+ if secret[i] == '_' {
+ prefix = secret[:i+1]
+ break
+ }
+ }
+ if len(prefix) == 0 {
+ prefix = secret[:2]
+ }
+
+ if len(secret) <= 8 {
+ return prefix + "xxxx"
+ }
+ return prefix + "xxxxxxxx" + secret[len(secret)-4:]
+}
+
+func buildLineText(record maps.Map) string {
+ parts := []string{}
+ if strings.TrimSpace(record.GetString("lineScope")) == "overseas" {
+ parts = append(parts,
+ strings.TrimSpace(record.GetString("lineContinent")),
+ strings.TrimSpace(record.GetString("lineCountry")),
+ )
+ } else {
+ parts = append(parts,
+ strings.TrimSpace(record.GetString("lineCarrier")),
+ strings.TrimSpace(record.GetString("lineRegion")),
+ strings.TrimSpace(record.GetString("lineProvince")),
+ )
+ }
+
+ finalParts := make([]string, 0, len(parts))
+ for _, part := range parts {
+ if len(part) == 0 || part == "默认" {
+ continue
+ }
+ finalParts = append(finalParts, part)
+ }
+ if len(finalParts) == 0 {
+ return "默认"
+ }
+ return strings.Join(finalParts, " / ")
+}
+
+func buildRecordValueText(record maps.Map) string {
+ values, ok := record["recordValues"].([]maps.Map)
+ if !ok || len(values) == 0 {
+ return "-"
+ }
+
+ weightEnabled := record.GetBool("weightEnabled")
+ defaultType := strings.ToUpper(strings.TrimSpace(record.GetString("recordType")))
+ parts := make([]string, 0, len(values))
+ for _, item := range values {
+ value := strings.TrimSpace(item.GetString("value"))
+ if len(value) == 0 {
+ continue
+ }
+ recordType := strings.ToUpper(strings.TrimSpace(item.GetString("type")))
+ if len(recordType) == 0 {
+ recordType = defaultType
+ }
+ if recordType != "A" && recordType != "AAAA" {
+ recordType = "A"
+ }
+ part := recordType + " " + value
+ if weightEnabled {
+ part += "(" + strconv.Itoa(item.GetInt("weight")) + ")"
+ }
+ parts = append(parts, part)
+ }
+ if len(parts) == 0 {
+ return "-"
+ }
+ return strings.Join(parts, ", ")
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/index.go b/EdgeUser/internal/web/actions/default/httpdns/apps/index.go
new file mode 100644
index 0000000..aabd719
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/index.go
@@ -0,0 +1,28 @@
+package apps
+
+import (
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/httpdns/httpdnsutils"
+)
+
+type IndexAction struct {
+ actionutils.ParentAction
+}
+
+func (this *IndexAction) Init() {
+ this.Nav("httpdns", "app", "")
+}
+
+func (this *IndexAction) RunGet(params struct {
+ Keyword string
+}) {
+ httpdnsutils.AddLeftMenu(this.Parent())
+ this.Data["keyword"] = params.Keyword
+ apps, err := listAppMaps(this.Parent(), params.Keyword)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ this.Data["apps"] = apps
+ this.Show()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/init.go b/EdgeUser/internal/web/actions/default/httpdns/apps/init.go
new file mode 100644
index 0000000..e900b4f
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/init.go
@@ -0,0 +1,35 @@
+package apps
+
+import (
+ "github.com/TeaOSLab/EdgeUser/internal/web/helpers"
+ "github.com/iwind/TeaGo"
+)
+
+func init() {
+ TeaGo.BeforeStart(func(server *TeaGo.Server) {
+ server.
+ Helper(helpers.NewUserMustAuth("")).
+ Data("teaMenu", "httpdns").
+ Data("teaSubMenu", "app").
+ Prefix("/httpdns/apps").
+ Get("", new(IndexAction)).
+ Get("/app", new(AppAction)).
+ Get("/sdk", new(SdkAction)).
+ Get("/sdk/check", new(SdkCheckAction)).
+ Get("/sdk/download", new(SdkDownloadAction)).
+ Get("/sdk/doc", new(SdkDocAction)).
+ GetPost("/app/settings", new(AppSettingsAction)).
+ Post("/app/settings/toggleSignEnabled", new(AppSettingsToggleSignEnabledAction)).
+ Post("/app/settings/resetSignSecret", new(AppSettingsResetSignSecretAction)).
+ Get("/domains", new(DomainsAction)).
+ Get("/customRecords", new(CustomRecordsAction)).
+ GetPost("/create", new(CreateAction)).
+ GetPost("/delete", new(DeleteAction)).
+ GetPost("/domains/createPopup", new(DomainsCreatePopupAction)).
+ Post("/domains/delete", new(DomainsDeleteAction)).
+ GetPost("/customRecords/createPopup", new(CustomRecordsCreatePopupAction)).
+ Post("/customRecords/delete", new(CustomRecordsDeleteAction)).
+ Post("/customRecords/toggle", new(CustomRecordsToggleAction)).
+ EndAll()
+ })
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/rpc_helpers.go b/EdgeUser/internal/web/actions/default/httpdns/apps/rpc_helpers.go
new file mode 100644
index 0000000..d356644
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/rpc_helpers.go
@@ -0,0 +1,302 @@
+package apps
+
+import (
+ "encoding/json"
+ "errors"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/iwind/TeaGo/maps"
+ timeutil "github.com/iwind/TeaGo/utils/time"
+)
+
+func listAppMaps(parent *actionutils.ParentAction, keyword string) ([]maps.Map, error) {
+ resp, err := parent.RPC().HTTPDNSAppRPC().ListHTTPDNSApps(parent.UserContext(), &pb.ListHTTPDNSAppsRequest{
+ Offset: 0,
+ Size: 10_000,
+ Keyword: strings.TrimSpace(keyword),
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ result := make([]maps.Map, 0, len(resp.GetApps()))
+ for _, app := range resp.GetApps() {
+ domainResp, err := parent.RPC().HTTPDNSDomainRPC().ListHTTPDNSDomainsWithAppId(parent.UserContext(), &pb.ListHTTPDNSDomainsWithAppIdRequest{
+ AppDbId: app.GetId(),
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ result = append(result, appPBToMap(app, int64(len(domainResp.GetDomains()))))
+ }
+
+ return result, nil
+}
+
+func findAppMap(parent *actionutils.ParentAction, appDbId int64) (maps.Map, error) {
+ if appDbId > 0 {
+ resp, err := parent.RPC().HTTPDNSAppRPC().FindHTTPDNSApp(parent.UserContext(), &pb.FindHTTPDNSAppRequest{
+ AppDbId: appDbId,
+ })
+ if err != nil {
+ return nil, err
+ }
+ if resp.GetApp() != nil {
+ domainResp, err := parent.RPC().HTTPDNSDomainRPC().ListHTTPDNSDomainsWithAppId(parent.UserContext(), &pb.ListHTTPDNSDomainsWithAppIdRequest{
+ AppDbId: appDbId,
+ })
+ if err != nil {
+ return nil, err
+ }
+ return appPBToMap(resp.GetApp(), int64(len(domainResp.GetDomains()))), nil
+ }
+
+ return nil, errors.New("应用不存在或无权限访问")
+ }
+
+ apps, err := listAppMaps(parent, "")
+ if err != nil {
+ return nil, err
+ }
+ if len(apps) == 0 {
+ return maps.Map{
+ "id": int64(0),
+ "name": "",
+ "appId": "",
+ }, nil
+ }
+ return apps[0], nil
+}
+
+func createApp(parent *actionutils.ParentAction, name string, clusterIdsJSON []byte) (int64, error) {
+ newAppId := "app" + strconv.FormatInt(time.Now().UnixNano()%1_000_000_000_000, 36)
+ resp, err := parent.RPC().HTTPDNSAppRPC().CreateHTTPDNSApp(parent.UserContext(), &pb.CreateHTTPDNSAppRequest{
+ Name: strings.TrimSpace(name),
+ AppId: newAppId,
+ ClusterIdsJSON: clusterIdsJSON,
+ IsOn: true,
+ SignEnabled: true,
+ })
+ if err != nil {
+ return 0, err
+ }
+ return resp.GetAppDbId(), nil
+}
+
+func deleteAppByID(parent *actionutils.ParentAction, appDbId int64) error {
+ _, err := parent.RPC().HTTPDNSAppRPC().DeleteHTTPDNSApp(parent.UserContext(), &pb.DeleteHTTPDNSAppRequest{
+ AppDbId: appDbId,
+ })
+ return err
+}
+
+func updateAppSettings(parent *actionutils.ParentAction, appDbId int64, name string, clusterIdsJSON []byte, isOn bool, userId int64) error {
+ _, err := parent.RPC().HTTPDNSAppRPC().UpdateHTTPDNSApp(parent.UserContext(), &pb.UpdateHTTPDNSAppRequest{
+ AppDbId: appDbId,
+ Name: strings.TrimSpace(name),
+ ClusterIdsJSON: clusterIdsJSON,
+ IsOn: isOn,
+ UserId: userId,
+ })
+ return err
+}
+
+func updateAppSignEnabled(parent *actionutils.ParentAction, appDbId int64, signEnabled bool) error {
+ _, err := parent.RPC().HTTPDNSAppRPC().UpdateHTTPDNSAppSignEnabled(parent.UserContext(), &pb.UpdateHTTPDNSAppSignEnabledRequest{
+ AppDbId: appDbId,
+ SignEnabled: signEnabled,
+ })
+ return err
+}
+
+func resetAppSignSecret(parent *actionutils.ParentAction, appDbId int64) (*pb.ResetHTTPDNSAppSignSecretResponse, error) {
+ return parent.RPC().HTTPDNSAppRPC().ResetHTTPDNSAppSignSecret(parent.UserContext(), &pb.ResetHTTPDNSAppSignSecretRequest{
+ AppDbId: appDbId,
+ })
+}
+
+func listDomainMaps(parent *actionutils.ParentAction, appDbId int64, keyword string) ([]maps.Map, error) {
+ resp, err := parent.RPC().HTTPDNSDomainRPC().ListHTTPDNSDomainsWithAppId(parent.UserContext(), &pb.ListHTTPDNSDomainsWithAppIdRequest{
+ AppDbId: appDbId,
+ Keyword: strings.TrimSpace(keyword),
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ result := make([]maps.Map, 0, len(resp.GetDomains()))
+ for _, domain := range resp.GetDomains() {
+ result = append(result, maps.Map{
+ "id": domain.GetId(),
+ "name": domain.GetDomain(),
+ "isOn": domain.GetIsOn(),
+ "customRecordCount": domain.GetRuleCount(),
+ })
+ }
+ return result, nil
+}
+
+func createDomain(parent *actionutils.ParentAction, appDbId int64, domain string) error {
+ _, err := parent.RPC().HTTPDNSDomainRPC().CreateHTTPDNSDomain(parent.UserContext(), &pb.CreateHTTPDNSDomainRequest{
+ AppDbId: appDbId,
+ Domain: strings.TrimSpace(domain),
+ IsOn: true,
+ })
+ return err
+}
+
+func deleteDomain(parent *actionutils.ParentAction, domainId int64) error {
+ _, err := parent.RPC().HTTPDNSDomainRPC().DeleteHTTPDNSDomain(parent.UserContext(), &pb.DeleteHTTPDNSDomainRequest{
+ DomainId: domainId,
+ })
+ return err
+}
+
+func findDomainMap(domains []maps.Map, domainID int64) maps.Map {
+ if len(domains) == 0 {
+ return maps.Map{}
+ }
+ if domainID <= 0 {
+ return domains[0]
+ }
+ for _, domain := range domains {
+ if domain.GetInt64("id") == domainID {
+ return domain
+ }
+ }
+ return domains[0]
+}
+
+func listCustomRuleMaps(parent *actionutils.ParentAction, domainId int64) ([]maps.Map, error) {
+ resp, err := parent.RPC().HTTPDNSRuleRPC().ListHTTPDNSCustomRulesWithDomainId(parent.UserContext(), &pb.ListHTTPDNSCustomRulesWithDomainIdRequest{
+ DomainId: domainId,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ result := make([]maps.Map, 0, len(resp.GetRules()))
+ for _, rule := range resp.GetRules() {
+ recordValues := make([]maps.Map, 0, len(rule.GetRecords()))
+ recordType := "A"
+ weightEnabled := false
+ for _, record := range rule.GetRecords() {
+ if len(recordType) == 0 {
+ recordType = strings.ToUpper(strings.TrimSpace(record.GetRecordType()))
+ }
+ if record.GetWeight() > 0 && record.GetWeight() != 100 {
+ weightEnabled = true
+ }
+ recordValues = append(recordValues, maps.Map{
+ "type": strings.ToUpper(strings.TrimSpace(record.GetRecordType())),
+ "value": record.GetRecordValue(),
+ "weight": record.GetWeight(),
+ })
+ }
+ if len(recordValues) == 0 {
+ recordValues = append(recordValues, maps.Map{
+ "type": "A",
+ "value": "",
+ "weight": 100,
+ })
+ }
+
+ item := maps.Map{
+ "id": rule.GetId(),
+ "lineScope": rule.GetLineScope(),
+ "lineCarrier": defaultLineField(rule.GetLineCarrier()),
+ "lineRegion": defaultLineField(rule.GetLineRegion()),
+ "lineProvince": defaultLineField(rule.GetLineProvince()),
+ "lineContinent": defaultLineField(rule.GetLineContinent()),
+ "lineCountry": defaultLineField(rule.GetLineCountry()),
+ "ruleName": rule.GetRuleName(),
+ "recordType": recordType,
+ "recordValues": recordValues,
+ "weightEnabled": weightEnabled,
+ "ttl": rule.GetTtl(),
+ "isOn": rule.GetIsOn(),
+ "updatedAt": formatDateTime(rule.GetUpdatedAt()),
+ }
+ item["lineText"] = buildLineText(item)
+ item["recordValueText"] = buildRecordValueText(item)
+ result = append(result, item)
+ }
+ return result, nil
+}
+
+func createCustomRule(parent *actionutils.ParentAction, rule *pb.HTTPDNSCustomRule) (int64, error) {
+ resp, err := parent.RPC().HTTPDNSRuleRPC().CreateHTTPDNSCustomRule(parent.UserContext(), &pb.CreateHTTPDNSCustomRuleRequest{
+ Rule: rule,
+ })
+ if err != nil {
+ return 0, err
+ }
+ return resp.GetRuleId(), nil
+}
+
+func updateCustomRule(parent *actionutils.ParentAction, rule *pb.HTTPDNSCustomRule) error {
+ _, err := parent.RPC().HTTPDNSRuleRPC().UpdateHTTPDNSCustomRule(parent.UserContext(), &pb.UpdateHTTPDNSCustomRuleRequest{
+ Rule: rule,
+ })
+ return err
+}
+
+func deleteCustomRule(parent *actionutils.ParentAction, ruleId int64) error {
+ _, err := parent.RPC().HTTPDNSRuleRPC().DeleteHTTPDNSCustomRule(parent.UserContext(), &pb.DeleteHTTPDNSCustomRuleRequest{
+ RuleId: ruleId,
+ })
+ return err
+}
+
+func toggleCustomRule(parent *actionutils.ParentAction, ruleId int64, isOn bool) error {
+ _, err := parent.RPC().HTTPDNSRuleRPC().UpdateHTTPDNSCustomRuleStatus(parent.UserContext(), &pb.UpdateHTTPDNSCustomRuleStatusRequest{
+ RuleId: ruleId,
+ IsOn: isOn,
+ })
+ return err
+}
+
+func appPBToMap(app *pb.HTTPDNSApp, domainCount int64) maps.Map {
+ signSecret := app.GetSignSecret()
+
+ // 读取集群 ID 列表
+ var clusterIds []int64
+ if len(app.GetClusterIdsJSON()) > 0 {
+ _ = json.Unmarshal(app.GetClusterIdsJSON(), &clusterIds)
+ }
+
+ return maps.Map{
+ "id": app.GetId(),
+ "name": app.GetName(),
+ "appId": app.GetAppId(),
+ "clusterIds": clusterIds,
+ "userId": app.GetUserId(),
+ "isOn": app.GetIsOn(),
+ "domainCount": domainCount,
+ "sniPolicyText": "隐匿 SNI",
+ "signEnabled": app.GetSignEnabled(),
+ "signSecretPlain": signSecret,
+ "signSecretMasked": maskSecret(signSecret),
+ "signSecretUpdated": formatDateTime(app.GetSignUpdatedAt()),
+ }
+}
+
+func defaultLineField(value string) string {
+ value = strings.TrimSpace(value)
+ if len(value) == 0 {
+ return "默认"
+ }
+ return value
+}
+
+func formatDateTime(ts int64) string {
+ if ts <= 0 {
+ return ""
+ }
+ return timeutil.FormatTime("Y-m-d H:i:s", ts)
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/sdk.go b/EdgeUser/internal/web/actions/default/httpdns/apps/sdk.go
new file mode 100644
index 0000000..969cf2c
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/sdk.go
@@ -0,0 +1,30 @@
+package apps
+
+import (
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/httpdns/httpdnsutils"
+)
+
+type SdkAction struct {
+ actionutils.ParentAction
+}
+
+func (this *SdkAction) Init() {
+ this.Nav("httpdns", "app", "sdk")
+}
+
+func (this *SdkAction) RunGet(params struct {
+ AppId int64
+}) {
+ httpdnsutils.AddLeftMenu(this.Parent())
+
+ app, err := findAppMap(this.Parent(), params.AppId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ httpdnsutils.AddAppTabbar(this.Parent(), app.GetString("name"), params.AppId, "sdk")
+ this.Data["app"] = app
+ this.Show()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/sdk_check.go b/EdgeUser/internal/web/actions/default/httpdns/apps/sdk_check.go
new file mode 100644
index 0000000..09156d8
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/sdk_check.go
@@ -0,0 +1,68 @@
+package apps
+
+import (
+ "net/url"
+ "strings"
+
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+)
+
+type SdkCheckAction struct {
+ actionutils.ParentAction
+}
+
+func (this *SdkCheckAction) Init() {
+ this.Nav("", "", "")
+}
+
+func (this *SdkCheckAction) RunGet(params struct {
+ Platform string
+ Version string
+ Type string
+}) {
+ platform, _, _, filename, err := resolveSDKPlatform(params.Platform)
+ if err != nil {
+ this.Data["exists"] = false
+ this.Data["message"] = err.Error()
+ this.Success()
+ return
+ }
+
+ version := strings.TrimSpace(params.Version)
+ t := strings.ToLower(strings.TrimSpace(params.Type))
+ if t == "doc" {
+ docPath := findUploadedSDKDocPath(platform, version)
+ if len(docPath) == 0 {
+ this.Data["exists"] = false
+ this.Data["message"] = "当前平台/版本尚未上传集成文档"
+ this.Success()
+ return
+ }
+
+ downloadURL := "/httpdns/apps/sdk/doc?platform=" + url.QueryEscape(platform)
+ if len(version) > 0 {
+ downloadURL += "&version=" + url.QueryEscape(version)
+ }
+ this.Data["exists"] = true
+ this.Data["url"] = downloadURL
+ this.Success()
+ return
+ }
+
+ archivePath := findSDKArchivePath(filename, version)
+ if len(archivePath) == 0 {
+ this.Data["exists"] = false
+ this.Data["message"] = "当前平台/版本尚未上传 SDK 安装包"
+ this.Success()
+ return
+ }
+
+ downloadURL := "/httpdns/apps/sdk/download?platform=" + url.QueryEscape(platform)
+ if len(version) > 0 {
+ downloadURL += "&version=" + url.QueryEscape(version)
+ }
+ downloadURL += "&raw=1"
+ this.Data["exists"] = true
+ this.Data["url"] = downloadURL
+ this.Success()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/sdk_doc.go b/EdgeUser/internal/web/actions/default/httpdns/apps/sdk_doc.go
new file mode 100644
index 0000000..f699fab
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/sdk_doc.go
@@ -0,0 +1,55 @@
+package apps
+
+import (
+ "net/url"
+ "os"
+ "path/filepath"
+
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+)
+
+type SdkDocAction struct {
+ actionutils.ParentAction
+}
+
+func (this *SdkDocAction) Init() {
+ this.Nav("", "", "")
+}
+
+func (this *SdkDocAction) RunGet(params struct {
+ Platform string
+ Version string
+}) {
+ platform, _, _, _, err := resolveSDKPlatform(params.Platform)
+ if err != nil {
+ this.Data["exists"] = false
+ this.Data["message"] = err.Error()
+ this.Success()
+ return
+ }
+
+ docPath := findUploadedSDKDocPath(platform, params.Version)
+ if len(docPath) == 0 {
+ this.Data["exists"] = false
+ this.Data["message"] = "当前平台/版本尚未上传集成文档"
+ this.Success()
+ return
+ }
+
+ data, err := os.ReadFile(docPath)
+ if err != nil || len(data) == 0 {
+ this.Data["exists"] = false
+ this.Data["message"] = "读取集成文档失败"
+ this.Success()
+ return
+ }
+
+ downloadName := filepath.Base(docPath)
+ if len(downloadName) == 0 || downloadName == "." || downloadName == string(filepath.Separator) {
+ downloadName = "sdk-doc.md"
+ }
+
+ this.AddHeader("Content-Type", "text/markdown; charset=utf-8")
+ this.AddHeader("Content-Disposition", "attachment; filename=\"sdk-doc.md\"; filename*=UTF-8''"+url.PathEscape(downloadName))
+ _, _ = this.ResponseWriter.Write(data)
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/sdk_download.go b/EdgeUser/internal/web/actions/default/httpdns/apps/sdk_download.go
new file mode 100644
index 0000000..0423133
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/sdk_download.go
@@ -0,0 +1,66 @@
+package apps
+
+import (
+ "io"
+ "net/url"
+ "os"
+ "path/filepath"
+
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+)
+
+type SdkDownloadAction struct {
+ actionutils.ParentAction
+}
+
+func (this *SdkDownloadAction) Init() {
+ this.Nav("", "", "")
+}
+
+func (this *SdkDownloadAction) RunGet(params struct {
+ Platform string
+ Version string
+ Raw int
+}) {
+ _, _, _, filename, err := resolveSDKPlatform(params.Platform)
+ if err != nil {
+ this.Data["exists"] = false
+ this.Data["message"] = err.Error()
+ this.Success()
+ return
+ }
+
+ archivePath := findSDKArchivePath(filename, params.Version)
+ if len(archivePath) == 0 {
+ this.Data["exists"] = false
+ this.Data["message"] = "当前平台/版本尚未上传 SDK 安装包"
+ this.Success()
+ return
+ }
+
+ fp, err := os.Open(archivePath)
+ if err != nil {
+ this.Data["exists"] = false
+ this.Data["message"] = "打开 SDK 安装包失败: " + err.Error()
+ this.Success()
+ return
+ }
+ defer func() {
+ _ = fp.Close()
+ }()
+
+ downloadName := filepath.Base(archivePath)
+ if len(downloadName) == 0 || downloadName == "." || downloadName == string(filepath.Separator) {
+ downloadName = filename
+ }
+
+ if params.Raw == 1 {
+ this.AddHeader("Content-Type", "application/octet-stream")
+ this.AddHeader("X-SDK-Filename", downloadName)
+ } else {
+ this.AddHeader("Content-Type", "application/zip")
+ this.AddHeader("Content-Disposition", "attachment; filename=\"sdk-download\"; filename*=UTF-8''"+url.PathEscape(downloadName))
+ }
+ this.AddHeader("X-Accel-Buffering", "no")
+ _, _ = io.Copy(this.ResponseWriter, fp)
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/apps/sdk_helpers.go b/EdgeUser/internal/web/actions/default/httpdns/apps/sdk_helpers.go
new file mode 100644
index 0000000..236d5c9
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/apps/sdk_helpers.go
@@ -0,0 +1,262 @@
+package apps
+
+import (
+ "encoding/json"
+ "errors"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/iwind/TeaGo/Tea"
+)
+
+type sdkUploadMeta struct {
+ Platform string `json:"platform"`
+ Version string `json:"version"`
+ FileType string `json:"fileType"` // sdk | doc
+ Filename string `json:"filename"`
+ UpdatedAt int64 `json:"updatedAt"`
+}
+
+type sdkUploadMetaRecord struct {
+ Meta sdkUploadMeta
+ Dir string
+ FilePath string
+}
+
+func sdkUploadMetaFilename(platform string, version string, fileType string) string {
+ platform = strings.ToLower(strings.TrimSpace(platform))
+ version = strings.TrimSpace(version)
+ fileType = strings.ToLower(strings.TrimSpace(fileType))
+ return ".httpdns-sdk-meta-" + platform + "-v" + version + "-" + fileType + ".json"
+}
+
+func isSDKUploadMetaFile(name string) bool {
+ name = strings.ToLower(strings.TrimSpace(name))
+ return strings.HasPrefix(name, ".httpdns-sdk-meta-") && strings.HasSuffix(name, ".json")
+}
+
+func parseSDKPlatformFromDownloadFilename(downloadFilename string) string {
+ name := strings.ToLower(strings.TrimSpace(downloadFilename))
+ if !strings.HasPrefix(name, "httpdns-sdk-") || !strings.HasSuffix(name, ".zip") {
+ return ""
+ }
+
+ platform := strings.TrimSuffix(strings.TrimPrefix(name, "httpdns-sdk-"), ".zip")
+ switch platform {
+ case "android", "ios", "flutter":
+ return platform
+ default:
+ return ""
+ }
+}
+
+func listSDKUploadMetaRecords() []sdkUploadMetaRecord {
+ type wrapped struct {
+ record sdkUploadMetaRecord
+ modTime time.Time
+ }
+
+ byKey := map[string]wrapped{}
+ for _, dir := range sdkUploadSearchDirs() {
+ entries, err := os.ReadDir(dir)
+ if err != nil {
+ continue
+ }
+
+ for _, entry := range entries {
+ if entry.IsDir() {
+ continue
+ }
+
+ name := entry.Name()
+ if !isSDKUploadMetaFile(name) {
+ continue
+ }
+
+ metaPath := filepath.Join(dir, name)
+ data, err := os.ReadFile(metaPath)
+ if err != nil || len(data) == 0 {
+ continue
+ }
+
+ var meta sdkUploadMeta
+ if err = json.Unmarshal(data, &meta); err != nil {
+ continue
+ }
+
+ meta.Platform = strings.ToLower(strings.TrimSpace(meta.Platform))
+ meta.Version = strings.TrimSpace(meta.Version)
+ meta.FileType = strings.ToLower(strings.TrimSpace(meta.FileType))
+ meta.Filename = filepath.Base(strings.TrimSpace(meta.Filename))
+ if len(meta.Platform) == 0 || len(meta.Version) == 0 || len(meta.Filename) == 0 {
+ continue
+ }
+ if meta.FileType != "sdk" && meta.FileType != "doc" {
+ continue
+ }
+ if strings.Contains(meta.Filename, "..") || strings.Contains(meta.Filename, "/") || strings.Contains(meta.Filename, "\\") {
+ continue
+ }
+
+ filePath := filepath.Join(dir, meta.Filename)
+ fileStat, err := os.Stat(filePath)
+ if err != nil || fileStat.IsDir() || fileStat.Size() <= 0 {
+ continue
+ }
+
+ metaStat, err := os.Stat(metaPath)
+ if err != nil {
+ continue
+ }
+ if meta.UpdatedAt <= 0 {
+ meta.UpdatedAt = metaStat.ModTime().Unix()
+ }
+
+ key := meta.Platform + "|" + meta.Version + "|" + meta.FileType
+ current := wrapped{
+ record: sdkUploadMetaRecord{
+ Meta: meta,
+ Dir: dir,
+ FilePath: filePath,
+ },
+ modTime: metaStat.ModTime(),
+ }
+ old, ok := byKey[key]
+ if !ok ||
+ current.record.Meta.UpdatedAt > old.record.Meta.UpdatedAt ||
+ (current.record.Meta.UpdatedAt == old.record.Meta.UpdatedAt && current.modTime.After(old.modTime)) ||
+ (current.record.Meta.UpdatedAt == old.record.Meta.UpdatedAt && current.modTime.Equal(old.modTime) && current.record.FilePath > old.record.FilePath) {
+ byKey[key] = current
+ }
+ }
+ }
+
+ result := make([]sdkUploadMetaRecord, 0, len(byKey))
+ for _, item := range byKey {
+ result = append(result, item.record)
+ }
+ return result
+}
+
+func findSDKUploadFileByMeta(platform string, version string, fileType string) string {
+ platform = strings.ToLower(strings.TrimSpace(platform))
+ version = strings.TrimSpace(version)
+ fileType = strings.ToLower(strings.TrimSpace(fileType))
+ if len(platform) == 0 || len(version) == 0 {
+ return ""
+ }
+
+ for _, record := range listSDKUploadMetaRecords() {
+ if record.Meta.Platform == platform && record.Meta.Version == version && record.Meta.FileType == fileType {
+ return record.FilePath
+ }
+ }
+ return ""
+}
+
+func findNewestSDKUploadFileByMeta(platform string, fileType string) string {
+ platform = strings.ToLower(strings.TrimSpace(platform))
+ fileType = strings.ToLower(strings.TrimSpace(fileType))
+ if len(platform) == 0 {
+ return ""
+ }
+
+ var foundPath string
+ var foundUpdatedAt int64
+ for _, record := range listSDKUploadMetaRecords() {
+ if record.Meta.Platform != platform || record.Meta.FileType != fileType {
+ continue
+ }
+
+ if len(foundPath) == 0 || record.Meta.UpdatedAt > foundUpdatedAt || (record.Meta.UpdatedAt == foundUpdatedAt && record.FilePath > foundPath) {
+ foundPath = record.FilePath
+ foundUpdatedAt = record.Meta.UpdatedAt
+ }
+ }
+ return foundPath
+}
+
+func sdkUploadDir() string {
+ dirs := sdkUploadDirs()
+ if len(dirs) > 0 {
+ return dirs[0]
+ }
+ return filepath.Clean(Tea.Root + "/data/httpdns/sdk")
+}
+
+func sdkUploadDirs() []string {
+ candidates := []string{
+ filepath.Clean(Tea.Root + "/../data/httpdns/sdk"),
+ filepath.Clean(Tea.Root + "/data/httpdns/sdk"),
+ filepath.Clean(Tea.Root + "/../edge-admin/data/httpdns/sdk"),
+ filepath.Clean(Tea.Root + "/../edge-user/data/httpdns/sdk"),
+ filepath.Clean(Tea.Root + "/../../data/httpdns/sdk"),
+ }
+
+ results := make([]string, 0, len(candidates))
+ seen := map[string]bool{}
+ for _, dir := range candidates {
+ if len(dir) == 0 || seen[dir] {
+ continue
+ }
+ seen[dir] = true
+ results = append(results, dir)
+ }
+ return results
+}
+
+func sdkUploadSearchDirs() []string {
+ dirs := sdkUploadDirs()
+ results := make([]string, 0, len(dirs))
+ for _, dir := range dirs {
+ stat, err := os.Stat(dir)
+ if err == nil && stat.IsDir() {
+ results = append(results, dir)
+ }
+ }
+ if len(results) == 0 {
+ results = append(results, sdkUploadDir())
+ }
+ return results
+}
+
+func resolveSDKPlatform(platform string) (key string, relativeDir string, readmeRelativePath string, downloadFilename string, err error) {
+ switch strings.ToLower(strings.TrimSpace(platform)) {
+ case "android":
+ return "android", "android", "android/README.md", "httpdns-sdk-android.zip", nil
+ case "ios":
+ return "ios", "ios", "ios/README.md", "httpdns-sdk-ios.zip", nil
+ case "flutter":
+ return "flutter", "flutter/new_httpdns", "flutter/new_httpdns/README.md", "httpdns-sdk-flutter.zip", nil
+ default:
+ return "", "", "", "", errors.New("不支持的平台,可选值:android、ios、flutter")
+ }
+}
+
+func findSDKArchivePath(downloadFilename string, version string) string {
+ platform := parseSDKPlatformFromDownloadFilename(downloadFilename)
+ if len(platform) == 0 {
+ return ""
+ }
+
+ normalizedVersion := strings.TrimSpace(version)
+ if len(normalizedVersion) > 0 {
+ return findSDKUploadFileByMeta(platform, normalizedVersion, "sdk")
+ }
+ return findNewestSDKUploadFileByMeta(platform, "sdk")
+}
+
+func findUploadedSDKDocPath(platform string, version string) string {
+ platform = strings.ToLower(strings.TrimSpace(platform))
+ if len(platform) == 0 {
+ return ""
+ }
+
+ normalizedVersion := strings.TrimSpace(version)
+ if len(normalizedVersion) > 0 {
+ return findSDKUploadFileByMeta(platform, normalizedVersion, "doc")
+ }
+ return findNewestSDKUploadFileByMeta(platform, "doc")
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/httpdnsutils/helper.go b/EdgeUser/internal/web/actions/default/httpdns/httpdnsutils/helper.go
new file mode 100644
index 0000000..1856e6f
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/httpdnsutils/helper.go
@@ -0,0 +1,57 @@
+package httpdnsutils
+
+import (
+ "strconv"
+
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/iwind/TeaGo/maps"
+)
+
+func AddLeftMenu(action *actionutils.ParentAction) {
+ tab := action.Data.GetString("mainTab")
+ action.Data["teaMenu"] = "httpdns"
+ action.Data["teaSubMenu"] = tab
+ action.Data["leftMenuItems"] = []maps.Map{
+ {
+ "name": "\u5e94\u7528\u7ba1\u7406",
+ "url": "/httpdns/apps",
+ "isActive": tab == "app",
+ },
+ {
+ "name": "\u8bbf\u95ee\u65e5\u5fd7",
+ "url": "/httpdns/resolveLogs",
+ "isActive": tab == "resolveLogs",
+ },
+ {
+ "name": "\u89e3\u6790\u6d4b\u8bd5",
+ "url": "/httpdns/sandbox",
+ "isActive": tab == "sandbox",
+ },
+ }
+}
+
+// AddClusterTabbar builds the top tabbar on cluster pages.
+func AddClusterTabbar(action *actionutils.ParentAction, clusterName string, clusterId int64, selectedTab string) {
+ cid := strconv.FormatInt(clusterId, 10)
+ tabbar := actionutils.NewTabbar()
+ tabbar.Add("", "", "/httpdns/clusters", "arrow left", false)
+ titleItem := tabbar.Add(clusterName, "", "/httpdns/clusters/cluster?clusterId="+cid, "angle right", true)
+ titleItem["isTitle"] = true
+ tabbar.Add("\u8282\u70b9\u5217\u8868", "", "/httpdns/clusters/cluster?clusterId="+cid, "server", selectedTab == "node")
+ tabbar.Add("\u96c6\u7fa4\u8bbe\u7f6e", "", "/httpdns/clusters/cluster/settings?clusterId="+cid, "setting", selectedTab == "setting")
+ tabbar.Add("\u5220\u9664\u96c6\u7fa4", "", "/httpdns/clusters/delete?clusterId="+cid, "trash", selectedTab == "delete")
+ actionutils.SetTabbar(action, tabbar)
+}
+
+// AddAppTabbar builds the top tabbar on app pages.
+func AddAppTabbar(action *actionutils.ParentAction, appName string, appId int64, selectedTab string) {
+ aid := strconv.FormatInt(appId, 10)
+ tabbar := actionutils.NewTabbar()
+ tabbar.Add("", "", "/httpdns/apps", "arrow left", false)
+ titleItem := tabbar.Add(appName, "", "/httpdns/apps/domains?appId="+aid, "angle right", true)
+ titleItem["isTitle"] = true
+ tabbar.Add("\u57df\u540d\u5217\u8868", "", "/httpdns/apps/domains?appId="+aid, "list", selectedTab == "domains")
+ tabbar.Add("\u5e94\u7528\u8bbe\u7f6e", "", "/httpdns/apps/app/settings?appId="+aid, "setting", selectedTab == "settings")
+ tabbar.Add("\u5220\u9664\u5e94\u7528", "", "/httpdns/apps/delete?appId="+aid, "trash", selectedTab == "delete")
+ actionutils.SetTabbar(action, tabbar)
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/index.go b/EdgeUser/internal/web/actions/default/httpdns/index.go
new file mode 100644
index 0000000..aa12486
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/index.go
@@ -0,0 +1,11 @@
+package httpdns
+
+import "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+
+type IndexAction struct {
+ actionutils.ParentAction
+}
+
+func (this *IndexAction) RunGet(params struct{}) {
+ this.RedirectURL("/httpdns/apps")
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/init.go b/EdgeUser/internal/web/actions/default/httpdns/init.go
new file mode 100644
index 0000000..7250741
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/init.go
@@ -0,0 +1,18 @@
+package httpdns
+
+import (
+ "github.com/TeaOSLab/EdgeUser/internal/web/helpers"
+ "github.com/iwind/TeaGo"
+)
+
+func init() {
+ TeaGo.BeforeStart(func(server *TeaGo.Server) {
+ server.
+ Helper(helpers.NewUserMustAuth("")).
+ Data("teaMenu", "httpdns").
+ Data("teaSubMenu", "app").
+ Prefix("/httpdns").
+ Get("", new(IndexAction)).
+ EndAll()
+ })
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/resolveLogs/index.go b/EdgeUser/internal/web/actions/default/httpdns/resolveLogs/index.go
new file mode 100644
index 0000000..b61403b
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/resolveLogs/index.go
@@ -0,0 +1,145 @@
+package resolveLogs
+
+import (
+ "encoding/json"
+ "strings"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/httpdns/httpdnsutils"
+ timeutil "github.com/iwind/TeaGo/utils/time"
+)
+
+type IndexAction struct {
+ actionutils.ParentAction
+}
+
+func (this *IndexAction) Init() {
+ this.Nav("httpdns", "resolveLogs", "")
+}
+
+func (this *IndexAction) RunGet(params struct {
+ ClusterId int64
+ AppId string
+ Domain string
+ Status string
+ Keyword string
+}) {
+ httpdnsutils.AddLeftMenu(this.Parent())
+
+ if params.ClusterId > 0 {
+ this.Data["clusterId"] = params.ClusterId
+ } else {
+ this.Data["clusterId"] = ""
+ }
+ this.Data["appId"] = params.AppId
+ this.Data["domain"] = params.Domain
+ this.Data["status"] = params.Status
+ this.Data["keyword"] = params.Keyword
+
+ clusterResp, err := this.RPC().HTTPDNSClusterRPC().FindAllHTTPDNSClusters(this.UserContext(), &pb.FindAllHTTPDNSClustersRequest{})
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ clusters := make([]map[string]interface{}, 0, len(clusterResp.GetClusters()))
+ clusterDomainMap := map[int64]string{}
+ for _, cluster := range clusterResp.GetClusters() {
+ serviceDomain := strings.TrimSpace(cluster.GetServiceDomain())
+
+ port := "443"
+ if rawTLS := cluster.GetTlsPolicyJSON(); len(rawTLS) > 0 {
+ var tlsConfig map[string]interface{}
+ if err := json.Unmarshal(rawTLS, &tlsConfig); err == nil {
+ if listenRaw, ok := tlsConfig["listen"]; ok && listenRaw != nil {
+ if data, err := json.Marshal(listenRaw); err == nil {
+ var listenAddresses []map[string]interface{}
+ if err := json.Unmarshal(data, &listenAddresses); err == nil {
+ if len(listenAddresses) > 0 {
+ if portRange, ok := listenAddresses[0]["portRange"].(string); ok && len(portRange) > 0 {
+ port = portRange
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ apiAddress := "https://" + serviceDomain + ":" + port
+
+ displayName := apiAddress
+ if len(serviceDomain) == 0 {
+ displayName = cluster.GetName()
+ }
+
+ clusters = append(clusters, map[string]interface{}{
+ "id": cluster.GetId(),
+ "name": cluster.GetName(),
+ "serviceDomain": serviceDomain,
+ "displayName": displayName,
+ })
+ clusterDomainMap[cluster.GetId()] = apiAddress
+ }
+ this.Data["clusters"] = clusters
+
+ logResp, err := this.RPC().HTTPDNSAccessLogRPC().ListHTTPDNSAccessLogs(this.UserContext(), &pb.ListHTTPDNSAccessLogsRequest{
+ Day: "",
+ ClusterId: params.ClusterId,
+ NodeId: 0,
+ AppId: strings.TrimSpace(params.AppId),
+ Domain: strings.TrimSpace(params.Domain),
+ Status: strings.TrimSpace(params.Status),
+ Keyword: strings.TrimSpace(params.Keyword),
+ Offset: 0,
+ Size: 100,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ logs := make([]map[string]interface{}, 0, len(logResp.GetLogs()))
+ for _, item := range logResp.GetLogs() {
+ createdTime := ""
+ if item.GetCreatedAt() > 0 {
+ createdTime = timeutil.FormatTime("Y-m-d H:i:s", item.GetCreatedAt())
+ }
+ status := item.GetStatus()
+ if len(status) == 0 {
+ status = "failed"
+ }
+ errorCode := item.GetErrorCode()
+ if len(errorCode) == 0 {
+ errorCode = "none"
+ }
+
+ logs = append(logs, map[string]interface{}{
+ "time": createdTime,
+ "clusterId": item.GetClusterId(),
+ "serviceDomain": func() string {
+ serviceDomain := strings.TrimSpace(clusterDomainMap[item.GetClusterId()])
+ if len(serviceDomain) > 0 {
+ return serviceDomain
+ }
+ if len(strings.TrimSpace(item.GetClusterName())) > 0 {
+ return item.GetClusterName()
+ }
+ return "-"
+ }(),
+ "appName": item.GetAppName(),
+ "appId": item.GetAppId(),
+ "domain": item.GetDomain(),
+ "query": item.GetQtype(),
+ "clientIp": item.GetClientIP(),
+ "os": item.GetOs(),
+ "sdkVersion": item.GetSdkVersion(),
+ "ips": item.GetResultIPs(),
+ "status": status,
+ "errorCode": errorCode,
+ "costMs": item.GetCostMs(),
+ })
+ }
+
+ this.Data["resolveLogs"] = logs
+ this.Show()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/resolveLogs/init.go b/EdgeUser/internal/web/actions/default/httpdns/resolveLogs/init.go
new file mode 100644
index 0000000..05ce710
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/resolveLogs/init.go
@@ -0,0 +1,18 @@
+package resolveLogs
+
+import (
+ "github.com/TeaOSLab/EdgeUser/internal/web/helpers"
+ "github.com/iwind/TeaGo"
+)
+
+func init() {
+ TeaGo.BeforeStart(func(server *TeaGo.Server) {
+ server.
+ Helper(helpers.NewUserMustAuth("")).
+ Data("teaMenu", "httpdns").
+ Data("teaSubMenu", "resolveLogs").
+ Prefix("/httpdns/resolveLogs").
+ Get("", new(IndexAction)).
+ EndAll()
+ })
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/sandbox/index.go b/EdgeUser/internal/web/actions/default/httpdns/sandbox/index.go
new file mode 100644
index 0000000..316b8cd
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/sandbox/index.go
@@ -0,0 +1,100 @@
+package sandbox
+
+import (
+ "encoding/json"
+ "strings"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/httpdns/httpdnsutils"
+ "github.com/iwind/TeaGo/maps"
+)
+
+type IndexAction struct {
+ actionutils.ParentAction
+}
+
+func (this *IndexAction) Init() {
+ this.Nav("httpdns", "sandbox", "")
+}
+
+func (this *IndexAction) RunGet(params struct{}) {
+ httpdnsutils.AddLeftMenu(this.Parent())
+
+ clusterResp, err := this.RPC().HTTPDNSClusterRPC().FindAllHTTPDNSClusters(this.UserContext(), &pb.FindAllHTTPDNSClustersRequest{})
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ clusters := make([]maps.Map, 0, len(clusterResp.GetClusters()))
+ for _, cluster := range clusterResp.GetClusters() {
+ serviceDomain := strings.TrimSpace(cluster.GetServiceDomain())
+
+ port := "443"
+ if rawTLS := cluster.GetTlsPolicyJSON(); len(rawTLS) > 0 {
+ var tlsConfig map[string]interface{}
+ if err := json.Unmarshal(rawTLS, &tlsConfig); err == nil {
+ if listenRaw, ok := tlsConfig["listen"]; ok && listenRaw != nil {
+ if data, err := json.Marshal(listenRaw); err == nil {
+ var listenAddresses []map[string]interface{}
+ if err := json.Unmarshal(data, &listenAddresses); err == nil {
+ if len(listenAddresses) > 0 {
+ if portRange, ok := listenAddresses[0]["portRange"].(string); ok && len(portRange) > 0 {
+ port = portRange
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ apiAddress := "https://" + serviceDomain + ":" + port
+
+ displayName := apiAddress
+ if len(serviceDomain) == 0 {
+ displayName = cluster.GetName()
+ }
+ clusters = append(clusters, maps.Map{
+ "id": cluster.GetId(),
+ "name": cluster.GetName(),
+ "serviceDomain": serviceDomain,
+ "displayName": displayName,
+ })
+ }
+ this.Data["clusters"] = clusters
+
+ appResp, err := this.RPC().HTTPDNSAppRPC().FindAllHTTPDNSApps(this.UserContext(), &pb.FindAllHTTPDNSAppsRequest{})
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ apps := make([]maps.Map, 0, len(appResp.GetApps()))
+ for _, app := range appResp.GetApps() {
+ domainResp, err := this.RPC().HTTPDNSDomainRPC().ListHTTPDNSDomainsWithAppId(this.UserContext(), &pb.ListHTTPDNSDomainsWithAppIdRequest{
+ AppDbId: app.GetId(),
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ domains := make([]string, 0, len(domainResp.GetDomains()))
+ for _, domain := range domainResp.GetDomains() {
+ domains = append(domains, domain.GetDomain())
+ }
+ // 解析集群ID列表
+ var clusterIds []int64
+ if len(app.GetClusterIdsJSON()) > 0 {
+ _ = json.Unmarshal(app.GetClusterIdsJSON(), &clusterIds)
+ }
+
+ apps = append(apps, maps.Map{
+ "id": app.GetId(),
+ "name": app.GetName(),
+ "appId": app.GetAppId(),
+ "clusterIds": clusterIds,
+ "domains": domains,
+ })
+ }
+ this.Data["apps"] = apps
+ this.Show()
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/sandbox/init.go b/EdgeUser/internal/web/actions/default/httpdns/sandbox/init.go
new file mode 100644
index 0000000..99545ed
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/sandbox/init.go
@@ -0,0 +1,19 @@
+package sandbox
+
+import (
+ "github.com/TeaOSLab/EdgeUser/internal/web/helpers"
+ "github.com/iwind/TeaGo"
+)
+
+func init() {
+ TeaGo.BeforeStart(func(server *TeaGo.Server) {
+ server.
+ Helper(helpers.NewUserMustAuth("")).
+ Data("teaMenu", "httpdns").
+ Data("teaSubMenu", "sandbox").
+ Prefix("/httpdns/sandbox").
+ Get("", new(IndexAction)).
+ Post("/test", new(TestAction)).
+ EndAll()
+ })
+}
diff --git a/EdgeUser/internal/web/actions/default/httpdns/sandbox/test.go b/EdgeUser/internal/web/actions/default/httpdns/sandbox/test.go
new file mode 100644
index 0000000..997ad05
--- /dev/null
+++ b/EdgeUser/internal/web/actions/default/httpdns/sandbox/test.go
@@ -0,0 +1,173 @@
+package sandbox
+
+import (
+ "crypto/hmac"
+ "crypto/sha256"
+ "encoding/json"
+ "encoding/hex"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/login/loginutils"
+ "github.com/iwind/TeaGo/maps"
+ "github.com/iwind/TeaGo/rands"
+)
+
+type TestAction struct {
+ actionutils.ParentAction
+}
+
+func (this *TestAction) RunPost(params struct {
+ AppId string
+ ClusterId int64
+ Domain string
+ ClientIp string
+ Qtype string
+}) {
+ clientIP := strings.TrimSpace(params.ClientIp)
+ if len(clientIP) == 0 {
+ clientIP = strings.TrimSpace(loginutils.RemoteIP(&this.ActionObject))
+ }
+ qtype := strings.ToUpper(strings.TrimSpace(params.Qtype))
+ if len(qtype) == 0 {
+ qtype = "A"
+ }
+
+ resp, err := this.RPC().HTTPDNSSandboxRPC().TestHTTPDNSResolve(this.UserContext(), &pb.TestHTTPDNSResolveRequest{
+ ClusterId: params.ClusterId,
+ AppId: strings.TrimSpace(params.AppId),
+ Domain: strings.TrimSpace(params.Domain),
+ Qtype: qtype,
+ ClientIP: clientIP,
+ Sid: "",
+ SdkVersion: "",
+ Os: "",
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ clusterDomain := ""
+ port := "443"
+ if params.ClusterId > 0 {
+ clusterResp, findErr := this.RPC().HTTPDNSClusterRPC().FindAllHTTPDNSClusters(this.UserContext(), &pb.FindAllHTTPDNSClustersRequest{})
+ if findErr == nil {
+ for _, cluster := range clusterResp.GetClusters() {
+ if cluster.GetId() == params.ClusterId {
+ clusterDomain = strings.TrimSpace(cluster.GetServiceDomain())
+ if rawTLS := cluster.GetTlsPolicyJSON(); len(rawTLS) > 0 {
+ var tlsConfig map[string]interface{}
+ if err := json.Unmarshal(rawTLS, &tlsConfig); err == nil {
+ if listenRaw, ok := tlsConfig["listen"]; ok && listenRaw != nil {
+ if data, err := json.Marshal(listenRaw); err == nil {
+ var listenAddresses []map[string]interface{}
+ if err := json.Unmarshal(data, &listenAddresses); err == nil {
+ if len(listenAddresses) > 0 {
+ if portRange, ok := listenAddresses[0]["portRange"].(string); ok && len(portRange) > 0 {
+ port = portRange
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ break
+ }
+ }
+ }
+ }
+ if len(clusterDomain) == 0 {
+ clusterDomain = "httpdns.example.com"
+ }
+ query := url.Values{}
+ query.Set("appId", params.AppId)
+ query.Set("dn", params.Domain)
+ query.Set("qtype", qtype)
+ if len(clientIP) > 0 {
+ query.Set("cip", clientIP)
+ }
+
+ signEnabled, signSecret := this.findAppSignConfig(params.AppId)
+ if signEnabled && len(signSecret) > 0 {
+ exp := strconv.FormatInt(time.Now().Unix()+300, 10)
+ nonce := "sandbox-" + rands.HexString(16)
+ sign := buildSandboxResolveSign(signSecret, params.AppId, params.Domain, qtype, exp, nonce)
+ query.Set("exp", exp)
+ query.Set("nonce", nonce)
+ query.Set("sign", sign)
+ }
+ requestURL := "https://" + clusterDomain + ":" + port + "/resolve?" + query.Encode()
+
+ resultCode := 1
+ if strings.EqualFold(resp.GetCode(), "SUCCESS") {
+ resultCode = 0
+ }
+ rows := make([]maps.Map, 0, len(resp.GetRecords()))
+ ips := make([]string, 0, len(resp.GetRecords()))
+ lineName := strings.TrimSpace(resp.GetClientCarrier())
+ if len(lineName) == 0 {
+ lineName = "-"
+ }
+ for _, record := range resp.GetRecords() {
+ ips = append(ips, record.GetIp())
+ if lineName == "-" && len(record.GetLine()) > 0 {
+ lineName = record.GetLine()
+ }
+ rows = append(rows, maps.Map{
+ "domain": resp.GetDomain(),
+ "type": record.GetType(),
+ "ip": record.GetIp(),
+ "ttl": record.GetTtl(),
+ "region": record.GetRegion(),
+ "line": record.GetLine(),
+ })
+ }
+
+ this.Data["result"] = maps.Map{
+ "code": resultCode,
+ "message": resp.GetMessage(),
+ "requestId": resp.GetRequestId(),
+ "data": maps.Map{
+ "request_url": requestURL,
+ "client_ip": resp.GetClientIP(),
+ "client_region": resp.GetClientRegion(),
+ "line_name": lineName,
+ "ips": ips,
+ "records": rows,
+ "ttl": resp.GetTtl(),
+ },
+ }
+ this.Success()
+}
+
+func (this *TestAction) findAppSignConfig(appId string) (bool, string) {
+ appId = strings.TrimSpace(appId)
+ if len(appId) == 0 {
+ return false, ""
+ }
+
+ resp, err := this.RPC().HTTPDNSAppRPC().FindAllHTTPDNSApps(this.UserContext(), &pb.FindAllHTTPDNSAppsRequest{})
+ if err != nil {
+ return false, ""
+ }
+
+ for _, app := range resp.GetApps() {
+ if strings.EqualFold(strings.TrimSpace(app.GetAppId()), appId) {
+ return app.GetSignEnabled(), strings.TrimSpace(app.GetSignSecret())
+ }
+ }
+ return false, ""
+}
+
+func buildSandboxResolveSign(signSecret string, appID string, domain string, qtype string, exp string, nonce string) string {
+ raw := strings.TrimSpace(appID) + "|" + strings.ToLower(strings.TrimSpace(domain)) + "|" + strings.ToUpper(strings.TrimSpace(qtype)) + "|" + strings.TrimSpace(exp) + "|" + strings.TrimSpace(nonce)
+ mac := hmac.New(sha256.New, []byte(strings.TrimSpace(signSecret)))
+ _, _ = mac.Write([]byte(raw))
+ return hex.EncodeToString(mac.Sum(nil))
+}
diff --git a/EdgeUser/internal/web/helpers/user_must_auth.go b/EdgeUser/internal/web/helpers/user_must_auth.go
index 8954213..b9563f3 100644
--- a/EdgeUser/internal/web/helpers/user_must_auth.go
+++ b/EdgeUser/internal/web/helpers/user_must_auth.go
@@ -426,6 +426,29 @@ func (this *userMustAuth) modules(userId int64, isVerified bool, isIdentified bo
},**/
},
},
+ {
+ "code": "httpdns",
+ "name": "HTTPDNS",
+ "icon": "shield alternate",
+ "isOn": registerConfig != nil && registerConfig.HTTPDNSIsOn,
+ "subItems": []maps.Map{
+ {
+ "name": "应用管理",
+ "code": "app",
+ "url": "/httpdns/apps",
+ },
+ {
+ "name": "访问日志",
+ "code": "resolveLogs",
+ "url": "/httpdns/resolveLogs",
+ },
+ {
+ "name": "解析测试",
+ "code": "sandbox",
+ "url": "/httpdns/sandbox",
+ },
+ },
+ },
{
"code": "finance",
"name": "财务管理",
diff --git a/EdgeUser/internal/web/import.go b/EdgeUser/internal/web/import.go
index 1a415e8..9f0ed26 100644
--- a/EdgeUser/internal/web/import.go
+++ b/EdgeUser/internal/web/import.go
@@ -106,6 +106,12 @@ import (
_ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns"
_ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/routes"
+ // httpdns
+ _ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/httpdns"
+ _ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/httpdns/apps"
+ _ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/httpdns/resolveLogs"
+ _ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/httpdns/sandbox"
+
// api
_ "github.com/TeaOSLab/EdgeUser/internal/web/actions/default/api"
diff --git a/EdgeUser/web/views/@default/@layout.css b/EdgeUser/web/views/@default/@layout.css
index 30b7d37..38c8923 100644
--- a/EdgeUser/web/views/@default/@layout.css
+++ b/EdgeUser/web/views/@default/@layout.css
@@ -7,25 +7,30 @@
overflow-x: hidden;
border-right: 1px #ddd solid;
}
+
.left-box .menu {
width: 95% !important;
}
+
.left-box .menu .item {
line-height: 1.2;
position: relative;
padding-left: 1em !important;
}
+
.left-box .menu .item .icon {
position: absolute;
top: 50%;
left: 0;
margin-top: -0.4em !important;
}
+
.left-box .menu .item .sub-name {
font-size: 0.7em;
font-style: normal;
color: grey;
}
+
.left-box .menu .item.separator {
border-bottom: 1px #eee solid !important;
padding-top: 0;
@@ -33,9 +38,11 @@
margin-top: 0 !important;
margin-bottom: 0 !important;
}
+
.left-box .menu .item.on span {
border-bottom: 1px #666 dashed;
}
+
.left-box .menu .item.off span var {
font-style: normal;
background: #db2828;
@@ -45,33 +52,42 @@
border-radius: 2px;
margin-left: 1em;
}
+
.left-box .menu .item.active {
background: rgba(230, 230, 230, 0.35) !important;
border-radius: 3px;
}
+
.left-box .menu .header {
border-bottom: 1px #ddd solid;
padding-left: 0 !important;
padding-bottom: 1em !important;
}
+
.left-box::-webkit-scrollbar {
width: 4px;
}
+
.left-box.disabled {
opacity: 0.1;
}
+
.left-box.tiny {
top: 10.5em;
}
+
.left-box.without-tabbar {
top: 3em;
}
+
.left-box.with-menu {
top: 10em;
}
+
.left-box.without-menu {
top: 6em;
}
+
.right-box {
position: fixed;
top: 7.5em;
@@ -82,41 +98,52 @@
padding-bottom: 2em;
overflow-y: auto;
}
+
@media screen and (max-width: 512px) {
.right-box {
left: 13em;
padding-right: 1em;
}
}
+
body.expanded .right-box {
left: 10em;
}
+
.right-box.tiny {
top: 10.4em;
left: 26.5em;
}
+
.right-box::-webkit-scrollbar {
width: 4px;
}
+
.right-box.without-tabbar {
top: 3em;
}
+
.right-box.with-menu {
top: 10em;
}
+
.right-box.without-menu {
top: 6em;
}
+
.main.without-footer .left-box {
bottom: 0.2em;
}
+
.narrow-scrollbar::-webkit-scrollbar {
width: 4px;
}
+
.grid.counter-chart {
margin-top: 1em !important;
margin-left: 0.4em !important;
}
+
.grid.counter-chart .column {
margin-bottom: 1em;
font-size: 0.85em;
@@ -125,172 +152,216 @@ body.expanded .right-box {
border: 1px rgba(0, 0, 0, 0.1) solid;
border-right: 0;
}
+
.grid.counter-chart .column div.value {
margin-top: 1.5em;
font-weight: normal;
}
+
.grid.counter-chart .column div.value span {
font-size: 1.5em;
margin-right: 0.2em;
}
+
.grid.counter-chart .column.with-border {
border-right: 1px rgba(0, 0, 0, 0.1) solid;
}
+
.grid.counter-chart h4 {
color: grey;
position: relative;
font-size: 1em;
text-align: left;
}
+
.grid.counter-chart h4 a {
position: absolute;
right: 0.1em;
font-size: 1.26em;
display: none;
}
+
.grid.counter-chart .column:hover {
background: rgba(0, 0, 0, 0.03) !important;
}
+
.grid.counter-chart .column:hover a {
display: inline;
}
+
/** 通用 **/
* {
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
scrollbar-width: thin;
}
+
.clear {
clear: both;
}
+
.hidden {
display: none;
}
+
pre {
white-space: pre-wrap;
}
+
a.disabled,
a.disabled:hover,
a.disabled:active,
span.disabled {
color: #ccc !important;
}
+
a.enabled,
span.enabled,
span.green {
color: #21ba45;
}
+
a.grey,
span.grey,
label.grey,
p.grey {
color: grey !important;
}
+
p.grey {
margin-top: 0.8em;
}
+
span.red,
pre.red {
color: #db2828;
}
+
span.blue {
color: #4183c4;
}
+
span.orange {
color: #ff851b;
}
+
pre:not(.CodeMirror-line) {
font-family: Lato, 'Helvetica Neue', Arial, Helvetica, sans-serif !important;
}
+
tbody {
background: transparent;
}
+
.table.width30 {
width: 30em !important;
}
+
.table.width35 {
width: 35em !important;
}
+
.table.width40 {
width: 40em !important;
}
+
.table th,
.table td {
font-size: 0.9em !important;
}
+
.table tr.active td {
background: rgba(0, 0, 0, 0.01) !important;
}
+
p.comment,
div.comment {
color: #959da6;
padding-top: 0.4em;
font-size: 1em;
}
+
p.comment em,
div.comment em {
font-style: italic !important;
}
+
.truncate {
white-space: nowrap;
-ms-text-overflow: ellipsis;
overflow: hidden;
text-overflow: ellipsis;
}
+
div.margin,
p.margin {
margin-top: 1em;
}
+
/** 操作按钮容器 **/
.op.one {
width: 4em;
}
+
.op.two {
width: 7.4em;
}
+
.op.three {
width: 9em;
}
+
.op.four {
width: 10em;
}
+
/** 主菜单 **/
.main-menu {
width: 8em !important;
}
+
.main-menu .ui.menu {
width: 100% !important;
border-radius: 0 !important;
}
+
.main-menu .ui.menu .item.separator {
border-top: 1px rgba(0, 0, 0, 0.2) solid;
height: 1px;
min-height: 0;
padding: 0;
}
+
@media screen and (max-width: 512px) {
.main-menu {
width: auto !important;
}
+
.main-menu .ui.menu {
width: 3.6em !important;
}
+
.main-menu .ui.menu .item.separator {
display: none;
}
+
.main-menu .ui.menu .item {
padding-top: 2em;
padding-bottom: 2.4em;
}
}
+
.main-menu .ui.labeled.icon.menu .item {
font-size: 0.9em;
}
+
.main-menu .ui.menu {
padding-bottom: 3em;
}
+
.main-menu .ui.menu .item .subtitle {
display: none;
}
+
.main-menu .ui.menu .item.expend .subtitle {
display: block;
font-size: 10px;
@@ -298,20 +369,24 @@ p.margin {
margin-top: 0.5em;
color: grey;
}
+
@media screen and (max-width: 512px) {
.main-menu .ui.menu .item.expend .subtitle {
display: none;
}
}
+
.main-menu .ui.menu .sub-items .item {
padding-left: 2.8em !important;
padding-right: 0.4em !important;
}
+
.main-menu .ui.menu .sub-items .item .icon {
position: absolute;
left: 1.1em;
top: 0.93em;
}
+
.main-menu .ui.menu .sub-items .item .label {
margin-left: 0;
margin-right: 0;
@@ -319,42 +394,53 @@ p.margin {
padding-right: 0.4em;
min-width: 2em;
}
+
@media screen and (max-width: 512px) {
.main-menu .ui.menu .sub-items .item {
padding-left: 1em !important;
}
}
+
.main-menu .ui.menu .item.active {
background: rgba(230, 230, 230, 0.45) !important;
}
+
.main-menu .ui.menu .sub-items .item.active {
background: rgba(230, 230, 230, 0.55) !important;
}
+
/** 扩展UI **/
.field.text {
padding: 0.5em;
}
+
/** body **/
@keyframes blink {
from {
opacity: 0.1;
}
+
to {
opacity: 0.8;
}
}
+
body .ui.menu .item .blink {
animation: blink 1s infinite;
}
+
body.expanded .main-menu {
display: none;
}
+
body.expanded .sub-menu {
display: none;
}
+
body.expanded .main {
left: 1em;
}
+
/** 布局相关 */
.top-nav {
border-radius: 0 !important;
@@ -364,9 +450,11 @@ body.expanded .main {
overflow-x: auto;
background: #14539A !important;
}
+
.top-nav::-webkit-scrollbar {
height: 2px;
}
+
.top-nav img.avatar {
width: 1.6em !important;
height: 1.6em !important;
@@ -375,20 +463,25 @@ body.expanded .main {
border-radius: 0.9em;
margin-right: 0.5em !important;
}
+
.top-nav em {
font-style: normal;
font-size: 0.9em;
padding-left: 0.2em;
}
+
.top-nav .item.red {
color: red !important;
}
+
.top-nav .item .hover-span span {
display: none;
}
+
.top-nav .item:hover .hover-span span {
display: inline;
}
+
/** 顶部菜单 **/
.top-secondary-menu {
position: fixed;
@@ -398,23 +491,28 @@ body.expanded .main {
z-index: 100;
background: white;
}
+
.top-secondary-menu .menu {
margin-top: 0 !important;
margin-bottom: 0 !important;
border-radius: 0 !important;
}
+
.top-secondary-menu .menu var {
font-style: normal;
}
+
.top-secondary-menu .divider {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
+
@media screen and (max-width: 512px) {
.top-secondary-menu {
left: 4em;
}
}
+
/** 右侧主操作区 **/
.main {
position: absolute;
@@ -424,78 +522,99 @@ body.expanded .main {
padding-right: 1em;
right: 1em;
}
+
@media screen and (max-width: 512px) {
.main {
left: 4em;
}
}
+
.main.without-menu {
left: 9em;
}
+
.main.without-secondary-menu {
top: 2.9em;
}
+
@media screen and (max-width: 512px) {
.main.without-menu {
left: 4em;
}
}
+
.main table td.title {
width: 10em;
}
+
.main table td.middle-title {
width: 14em;
}
+
.main table td {
vertical-align: top;
}
+
.main table td.color-border {
border-left: 1px #276ac6 solid !important;
}
+
.main table td.vertical-top {
vertical-align: top;
}
+
.main table td.vertical-middle {
vertical-align: middle;
}
+
.main table td[colspan="2"] a {
font-weight: normal;
}
+
.main table td em {
font-weight: normal;
font-style: normal;
font-size: 0.9em;
}
+
.main h3 {
font-weight: normal;
margin-top: 1em !important;
position: relative;
}
+
.main h3 span {
font-size: 0.8em;
}
+
.main h3 span.label {
color: #6435c9;
}
+
.main h3 a {
margin-left: 1em;
font-size: 14px !important;
right: 1em;
}
+
.main h4 {
font-weight: normal;
}
+
.main form h4 {
margin-top: 0.6em;
}
+
.main td span.small {
font-size: 0.8em;
}
+
.main .button.mini {
font-size: 0.8em;
padding: 0.2em;
margin-left: 1em;
}
+
.main-menu {
position: fixed;
/**top: 1.05em;**/
@@ -505,37 +624,47 @@ body.expanded .main {
background: #14539A !important;
z-index: 10;
}
+
.main-menu .menu {
background: #14539A !important;
}
+
.main-menu::-webkit-scrollbar {
width: 2px;
}
+
.main .tab-menu {
margin-top: 1em !important;
margin-bottom: 0 !important;
overflow-x: auto;
overflow-y: hidden;
}
+
.main .tab-menu .item {
padding: 1em !important;
}
+
.main .tab-menu .item var {
font-style: normal;
}
+
.main .tab-menu .item span {
font-size: 0.8em;
padding-left: 0.3em;
}
+
.main .tab-menu .item .icon {
margin-left: 0.6em;
}
+
.main .tab-menu .item.active {
background: #f8f8f9 !important;
}
+
.main .tab-menu::-webkit-scrollbar {
height: 4px;
}
+
.main .go-top-btn {
position: fixed;
right: 2.6em;
@@ -546,10 +675,12 @@ body.expanded .main {
z-index: 999999;
background: white;
}
+
/** 子菜单 **/
.main.without-menu .sub-menu {
display: none;
}
+
.sub-menu {
position: fixed;
left: 8em;
@@ -557,6 +688,7 @@ body.expanded .main {
top: 3em;
bottom: 2.8em;
}
+
.sub-menu .menus-box {
overflow-y: auto;
position: absolute;
@@ -566,14 +698,17 @@ body.expanded .main {
left: 0;
padding-right: 0.4em !important;
}
+
.sub-menu .menus-box::-webkit-scrollbar {
width: 4px;
height: 4px;
}
+
.sub-menu .menu {
max-width: 12em !important;
border-right: 0 !important;
}
+
@media screen and (max-width: 512px) {
.sub-menu {
position: relative;
@@ -581,32 +716,39 @@ body.expanded .main {
left: 0;
top: 0;
}
+
.sub-menu .menus-box {
position: relative !important;
}
+
.sub-menu .menu {
width: 100% !important;
max-width: 30em !important;
}
+
.sub-menu .menus-box .menu .item {
width: 100% !important;
max-width: 30em !important;
}
}
+
.sub-menu .menu .item.active {
font-weight: normal !important;
outline: none !important;
}
+
.sub-menu .menu .item:not(.header) {
padding-top: 0.7em !important;
padding-bottom: 0.7em !important;
}
+
.sub-menu .menu .item:not(.header) span {
font-size: 0.8em;
display: block;
margin-top: 0.6em !important;
line-height: 1.5;
}
+
.sub-menu .menu .item:not(.active):hover {
background: rgba(0, 0, 0, 0.05) !important;
border-top: 1px white solid !important;
@@ -614,53 +756,67 @@ body.expanded .main {
margin-top: -1px !important;
margin-bottom: -1px !important;
}
+
.sub-menu .menu .item.active {
background: rgba(0, 0, 0, 0.05) !important;
}
+
.sub-menu .menu .item var {
font-style: normal;
}
+
.sub-menu .menu .item:not(.active) var.grey {
color: grey;
}
+
.sub-menu .menu .item span:not(.green) {
color: grey;
}
+
.sub-menu .menu .item span.red {
color: #db2828 !important;
}
+
.sub-menu .menus-box .menu .item.header {
padding-right: 0.2em !important;
cursor: pointer;
}
+
.sub-menu .menus-box .menu .item.header span {
font-weight: normal;
color: grey;
font-size: 0.8em;
}
+
.sub-menu .menus-box .menu a {
display: block;
word-break: break-all;
line-height: 1.6 !important;
}
+
.sub-menu .menus-box .menu .item .menu {
margin-top: 0 !important;
}
+
.sub-menu .fourth-menu {
margin-left: 1.2em;
}
+
.sub-menu .fourth-menu .icon,
.sub-menu .third-menu .icon {
float: left !important;
}
+
/** 右侧文本子菜单 **/
.text.menu {
overflow-x: auto;
}
+
.text.menu::-webkit-scrollbar {
width: 4px;
height: 4px;
}
+
/** 脚部相关样式 **/
#footer {
position: fixed;
@@ -672,27 +828,34 @@ body.expanded .main {
z-index: 10;
overflow-x: auto;
}
+
#footer::-webkit-scrollbar {
height: 2px;
}
+
#footer a {
font-size: 0.9em;
}
+
#footer a form {
display: none;
}
+
#footer a:hover span,
#footer a:active span {
display: none;
}
+
#footer a:hover form,
#footer a:active form {
display: block;
}
+
#footer form input {
padding: 0;
margin: 0;
}
+
#footer-outer-box {
z-index: 999999;
position: fixed;
@@ -702,6 +865,7 @@ body.expanded .main {
background: rgba(0, 0, 0, 0.8);
bottom: 2.6em;
}
+
#footer-outer-box .qrcode {
width: 20em;
position: absolute;
@@ -710,92 +874,115 @@ body.expanded .main {
margin-top: -14em;
margin-left: -10em;
}
+
#footer-outer-box .qrcode img {
width: 100%;
}
+
#footer-outer-box .qrcode a {
position: absolute;
right: 0.5em;
top: 0.5em;
}
+
@media screen and (max-width: 512px) {
#footer-outer-box .qrcode {
margin-left: 0;
left: 3.5em;
}
}
+
/** Vue **/
[v-cloak] {
display: none !important;
}
+
/** auto complete **/
.autocomplete-box .menu {
background: #eee !important;
}
+
.autocomplete-box .menu::-webkit-scrollbar {
width: 4px;
}
+
.autocomplete-box .menu .item {
border-top: none !important;
}
+
select.auto-width {
width: auto !important;
}
+
/** column **/
@media screen and (max-width: 512px) {
.column:not(.one) {
width: 100% !important;
}
}
+
label[for] {
cursor: pointer !important;
}
+
label.blue {
color: #2185d0 !important;
}
+
/** Menu **/
.first-menu .menu.text {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
+
.first-menu .divider {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
+
.second-menu .menu.text {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
+
.second-menu .menu.text em {
font-style: normal;
}
+
.second-menu .divider {
margin-top: 0 !important;
}
+
.menu a {
outline: none;
}
+
/** var **/
span.olive,
var.olive {
color: #b5cc18 !important;
}
+
span.dash {
border-bottom: 1px dashed grey;
}
+
span.hover:hover {
background: #eee;
}
+
/** checkbox **/
.checkbox label a,
.checkbox label {
font-size: 0.9em !important;
}
+
/** page **/
.page {
margin-top: 1em;
border-left: 1px solid #ddd;
}
+
.page a {
display: inline-block;
background: #fafafa;
@@ -806,62 +993,78 @@ span.hover:hover {
border: 1px solid #ddd;
border-left: 0;
}
+
.page a.active {
background: #2185d0 !important;
color: white;
}
+
.page a:hover {
background: #eee;
}
+
.page select {
padding-top: 0.3em !important;
padding-bottom: 0.3em !important;
}
+
/** popup **/
.swal2-html-container {
overflow-x: hidden;
}
+
.swal2-close,
.swal2-close:focus {
border: 0;
}
+
.swal2-confirm:focus,
.swal2-cancel:focus {
border: 3px #ddd solid !important;
}
+
.swal2-confirm,
.swal2-cancel {
border: 3px #fff solid !important;
}
+
.swal2-cancel {
margin-left: 2em !important;
}
+
/** 排序 **/
.sortable-ghost {
background: #ddd !important;
opacity: 0.1;
}
+
.sortable-drag {
opacity: 1;
}
+
.icon.handle {
cursor: pointer;
}
+
.label.port-label {
margin-top: 0.4em !important;
margin-bottom: 0.4em !important;
display: block;
line-height: 1.5;
}
+
.label {
word-break: break-all;
}
+
td .label.small {
margin-bottom: 0.2em !important;
}
+
td {
word-break: break-all;
}
+
.combo-box .menu {
max-height: 17em;
overflow-y: auto;
@@ -870,29 +1073,94 @@ td {
border-top: 0;
z-index: 100;
}
+
.combo-box .menu::-webkit-scrollbar {
width: 4px;
}
+
.methods-box {
background: white;
}
+
.methods-box .method-box {
margin-bottom: 1em;
padding: 0.5em 1em;
border: 1px #eee solid;
}
+
.methods-box .method-box.active {
border: 1px #eee solid;
background: #eee;
}
+
.methods-box .method-box:hover {
background: #eee;
cursor: pointer;
}
+
.scroll-box {
overflow-y: auto;
}
+
.scroll-box::-webkit-scrollbar {
width: 4px;
}
-/*# sourceMappingURL=@layout.css.map */
\ No newline at end of file
+
+/*# sourceMappingURL=@layout.css.map */
+/* Override Primary Button Color for WAF Platform */
+.ui.primary.button,
+.ui.primary.buttons .button {
+ background-color: #0f2c54 !important;
+ color: #ffffff !important;
+}
+
+.ui.primary.button:hover,
+.ui.primary.buttons .button:hover {
+ background-color: #0a1f3a !important;
+}
+
+.ui.primary.button:focus,
+.ui.primary.buttons .button:focus {
+ background-color: #08192e !important;
+}
+
+.ui.primary.button:active,
+.ui.primary.buttons .button:active,
+.ui.primary.active.button {
+ background-color: #050d18 !important;
+}
+
+.text-primary,
+.blue {
+ color: #0f2c54 !important;
+}
+
+/* Override Semantic UI Default Blue */
+.ui.blue.button,
+.ui.blue.buttons .button {
+ background-color: #0f2c54 !important;
+ color: #ffffff !important;
+}
+
+.ui.blue.button:hover,
+.ui.blue.buttons .button:hover {
+ background-color: #0a1f3a !important;
+}
+
+.ui.basic.blue.button,
+.ui.basic.blue.buttons .button {
+ box-shadow: 0 0 0 1px #0f2c54 inset !important;
+ color: #0f2c54 !important;
+}
+
+.ui.basic.blue.button:hover,
+.ui.basic.blue.buttons .button:hover {
+ background: transparent !important;
+ box-shadow: 0 0 0 1px #0a1f3a inset !important;
+ color: #0a1f3a !important;
+}
+
+.ui.menu .active.item {
+ border-color: #2185d0 !important;
+ color: #2185d0 !important;
+}
\ No newline at end of file
diff --git a/EdgeUser/web/views/@default/@layout.html b/EdgeUser/web/views/@default/@layout.html
index b66981f..0344605 100644
--- a/EdgeUser/web/views/@default/@layout.html
+++ b/EdgeUser/web/views/@default/@layout.html
@@ -18,10 +18,10 @@
{$echo "header"}
@@ -80,8 +80,8 @@
class="disabled">消息(0)
-
-
+
+
{{teaUsername}}
-
+ :class="{active:teaMenu == module.code && (teaSubMenu || '').length == 0, separator:(module.code || '').length == 0}"
+ :style="(teaMenu == module.code && (teaSubMenu || '').length == 0) ? 'background: rgba(230, 230, 230, 0.45) !important;' : ''">
+
{{module.name}}
@@ -131,14 +131,14 @@
-
{$echo "footer"}
diff --git a/EdgeUser/web/views/@default/@layout_popup.css b/EdgeUser/web/views/@default/@layout_popup.css
index 0fcc986..c98900b 100644
--- a/EdgeUser/web/views/@default/@layout_popup.css
+++ b/EdgeUser/web/views/@default/@layout_popup.css
@@ -3,57 +3,72 @@
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
scrollbar-width: thin;
}
+
.clear {
clear: both;
}
+
.hidden {
display: none;
}
+
pre {
white-space: pre-wrap;
}
+
a.disabled,
a.disabled:hover,
a.disabled:active,
span.disabled {
color: #ccc !important;
}
+
a.enabled,
span.enabled,
span.green {
color: #21ba45;
}
+
span.grey,
label.grey,
p.grey {
color: grey !important;
}
+
p.grey {
margin-top: 0.8em;
}
+
span.red,
pre.red {
color: #db2828;
}
+
pre:not(.CodeMirror-line) {
font-family: Lato, 'Helvetica Neue', Arial, Helvetica, sans-serif !important;
}
+
tbody {
background: transparent;
}
+
.table.width30 {
width: 30em !important;
}
+
.table.width35 {
width: 35em !important;
}
+
.table.width40 {
width: 40em !important;
}
+
.table th,
.table td {
font-size: 0.9em !important;
}
+
p.comment,
div.comment {
color: #959da6;
@@ -62,37 +77,46 @@ div.comment {
word-break: break-all;
line-height: 1.8;
}
+
p.comment em,
div.comment em {
font-style: italic !important;
}
+
.truncate {
white-space: nowrap;
-ms-text-overflow: ellipsis;
overflow: hidden;
text-overflow: ellipsis;
}
+
div.margin,
p.margin {
margin-top: 1em;
}
+
/** 操作按钮容器 **/
.op.one {
width: 4em;
}
+
.op.two {
width: 7.4em;
}
+
.op.three {
width: 9em;
}
+
.op.four {
width: 10em;
}
+
/** 扩展UI **/
.field.text {
padding: 0.5em;
}
+
/** 右侧主操作区 **/
.main {
position: absolute;
@@ -102,169 +126,214 @@ p.margin {
padding-right: 1em;
right: 1em;
}
+
@media screen and (max-width: 512px) {
.main {
left: 4em;
}
}
+
.main.without-menu {
left: 9em;
}
+
.main.without-secondary-menu {
top: 2.9em;
}
+
@media screen and (max-width: 512px) {
.main.without-menu {
left: 4em;
}
}
+
.main table td.title {
width: 10em;
}
+
.main table td.middle-title {
width: 14em;
}
+
.main table td {
vertical-align: top;
}
+
.main table td.color-border {
border-left: 1px #276ac6 solid !important;
}
+
.main table td.vertical-top {
vertical-align: top;
}
+
.main table td.vertical-middle {
vertical-align: middle;
}
+
.main table td[colspan="2"] a {
font-weight: normal;
}
+
.main table td em {
font-weight: normal;
font-style: normal;
font-size: 0.9em;
}
+
.main h3 {
font-weight: normal;
margin-top: 0.5em !important;
}
+
.main h3 span {
font-size: 0.8em;
}
+
.main h3 span.label {
color: #6435c9;
}
+
.main h3 a {
margin-left: 1em;
font-size: 14px !important;
right: 1em;
}
+
.main h3 a::before {
content: "[";
}
+
.main h3 a::after {
content: "]";
}
+
.main h4 {
font-weight: normal;
}
+
.main td span.small {
font-size: 0.8em;
}
+
.main .button.mini {
font-size: 0.8em;
padding: 0.2em;
margin-left: 1em;
}
+
/** 右侧文本子菜单 **/
.text.menu {
overflow-x: auto;
}
+
.text.menu::-webkit-scrollbar {
width: 4px;
height: 4px;
}
+
/** Vue **/
[v-cloak] {
display: none !important;
}
+
/** auto complete **/
.autocomplete-box .menu {
background: #eee !important;
}
+
.autocomplete-box .menu::-webkit-scrollbar {
width: 4px;
}
+
.autocomplete-box .menu .item {
border-top: none !important;
}
+
select.auto-width {
width: auto !important;
}
+
/** column **/
@media screen and (max-width: 512px) {
.column:not(.one) {
width: 100% !important;
}
}
+
/** label **/
label[for] {
cursor: pointer !important;
}
+
label.blue {
color: #2185d0 !important;
}
+
span.blue {
color: #4183c4;
}
+
/** Menu **/
.first-menu .menu.text {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
+
.first-menu .divider {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
+
.second-menu .menu.text {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
+
.second-menu .menu.text em {
font-style: normal;
}
+
.second-menu .divider {
margin-top: 0 !important;
}
+
.menu a {
outline: none;
}
+
/** var **/
span.olive,
var.olive {
color: #b5cc18 !important;
}
+
span.dash {
border-bottom: 1px dashed grey;
}
+
span.hover:hover {
background: #eee;
}
+
/** Message **/
.message .gopher {
width: 30px;
margin-right: 10px;
}
+
/** checkbox **/
.checkbox label a,
.checkbox label {
font-size: 0.8em !important;
}
+
/** page **/
.page {
margin-top: 1em;
border-left: 1px solid #ddd;
}
+
.page a {
display: inline-block;
background: #fafafa;
@@ -275,30 +344,37 @@ span.hover:hover {
border: 1px solid #ddd;
border-left: 0;
}
+
.page a.active {
background: #2185d0 !important;
color: white;
}
+
.page a:hover {
background: #eee;
}
+
/** popup **/
.swal2-html-container {
overflow-x: hidden;
}
+
.swal2-confirm:focus,
.swal2-cancel:focus,
.swal2-close:focus {
border: 3px #ddd solid !important;
}
+
.swal2-confirm,
.swal2-cancel,
.swal2-close {
border: 3px #fff solid !important;
}
+
.swal2-cancel {
margin-left: 2em !important;
}
+
.combo-box .menu {
max-height: 17em;
overflow-y: auto;
@@ -307,9 +383,11 @@ span.hover:hover {
border-top: 0;
z-index: 100;
}
+
.combo-box .menu::-webkit-scrollbar {
width: 4px;
}
+
code-label {
background: #fff;
border: 1px solid rgba(34, 36, 38, 0.15);
@@ -323,4 +401,62 @@ code-label {
font-weight: 700;
vertical-align: baseline;
}
-/*# sourceMappingURL=@layout_popup.css.map */
\ No newline at end of file
+
+/*# sourceMappingURL=@layout_popup.css.map */
+/* Override Primary Button Color for WAF Platform */
+.ui.primary.button,
+.ui.primary.buttons .button {
+ background-color: #0f2c54 !important;
+ color: #ffffff !important;
+}
+
+.ui.primary.button:hover,
+.ui.primary.buttons .button:hover {
+ background-color: #0a1f3a !important;
+}
+
+.ui.primary.button:focus,
+.ui.primary.buttons .button:focus {
+ background-color: #08192e !important;
+}
+
+.ui.primary.button:active,
+.ui.primary.buttons .button:active,
+.ui.primary.active.button {
+ background-color: #050d18 !important;
+}
+
+.text-primary,
+.blue {
+ color: #0f2c54 !important;
+}
+
+/* Override Semantic UI Default Blue */
+.ui.blue.button,
+.ui.blue.buttons .button {
+ background-color: #0f2c54 !important;
+ color: #ffffff !important;
+}
+
+.ui.blue.button:hover,
+.ui.blue.buttons .button:hover {
+ background-color: #0a1f3a !important;
+}
+
+.ui.basic.blue.button,
+.ui.basic.blue.buttons .button {
+ box-shadow: 0 0 0 1px #0f2c54 inset !important;
+ color: #0f2c54 !important;
+}
+
+.ui.basic.blue.button:hover,
+.ui.basic.blue.buttons .button:hover {
+ background: transparent !important;
+ box-shadow: 0 0 0 1px #0a1f3a inset !important;
+ color: #0a1f3a !important;
+}
+
+.ui.menu .active.item {
+ border-color: #2185d0 !important;
+ color: #2185d0 !important;
+}
\ No newline at end of file
diff --git a/EdgeUser/web/views/@default/httpdns/apps/@menu.html b/EdgeUser/web/views/@default/httpdns/apps/@menu.html
new file mode 100644
index 0000000..dda96cc
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/@menu.html
@@ -0,0 +1,4 @@
+
+ 应用列表
+ [添加应用]
+
\ No newline at end of file
diff --git a/EdgeUser/web/views/@default/httpdns/apps/appSettings.html b/EdgeUser/web/views/@default/httpdns/apps/appSettings.html
new file mode 100644
index 0000000..dd3e861
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/appSettings.html
@@ -0,0 +1,140 @@
+{$layout}
+{$template "menu"}
+{$template "/left_menu_with_menu"}
+
+
+
+
\ No newline at end of file
diff --git a/EdgeUser/web/views/@default/httpdns/apps/appSettings.js b/EdgeUser/web/views/@default/httpdns/apps/appSettings.js
new file mode 100644
index 0000000..1f5d8f6
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/appSettings.js
@@ -0,0 +1,95 @@
+Tea.context(function () {
+ this.activeSection = this.activeSection || "basic";
+ this.success = NotifyReloadSuccess("保存成功");
+ this.signSecretVisible = false;
+
+ this.toggleSignEnabled = function () {
+ let that = this;
+ let targetIsOn = !this.settings.signEnabled;
+
+ if (targetIsOn) {
+ teaweb.confirm("html:开启后,服务端会对解析请求进行签名鉴权,未签名、签名无效或过期的请求都会解析失败 ,确认开启吗?", function () {
+ that.$post("/httpdns/apps/app/settings/toggleSignEnabled")
+ .params({
+ appId: that.app.id,
+ isOn: 1
+ })
+ .success(function () {
+ that.settings.signEnabled = true;
+ teaweb.success("请求验签已开启");
+ });
+ });
+ return;
+ }
+
+ teaweb.confirm("html:关闭后,服务端不会对解析请求进行签名鉴权,可能存在被刷风险 ,确认关闭吗?", function () {
+ that.$post("/httpdns/apps/app/settings/toggleSignEnabled")
+ .params({
+ appId: that.app.id,
+ isOn: 0
+ })
+ .success(function () {
+ that.settings.signEnabled = false;
+ teaweb.success("请求验签已关闭");
+ });
+ });
+ };
+
+ this.copySecret = function (text, name) {
+ if (typeof text != "string" || text.length == 0) {
+ teaweb.warn("没有可复制的内容");
+ return;
+ }
+
+ if (navigator.clipboard && navigator.clipboard.writeText) {
+ navigator.clipboard.writeText(text).then(function () {
+ teaweb.success(name + "已复制");
+ }).catch(function () {
+ this.copyByTextarea(text, name);
+ }.bind(this));
+ return;
+ }
+
+ this.copyByTextarea(text, name);
+ };
+
+ this.copyByTextarea = function (text, name) {
+ let input = document.createElement("textarea");
+ input.value = text;
+ input.setAttribute("readonly", "readonly");
+ input.style.position = "fixed";
+ input.style.left = "-10000px";
+ input.style.top = "-10000px";
+ document.body.appendChild(input);
+ input.select();
+
+ let ok = false;
+ try {
+ ok = document.execCommand("copy");
+ } catch (e) {
+ ok = false;
+ }
+ document.body.removeChild(input);
+
+ if (ok) {
+ teaweb.success(name + "已复制");
+ } else {
+ teaweb.warn("复制失败,请手动复制");
+ }
+ };
+
+ this.resetSignSecret = function () {
+ let that = this;
+ teaweb.confirm("确定要重置加签 Secret 吗?", function () {
+ that.$post("/httpdns/apps/app/settings/resetSignSecret")
+ .params({
+ appId: that.app.id
+ })
+ .success(function () {
+ teaweb.success("加签 Secret 已重置", function () {
+ teaweb.reload();
+ });
+ });
+ });
+ };
+});
diff --git a/EdgeUser/web/views/@default/httpdns/apps/create.html b/EdgeUser/web/views/@default/httpdns/apps/create.html
new file mode 100644
index 0000000..7f329f4
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/create.html
@@ -0,0 +1,16 @@
+{$layout}
+{$template "menu"}
+
+
\ No newline at end of file
diff --git a/EdgeUser/web/views/@default/httpdns/apps/create.js b/EdgeUser/web/views/@default/httpdns/apps/create.js
new file mode 100644
index 0000000..79b655f
Binary files /dev/null and b/EdgeUser/web/views/@default/httpdns/apps/create.js differ
diff --git a/EdgeUser/web/views/@default/httpdns/apps/customRecords.html b/EdgeUser/web/views/@default/httpdns/apps/customRecords.html
new file mode 100644
index 0000000..9a0763c
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/customRecords.html
@@ -0,0 +1,55 @@
+{$layout}
+
+
+
+
+ {{app.name}}
+ »
+ 域名列表
+ »
+ {{domain.name}}
+ 创建规则
+
+
+
+
+
+ 线路
+ 规则名称
+ 解析记录
+ TTL
+ 状态
+ 操作
+
+
+
+
+ {{record.lineText}}
+ {{record.ruleName}}
+ {{record.recordValueText}}
+ {{record.ttl}}s
+
+ 已启用
+ 已停用
+
+
+ 编辑 |
+ {{record.isOn ? "停用" : "启用"}} |
+ 删除
+
+
+
+
+
+当前应用暂无可用域名,请先到域名管理中添加域名。
+当前域名还没有自定义解析规则。
diff --git a/EdgeUser/web/views/@default/httpdns/apps/customRecords.js b/EdgeUser/web/views/@default/httpdns/apps/customRecords.js
new file mode 100644
index 0000000..cd65c73
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/customRecords.js
@@ -0,0 +1,60 @@
+Tea.context(function () {
+ if (typeof this.records == "undefined") {
+ this.records = [];
+ }
+
+ this.createRecord = function () {
+ if (!this.domain || !this.domain.id) {
+ return;
+ }
+ teaweb.popup("/httpdns/apps/customRecords/createPopup?appId=" + this.app.id + "&domainId=" + this.domain.id, {
+ width: "42em",
+ height: "33em",
+ title: "新增自定义解析规则",
+ callback: function () {
+ teaweb.success("保存成功", function () {
+ teaweb.reload();
+ });
+ }
+ });
+ };
+
+ this.editRecord = function (recordId) {
+ if (!this.domain || !this.domain.id) {
+ return;
+ }
+ teaweb.popup("/httpdns/apps/customRecords/createPopup?appId=" + this.app.id + "&domainId=" + this.domain.id + "&recordId=" + recordId, {
+ width: "42em",
+ height: "33em",
+ title: "编辑自定义解析规则",
+ callback: function () {
+ teaweb.success("保存成功", function () {
+ teaweb.reload();
+ });
+ }
+ });
+ };
+
+ this.deleteRecord = function (recordId) {
+ let that = this;
+ teaweb.confirm("确定要删除这条自定义解析规则吗?", function () {
+ that.$post("/httpdns/apps/customRecords/delete")
+ .params({
+ appId: that.app.id,
+ recordId: recordId
+ })
+ .refresh();
+ });
+ };
+
+ this.toggleRecord = function (record) {
+ let that = this;
+ that.$post("/httpdns/apps/customRecords/toggle")
+ .params({
+ appId: that.app.id,
+ recordId: record.id,
+ isOn: record.isOn ? 0 : 1
+ })
+ .refresh();
+ };
+});
diff --git a/EdgeUser/web/views/@default/httpdns/apps/customRecordsCreatePopup.html b/EdgeUser/web/views/@default/httpdns/apps/customRecordsCreatePopup.html
new file mode 100644
index 0000000..c286ddc
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/customRecordsCreatePopup.html
@@ -0,0 +1,160 @@
+{$layout "layout_popup"}
+
+
+
+编辑自定义解析规则
+新增自定义解析规则
+
+
diff --git a/EdgeUser/web/views/@default/httpdns/apps/customRecordsCreatePopup.js b/EdgeUser/web/views/@default/httpdns/apps/customRecordsCreatePopup.js
new file mode 100644
index 0000000..e8bc6a0
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/customRecordsCreatePopup.js
@@ -0,0 +1,158 @@
+Tea.context(function () {
+ var vm = this;
+
+ if (typeof vm.record == "undefined" || vm.record == null) {
+ vm.record = {};
+ }
+
+ vm.chinaCarriers = ["默认", "电信", "联通", "移动", "教育网", "鹏博士", "广电"];
+ vm.chinaRegions = ["默认", "东北", "华北", "华东", "华南", "华中", "西北", "西南"];
+ vm.chinaRegionProvinces = {
+ "默认": ["默认"],
+ "东北": ["默认", "辽宁", "吉林", "黑龙江"],
+ "华北": ["默认", "北京", "天津", "河北", "山西", "内蒙古"],
+ "华东": ["默认", "上海", "江苏", "浙江", "安徽", "福建", "江西", "山东"],
+ "华南": ["默认", "广东", "广西", "海南"],
+ "华中": ["默认", "河南", "湖北", "湖南"],
+ "西北": ["默认", "陕西", "甘肃", "青海", "宁夏", "新疆"],
+ "西南": ["默认", "重庆", "四川", "贵州", "云南", "西藏"]
+ };
+
+ vm.continents = ["默认", "亚洲", "欧洲", "北美洲", "南美洲", "非洲", "大洋洲"];
+ vm.continentCountries = {
+ "默认": ["默认"],
+ "亚洲": ["默认", "中国香港", "中国澳门", "中国台湾", "日本", "韩国", "新加坡", "印度", "泰国", "越南",
+ "印度尼西亚", "马来西亚", "菲律宾", "柬埔寨", "缅甸", "老挝", "斯里兰卡", "孟加拉国", "巴基斯坦", "尼泊尔",
+ "阿联酋", "沙特阿拉伯", "土耳其", "以色列", "伊朗", "伊拉克", "卡塔尔", "科威特", "蒙古"],
+ "欧洲": ["默认", "德国", "英国", "法国", "荷兰", "西班牙", "意大利", "俄罗斯",
+ "波兰", "瑞典", "瑞士", "挪威", "芬兰", "丹麦", "葡萄牙", "爱尔兰", "比利时", "奥地利",
+ "乌克兰", "捷克", "罗马尼亚", "匈牙利", "希腊"],
+ "北美洲": ["默认", "美国", "加拿大", "墨西哥", "巴拿马", "哥斯达黎加", "古巴"],
+ "南美洲": ["默认", "巴西", "阿根廷", "智利", "哥伦比亚", "秘鲁", "委内瑞拉", "厄瓜多尔"],
+ "非洲": ["默认", "南非", "埃及", "尼日利亚", "肯尼亚", "摩洛哥", "阿尔及利亚", "坦桑尼亚", "埃塞俄比亚", "加纳", "突尼斯"],
+ "大洋洲": ["默认", "澳大利亚", "新西兰"]
+ };
+
+ vm.parseJSONList = function (raw) {
+ if (typeof raw == "undefined" || raw == null || raw == "") {
+ return [];
+ }
+
+ if (Array.isArray(raw)) {
+ return raw;
+ }
+
+ try {
+ var list = JSON.parse(raw);
+ if (Array.isArray(list)) {
+ return list;
+ }
+ } catch (e) {
+ }
+
+ return [];
+ };
+
+ vm.normalizeBoolean = function (value, defaultValue) {
+ if (typeof value == "boolean") {
+ return value;
+ }
+ if (typeof value == "number") {
+ return value > 0;
+ }
+ if (typeof value == "string") {
+ value = value.toLowerCase();
+ return value == "1" || value == "true" || value == "yes" || value == "on";
+ }
+ return defaultValue;
+ };
+
+ vm.record.lineScope = vm.record.lineScope == "overseas" ? "overseas" : "china";
+ vm.record.lineCarrier = vm.record.lineCarrier || "默认";
+ vm.record.lineRegion = vm.record.lineRegion || "默认";
+ vm.record.lineProvince = vm.record.lineProvince || "默认";
+ vm.record.lineContinent = vm.record.lineContinent || "默认";
+ vm.record.lineCountry = vm.record.lineCountry || "默认";
+ vm.record.ruleName = vm.record.ruleName || "";
+ vm.record.ttl = vm.record.ttl || 30;
+ vm.record.weightEnabled = vm.normalizeBoolean(vm.record.weightEnabled, false);
+ vm.record.isOn = vm.normalizeBoolean(vm.record.isOn, true);
+
+ vm.recordItems = vm.parseJSONList(vm.record.recordItemsJson);
+ if (vm.recordItems.length == 0) {
+ vm.recordItems.push({type: "A", value: "", weight: 100});
+ } else {
+ for (var i = 0; i < vm.recordItems.length; i++) {
+ var item = vm.recordItems[i];
+ if (item.type != "A" && item.type != "AAAA") {
+ item.type = "A";
+ }
+ if (typeof item.weight == "undefined" || item.weight == null || item.weight === "") {
+ item.weight = 100;
+ }
+ }
+ }
+
+ vm.provinceOptions = ["默认"];
+ vm.countryOptions = ["默认"];
+
+ vm.refreshProvinceOptions = function () {
+ var provinces = vm.chinaRegionProvinces[vm.record.lineRegion];
+ if (!Array.isArray(provinces) || provinces.length == 0) {
+ provinces = ["默认"];
+ }
+ vm.provinceOptions = provinces;
+ if (vm.provinceOptions.indexOf(vm.record.lineProvince) < 0) {
+ vm.record.lineProvince = vm.provinceOptions[0];
+ }
+ };
+
+ vm.refreshCountryOptions = function () {
+ var countries = vm.continentCountries[vm.record.lineContinent];
+ if (!Array.isArray(countries) || countries.length == 0) {
+ countries = ["默认"];
+ }
+ vm.countryOptions = countries;
+ if (vm.countryOptions.indexOf(vm.record.lineCountry) < 0) {
+ vm.record.lineCountry = vm.countryOptions[0];
+ }
+ };
+
+ vm.onChinaRegionChange = function () {
+ vm.refreshProvinceOptions();
+ };
+
+ vm.onContinentChange = function () {
+ vm.refreshCountryOptions();
+ };
+
+ vm.onLineScopeChange = function () {
+ if (vm.record.lineScope == "overseas") {
+ vm.record.lineContinent = vm.record.lineContinent || "默认";
+ vm.refreshCountryOptions();
+ } else {
+ vm.record.lineCarrier = vm.record.lineCarrier || "默认";
+ vm.record.lineRegion = vm.record.lineRegion || "默认";
+ vm.refreshProvinceOptions();
+ }
+ };
+
+ vm.addRecordItem = function () {
+ if (vm.recordItems.length >= 10) {
+ return;
+ }
+ vm.recordItems.push({type: "A", value: "", weight: 100});
+ };
+
+ vm.removeRecordItem = function (index) {
+ if (index < 0 || index >= vm.recordItems.length) {
+ return;
+ }
+ vm.recordItems.splice(index, 1);
+ if (vm.recordItems.length == 0) {
+ vm.recordItems.push({type: "A", value: "", weight: 100});
+ }
+ };
+
+ vm.onLineScopeChange();
+});
diff --git a/EdgeUser/web/views/@default/httpdns/apps/delete.html b/EdgeUser/web/views/@default/httpdns/apps/delete.html
new file mode 100644
index 0000000..b374ce3
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/delete.html
@@ -0,0 +1,12 @@
+{$layout}
+
+
+ {{app.name}}
+ »
+ 删除应用
+
+
+
+ 删除当前应用
+
+
diff --git a/EdgeUser/web/views/@default/httpdns/apps/delete.js b/EdgeUser/web/views/@default/httpdns/apps/delete.js
new file mode 100644
index 0000000..6c30c8e
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/delete.js
@@ -0,0 +1,16 @@
+Tea.context(function () {
+ this.deleteApp = function (appId) {
+ let that = this;
+ teaweb.confirm("确定要删除此应用吗?", function () {
+ that.$post("/httpdns/apps/delete")
+ .params({
+ appId: appId
+ })
+ .success(function () {
+ teaweb.success("删除成功", function () {
+ window.location = "/httpdns/apps";
+ });
+ });
+ });
+ };
+});
diff --git a/EdgeUser/web/views/@default/httpdns/apps/docs/android.md b/EdgeUser/web/views/@default/httpdns/apps/docs/android.md
new file mode 100644
index 0000000..795d558
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/docs/android.md
@@ -0,0 +1,36 @@
+# Android SDK
+
+## 初始化
+
+```java
+new InitConfig.Builder()
+ .setContext(context)
+ .setPrimaryServiceHost("httpdns-a.example.com")
+ .setBackupServiceHost("httpdns-b.example.com")
+ .setServicePort(443)
+ .setSecretKey("your-sign-secret")
+ .setEnableHttps(true)
+ .buildFor("app1f1ndpo9");
+```
+
+## 解析
+
+```java
+HTTPDNSResult result = httpDnsService.getHttpDnsResultForHostSyncNonBlocking(
+ "api.business.com",
+ RequestIpType.auto,
+ null,
+ null
+);
+```
+
+## 官方业务适配器
+
+```java
+HttpDnsHttpAdapter adapter = HttpDns.buildHttpClientAdapter(httpDnsService);
+HttpDnsAdapterResponse resp = adapter.execute(
+ new HttpDnsAdapterRequest("GET", "https://api.business.com/v1/ping")
+);
+```
+
+固定策略:IP 直连 + 空 SNI + Host=真实域名,不回退到带 SNI。
diff --git a/EdgeUser/web/views/@default/httpdns/apps/docs/flutter.md b/EdgeUser/web/views/@default/httpdns/apps/docs/flutter.md
new file mode 100644
index 0000000..7a1b112
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/docs/flutter.md
@@ -0,0 +1,35 @@
+# Flutter SDK
+
+## 初始化
+
+```dart
+await AliyunHttpdns.init(
+ appId: 'app1f1ndpo9',
+ primaryServiceHost: 'httpdns-a.example.com',
+ backupServiceHost: 'httpdns-b.example.com',
+ servicePort: 443,
+ secretKey: 'your-sign-secret',
+);
+await AliyunHttpdns.build();
+```
+
+## 解析
+
+```dart
+final result = await AliyunHttpdns.resolveHostSyncNonBlocking(
+ 'api.business.com',
+ ipType: 'both',
+);
+```
+
+## 官方业务适配器
+
+```dart
+final adapter = AliyunHttpdns.createHttpAdapter();
+final resp = await adapter.request(
+ Uri.parse('https://api.business.com/v1/ping'),
+ method: 'GET',
+);
+```
+
+固定策略:IP 直连 + 空 SNI + Host=真实域名,不回退到带 SNI。
diff --git a/EdgeUser/web/views/@default/httpdns/apps/docs/ios.md b/EdgeUser/web/views/@default/httpdns/apps/docs/ios.md
new file mode 100644
index 0000000..a90381e
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/docs/ios.md
@@ -0,0 +1,31 @@
+# iOS SDK
+
+## 初始化
+
+```objc
+HttpdnsEdgeService *service = [[HttpdnsEdgeService alloc]
+ initWithAppId:@"app1f1ndpo9"
+primaryServiceHost:@"httpdns-a.example.com"
+ backupServiceHost:@"httpdns-b.example.com"
+ servicePort:443
+ signSecret:@"your-sign-secret"];
+```
+
+## 解析
+
+```objc
+[service resolveHost:@"api.business.com" queryType:@"A" completion:^(HttpdnsEdgeResolveResult * _Nullable result, NSError * _Nullable error) {
+ // result.ipv4s / result.ipv6s
+}];
+```
+
+## 官方业务适配器
+
+```objc
+NSURL *url = [NSURL URLWithString:@"https://api.business.com/v1/ping"];
+[service requestURL:url method:@"GET" headers:nil body:nil completion:^(NSData * _Nullable data, NSHTTPURLResponse * _Nullable response, NSError * _Nullable error) {
+ // handle
+}];
+```
+
+固定策略:IP 直连 + 空 SNI + Host=真实域名,不回退到带 SNI。
diff --git a/EdgeUser/web/views/@default/httpdns/apps/domains.html b/EdgeUser/web/views/@default/httpdns/apps/domains.html
new file mode 100644
index 0000000..7baf7a7
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/domains.html
@@ -0,0 +1,62 @@
+{$layout}
+
+
+
+
+
+ {{app.name}}
+ »
+ 域名列表
+ 创建域名
+
+
+
+
+
+
+
+
+
+
+
+
+ 服务域名
+ 规则策略
+ 操作
+
+
+
+
+
+ {{domain.name}}
+
+
+ {{domain.customRecordCount}}
+
+
+ 自定义解析
+ |
+ 解绑
+
+
+
+
+
+当前应用尚未绑定域名。
+没有匹配的域名。
diff --git a/EdgeUser/web/views/@default/httpdns/apps/domains.js b/EdgeUser/web/views/@default/httpdns/apps/domains.js
new file mode 100644
index 0000000..cc5678b
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/domains.js
@@ -0,0 +1,73 @@
+Tea.context(function () {
+ var that = this;
+
+ if (typeof this.keywordInput == "undefined" || this.keywordInput == null) {
+ this.keywordInput = "";
+ }
+ if (typeof this.keyword == "undefined" || this.keyword == null) {
+ this.keyword = "";
+ }
+
+ if (typeof this.domains == "undefined" || this.domains == null) {
+ this.domains = [];
+ }
+
+ this.keywordInput = String(this.keyword);
+
+ this.doSearch = function () {
+ that.keyword = String(that.keywordInput || "").trim();
+ };
+
+ this.clearSearch = function () {
+ that.keywordInput = "";
+ that.keyword = "";
+ };
+
+ this.filteredDomains = function () {
+ let keyword = (that.keyword || "").trim().toLowerCase();
+ if (keyword.length == 0) {
+ return that.domains || [];
+ }
+ return (that.domains || []).filter(function (domain) {
+ let name = (domain.name || "").toLowerCase();
+ return name.indexOf(keyword) >= 0;
+ });
+ };
+
+ this.bindDomain = function () {
+ teaweb.popup("/httpdns/apps/domains/createPopup?appId=" + that.app.id, {
+ height: "12em",
+ width: "36em",
+ title: "添加域名",
+ callback: function () {
+ teaweb.success("保存成功", function () {
+ teaweb.reload();
+ });
+ }
+ });
+ };
+
+ this.deleteApp = function () {
+ let that = this;
+ teaweb.confirm("确定要删除当前应用吗?", function () {
+ that.$post("/httpdns/apps/delete")
+ .params({
+ appId: that.app.id
+ })
+ .success(function () {
+ window.location = "/httpdns/apps";
+ });
+ });
+ };
+
+ this.deleteDomain = function (domainId) {
+ let that = this;
+ teaweb.confirm("确定要解绑这个域名吗?", function () {
+ that.$post("/httpdns/apps/domains/delete")
+ .params({
+ domainId: domainId
+ })
+ .refresh();
+ });
+ };
+});
diff --git a/EdgeUser/web/views/@default/httpdns/apps/domainsCreatePopup.html b/EdgeUser/web/views/@default/httpdns/apps/domainsCreatePopup.html
new file mode 100644
index 0000000..f55fd69
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/domainsCreatePopup.html
@@ -0,0 +1,18 @@
+{$layout "layout_popup"}
+
+添加域名
+
+
diff --git a/EdgeUser/web/views/@default/httpdns/apps/index.html b/EdgeUser/web/views/@default/httpdns/apps/index.html
new file mode 100644
index 0000000..0d9bc35
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/index.html
@@ -0,0 +1,71 @@
+{$layout}
+{$template "menu"}
+
+
+
+
+
+
+
+
+
暂时没有符合条件的 HTTPDNS 应用。
+
+
+
+
+
\ No newline at end of file
diff --git a/EdgeUser/web/views/@default/httpdns/apps/index.js b/EdgeUser/web/views/@default/httpdns/apps/index.js
new file mode 100644
index 0000000..a415a1d
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/index.js
@@ -0,0 +1,9 @@
+Tea.context(function () {
+ if (typeof this.apps == "undefined") {
+ this.apps = [];
+ }
+
+ this.createApp = function () {
+ window.location = "/httpdns/apps/create";
+ };
+});
diff --git a/EdgeUser/web/views/@default/httpdns/apps/sdk.html b/EdgeUser/web/views/@default/httpdns/apps/sdk.html
new file mode 100644
index 0000000..c4b7e85
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/sdk.html
@@ -0,0 +1,79 @@
+{$layout}
+
+
+
+
+ {{app.name}}
+ »
+ SDK 集成
+
+
+
+
+
+
+
Java / Kotlin
+
适用于 Android 客户端接入。
+
+
+
+
+
+
+
+
Objective-C / Swift
+
适用于 iOS 客户端接入。
+
+
+
+
+
+
+
+
Dart / Plugin
+
适用于 Flutter 跨平台接入。
+
+
+
+
diff --git a/EdgeUser/web/views/@default/httpdns/apps/sdk.js b/EdgeUser/web/views/@default/httpdns/apps/sdk.js
new file mode 100644
index 0000000..fcf5fd4
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/apps/sdk.js
@@ -0,0 +1,123 @@
+Tea.context(function () {
+ this.downloadSDK = function (platform, event) {
+ this.checkAndDownload(platform, "sdk", event)
+ }
+
+ this.downloadDoc = function (platform, event) {
+ this.checkAndDownload(platform, "doc", event)
+ }
+
+ this.checkAndDownload = function (platform, type, event) {
+ if (event != null && typeof event.preventDefault == "function") {
+ event.preventDefault()
+ }
+
+ this.$get("/httpdns/apps/sdk/check")
+ .params({
+ platform: platform,
+ type: type
+ })
+ .success(function (resp) {
+ let data = (resp != null && resp.data != null) ? resp.data : {}
+ if (!data.exists) {
+ teaweb.warn(data.message || "当前暂无可下载文件")
+ return
+ }
+ if (typeof data.url == "string" && data.url.length > 0) {
+ this.downloadByBlob(data.url, platform, type)
+ return
+ }
+ teaweb.warn("下载地址生成失败,请稍后重试")
+ }.bind(this))
+ }
+
+ this.downloadByBlob = function (url, platform, type) {
+ let defaultFileName = "httpdns-sdk-" + platform + (type == "doc" ? ".md" : ".zip")
+
+ let xhr = new XMLHttpRequest()
+ xhr.open("GET", url, true)
+ xhr.responseType = "blob"
+
+ xhr.onload = function () {
+ if (xhr.status < 200 || xhr.status >= 300) {
+ teaweb.warn("下载失败(HTTP " + xhr.status + ")")
+ return
+ }
+ if (xhr.status == 204) {
+ teaweb.warn("下载被浏览器扩展或下载工具拦截,请暂时关闭相关扩展后重试")
+ return
+ }
+
+ let contentType = (xhr.getResponseHeader("Content-Type") || "").toLowerCase()
+ if (contentType.indexOf("application/json") >= 0) {
+ let reader = new FileReader()
+ reader.onload = function () {
+ try {
+ let json = JSON.parse(reader.result)
+ teaweb.warn((json && json.message) ? json.message : "下载失败,请稍后重试")
+ } catch (_e) {
+ teaweb.warn("下载失败,请稍后重试")
+ }
+ }
+ reader.readAsText(xhr.response)
+ return
+ }
+
+ let disposition = xhr.getResponseHeader("Content-Disposition") || ""
+ let fileName = xhr.getResponseHeader("X-SDK-Filename") || this.parseFileName(disposition) || defaultFileName
+ if (xhr.response == null || xhr.response.size <= 0) {
+ teaweb.warn("下载文件为空,请检查已上传 SDK 包是否完整")
+ return
+ }
+ this.saveBlob(xhr.response, fileName)
+ }.bind(this)
+
+ xhr.onerror = function () {
+ teaweb.warn("下载失败,请检查网络后重试")
+ }
+
+ xhr.send()
+ }
+
+ this.parseFileName = function (disposition) {
+ if (typeof disposition != "string" || disposition.length == 0) {
+ return ""
+ }
+
+ let utf8Match = disposition.match(/filename\*=UTF-8''([^;]+)/i)
+ if (utf8Match != null && utf8Match.length > 1) {
+ try {
+ return decodeURIComponent(utf8Match[1])
+ } catch (_e) {
+ }
+ }
+
+ let plainMatch = disposition.match(/filename="?([^";]+)"?/i)
+ if (plainMatch != null && plainMatch.length > 1) {
+ return plainMatch[1]
+ }
+
+ return ""
+ }
+
+ this.saveBlob = function (blob, fileName) {
+ if (window.navigator != null && typeof window.navigator.msSaveOrOpenBlob == "function") {
+ window.navigator.msSaveOrOpenBlob(blob, fileName)
+ return
+ }
+
+ let objectURL = window.URL.createObjectURL(blob)
+ let a = document.createElement("a")
+ a.style.display = "none"
+ a.href = objectURL
+ a.download = fileName
+ document.body.appendChild(a)
+ a.click()
+ setTimeout(function () {
+ window.URL.revokeObjectURL(objectURL)
+ if (a.parentNode != null) {
+ a.parentNode.removeChild(a)
+ }
+ }, 30000)
+ }
+})
diff --git a/EdgeUser/web/views/@default/httpdns/resolveLogs/@menu.html b/EdgeUser/web/views/@default/httpdns/resolveLogs/@menu.html
new file mode 100644
index 0000000..72927ed
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/resolveLogs/@menu.html
@@ -0,0 +1,3 @@
+
+ 访问日志
+
diff --git a/EdgeUser/web/views/@default/httpdns/resolveLogs/index.html b/EdgeUser/web/views/@default/httpdns/resolveLogs/index.html
new file mode 100644
index 0000000..4bfc158
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/resolveLogs/index.html
@@ -0,0 +1,94 @@
+{$layout}
+
+
+
+
+
+
+
+
+
+暂时还没有访问日志。
+
+
+
+
+
+
+ API服务地址
+ 域名
+ 类型
+ 概要
+
+
+
+
+ {{log.serviceDomain}}
+ {{log.domain}}
+ {{log.query}}
+
+
+ {{log.time}}
+ | {{log.appName}} ({{log.appId}})
+ | {{log.clientIp}}
+ | {{log.os}}/{{log.sdkVersion}}
+ | {{log.query}} {{log.domain}} ->
+ {{log.ips}}
+ [无记录]
+ |
+ 成功
+ 失败
+ ({{log.errorCode}})
+ | {{log.costMs}}ms
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EdgeUser/web/views/@default/httpdns/sandbox/@menu.html b/EdgeUser/web/views/@default/httpdns/sandbox/@menu.html
new file mode 100644
index 0000000..397eae3
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/sandbox/@menu.html
@@ -0,0 +1,4 @@
+
+
+ 解析测试
+
\ No newline at end of file
diff --git a/EdgeUser/web/views/@default/httpdns/sandbox/index.html b/EdgeUser/web/views/@default/httpdns/sandbox/index.html
new file mode 100644
index 0000000..ffb8af1
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/sandbox/index.html
@@ -0,0 +1,149 @@
+{$layout}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{response.message}}
+
Request ID: {{response.requestId}}
+
+
+
+
+
+
+
请求URL
+
+ {{response.data.request_url || '-'}}
+
+
+
+
+
+
+
+
客户端 IP
+
+ {{response.data.client_ip || request.clientIp || '-'}}
+
+
+
+
+
+
地区
+
{{response.data.client_region || '-'}}
+
+
+
+
+
线路
+
{{response.data.line_name || '-'}}
+
+
+
+
+
+
+
+
+
+ 解析域名
+ 解析类型
+ IP地址
+ TTL
+ 地区
+ 线路
+
+
+
+
+ {{row.domain ||
+ request.domain}}
+ {{row.type || request.qtype}}
+ {{row.ip}}
+ {{row.ttl}}s
+ {{row.region || '-'}}
+ {{row.line || '-'}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EdgeUser/web/views/@default/httpdns/sandbox/index.js b/EdgeUser/web/views/@default/httpdns/sandbox/index.js
new file mode 100644
index 0000000..0fb9b6f
--- /dev/null
+++ b/EdgeUser/web/views/@default/httpdns/sandbox/index.js
@@ -0,0 +1,160 @@
+Tea.context(function () {
+ this.newRequest = function () {
+ return {
+ appId: "",
+ clusterId: "",
+ domain: "",
+ clientIp: "",
+ qtype: "A"
+ }
+ }
+
+ this.request = this.newRequest()
+
+ this.response = {
+ hasResult: false,
+ code: -1,
+ message: "",
+ data: null,
+ requestId: "",
+ resultRows: []
+ }
+
+ this.isRequesting = false
+ this.currentDomains = []
+ this.currentClusters = []
+
+ if (typeof this.apps === "undefined" || this.apps == null) {
+ this.apps = []
+ }
+ if (typeof this.clusters === "undefined" || this.clusters == null) {
+ this.clusters = []
+ }
+
+ this.onAppChanged = function () {
+ let selectedApp = null
+ for (let i = 0; i < this.apps.length; i++) {
+ if (this.apps[i].appId === this.request.appId) {
+ selectedApp = this.apps[i]
+ break
+ }
+ }
+
+ if (selectedApp == null) {
+ this.currentDomains = []
+ this.currentClusters = []
+ this.request.domain = ""
+ this.request.clusterId = ""
+ return
+ }
+
+ this.currentDomains = Array.isArray(selectedApp.domains) ? selectedApp.domains : []
+
+ if (this.currentDomains.length > 0) {
+ if (this.currentDomains.indexOf(this.request.domain) < 0) {
+ this.request.domain = this.currentDomains[0]
+ }
+ } else {
+ this.request.domain = ""
+ }
+
+ let appClusterIds = Array.isArray(selectedApp.clusterIds) ? selectedApp.clusterIds.map(Number) : []
+
+ let allowed = []
+ for (let i = 0; i < this.clusters.length; i++) {
+ let cluster = this.clusters[i]
+ let clusterId = Number(cluster.id)
+ if (clusterId <= 0) {
+ continue
+ }
+ if (appClusterIds.indexOf(clusterId) >= 0) {
+ allowed.push(cluster)
+ }
+ }
+ this.currentClusters = allowed
+
+ if (allowed.length > 0) {
+ if (!allowed.some((c) => String(c.id) === String(this.request.clusterId))) {
+ this.request.clusterId = String(allowed[0].id)
+ }
+ } else {
+ this.request.clusterId = ""
+ }
+ }
+
+ this.normalizeResultRows = function (data) {
+ if (typeof data === "undefined" || data == null) {
+ return []
+ }
+
+ if (Array.isArray(data.records) && data.records.length > 0) {
+ return data.records
+ }
+
+ let rows = []
+ let ips = Array.isArray(data.ips) ? data.ips : []
+ let domain = this.request.domain
+ let qtype = this.request.qtype
+ let ttl = data.ttl || 0
+ let region = data.client_region || "-"
+ let line = data.line_name || "-"
+
+ ips.forEach(function (ip) {
+ rows.push({
+ domain: domain,
+ type: qtype,
+ ip: ip,
+ ttl: ttl,
+ region: region,
+ line: line
+ })
+ })
+
+ return rows
+ }
+
+ this.sendTestRequest = function () {
+ if (this.request.appId.length === 0) {
+ teaweb.warn("请选择目标应用")
+ return
+ }
+ if (this.request.clusterId.length === 0) {
+ teaweb.warn("当前应用未绑定可用集群,请先在应用设置中配置所属集群")
+ return
+ }
+ if (this.request.domain.length === 0) {
+ teaweb.warn("请选择要解析的域名")
+ return
+ }
+
+ this.isRequesting = true
+ this.response.hasResult = false
+
+ let payload = Object.assign({}, this.request)
+
+ this.$post("/httpdns/sandbox/test")
+ .params(payload)
+ .success(function (resp) {
+ this.response = resp.data.result
+ this.response.hasResult = true
+ this.response.resultRows = this.normalizeResultRows(this.response.data)
+ })
+ .done(function () {
+ this.isRequesting = false
+ })
+ }
+
+ this.resetForm = function () {
+ this.request = this.newRequest()
+ this.currentDomains = []
+ this.currentClusters = []
+ this.response = {
+ hasResult: false,
+ code: -1,
+ message: "",
+ data: null,
+ requestId: "",
+ resultRows: []
+ }
+ }
+})
diff --git a/HttpDNSSDK/.gitignore b/HttpDNSSDK/.gitignore
new file mode 100644
index 0000000..115313d
--- /dev/null
+++ b/HttpDNSSDK/.gitignore
@@ -0,0 +1,130 @@
+# ==========================================
+# HttpDNSSDK Unified .gitignore
+# ==========================================
+
+# OS generated files
+.DS_Store
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+Icon?
+ehthumbs.db
+Thumbs.db
+*.swp
+
+# IDEs and Editors
+.idea/
+.vscode/
+.kiro/
+*.iml
+*.ipr
+*.iws
+.classpath
+.project
+.settings/
+.cursor/
+.claude/
+.AGENTS.md
+
+# General Build & Gradle
+build/
+Build/
+.gradle/
+target/
+gen/
+out/
+bin/
+/gradlew
+/gradlew.bat
+
+# Android
+*.apk
+*.aab
+*.ap_
+*.dex
+*.class
+captures/
+.externalNativeBuild/
+.cxx/
+local.properties
+nohup.out
+*.hprof
+google-services.json
+sdk/android/app/libs/new-android-httpdns-*.aar
+
+# Keys and Keystores
+*.jks
+*.keystore
+key.properties
+
+# iOS / Xcode
+xcuserdata
+*.xccheckout
+*.xcworkspace
+Products/
+xcodebuild.log
+sdk/ios/src/Documentation/*
+sdk/ios/src/docs/docset/*
+sdk/ios/src/docs/docset-installed.txt
+sdk/ios/src/aws-ios-sdk-*.zip
+sdk/ios/tmpFileRunSonarSh
+
+# CocoaPods
+Pods/
+Podfile.lock
+
+# Flutter
+.dart_tool/
+.packages
+.symlinks/
+.generated/
+Flutter/App.framework
+Flutter/Flutter.framework
+Flutter/Flutter.podspec
+Flutter/Generated.xcconfig
+Flutter/ephemeral/
+Flutter/app.flx
+Flutter/app.zip
+Flutter/flutter_assets/
+Flutter/flutter_export_environment.sh
+Runner/GeneratedPluginRegistrant.*
+GeneratedPluginRegistrant.java
+
+# Patched code / Sonar
+*.bak
+.sonar/
+infer-out/
+compile_commands.json
+oclint.xml
+sonar-reports/
+
+# Stuff that can't be committed
+credentials.json
+Documentation
+Scripts/build.sh
+Scripts/gcovr
+Scripts/jenkins.py
+Scripts/ocunit2junit
+
+# specific files
+sdk/ios/NewHttpDNSTests/Network/server.pem
+ServiceDefinitions.json
+profile
+
+# Flutter Example iOS Exceptions
+!default.mode1v3
+!default.mode2v3
+!default.pbxuser
+!default.perspectivev3
+**/dgph
+*.mode1v3
+*.mode2v3
+*.moved-aside
+*.pbxuser
+*.perspectivev3
+**/*sync/
+.sconsign.dblite
+.tags*
+**/.vagrant/
+**/DerivedData/
diff --git a/HttpDNSSDK/docs/Flutter SDK集成文档.md b/HttpDNSSDK/docs/Flutter SDK集成文档.md
new file mode 100644
index 0000000..0ede62c
--- /dev/null
+++ b/HttpDNSSDK/docs/Flutter SDK集成文档.md
@@ -0,0 +1,133 @@
+# Flutter SDK 集成文档(Edge HTTPDNS)
+
+## 1. 版本与依赖
+
+- SDK 插件:`HttpDNSSDK/sdk/flutter/new_httpdns`
+- 环境要求:Flutter 2.15+ / Dart 2.15+
+
+在 `pubspec.yaml` 中引用本地插件:
+
+```yaml
+dependencies:
+ new_httpdns:
+ path: path/to/sdk/flutter/new_httpdns
+```
+
+执行 `flutter pub get` 完成安装。
+
+## 2. SNI 行为说明(关键)
+
+1. **/resolve 请求链路**(SDK -> 你的 HTTPDNS 服务域名)
+- 走标准 HTTPS,默认携带 SNI(用于路由到边缘控制节点)。
+
+2. **业务请求链路**(拿到 CDN IP 后发起业务 HTTPS)
+- **IP 直连 + No-SNI**:使用 `TrustAPPHttpdnsHttpAdapter` 进行请求。
+- 逻辑:解析域名 -> 拿到 IP 列表 -> `uri.replace(host: ip)` -> `req.headers.host = uri.host` -> **清空 SNI**。
+- 仅支持 HTTPS URL。
+
+## 3. 初始化 SDK(推荐用 TrustAPP 封装)
+
+### Dart
+
+```dart
+import 'package:new_httpdns/new_httpdns.dart';
+
+bool ok = await TrustAPPHttpdns.init(
+ appId: "your-app-id",
+ primaryServiceHost: "httpdns.example.com",
+ backupServiceHost: "httpdns-backup.example.com",
+ servicePort: 443,
+ secretKey: "your-sign-secret" // 可选,开启签名校验需传入
+);
+
+if (ok) {
+ print("Edge HTTPDNS 初始化成功");
+}
+```
+
+## 4. 解析域名获取 CDN IP
+
+### Dart
+
+```dart
+// V1 风格解析接口
+Map result = await TrustAPPHttpdns.resolveHost(
+ "api.example.com",
+ qtype: 'A', // 可选 'A' 或 'AAAA'
+ cip: '1.2.3.4' // 可选,模拟客户端 IP
+);
+
+List ipv4s = result['ipv4'];
+int ttl = result['ttl'];
+```
+
+## 5. 业务请求接入方式
+
+使用 `TrustAPPHttpdnsHttpAdapter` 实现“SNI 隐匿”业务请求。
+
+### Dart
+
+```dart
+final adapter = TrustAPPHttpdns.createHttpAdapter(
+ options: const TrustAPPHttpdnsAdapterOptions(
+ connectTimeoutMs: 3000,
+ readTimeoutMs: 5000,
+ ipType: 'auto', // auto/ipv4/ipv6
+ )
+);
+
+try {
+ final res = await adapter.request(
+ Uri.parse("https://api.example.com/path?x=1"),
+ method: 'GET',
+ headers: {'Custom-Header': 'Value'},
+ body: null
+ );
+
+ print("Status Code: ${res.statusCode}");
+ print("Body Length: ${res.body.length}");
+ print("Used IP: ${res.usedIp}");
+} catch (e) {
+ print("请求失败: $e");
+}
+```
+
+## 6. 其他常用接口
+
+```dart
+// 1. 设置预解析域名
+await TrustAPPHttpdns.setPreResolveHosts(["api.example.com", "img.example.com"]);
+
+// 2. 只有开启缓存时可用
+Map> cacheRes = await TrustAPPHttpdns.resolveHostSyncNonBlocking("api.example.com");
+
+// 3. 开启持久化缓存(重启 App 后任然可用)
+await TrustAPPHttpdns.setPersistentCacheIPEnabled(true);
+
+// 4. 控制台日志(建议仅调试开启)
+await TrustAPPHttpdns.setLogEnabled(true);
+```
+
+## 7. 验证建议
+
+1. **验证 /resolve**
+- 观察控制台日志或抓包工具,解析请求应指向 `https://:/resolve...`。
+
+2. **验证业务请求**
+- 如果使用 `TrustAPPHttpdnsHttpAdapter`,观察抓包:
+ - TCP 连接 IP 为 CDN 私有/边缘 IP。
+ - HTTP `Host` 为原始域名。
+ - TLS ClientHello 中 **无 SNI** 扩展。
+
+## 8. 平台配置事项
+
+- **Android**: 参照 Android SDK 文档配置混淆。
+- **iOS**: 如果是手动集成 Flutter 插件,请确保 iOS 模块已包含依赖的静态库,并设置 `Allow Arbitrary Loads` (如果启用 HTTP)。
+
+## 9. 常见问题
+
+1. **Flutter 端报错:NO_IP_AVAILABLE**
+- SDK 尚未解析出有效结果,请确认域名是否已在控制台添加并配置规则。
+
+2. **请求报错:TLS_EMPTY_SNI_FAILED**
+- 仅支持 HTTPS 网站。如果所有 IP 尝试均失败,请检查网络权限及服务端防火墙。
diff --git a/HttpDNSSDK/docs/HTTPDNS SDK 集成文档(Android).md b/HttpDNSSDK/docs/HTTPDNS SDK 集成文档(Android).md
new file mode 100644
index 0000000..fd75e5b
--- /dev/null
+++ b/HttpDNSSDK/docs/HTTPDNS SDK 集成文档(Android).md
@@ -0,0 +1,161 @@
+# HTTPDNS SDK 集成文档(Android)
+
+## 1. 版本与依赖
+
+- SDK 模块:`HttpDNSSDK/sdk/android/httpdns-sdk`
+- `minSdkVersion`:19
+- `targetSdkVersion`:33
+- `compileSdk`:33
+
+将发布包中的 `jar/aar` 放到应用模块 `libs/`,在 `app/build.gradle` 中添加:
+
+```gradle
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
+ implementation 'androidx.appcompat:appcompat:1.6.1'
+}
+```
+
+## 2. SNI 行为说明(关键)
+
+当前 SDK 行为与代码一致:
+
+1. `/resolve` 请求链路(SDK -> 你的 HTTPDNS 服务域名)
+- 走域名 HTTPS
+- 默认 TLS 行为(会带 SNI)
+
+2. 业务请求链路(拿到 CDN IP 后发起业务 HTTPS)
+- 使用 `HttpDnsHttpAdapter`:按 IP 建连,`Host` 保留原域名,并清空 SNI(No-SNI)
+
+## 3. 初始化 SDK(推荐用 V1 客户端)
+
+### Kotlin
+
+```kotlin
+import com.newsdk.sdk.android.httpdns.HttpDnsV1Client
+import com.newsdk.sdk.android.httpdns.HttpDnsService
+
+val service: HttpDnsService = HttpDnsV1Client.init(
+ applicationContext,
+ "your-app-id",
+ "https://httpdns.example.com:8445", // serviceUrl,支持填写协议+端口
+ "your-sign-secret" // 可传 ""
+)
+```
+
+### Java
+
+```java
+import com.newsdk.sdk.android.httpdns.HttpDnsService;
+import com.newsdk.sdk.android.httpdns.HttpDnsV1Client;
+
+HttpDnsService service = HttpDnsV1Client.init(
+ getApplicationContext(),
+ "your-app-id",
+ "https://httpdns.example.com:8445", // serviceUrl
+ "your-sign-secret" // 可传 ""
+);
+```
+
+## 4. 解析域名获取 CDN IP
+
+### Kotlin
+
+```kotlin
+import com.newsdk.sdk.android.httpdns.HTTPDNSResult
+
+val result: HTTPDNSResult = HttpDnsV1Client.resolveHost(
+ service = service,
+ host = "api.example.com",
+ qtype = "A", // "A" 或 "AAAA"
+ cip = null // 可选,客户端 IP 透传
+)
+
+val ips = result.ips ?: emptyArray()
+```
+
+### Java
+
+```java
+import com.newsdk.sdk.android.httpdns.HTTPDNSResult;
+
+HTTPDNSResult result = HttpDnsV1Client.resolveHost(
+ service,
+ "api.example.com",
+ "A",
+ null
+);
+
+String[] ips = result.getIps();
+```
+
+## 5. 业务请求接入方式
+
+### 使用 `HttpDnsHttpAdapter`(IP 直连 + No-SNI)
+
+业务请求侧做“隐匿 SNI”。该适配器仅支持 HTTPS URL。
+
+```kotlin
+import com.newsdk.sdk.android.httpdns.HttpDnsV1Client
+import com.newsdk.sdk.android.httpdns.network.HttpDnsAdapterOptions
+import com.newsdk.sdk.android.httpdns.network.HttpDnsAdapterRequest
+
+val adapter = HttpDnsV1Client.buildHttpClientAdapter(
+ service,
+ HttpDnsAdapterOptions.Builder()
+ .setConnectTimeoutMillis(3000)
+ .setReadTimeoutMillis(5000)
+ .setRequestIpType(com.newsdk.sdk.android.httpdns.RequestIpType.auto)
+ .build()
+)
+
+val req = HttpDnsAdapterRequest(
+ "GET",
+ "https://api.example.com/path?x=1"
+)
+
+val resp = adapter.execute(req)
+val code = resp.statusCode
+val bodyBytes = resp.body
+val usedIp = resp.usedIp
+```
+
+## 6. 预解析与常用接口
+
+```kotlin
+service.setPreResolveHosts(listOf("api.example.com", "img.example.com"))
+
+val r1 = service.getHttpDnsResultForHostSync("api.example.com", com.newsdk.sdk.android.httpdns.RequestIpType.auto)
+val r2 = service.getHttpDnsResultForHostSyncNonBlocking("api.example.com", com.newsdk.sdk.android.httpdns.RequestIpType.auto)
+```
+
+- `Sync`:允许阻塞等待刷新结果(上限受 timeout 等配置影响)
+- `NonBlocking`:快速返回当前可用缓存/结果,不阻塞等待
+
+## 7. 验证建议
+
+1. 验证 `/resolve`
+- 抓包看目标应为 `https:///resolve...`(即初始化时传入的 URL)
+
+2. 验证业务请求(若使用 `HttpDnsHttpAdapter`)
+- 目标地址应是 CDN IP
+- HTTP `Host` 应为原域名
+- TLS ClientHello 不应携带 SNI(No-SNI)
+
+## 8. 混淆配置
+
+```proguard
+-keep class com.newsdk.sdk.android.** { *; }
+```
+
+## 9. 常见问题
+
+1. HTTPDNS 没生效
+- 检查是否真正使用了 SDK 返回 IP(或用了 `HttpDnsHttpAdapter`)
+- 检查失败回退逻辑是否总是直接走了系统 DNS
+
+2. 使用 `HttpDnsHttpAdapter` 仍失败
+- 只支持 HTTPS URL
+
+3. 线上不要开启不安全证书
+- `HttpDnsAdapterOptions.Builder#setAllowInsecureCertificatesForDebugOnly(true)` 仅限调试环境
diff --git a/HttpDNSSDK/docs/iOS SDK集成文档.md b/HttpDNSSDK/docs/iOS SDK集成文档.md
new file mode 100644
index 0000000..e1797df
--- /dev/null
+++ b/HttpDNSSDK/docs/iOS SDK集成文档.md
@@ -0,0 +1,124 @@
+# iOS SDK 集成文档(Edge HTTPDNS)
+
+## 1. 版本与依赖
+
+- SDK 模块:`HttpDNSSDK/sdk/ios/NewHttpDNS`
+- 支持系统:iOS 11.0+
+- 集成方式:
+ - **CocoaPods**:在 `Podfile` 中添加 `pod 'NewHTTPDNS', :path => 'path/to/sdk/ios'`
+ - **手动集成**:将 `NewHttpDNS` 源码或编译后的静态库导入项目,并添加依赖的系统库(Foundation, CFNetwork, SystemConfiguration)。
+
+## 2. SNI 行为说明(关键)
+
+1. **/resolve 请求链路**(SDK -> 你的 HTTPDNS 服务域名)
+- 使用标准 HTTPS 请求。
+- 默认携带 SNI(用于通过 WAF/CDN 识别服务域名)。
+
+2. **业务请求链路**(拿到 CDN IP 后通过 `HttpdnsEdgeService` 发起业务 HTTPS)
+- **IP 直连 + No-SNI**:SDK 会建立与 IP 的连接,并将 `NSURLRequest` 的 `URL` 替换为 IP,同时保留 `Host` 头部为原域名。
+- **证书校验**:由于清空了 SNI,常规 SNI 校验会跳过,需确保后端节点支持 Host 匹配证书。
+
+## 3. 初始化 SDK(推荐用 EdgeService 封装)
+
+### Objective-C
+
+```objective-c
+#import
+
+HttpdnsEdgeService *service = [[HttpdnsEdgeService alloc] initWithAppId:@"your-app-id"
+ primaryServiceHost:@"httpdns.example.com"
+ backupServiceHost:@"httpdns-backup.example.com"
+ servicePort:443
+ signSecret:@"your-sign-secret"];
+```
+
+### Swift
+
+```swift
+import NewHttpDNS
+
+let service = HttpdnsEdgeService(appId: "your-app-id",
+ primaryServiceHost: "httpdns.example.com",
+ backupServiceHost: "httpdns-backup.example.com",
+ servicePort: 443,
+ signSecret: "your-sign-secret")
+```
+
+## 4. 解析域名获取 CDN IP
+
+### Objective-C
+
+```objective-c
+[service resolveHost:@"api.example.com"
+ queryType:@"A"
+ completion:^(HttpdnsEdgeResolveResult * _Nullable result, NSError * _Nullable error) {
+ if (result) {
+ NSLog(@"IPv4s: %@", result.ipv4s);
+ NSLog(@"TTL: %ld", (long)result.ttl);
+ }
+}];
+```
+
+### Swift
+
+```swift
+service.resolveHost("api.example.com", queryType: "A") { result, error in
+ if let ips = result?.ipv4s {
+ print("Resolved IPs: \(ips)")
+ }
+}
+```
+
+## 5. 业务请求接入方式
+
+使用 `HttpdnsEdgeService` 提供的 `requestURL` 方法,自动处理 IP 直连与 SNI 隐藏。
+
+### Objective-C
+
+```objective-c
+NSURL *url = [NSURL URLWithString:@"https://api.example.com/path?x=1"];
+[service requestURL:url
+ method:@"GET"
+ headers:@{@"Custom-Header": @"Value"}
+ body:nil
+ completion:^(NSData * _Nullable data, NSHTTPURLResponse * _Nullable response, NSError * _Nullable error) {
+ if (!error) {
+ NSLog(@"Status Code: %ld", (long)response.statusCode);
+ // 处理 data
+ }
+}];
+```
+
+### Swift
+
+```swift
+let url = URL(string: "https://api.example.com/path?x=1")!
+service.requestURL(url, method: "GET", headers: ["Custom-Header": "Value"], body: nil) { data, response, error in
+ if let resp = response {
+ print("Status Code: \(resp.statusCode)")
+ }
+}
+```
+
+## 6. 验证建议
+
+1. **验证 /resolve**
+- 观察网络请求,应指向 `https://httpdns.example.com/resolve?appId=...&dn=...`。
+- 确认返回 JSON 包含 `code: "SUCCESS"`。
+
+2. **验证业务请求**
+- 确认请求握手阶段不携带 SNI 扩展。
+- 确认请求的 TCP 连接目标为解析出的私有 IP/CDN IP。
+
+## 7. 常见问题
+
+1. **编译报错:找不到头文件**
+- 请确认 `Header Search Paths` 包含 SDK 路径。
+- 如果使用 CocoaPods,请确保执行 `pod install` 并打开 `.xcworkspace`。
+
+2. **请求返回 403 (Sign Invalid)**
+- 确认控制台已开启“签名校验”,且本地传入的 `signSecret` 与控制台一致。
+- 确认系统时间正常(差值超过 30s 可能导致签名失效)。
+
+3. **HTTPS 证书验证失败**
+- 检查 `HttpdnsEdgeService` 是否能正确匹配证书,通常是在 No-SNI 模式下通过 `Host` 字段匹配。
diff --git a/HttpDNSSDK/sdk/SOURCE_LOCK.md b/HttpDNSSDK/sdk/SOURCE_LOCK.md
new file mode 100644
index 0000000..86bf55c
--- /dev/null
+++ b/HttpDNSSDK/sdk/SOURCE_LOCK.md
@@ -0,0 +1,25 @@
+# HttpDNSSDK Source Lock
+
+This directory vendors upstream SDK source snapshots for HTTPDNS integration.
+
+Fetched at (UTC): `2026-02-18T09:31:28Z`
+
+## Android SDK
+
+- Upstream repository: `https://github.com/TrustAPP/Trustcloud-httpdns-android-sdk`
+- Locked commit: `eeb17d677161ec94b5f41a9d6437501ddc24e6d2`
+- Local path: `HttpDNSSDK/sdk/android`
+
+## iOS SDK
+
+- Upstream repository: `https://github.com/TrustAPP/Trustcloud-httpdns-ios-sdk`
+- Locked commit: `19f5bacd1d1399a00ba654bb72ababb3e91d0a3a`
+- Local path: `HttpDNSSDK/sdk/ios`
+
+## Flutter Plugin SDK
+
+- Upstream repository: `https://github.com/TrustAPP/Trust-flutter-demo`
+- Locked commit: `588b807e5480d8592c57d439a6b1c52e8c313569`
+- Imported subtree: `httpdns_flutter_demo/packages/new_httpdns`
+- Local path: `HttpDNSSDK/sdk/flutter/new_httpdns`
+
diff --git a/HttpDNSSDK/sdk/THIRD_PARTY_NOTICES.md b/HttpDNSSDK/sdk/THIRD_PARTY_NOTICES.md
new file mode 100644
index 0000000..a3d521a
--- /dev/null
+++ b/HttpDNSSDK/sdk/THIRD_PARTY_NOTICES.md
@@ -0,0 +1,31 @@
+# Third-Party Notices for HttpDNSSDK SDK Sources
+
+This directory includes third-party source snapshots imported from Trust Cloud open-source repositories.
+
+## 1) Android SDK (`HttpDNSSDK/sdk/android`)
+
+- Source: `https://github.com/TrustAPP/Trustcloud-httpdns-android-sdk`
+- Commit: `eeb17d677161ec94b5f41a9d6437501ddc24e6d2`
+- License file in imported source:
+ - `HttpDNSSDK/sdk/android/LICENSE`
+- Observed license: MIT License
+
+## 2) Flutter plugin (`HttpDNSSDK/sdk/flutter/new_httpdns`)
+
+- Source: `https://github.com/TrustAPP/Trust-flutter-demo`
+- Commit: `588b807e5480d8592c57d439a6b1c52e8c313569`
+- Imported subtree: `httpdns_flutter_demo/packages/new_httpdns`
+- License file in imported source:
+ - `HttpDNSSDK/sdk/flutter/new_httpdns/LICENSE`
+- Observed license: MIT License
+
+## 3) iOS SDK (`HttpDNSSDK/sdk/ios`)
+
+- Source: `https://github.com/TrustAPP/Trustcloud-httpdns-ios-sdk`
+- Commit: `19f5bacd1d1399a00ba654bb72ababb3e91d0a3a`
+- Current status:
+ - No standalone top-level `LICENSE` file was found in the upstream repository snapshot imported here.
+ - Some source headers reference Apache 2.0 notices, but repository-level license declaration is not explicit.
+- Action required before merging to protected branch:
+ - Complete legal/license confirmation for iOS source usage.
+
diff --git a/HttpDNSSDK/sdk/android/.github/ISSUE_TEMPLATE/bug_report.md b/HttpDNSSDK/sdk/android/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..466bf4b
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,32 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Logs**
+If applicable, add logcat logs to help explain your problem.
+
+**Environment (please complete the following information):**
+ - Device: [e.g. Pixel 3]
+ - OS: [e.g. Android 10]
+ - SDK Version [e.g. 2.0.2]
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/HttpDNSSDK/sdk/android/LICENSE b/HttpDNSSDK/sdk/android/LICENSE
new file mode 100644
index 0000000..c5a4392
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Alibaba Cloud
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/HttpDNSSDK/sdk/android/README.md b/HttpDNSSDK/sdk/android/README.md
new file mode 100644
index 0000000..1e072dc
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/README.md
@@ -0,0 +1,74 @@
+# HTTPDNS Android SDK (SNI Hidden v1.0.0)
+
+## 1. Init
+
+```java
+import com.newsdk.sdk.android.httpdns.HttpDns;
+import com.newsdk.sdk.android.httpdns.HttpDnsService;
+import com.newsdk.sdk.android.httpdns.InitConfig;
+
+String appId = "app1f1ndpo9";
+
+new InitConfig.Builder()
+ .setContext(context)
+ .setServiceUrl("https://httpdns.example.com:8445")
+ .setSecretKey("your-sign-secret") // optional if sign is enabled
+ .buildFor(appId);
+
+HttpDnsService httpDnsService = HttpDns.getService(appId);
+```
+
+## 2. Resolve
+
+```java
+HTTPDNSResult result = httpDnsService.getHttpDnsResultForHostSyncNonBlocking(
+ "api.business.com",
+ RequestIpType.auto,
+ null,
+ null
+);
+```
+
+## 3. Official HTTP Adapter (IP + Empty-SNI + Host)
+
+```java
+import com.newsdk.sdk.android.httpdns.network.HttpDnsAdapterOptions;
+import com.newsdk.sdk.android.httpdns.network.HttpDnsAdapterRequest;
+import com.newsdk.sdk.android.httpdns.network.HttpDnsAdapterResponse;
+import com.newsdk.sdk.android.httpdns.network.HttpDnsHttpAdapter;
+
+HttpDnsHttpAdapter adapter = HttpDns.buildHttpClientAdapter(
+ httpDnsService,
+ new HttpDnsAdapterOptions.Builder()
+ .setConnectTimeoutMillis(3000)
+ .setReadTimeoutMillis(5000)
+ .setRequestIpType(RequestIpType.auto)
+ .setAllowInsecureCertificatesForDebugOnly(false)
+ .build()
+);
+
+HttpDnsAdapterResponse response = adapter.execute(
+ new HttpDnsAdapterRequest("GET", "https://api.business.com/v1/ping")
+);
+```
+
+Behavior is fixed:
+- Resolve by `/resolve`.
+- Connect to resolved IP over HTTPS.
+- Keep `Host` header as business domain.
+- No fallback to domain direct request.
+
+## 4. Public Errors
+
+- `NO_IP_AVAILABLE`
+- `TLS_EMPTY_SNI_FAILED`
+- `HOST_ROUTE_REJECTED`
+- `RESOLVE_SIGN_INVALID`
+
+## 5. Removed Public Params
+
+Do not use legacy public parameters:
+- `accountId`
+- `serviceDomain`
+- `endpoint`
+- `aesSecretKey`
diff --git a/HttpDNSSDK/sdk/android/app/build.gradle b/HttpDNSSDK/sdk/android/app/build.gradle
new file mode 100644
index 0000000..215b031
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/build.gradle
@@ -0,0 +1,85 @@
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ namespace 'com.newsdk.ams.httpdns.demo'
+ compileSdkVersion 34
+ buildToolsVersion "30.0.2"
+ defaultConfig {
+ applicationId "com.newsdk.ams.httpdns.demo2"
+ minSdkVersion 19
+ targetSdkVersion 34
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ buildConfigField "String", "SERVICE_URL", "\"\""
+ }
+
+
+ buildTypes {
+ debug {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ release {
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ forTest {
+ // 娉ㄦ剰杩欓噷鐨勯厤缃紝骞朵笉鏄渶瑕佺紪璇慺orTest鐨刟pp锛岃€屾槸閬垮厤httpdns-sdk鍦ˋndroidStudio鏀逛负end2end杩愯娴嬭瘯鏃?BuildVariants鎶ラ敊
+ initWith release
+ debuggable true
+ }
+ }
+
+ variantFilter { variant ->
+ def names = variant.flavors*.name
+ def type = variant.buildType.name
+ // To check for a certain build type, use variant.buildType.name == ""
+ if ((names.contains("normal") && type.contains("forTest"))
+ || (names.contains("intl") && type.contains("forTest"))
+ || (names.contains("end2end") && type.contains("release"))
+ || (names.contains("end2end") && type.contains("debug"))
+ ) {
+ // Gradle ignores any variants that satisfy the conditions above.
+ setIgnore(true)
+ }
+ }
+
+ testOptions {
+ unitTests {
+ all {
+ jvmArgs '-noverify'
+ systemProperty 'robolectric.logging.enable', true
+ }
+ }
+ }
+
+ flavorDimensions "version"
+
+ productFlavors {
+ normal {
+
+ }
+
+ intl {
+
+ }
+
+ end2end {
+ // 娉ㄦ剰杩欓噷鐨勯厤缃紝骞朵笉鏄渶瑕佺紪璇慹nd2end鐨刟pp锛岃€屾槸閬垮厤httpdns-sdk鍦ˋndroidStudio鏀逛负end2end杩愯娴嬭瘯鏃?BuildVariants鎶ラ敊
+ }
+ }
+}
+
+configurations.all {
+ resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
+}
+
+dependencies {
+
+ implementation project(':httpdns-sdk')
+
+ implementation("com.squareup.okhttp3:okhttp:3.9.0")
+}
diff --git a/HttpDNSSDK/sdk/android/app/proguard-rules.pro b/HttpDNSSDK/sdk/android/app/proguard-rules.pro
new file mode 100644
index 0000000..b79bbd9
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/proguard-rules.pro
@@ -0,0 +1,30 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/liyazhou/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
+-dontwarn okhttp3.**
+-dontwarn okio.**
+-dontwarn com.newsdk.sdk.android.httpdns.test.**
+-dontwarn com.newsdk.sdk.android.httpdns.net.HttpDnsNetworkDetector
+-keep class com.aliyun.ams.ipdetector.Inet64Util{*;}
diff --git a/HttpDNSSDK/sdk/android/app/src/main/AndroidManifest.xml b/HttpDNSSDK/sdk/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..d8f2a0c
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/HttpDnsActivity.java b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/HttpDnsActivity.java
new file mode 100644
index 0000000..ba55f63
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/HttpDnsActivity.java
@@ -0,0 +1,160 @@
+package com.newsdk.ams.httpdns.demo;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AutoCompleteTextView;
+
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+import com.newsdk.ams.httpdns.demo.base.BaseActivity;
+import com.newsdk.ams.httpdns.demo.http.HttpUrlConnectionRequest;
+import com.newsdk.ams.httpdns.demo.okhttp.OkHttpRequest;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class HttpDnsActivity extends BaseActivity {
+
+ private static final String SCHEMA_HTTPS = "https://";
+ private static final String SCHEMA_HTTP = "http://";
+
+ private static final String[] HOSTS = new String[] {
+ "www.taobao.com",
+ "demo.cloudxdr.com"
+ };
+
+ private String schema = SCHEMA_HTTPS;
+ private String host = HOSTS[0];
+ private RequestIpType requestIpType = RequestIpType.v4;
+
+ private HttpUrlConnectionRequest httpUrlConnectionRequest;
+ private OkHttpRequest okHttpRequest;
+ private NetworkRequest networkRequest;
+
+ private final ExecutorService worker = Executors.newSingleThreadExecutor();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ httpUrlConnectionRequest = new HttpUrlConnectionRequest(this);
+ okHttpRequest = new OkHttpRequest(this);
+ networkRequest = httpUrlConnectionRequest;
+
+ addFourButton(
+ "Switch instance",
+ v -> {
+ MyApp.getInstance().changeHolder();
+ sendLog("Instance switched.");
+ },
+ "Show config",
+ v -> sendLog(MyApp.getInstance().getCurrentHolder().getCurrentConfig()),
+ "Clear holder cache",
+ v -> {
+ MyApp.getInstance().getCurrentHolder().cleanSp();
+ sendLog("Holder cache cleared.");
+ },
+ "Clear log",
+ v -> cleanLog()
+ );
+
+ addAutoCompleteTextViewButton(HOSTS, "Host", "Set host", view -> {
+ AutoCompleteTextView actv = (AutoCompleteTextView) view;
+ host = actv.getEditableText().toString();
+ sendLog("Host set to: " + host);
+ });
+
+ addTwoButton(
+ "Use HTTPS",
+ v -> {
+ schema = SCHEMA_HTTPS;
+ sendLog("Schema set to HTTPS.");
+ },
+ "Use HTTP",
+ v -> {
+ schema = SCHEMA_HTTP;
+ sendLog("Schema set to HTTP.");
+ }
+ );
+
+ addFourButton(
+ "IP type v4",
+ v -> {
+ requestIpType = RequestIpType.v4;
+ sendLog("Request IP type: v4");
+ },
+ "IP type v6",
+ v -> {
+ requestIpType = RequestIpType.v6;
+ sendLog("Request IP type: v6");
+ },
+ "IP type both",
+ v -> {
+ requestIpType = RequestIpType.both;
+ sendLog("Request IP type: both");
+ },
+ "IP type auto",
+ v -> {
+ requestIpType = RequestIpType.auto;
+ sendLog("Request IP type: auto");
+ }
+ );
+
+ addTwoButton(
+ "HttpUrlConnection",
+ v -> {
+ networkRequest = httpUrlConnectionRequest;
+ sendLog("Network stack: HttpUrlConnection");
+ },
+ "OkHttp",
+ v -> {
+ networkRequest = okHttpRequest;
+ sendLog("Network stack: OkHttp");
+ }
+ );
+
+ addTwoButton(
+ "Resolve sync",
+ v -> worker.execute(() -> executeResolve(false)),
+ "Resolve async",
+ v -> worker.execute(() -> executeResolve(true))
+ );
+
+ addTwoButton(
+ "Open SDNS page",
+ v -> startActivity(new Intent(HttpDnsActivity.this, SDNSActivity.class)),
+ "Open WebView page",
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startActivity(new Intent(HttpDnsActivity.this, WebViewActivity.class));
+ }
+ }
+ );
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ worker.shutdownNow();
+ }
+
+ private void executeResolve(boolean async) {
+ String url = schema + host;
+ sendLog("Request URL: " + url);
+ sendLog("Request IP type: " + requestIpType.name());
+ sendLog("Async mode: " + async);
+ sendLog("Stack: " + (networkRequest == httpUrlConnectionRequest ? "HttpUrlConnection" : "OkHttp"));
+ try {
+ networkRequest.updateHttpDnsConfig(async, requestIpType);
+ String response = networkRequest.httpGet(url);
+ if (response != null && response.length() > 120) {
+ response = response.substring(0, 120) + "...";
+ }
+ sendLog("Response: " + response);
+ } catch (Exception e) {
+ sendLog("Request failed: " + e.getClass().getSimpleName() + " " + e.getMessage());
+ }
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/HttpDnsHolder.java b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/HttpDnsHolder.java
new file mode 100644
index 0000000..35f6ac0
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/HttpDnsHolder.java
@@ -0,0 +1,353 @@
+package com.newsdk.ams.httpdns.demo;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import com.newsdk.sdk.android.httpdns.CacheTtlChanger;
+import com.newsdk.sdk.android.httpdns.HttpDns;
+import com.newsdk.sdk.android.httpdns.HttpDnsService;
+import com.newsdk.sdk.android.httpdns.InitConfig;
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+import com.newsdk.sdk.android.httpdns.ranking.IPRankingBean;
+import com.newsdk.ams.httpdns.demo.utils.SpUtil;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * 淇濆瓨Httpdns 鍙?鐩稿叧閰嶇疆锛?
+ * 鏂逛究淇敼
+ */
+public class HttpDnsHolder {
+
+ public static final String SP_PREFIX = "httpdns_config_";
+
+ public static String getSpName(String accountId) {
+ return SP_PREFIX + accountId;
+ }
+
+ public static final String KEY_EXPIRED_IP = "enableExpiredIp";
+ public static final String KEY_CACHE_IP = "enableCacheIp";
+ public static final String KEY_TIMEOUT = "timeout";
+ public static final String KEY_HTTPS = "enableHttps";
+ public static final String KEY_IP_RANKING_ITEMS = "ipProbeItems";
+ public static final String KEY_REGION = "region";
+ public static final String KEY_TTL_CHANGER = "cacheTtlChanger";
+ public static final String KEY_HOST_NOT_CHANGE = "hostListWithFixedIp";
+
+ private HttpDnsService service;
+ private String accountId;
+ private String secret;
+ private String serviceUrl;
+ private Context context;
+
+ private boolean enableExpiredIp;
+ private boolean enableCacheIp;
+ private int timeout;
+ private boolean enableHttps;
+ private ArrayList ipRankingList = null;
+ private String region;
+ private ArrayList hostListWithFixedIp;
+ private HashMap ttlCache;
+ private final CacheTtlChanger cacheTtlChanger = new CacheTtlChanger() {
+ @Override
+ public int changeCacheTtl(String host, RequestIpType type, int ttl) {
+ if (ttlCache != null && ttlCache.get(host) != null) {
+ return ttlCache.get(host);
+ }
+ return ttl;
+ }
+ };
+
+ public HttpDnsHolder(String accountId) {
+ this.accountId = accountId;
+ }
+
+ public HttpDnsHolder(String accountId, String secret) {
+ this.accountId = accountId;
+ this.secret = secret;
+ }
+
+ public HttpDnsHolder(String accountId, String secret, String serviceUrl) {
+ this.accountId = accountId;
+ this.secret = secret;
+ this.serviceUrl = serviceUrl;
+ }
+
+ /**
+ * 鍒濆鍖杊ttpdns鐨勯厤缃?
+ *
+ * @param context
+ */
+ public void init(Context context) {
+ this.context = context.getApplicationContext();
+ SpUtil.readSp(context, getSpName(accountId), new SpUtil.OnGetSp() {
+ @Override
+ public void onGetSp(SharedPreferences sp) {
+ enableExpiredIp = sp.getBoolean(KEY_EXPIRED_IP, true);
+ enableCacheIp = sp.getBoolean(KEY_CACHE_IP, false);
+ timeout = sp.getInt(KEY_TIMEOUT, 5 * 1000);
+ enableHttps = sp.getBoolean(KEY_HTTPS, false);
+ ipRankingList = convertToProbeList(sp.getString(KEY_IP_RANKING_ITEMS, null));
+ region = sp.getString(KEY_REGION, null);
+ ttlCache = convertToCacheTtlData(sp.getString(KEY_TTL_CHANGER, null));
+ hostListWithFixedIp = convertToStringList(sp.getString(KEY_HOST_NOT_CHANGE, null));
+ }
+ });
+
+ // 鍒濆鍖杊ttpdns 鐨勯厤缃紝姝ゆ楠ら渶瑕佸湪绗竴娆¤幏鍙朒ttpDnsService瀹炰緥涔嬪墠
+ InitConfig.Builder builder = new InitConfig.Builder()
+ .setEnableExpiredIp(enableExpiredIp)
+ .setEnableCacheIp(enableCacheIp)
+ .setTimeout(timeout)
+ .setIPRankingList(ipRankingList)
+ .configCacheTtlChanger(cacheTtlChanger)
+ .configHostWithFixedIp(hostListWithFixedIp)
+ .setEnableHttps(enableHttps)
+ .setRegion(region);
+ if (serviceUrl != null && !serviceUrl.trim().isEmpty()) {
+ builder.setServiceUrl(serviceUrl.trim());
+ }
+ builder.buildFor(accountId);
+
+ getService();
+ }
+
+ public HttpDnsService getService() {
+ if (service == null) {
+ if (secret != null) {
+ service = HttpDns.getService(context, accountId, secret);
+ } else {
+ service = HttpDns.getService(context, accountId);
+ }
+ }
+ return service;
+ }
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ public void setEnableExpiredIp(final boolean enableExpiredIp) {
+ this.enableExpiredIp = enableExpiredIp;
+ // 娉ㄦ剰锛氭閰嶇疆闇€瑕侀噸鍚簲鐢ㄧ敓鏁堬紝鍥犱负鐜板湪閫氳繃InitConfig璁剧疆
+ SpUtil.writeSp(context, getSpName(accountId), new SpUtil.OnGetSpEditor() {
+ @Override
+ public void onGetSpEditor(SharedPreferences.Editor editor) {
+ editor.putBoolean(KEY_EXPIRED_IP, enableExpiredIp);
+ }
+ });
+ }
+
+ public void setEnableCacheIp(final boolean enableCacheIp) {
+ this.enableCacheIp = enableCacheIp;
+ // 娉ㄦ剰锛氭閰嶇疆闇€瑕侀噸鍚簲鐢ㄧ敓鏁堬紝鍥犱负鐜板湪閫氳繃InitConfig璁剧疆
+ SpUtil.writeSp(context, getSpName(accountId), new SpUtil.OnGetSpEditor() {
+ @Override
+ public void onGetSpEditor(SharedPreferences.Editor editor) {
+ editor.putBoolean(KEY_CACHE_IP, enableCacheIp);
+ }
+ });
+ }
+
+ public void setTimeout(final int timeout) {
+ this.timeout = timeout;
+ // 娉ㄦ剰锛氭閰嶇疆闇€瑕侀噸鍚簲鐢ㄧ敓鏁堬紝鍥犱负鐜板湪閫氳繃InitConfig璁剧疆
+ SpUtil.writeSp(context, getSpName(accountId), new SpUtil.OnGetSpEditor() {
+ @Override
+ public void onGetSpEditor(SharedPreferences.Editor editor) {
+ editor.putInt(KEY_TIMEOUT, timeout);
+ }
+ });
+ }
+
+ public void setEnableHttps(final boolean enableHttps) {
+ this.enableHttps = enableHttps;
+ // 娉ㄦ剰锛氭閰嶇疆闇€瑕侀噸鍚簲鐢ㄧ敓鏁堬紝鍥犱负鐜板湪閫氳繃InitConfig璁剧疆
+ SpUtil.writeSp(context, getSpName(accountId), new SpUtil.OnGetSpEditor() {
+ @Override
+ public void onGetSpEditor(SharedPreferences.Editor editor) {
+ editor.putBoolean(KEY_HTTPS, enableHttps);
+ }
+ });
+ }
+
+ public void setRegion(final String region) {
+ this.region = region;
+ getService().setRegion(region);
+ SpUtil.writeSp(context, getSpName(accountId), new SpUtil.OnGetSpEditor() {
+ @Override
+ public void onGetSpEditor(SharedPreferences.Editor editor) {
+ editor.putString(KEY_REGION, region);
+ }
+ });
+ }
+
+ public void addHostWithFixedIp(String host) {
+ if (this.hostListWithFixedIp == null) {
+ this.hostListWithFixedIp = new ArrayList<>();
+ }
+ this.hostListWithFixedIp.add(host);
+ // 閲嶅惎鐢熸晥
+ SpUtil.writeSp(context, getSpName(accountId), new SpUtil.OnGetSpEditor() {
+ @Override
+ public void onGetSpEditor(SharedPreferences.Editor editor) {
+ editor.putString(KEY_HOST_NOT_CHANGE, convertHostList(hostListWithFixedIp));
+ }
+ });
+ }
+
+ public void addIpProbeItem(IPRankingBean ipProbeItem) {
+ if (this.ipRankingList == null) {
+ this.ipRankingList = new ArrayList<>();
+ }
+ this.ipRankingList.add(ipProbeItem);
+ // 娉ㄦ剰锛氭閰嶇疆闇€瑕侀噸鍚簲鐢ㄧ敓鏁堬紝鍥犱负鐜板湪閫氳繃InitConfig璁剧疆
+ SpUtil.writeSp(context, getSpName(accountId), new SpUtil.OnGetSpEditor() {
+ @Override
+ public void onGetSpEditor(SharedPreferences.Editor editor) {
+ editor.putString(KEY_IP_RANKING_ITEMS, convertProbeList(ipRankingList));
+ }
+ });
+ }
+
+
+ public void setHostTtl(String host, int ttl) {
+ if (ttlCache == null) {
+ ttlCache = new HashMap<>();
+ }
+ ttlCache.put(host, ttl);
+ SpUtil.writeSp(context, getSpName(accountId), new SpUtil.OnGetSpEditor() {
+ @Override
+ public void onGetSpEditor(SharedPreferences.Editor editor) {
+ editor.putString(KEY_TTL_CHANGER, convertTtlCache(ttlCache));
+ }
+ });
+ }
+
+ public void cleanSp() {
+ SpUtil.writeSp(context, getSpName(accountId), new SpUtil.OnGetSpEditor() {
+ @Override
+ public void onGetSpEditor(SharedPreferences.Editor editor) {
+ editor.clear();
+ }
+ });
+ }
+
+ public String getCurrentConfig() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("褰撳墠閰嶇疆 accountId : ").append(accountId).append("\n")
+ .append("鏄惁鍏佽杩囨湡IP : ").append(enableExpiredIp).append("\n")
+ .append("鏄惁寮€鍚湰鍦扮紦瀛?: ").append(enableCacheIp).append("\n")
+ .append("鏄惁寮€鍚疕TTPS : ").append(enableHttps).append("\n")
+ .append("褰撳墠region璁剧疆 : ").append(region).append("\n")
+ .append("褰撳墠瓒呮椂璁剧疆 : ").append(timeout).append("\n")
+ .append("褰撳墠鎺㈡祴閰嶇疆 : ").append(convertProbeList(ipRankingList)).append("\n")
+ .append("褰撳墠缂撳瓨閰嶇疆 : ").append(convertTtlCache(ttlCache)).append("\n")
+ .append("褰撳墠涓荤珯鍩熷悕閰嶇疆 : ").append(convertHostList(hostListWithFixedIp)).append("\n")
+ ;
+ return sb.toString();
+ }
+
+
+ private static String convertHostList(List hostListWithFixedIp) {
+ if (hostListWithFixedIp == null) {
+ return null;
+ }
+ JSONArray array = new JSONArray();
+ for (String host : hostListWithFixedIp) {
+ array.put(host);
+ }
+ return array.toString();
+ }
+
+ private static String convertTtlCache(HashMap ttlCache) {
+ if (ttlCache == null) {
+ return null;
+ }
+ JSONObject jsonObject = new JSONObject();
+ for (String host : ttlCache.keySet()) {
+ try {
+ jsonObject.put(host, ttlCache.get(host));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ return jsonObject.toString();
+ }
+
+ private static String convertProbeList(List ipProbeItems) {
+ if (ipProbeItems == null) {
+ return null;
+ }
+ JSONObject jsonObject = new JSONObject();
+ for (IPRankingBean item : ipProbeItems) {
+ try {
+ jsonObject.put(item.getHostName(), item.getPort());
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ return jsonObject.toString();
+ }
+
+ private static ArrayList convertToProbeList(String json) {
+ if (json == null) {
+ return null;
+ }
+ try {
+ JSONObject jsonObject = new JSONObject(json);
+ ArrayList list = new ArrayList<>();
+ for (Iterator it = jsonObject.keys(); it.hasNext(); ) {
+ String host = it.next();
+ list.add(new IPRankingBean(host, jsonObject.getInt(host)));
+ }
+ return list;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private static HashMap convertToCacheTtlData(String json) {
+ if (json == null) {
+ return null;
+ }
+ try {
+ JSONObject jsonObject = new JSONObject(json);
+ HashMap map = new HashMap<>();
+ for (Iterator it = jsonObject.keys(); it.hasNext(); ) {
+ String host = it.next();
+ map.put(host, jsonObject.getInt(host));
+ }
+ return map;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ private static ArrayList convertToStringList(String json) {
+ if (json != null) {
+ try {
+ JSONArray array = new JSONArray(json);
+ ArrayList list = new ArrayList<>();
+ for (int i = 0; i < array.length(); i++) {
+ list.add(array.getString(i));
+ }
+ return list;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/MyApp.java b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/MyApp.java
new file mode 100644
index 0000000..525bb1e
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/MyApp.java
@@ -0,0 +1,93 @@
+package com.newsdk.ams.httpdns.demo;
+
+import android.app.Application;
+import android.content.SharedPreferences;
+import android.util.Log;
+
+import com.newsdk.sdk.android.httpdns.HttpDnsService;
+import com.newsdk.sdk.android.httpdns.ILogger;
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog;
+import com.newsdk.ams.httpdns.demo.utils.SpUtil;
+
+public class MyApp extends Application {
+
+ private static final String SP_NAME = "HTTPDNS_DEMO";
+ private static final String KEY_INSTANCE = "KEY_INSTANCE";
+ private static final String VALUE_INSTANCE_A = "A";
+ private static final String VALUE_INSTANCE_B = "B";
+
+ public static final String TAG = "HTTPDNS DEMO";
+ private static MyApp instance;
+
+ public static MyApp getInstance() {
+ return instance;
+ }
+
+ private final HttpDnsHolder holderA = new HttpDnsHolder("replace-with-your-accountId-A", "replace-with-your-secret-A", BuildConfig.SERVICE_URL);
+ private final HttpDnsHolder holderB = new HttpDnsHolder("replace-with-your-accountId-B", null, BuildConfig.SERVICE_URL);
+
+ private HttpDnsHolder current = holderA;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ instance = this;
+
+ // Enable logcat output for debugging.
+ HttpDnsLog.enable(true);
+ // Hook the SDK logger into app logs.
+ HttpDnsLog.setLogger(new ILogger() {
+ @Override
+ public void log(String msg) {
+ Log.d("HttpDnsLogger", msg);
+ }
+ });
+
+ // Initialize HTTPDNS configuration.
+ holderA.init(this);
+ holderB.init(this);
+
+ SpUtil.readSp(this, SP_NAME, new SpUtil.OnGetSp() {
+ @Override
+ public void onGetSp(SharedPreferences sp) {
+ String flag = sp.getString(KEY_INSTANCE, VALUE_INSTANCE_A);
+ if (flag.equals(VALUE_INSTANCE_A)) {
+ current = holderA;
+ } else {
+ current = holderB;
+ }
+ }
+ });
+ }
+
+ public HttpDnsHolder getCurrentHolder() {
+ return current;
+ }
+
+ public HttpDnsHolder changeHolder() {
+ if (current == holderA) {
+ current = holderB;
+ SpUtil.writeSp(instance, SP_NAME, new SpUtil.OnGetSpEditor() {
+ @Override
+ public void onGetSpEditor(SharedPreferences.Editor editor) {
+ editor.putString(KEY_INSTANCE, VALUE_INSTANCE_B);
+ }
+ });
+ } else {
+ current = holderA;
+ SpUtil.writeSp(instance, SP_NAME, new SpUtil.OnGetSpEditor() {
+ @Override
+ public void onGetSpEditor(SharedPreferences.Editor editor) {
+ editor.putString(KEY_INSTANCE, VALUE_INSTANCE_A);
+ }
+ });
+ }
+ return current;
+ }
+
+ public HttpDnsService getService() {
+ return current.getService();
+ }
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/NetworkRequest.java b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/NetworkRequest.java
new file mode 100644
index 0000000..b41f0f1
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/NetworkRequest.java
@@ -0,0 +1,21 @@
+package com.newsdk.ams.httpdns.demo;
+
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+
+public interface NetworkRequest {
+
+ /**
+ * 璁剧疆httpdns鐨勯厤缃?
+ */
+ void updateHttpDnsConfig(boolean async, RequestIpType requestIpType);
+
+ /**
+ * get璇锋眰
+ *
+ * @param url
+ * @return
+ */
+ String httpGet(String url) throws Exception;
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/SDNSActivity.java b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/SDNSActivity.java
new file mode 100644
index 0000000..77c97b5
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/SDNSActivity.java
@@ -0,0 +1,127 @@
+package com.newsdk.ams.httpdns.demo;
+
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AutoCompleteTextView;
+import android.widget.EditText;
+
+import com.newsdk.sdk.android.httpdns.HTTPDNSResult;
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+import com.newsdk.ams.httpdns.demo.base.BaseActivity;
+
+import java.util.HashMap;
+
+public class SDNSActivity extends BaseActivity {
+
+ private static final String[] HOSTS = new String[] {
+ "demo.cloudxdr.com",
+ "www.taobao.com"
+ };
+
+ private final HashMap globalParams = new HashMap<>();
+ private String host = HOSTS[0];
+ private RequestIpType requestIpType = RequestIpType.v4;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addEditTextEditTextButton("key", "value", "Add global param", new OnButtonClickMoreView() {
+ @Override
+ public void onBtnClick(View[] views) {
+ EditText keyView = (EditText) views[0];
+ EditText valueView = (EditText) views[1];
+ String key = keyView.getEditableText().toString();
+ String value = valueView.getEditableText().toString();
+ globalParams.put(key, value);
+ sendLog("Global param added: " + key + "=" + value);
+ }
+ });
+
+ addOneButton("Clear global params", new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ globalParams.clear();
+ sendLog("Global params cleared.");
+ }
+ });
+
+ addFourButton(
+ "IP type v4",
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ requestIpType = RequestIpType.v4;
+ sendLog("Request IP type: v4");
+ }
+ },
+ "IP type v6",
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ requestIpType = RequestIpType.v6;
+ sendLog("Request IP type: v6");
+ }
+ },
+ "IP type both",
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ requestIpType = RequestIpType.both;
+ sendLog("Request IP type: both");
+ }
+ },
+ "IP type auto",
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ requestIpType = RequestIpType.auto;
+ sendLog("Request IP type: auto");
+ }
+ }
+ );
+
+ addAutoCompleteTextViewButton(HOSTS, "Host", "Set host", new OnButtonClick() {
+ @Override
+ public void onBtnClick(View view) {
+ AutoCompleteTextView hostView = (AutoCompleteTextView) view;
+ host = hostView.getEditableText().toString();
+ sendLog("Host set to: " + host);
+ }
+ });
+
+ addEditTextEditTextButton("key", "value", "Resolve with param", new OnButtonClickMoreView() {
+ @Override
+ public void onBtnClick(View[] views) {
+ EditText keyView = (EditText) views[0];
+ EditText valueView = (EditText) views[1];
+ HashMap params = new HashMap<>(globalParams);
+ params.put(keyView.getEditableText().toString(), valueView.getEditableText().toString());
+ HTTPDNSResult result = MyApp.getInstance().getService().getIpsByHostAsync(
+ host, requestIpType, params, "sdns-demo");
+ sendLog("SDNS result: " + result);
+ }
+ });
+
+ addTwoButton("Resolve scale1", new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ HashMap params = new HashMap<>(globalParams);
+ params.put("scale", "scale1");
+ HTTPDNSResult result = MyApp.getInstance().getService().getIpsByHostAsync(
+ host, requestIpType, params, "sdns-demo");
+ sendLog("scale1 result: " + result);
+ }
+ }, "Resolve scale2", new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ HashMap params = new HashMap<>(globalParams);
+ params.put("scale", "scale2");
+ HTTPDNSResult result = MyApp.getInstance().getService().getIpsByHostAsync(
+ host, requestIpType, params, "sdns-demo");
+ sendLog("scale2 result: " + result);
+ }
+ });
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/WebViewActivity.java b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/WebViewActivity.java
new file mode 100644
index 0000000..9381c5a
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/WebViewActivity.java
@@ -0,0 +1,403 @@
+package com.newsdk.ams.httpdns.demo;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.net.SSLCertificateSocketFactory;
+import android.os.Build;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.webkit.WebResourceRequest;
+import android.webkit.WebResourceResponse;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.TextView;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.Socket;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+public class WebViewActivity extends Activity {
+
+ private WebView webView;
+ private static final String targetUrl = "http://www.apple.com";
+
+ private static final String TAG = MyApp.TAG + "WebView";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_webview);
+
+ initBar();
+ initHttpDnsWebView();
+ }
+
+ @Override
+ public boolean
+ onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
+ webView.goBack();//杩斿洖涓婁釜椤甸潰
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);//閫€鍑篈ctivity
+ }
+
+ private void initBar() {
+ findViewById(R.id.bar_img).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ WebViewActivity.this.finish();
+ }
+ });
+
+ ((TextView) findViewById(R.id.bar_text)).setText("HTTPDNS");
+ }
+
+ private void initHttpDnsWebView() {
+
+ webView = (WebView) this.findViewById(R.id.wv_container);
+
+ webView.setWebViewClient(new WebViewClient() {
+
+ @SuppressLint("NewApi")
+ @Override
+ public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
+ String scheme = request.getUrl().getScheme().trim();
+ String method = request.getMethod();
+ Map headerFields = request.getRequestHeaders();
+ String url = request.getUrl().toString();
+ Log.e(TAG, "url:" + url);
+ // 鏃犳硶鎷︽埅body锛屾嫤鎴柟妗堝彧鑳芥甯稿鐞嗕笉甯ody鐨勮姹傦紱
+ if ((scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https"))
+ && method.equalsIgnoreCase("get")) {
+ try {
+ URLConnection connection = recursiveRequest(url, headerFields, null);
+
+ if (connection == null) {
+ Log.e(TAG, "connection null");
+ return super.shouldInterceptRequest(view, request);
+ }
+
+ // 娉?锛氬浜嶱OST璇锋眰鐨凚ody鏁版嵁锛學ebResourceRequest鎺ュ彛涓苟娌℃湁鎻愪緵锛岃繖閲屾棤娉曞鐞?
+ String contentType = connection.getContentType();
+ String mime = getMime(contentType);
+ String charset = getCharset(contentType);
+ HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
+ int statusCode = httpURLConnection.getResponseCode();
+ String response = httpURLConnection.getResponseMessage();
+ Map> headers = httpURLConnection.getHeaderFields();
+ Set headerKeySet = headers.keySet();
+ Log.e(TAG, "code:" + httpURLConnection.getResponseCode());
+ Log.e(TAG, "mime:" + mime + "; charset:" + charset);
+
+
+ // 鏃爉ime绫诲瀷鐨勮姹備笉鎷︽埅
+ if (TextUtils.isEmpty(mime)) {
+ Log.e(TAG, "no MIME");
+ return super.shouldInterceptRequest(view, request);
+ } else {
+ // 浜岃繘鍒惰祫婧愭棤闇€缂栫爜淇℃伅
+ if (!TextUtils.isEmpty(charset) || (isBinaryRes(mime))) {
+ WebResourceResponse resourceResponse = new WebResourceResponse(mime, charset, httpURLConnection.getInputStream());
+ resourceResponse.setStatusCodeAndReasonPhrase(statusCode, response);
+ Map responseHeader = new HashMap();
+ for (String key : headerKeySet) {
+ // HttpUrlConnection鍙兘鍖呭惈key涓簄ull鐨勬姤澶达紝鎸囧悜璇ttp璇锋眰鐘舵€佺爜
+ responseHeader.put(key, httpURLConnection.getHeaderField(key));
+ }
+ resourceResponse.setResponseHeaders(responseHeader);
+ return resourceResponse;
+ } else {
+ Log.e(TAG, "non binary resource for " + mime);
+ return super.shouldInterceptRequest(view, request);
+ }
+ }
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return super.shouldInterceptRequest(view, request);
+ }
+
+ @Override
+ public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
+ // API < 21 鍙兘鎷︽埅URL鍙傛暟
+ return super.shouldInterceptRequest(view, url);
+ }
+ });
+
+
+ webView.loadUrl(targetUrl);
+ }
+
+
+ /**
+ * 浠巆ontentType涓幏鍙朚IME绫诲瀷
+ *
+ * @param contentType
+ * @return
+ */
+ private String getMime(String contentType) {
+ if (contentType == null) {
+ return null;
+ }
+ return contentType.split(";")[0];
+ }
+
+ /**
+ * 浠巆ontentType涓幏鍙栫紪鐮佷俊鎭?
+ *
+ * @param contentType
+ * @return
+ */
+ private String getCharset(String contentType) {
+ if (contentType == null) {
+ return null;
+ }
+
+ String[] fields = contentType.split(";");
+ if (fields.length <= 1) {
+ return null;
+ }
+
+ String charset = fields[1];
+ if (!charset.contains("=")) {
+ return null;
+ }
+ charset = charset.substring(charset.indexOf("=") + 1);
+ return charset;
+ }
+
+
+ /**
+ * 鏄惁鏄簩杩涘埗璧勬簮锛屼簩杩涘埗璧勬簮鍙互涓嶉渶瑕佺紪鐮佷俊鎭?
+ */
+ private boolean isBinaryRes(String mime) {
+ if (mime.startsWith("image")
+ || mime.startsWith("audio")
+ || mime.startsWith("video")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ public URLConnection recursiveRequest(String path, Map headers, String reffer) {
+ HttpURLConnection conn;
+ URL url = null;
+ try {
+ url = new URL(path);
+ // 寮傛鎺ュ彛鑾峰彇IP
+ String ip = MyApp.getInstance().getService().getIpByHostAsync(url.getHost());
+ if (ip != null) {
+ // 閫氳繃HTTPDNS鑾峰彇IP鎴愬姛锛岃繘琛孶RL鏇挎崲鍜孒OST澶磋缃?
+ Log.d(TAG, "Get IP: " + ip + " for host: " + url.getHost() + " from HTTPDNS successfully!");
+ String newUrl = path.replaceFirst(url.getHost(), ip);
+ conn = (HttpURLConnection) new URL(newUrl).openConnection();
+
+ if (headers != null) {
+ for (Map.Entry field : headers.entrySet()) {
+ conn.setRequestProperty(field.getKey(), field.getValue());
+ }
+ }
+ // 璁剧疆HTTP璇锋眰澶碒ost鍩?
+ conn.setRequestProperty("Host", url.getHost());
+ } else {
+ return null;
+ }
+ conn.setConnectTimeout(30000);
+ conn.setReadTimeout(30000);
+ conn.setInstanceFollowRedirects(false);
+ if (conn instanceof HttpsURLConnection) {
+ final HttpsURLConnection httpsURLConnection = (HttpsURLConnection) conn;
+ WebviewTlsSniSocketFactory sslSocketFactory = new WebviewTlsSniSocketFactory(
+ (HttpsURLConnection)conn);
+
+ // sni鍦烘櫙锛屽垱寤篠SLScocket
+ httpsURLConnection.setSSLSocketFactory(sslSocketFactory);
+ // https鍦烘櫙锛岃瘉涔︽牎楠?
+ httpsURLConnection.setHostnameVerifier(new HostnameVerifier() {
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ String host = httpsURLConnection.getRequestProperty("Host");
+ if (null == host) {
+ host = httpsURLConnection.getURL().getHost();
+ }
+ return HttpsURLConnection.getDefaultHostnameVerifier().verify(host, session);
+ }
+ });
+ }
+ int code = conn.getResponseCode();// Network block
+ if (needRedirect(code)) {
+ // 鍘熸湁鎶ュご涓惈鏈塩ookie锛屾斁寮冩嫤鎴?
+ if (containCookie(headers)) {
+ return null;
+ }
+
+ String location = conn.getHeaderField("Location");
+ if (location == null) {
+ location = conn.getHeaderField("location");
+ }
+
+ if (location != null) {
+ if (!(location.startsWith("http://") || location
+ .startsWith("https://"))) {
+ //鏌愪簺鏃跺€欎細鐪佺暐host锛屽彧杩斿洖鍚庨潰鐨刾ath锛屾墍浠ラ渶瑕佽ˉ鍏╱rl
+ URL originalUrl = new URL(path);
+ location = originalUrl.getProtocol() + "://"
+ + originalUrl.getHost() + location;
+ }
+ Log.e(TAG, "code: " + code + "; location: " + location + "; path " + path);
+ return recursiveRequest(location, headers, path);
+ } else {
+ // 鏃犳硶鑾峰彇location淇℃伅锛岃娴忚鍣ㄨ幏鍙?
+ return null;
+ }
+ } else {
+ // redirect finish.
+ Log.e(TAG, "redirect finish");
+ return conn;
+ }
+ } catch (MalformedURLException e) {
+ Log.w(TAG, "recursiveRequest MalformedURLException");
+ } catch (IOException e) {
+ Log.w(TAG, "recursiveRequest IOException");
+ } catch (Exception e) {
+ Log.w(TAG, "unknow exception");
+ }
+ return null;
+ }
+
+
+ private boolean needRedirect(int code) {
+ return code >= 300 && code < 400;
+ }
+
+
+ /**
+ * header涓槸鍚﹀惈鏈塩ookie
+ */
+ private boolean containCookie(Map headers) {
+ for (Map.Entry headerField : headers.entrySet()) {
+ if (headerField.getKey().contains("Cookie")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ static class WebviewTlsSniSocketFactory extends SSLSocketFactory {
+ private final String TAG = WebviewTlsSniSocketFactory.class.getSimpleName();
+ HostnameVerifier hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
+ private final HttpsURLConnection conn;
+
+ public WebviewTlsSniSocketFactory(HttpsURLConnection conn) {
+ this.conn = conn;
+ }
+
+ @Override
+ public Socket createSocket() throws IOException {
+ return null;
+ }
+
+ @Override
+ public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
+ return null;
+ }
+
+ @Override
+ public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
+ return null;
+ }
+
+ @Override
+ public Socket createSocket(InetAddress host, int port) throws IOException {
+ return null;
+ }
+
+ @Override
+ public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
+ return null;
+ }
+
+ // TLS layer
+
+ @Override
+ public String[] getDefaultCipherSuites() {
+ return new String[0];
+ }
+
+ @Override
+ public String[] getSupportedCipherSuites() {
+ return new String[0];
+ }
+
+ @Override
+ public Socket createSocket(Socket plainSocket, String host, int port, boolean autoClose) throws IOException {
+ String peerHost = this.conn.getRequestProperty("Host");
+ if (peerHost == null)
+ peerHost = host;
+ Log.i(TAG, "customized createSocket. host: " + peerHost);
+ InetAddress address = plainSocket.getInetAddress();
+ if (autoClose) {
+ // we don't need the plainSocket
+ plainSocket.close();
+ }
+ // create and connect SSL socket, but don't do hostname/certificate verification yet
+ SSLCertificateSocketFactory sslSocketFactory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(0);
+ SSLSocket ssl = (SSLSocket) sslSocketFactory.createSocket(address, port);
+
+ // enable TLSv1.1/1.2 if available
+ ssl.setEnabledProtocols(ssl.getSupportedProtocols());
+
+ // set up SNI before the handshake
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ Log.i(TAG, "Setting SNI hostname");
+ sslSocketFactory.setHostname(ssl, peerHost);
+ } else {
+ Log.d(TAG, "No documented SNI support on Android <4.2, trying with reflection");
+ try {
+ java.lang.reflect.Method setHostnameMethod = ssl.getClass().getMethod("setHostname", String.class);
+ setHostnameMethod.invoke(ssl, peerHost);
+ } catch (Exception e) {
+ Log.w(TAG, "SNI not useable", e);
+ }
+ }
+
+ // verify hostname and certificate
+ SSLSession session = ssl.getSession();
+
+ if (!hostnameVerifier.verify(peerHost, session))
+ throw new SSLPeerUnverifiedException("Cannot verify hostname: " + peerHost);
+
+ Log.i(TAG, "Established " + session.getProtocol() + " connection with " + session.getPeerHost() +
+ " using " + session.getCipherSuite());
+
+ return ssl;
+ }
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/base/BaseActivity.java b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/base/BaseActivity.java
new file mode 100644
index 0000000..c30381d
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/base/BaseActivity.java
@@ -0,0 +1,264 @@
+package com.newsdk.ams.httpdns.demo.base;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import com.newsdk.ams.httpdns.demo.MyApp;
+import com.newsdk.ams.httpdns.demo.R;
+
+public class BaseActivity extends Activity {
+
+ public static final int MSG_WHAT_LOG = 10000;
+
+ private ScrollView logScrollView;
+ private TextView logView;
+ private LinearLayout llContainer;
+
+ private Handler handler;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_base);
+
+ handler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ switch (msg.what) {
+ case MSG_WHAT_LOG:
+ logView.setText(logView.getText() + "\n" + (String) msg.obj);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ logScrollView.fullScroll(View.FOCUS_DOWN);
+ }
+ });
+ break;
+ }
+ }
+ };
+
+ logScrollView = findViewById(R.id.logScrollView);
+ logView = findViewById(R.id.tvConsoleText);
+ llContainer = findViewById(R.id.llContainer);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ handler.removeCallbacksAndMessages(null);
+ handler = null;
+ }
+
+ /**
+ * 鍙戦€佹棩蹇楀埌鐣岄潰
+ *
+ * @param log
+ */
+ protected void sendLog(String log) {
+ Log.d(MyApp.TAG, log);
+ if (handler != null) {
+ Message msg = handler.obtainMessage(MSG_WHAT_LOG, log);
+ handler.sendMessage(msg);
+ }
+ }
+
+ protected void cleanLog() {
+ logView.setText("");
+ }
+
+ protected void addView(int layoutId, OnViewCreated created) {
+ FrameLayout container = new FrameLayout(this);
+ View.inflate(this, layoutId, container);
+ llContainer.addView(container, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ created.onViewCreated(container);
+ }
+
+ protected void addOneButton(
+ final String labelOne, final View.OnClickListener clickListenerOne
+ ) {
+ addView(R.layout.item_one_button, new OnViewCreated() {
+ @Override
+ public void onViewCreated(View view) {
+
+ Button btnOne = view.findViewById(R.id.btnOne);
+ btnOne.setText(labelOne);
+ btnOne.setOnClickListener(clickListenerOne);
+ }
+ });
+ }
+
+ protected void addTwoButton(
+ final String labelOne, final View.OnClickListener clickListenerOne,
+ final String labelTwo, final View.OnClickListener clickListenerTwo
+ ) {
+ addView(R.layout.item_two_button, new OnViewCreated() {
+ @Override
+ public void onViewCreated(View view) {
+
+ Button btnOne = view.findViewById(R.id.btnOne);
+ btnOne.setText(labelOne);
+ btnOne.setOnClickListener(clickListenerOne);
+
+ Button btnTwo = view.findViewById(R.id.btnTwo);
+ btnTwo.setText(labelTwo);
+ btnTwo.setOnClickListener(clickListenerTwo);
+ }
+ });
+ }
+
+ protected void addThreeButton(
+ final String labelOne, final View.OnClickListener clickListenerOne,
+ final String labelTwo, final View.OnClickListener clickListenerTwo,
+ final String labelThree, final View.OnClickListener clickListenerThree
+ ) {
+ addView(R.layout.item_three_button, new OnViewCreated() {
+ @Override
+ public void onViewCreated(View view) {
+
+ Button btnOne = view.findViewById(R.id.btnOne);
+ btnOne.setText(labelOne);
+ btnOne.setOnClickListener(clickListenerOne);
+
+ Button btnTwo = view.findViewById(R.id.btnTwo);
+ btnTwo.setText(labelTwo);
+ btnTwo.setOnClickListener(clickListenerTwo);
+
+ Button btnThree = view.findViewById(R.id.btnThree);
+ btnThree.setText(labelThree);
+ btnThree.setOnClickListener(clickListenerThree);
+ }
+ });
+ }
+
+
+ protected void addFourButton(
+ final String labelOne, final View.OnClickListener clickListenerOne,
+ final String labelTwo, final View.OnClickListener clickListenerTwo,
+ final String labelThree, final View.OnClickListener clickListenerThree,
+ final String labelFour, final View.OnClickListener clickListenerFour
+ ) {
+ addView(R.layout.item_four_button, new OnViewCreated() {
+ @Override
+ public void onViewCreated(View view) {
+
+ Button btnOne = view.findViewById(R.id.btnOne);
+ btnOne.setText(labelOne);
+ btnOne.setOnClickListener(clickListenerOne);
+
+ Button btnTwo = view.findViewById(R.id.btnTwo);
+ btnTwo.setText(labelTwo);
+ btnTwo.setOnClickListener(clickListenerTwo);
+
+ Button btnThree = view.findViewById(R.id.btnThree);
+ btnThree.setText(labelThree);
+ btnThree.setOnClickListener(clickListenerThree);
+
+ Button btnFour = view.findViewById(R.id.btnFour);
+ btnFour.setText(labelFour);
+ btnFour.setOnClickListener(clickListenerFour);
+ }
+ });
+ }
+
+ protected void addEditTextButton(
+ final String hint,
+ final String labelOne, final OnButtonClick clickListenerOne
+ ) {
+ addView(R.layout.item_edit_button, new OnViewCreated() {
+ @Override
+ public void onViewCreated(View view) {
+
+ Button btnOne = view.findViewById(R.id.btnOne);
+ btnOne.setText(labelOne);
+ final EditText editText = view.findViewById(R.id.etOne);
+ editText.setHint(hint);
+ btnOne.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ clickListenerOne.onBtnClick(editText);
+ }
+ });
+ }
+ });
+ }
+
+
+ protected void addEditTextEditTextButton(
+ final String hintOne, final String hintTwo,
+ final String labelOne, final OnButtonClickMoreView clickListenerOne
+ ) {
+ addView(R.layout.item_edit_edit_button, new OnViewCreated() {
+ @Override
+ public void onViewCreated(View view) {
+
+ Button btnOne = view.findViewById(R.id.btnOne);
+ btnOne.setText(labelOne);
+ final EditText editTextOne = view.findViewById(R.id.etOne);
+ editTextOne.setHint(hintOne);
+ final EditText editTextTwo = view.findViewById(R.id.etTwo);
+ editTextTwo.setHint(hintTwo);
+ btnOne.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ clickListenerOne.onBtnClick(new View[]{editTextOne, editTextTwo});
+ }
+ });
+ }
+ });
+ }
+
+ protected void addAutoCompleteTextViewButton(
+ final String[] strings, final String hint, final String labelOne, final OnButtonClick clickListenerOne
+ ) {
+ addView(R.layout.item_autocomplete_button, new OnViewCreated() {
+ @Override
+ public void onViewCreated(View view) {
+
+ Button btnOne = view.findViewById(R.id.btnOne);
+ btnOne.setText(labelOne);
+
+ final AutoCompleteTextView actvOne = view.findViewById(R.id.actvOne);
+ ArrayAdapter adapter = new ArrayAdapter(getApplicationContext(),
+ android.R.layout.simple_dropdown_item_1line, strings);
+ actvOne.setAdapter(adapter);
+ actvOne.setHint(hint);
+
+ btnOne.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ clickListenerOne.onBtnClick(actvOne);
+ }
+ });
+ }
+ });
+ }
+
+ public interface OnViewCreated {
+ void onViewCreated(View view);
+ }
+
+ public interface OnButtonClick {
+ void onBtnClick(View view);
+ }
+
+ public interface OnButtonClickMoreView {
+ void onBtnClick(View[] views);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/http/HttpUrlConnectionRequest.java b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/http/HttpUrlConnectionRequest.java
new file mode 100644
index 0000000..77f3dc3
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/http/HttpUrlConnectionRequest.java
@@ -0,0 +1,258 @@
+package com.newsdk.ams.httpdns.demo.http;
+
+
+import android.content.Context;
+import android.net.SSLCertificateSocketFactory;
+import android.os.Build;
+import android.util.Log;
+
+import com.newsdk.sdk.android.httpdns.HTTPDNSResult;
+import com.newsdk.sdk.android.httpdns.NetType;
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+import com.newsdk.sdk.android.httpdns.SyncService;
+import com.newsdk.sdk.android.httpdns.net.HttpDnsNetworkDetector;
+import com.newsdk.ams.httpdns.demo.MyApp;
+import com.newsdk.ams.httpdns.demo.NetworkRequest;
+import com.newsdk.ams.httpdns.demo.utils.Util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.URL;
+import java.net.UnknownHostException;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+/**
+ * 浣跨敤HttpUrlConnection 瀹炵幇璇锋眰
+ */
+public class HttpUrlConnectionRequest implements NetworkRequest {
+
+ public static final String TAG = MyApp.TAG + "HttpUrl";
+
+ private final Context context;
+ private boolean async;
+ private RequestIpType type;
+
+ public HttpUrlConnectionRequest(Context context) {
+ this.context = context.getApplicationContext();
+ }
+
+ @Override
+ public void updateHttpDnsConfig(boolean async, RequestIpType requestIpType) {
+ this.async = async;
+ this.type = requestIpType;
+ }
+
+ @Override
+ public String httpGet(String url) throws Exception {
+ Log.d(TAG, "浣跨敤httpUrlConnection 璇锋眰" + url + " 寮傛鎺ュ彛 " + async + " ip绫诲瀷 " + type.name());
+
+ HttpURLConnection conn = getConnection(url);
+ InputStream in = null;
+ BufferedReader streamReader = null;
+ if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
+ in = conn.getErrorStream();
+ String errStr = null;
+ if (in != null) {
+ streamReader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+ errStr = readStringFrom(streamReader).toString();
+ }
+ Log.d(TAG, "璇锋眰澶辫触 " + conn.getResponseCode() + " err " + errStr);
+ throw new Exception("Status Code : " + conn.getResponseCode() + " Msg : " + errStr);
+ } else {
+ in = conn.getInputStream();
+ streamReader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+ String responseStr = readStringFrom(streamReader).toString();
+ Log.d(TAG, "璇锋眰鎴愬姛 " + responseStr);
+ return responseStr;
+ }
+ }
+
+ private HttpURLConnection getConnection(String url) throws IOException {
+ final String host = new URL(url).getHost();
+ HttpURLConnection conn = null;
+ HTTPDNSResult result;
+ /* 鍒囨崲涓烘柊鐗堟爣鍑哸pi */
+ if (async) {
+ result = MyApp.getInstance().getService().getHttpDnsResultForHostAsync(host, type);
+ } else {
+ result = MyApp.getInstance().getService().getHttpDnsResultForHostSync(host, type);
+ }
+ Log.d(TAG, "httpdns 瑙f瀽 " + host + " 缁撴灉涓?" + result + " ttl is " + Util.getTtl(result));
+
+ // 杩欓噷闇€瑕佹牴鎹疄闄呮儏鍐甸€夋嫨浣跨敤ipv6鍦板潃 杩樻槸 ipv4鍦板潃锛?涓嬮潰绀轰緥鐨勪唬鐮佷紭鍏堜娇鐢ㄤ簡ipv6鍦板潃
+ if (result.getIpv6s() != null && result.getIpv6s().length > 0 && HttpDnsNetworkDetector.getInstance().getNetType(context) != NetType.v4) {
+ String newUrl = url.replace(host, "[" + result.getIpv6s()[0] + "]");
+ conn = (HttpURLConnection) new URL(newUrl).openConnection();
+ conn.setRequestProperty("Host", host);
+ Log.d(TAG, "浣跨敤ipv6鍦板潃 " + newUrl);
+ } else if (result.getIps() != null && result.getIps().length > 0 && HttpDnsNetworkDetector.getInstance().getNetType(context) != NetType.v6) {
+ String newUrl = url.replace(host, result.getIps()[0]);
+ conn = (HttpURLConnection) new URL(newUrl).openConnection();
+ conn.setRequestProperty("Host", host);
+ Log.d(TAG, "浣跨敤ipv4鍦板潃 " + newUrl);
+ }
+
+ if (conn == null) {
+ Log.d(TAG, "httpdns 鏈繑鍥炶В鏋愮粨鏋滐紝璧發ocaldns");
+ conn = (HttpURLConnection) new URL(url).openConnection();
+ }
+ conn.setConnectTimeout(30000);
+ conn.setReadTimeout(30000);
+ conn.setInstanceFollowRedirects(false);
+ if (conn instanceof HttpsURLConnection) {
+ final HttpsURLConnection httpsURLConnection = (HttpsURLConnection) conn;
+ WebviewTlsSniSocketFactory sslSocketFactory = new WebviewTlsSniSocketFactory(
+ (HttpsURLConnection)conn);
+
+ // sni鍦烘櫙锛屽垱寤篠SLSocket
+ httpsURLConnection.setSSLSocketFactory(sslSocketFactory);
+ // https鍦烘櫙锛岃瘉涔︽牎楠?
+ httpsURLConnection.setHostnameVerifier(new HostnameVerifier() {
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ String host = httpsURLConnection.getRequestProperty("Host");
+ if (null == host) {
+ host = httpsURLConnection.getURL().getHost();
+ }
+ return HttpsURLConnection.getDefaultHostnameVerifier().verify(host, session);
+ }
+ });
+ }
+ int code = conn.getResponseCode();// Network block
+ if (needRedirect(code)) {
+ //涓存椂閲嶅畾鍚戝拰姘镐箙閲嶅畾鍚憀ocation鐨勫ぇ灏忓啓鏈夊尯鍒?
+ String location = conn.getHeaderField("Location");
+ if (location == null) {
+ location = conn.getHeaderField("location");
+ }
+ if (!(location.startsWith("http://") || location
+ .startsWith("https://"))) {
+ //鏌愪簺鏃跺€欎細鐪佺暐host锛屽彧杩斿洖鍚庨潰鐨刾ath锛屾墍浠ラ渶瑕佽ˉ鍏╱rl
+ URL originalUrl = new URL(url);
+ location = originalUrl.getProtocol() + "://"
+ + originalUrl.getHost() + location;
+ }
+ return getConnection(location);
+ }
+ return conn;
+ }
+
+ private boolean needRedirect(int code) {
+ return code >= 300 && code < 400;
+ }
+
+ static class WebviewTlsSniSocketFactory extends SSLSocketFactory {
+ private final String TAG = WebviewTlsSniSocketFactory.class.getSimpleName();
+ HostnameVerifier hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
+ private HttpsURLConnection conn;
+
+ public WebviewTlsSniSocketFactory(HttpsURLConnection conn) {
+ this.conn = conn;
+ }
+
+ @Override
+ public Socket createSocket() throws IOException {
+ return null;
+ }
+
+ @Override
+ public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
+ return null;
+ }
+
+ @Override
+ public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
+ return null;
+ }
+
+ @Override
+ public Socket createSocket(InetAddress host, int port) throws IOException {
+ return null;
+ }
+
+ @Override
+ public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
+ return null;
+ }
+
+ // TLS layer
+
+ @Override
+ public String[] getDefaultCipherSuites() {
+ return new String[0];
+ }
+
+ @Override
+ public String[] getSupportedCipherSuites() {
+ return new String[0];
+ }
+
+ @Override
+ public Socket createSocket(Socket plainSocket, String host, int port, boolean autoClose) throws IOException {
+ String peerHost = this.conn.getRequestProperty("Host");
+ if (peerHost == null)
+ peerHost = host;
+ Log.i(TAG, "customized createSocket. host: " + peerHost);
+ InetAddress address = plainSocket.getInetAddress();
+ if (autoClose) {
+ // we don't need the plainSocket
+ plainSocket.close();
+ }
+ // create and connect SSL socket, but don't do hostname/certificate verification yet
+ SSLCertificateSocketFactory sslSocketFactory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(0);
+ SSLSocket ssl = (SSLSocket) sslSocketFactory.createSocket(address, port);
+
+ // enable TLSv1.1/1.2 if available
+ ssl.setEnabledProtocols(ssl.getSupportedProtocols());
+
+ // set up SNI before the handshake
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ Log.i(TAG, "Setting SNI hostname");
+ sslSocketFactory.setHostname(ssl, peerHost);
+ } else {
+ Log.d(TAG, "No documented SNI support on Android <4.2, trying with reflection");
+ try {
+ java.lang.reflect.Method setHostnameMethod = ssl.getClass().getMethod("setHostname", String.class);
+ setHostnameMethod.invoke(ssl, peerHost);
+ } catch (Exception e) {
+ Log.w(TAG, "SNI not useable", e);
+ }
+ }
+
+ // verify hostname and certificate
+ SSLSession session = ssl.getSession();
+
+ if (!hostnameVerifier.verify(peerHost, session))
+ throw new SSLPeerUnverifiedException("Cannot verify hostname: " + peerHost);
+
+ Log.i(TAG, "Established " + session.getProtocol() + " connection with " + session.getPeerHost() +
+ " using " + session.getCipherSuite());
+
+ return ssl;
+ }
+ }
+
+ /**
+ * stream to string
+ */
+ public static StringBuilder readStringFrom(BufferedReader streamReader) throws IOException {
+ StringBuilder sb = new StringBuilder();
+ String line;
+ while ((line = streamReader.readLine()) != null) {
+ sb.append(line);
+ }
+ return sb;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/okhttp/OkHttpRequest.java b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/okhttp/OkHttpRequest.java
new file mode 100644
index 0000000..f502dc6
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/okhttp/OkHttpRequest.java
@@ -0,0 +1,98 @@
+package com.newsdk.ams.httpdns.demo.okhttp;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.newsdk.sdk.android.httpdns.HTTPDNSResult;
+import com.newsdk.sdk.android.httpdns.NetType;
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+import com.newsdk.sdk.android.httpdns.SyncService;
+import com.newsdk.sdk.android.httpdns.net.HttpDnsNetworkDetector;
+import com.newsdk.ams.httpdns.demo.MyApp;
+import com.newsdk.ams.httpdns.demo.NetworkRequest;
+import com.newsdk.ams.httpdns.demo.utils.Util;
+
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.ConnectionPool;
+import okhttp3.Dns;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+/**
+ * okhttp瀹炵幇缃戠粶璇锋眰
+ */
+public class OkHttpRequest implements NetworkRequest {
+
+ public static final String TAG = MyApp.TAG + "Okhttp";
+ private final OkHttpClient client;
+
+ private boolean async;
+ private RequestIpType type;
+
+ public OkHttpRequest(final Context context) {
+ client = new OkHttpClient.Builder()
+ // 杩欓噷閰嶇疆杩炴帴姹狅紝鏄负浜嗘柟渚挎祴璇昲ttpdns鑳藉姏锛屾寮忎唬鐮佽涓嶈閰嶇疆
+ .connectionPool(new ConnectionPool(0, 10 * 1000, TimeUnit.MICROSECONDS))
+ .dns(new Dns() {
+ @Override
+ public List lookup(String hostname) throws UnknownHostException {
+ HTTPDNSResult result;
+ /* 鍒囨崲涓烘柊鐗堟爣鍑哸pi */
+ if (async) {
+ result = MyApp.getInstance().getService().getHttpDnsResultForHostAsync(hostname, type);
+ } else {
+ result = MyApp.getInstance().getService().getHttpDnsResultForHostSync(hostname, type);
+ }
+ Log.d(TAG, "httpdns 瑙f瀽 " + hostname + " 缁撴灉涓?" + result + " ttl is " + Util.getTtl(result));
+ List inetAddresses = new ArrayList<>();
+ // 杩欓噷闇€瑕佹牴鎹疄闄呮儏鍐甸€夋嫨浣跨敤ipv6鍦板潃 杩樻槸 ipv4鍦板潃锛?涓嬮潰绀轰緥鐨勪唬鐮佷紭鍏堜娇鐢ㄤ簡ipv6鍦板潃
+ Log.d(TAG, "netType is: " + HttpDnsNetworkDetector.getInstance().getNetType(context));
+ if (result.getIpv6s() != null && result.getIpv6s().length > 0 && HttpDnsNetworkDetector.getInstance().getNetType(context) != NetType.v4) {
+ for (int i = 0; i < result.getIpv6s().length; i++) {
+ inetAddresses.addAll(Arrays.asList(InetAddress.getAllByName(result.getIpv6s()[i])));
+ }
+ Log.d(TAG, "浣跨敤ipv6鍦板潃" + inetAddresses);
+ } else if (result.getIps() != null && result.getIps().length > 0 && HttpDnsNetworkDetector.getInstance().getNetType(context) != NetType.v6) {
+ for (int i = 0; i < result.getIps().length; i++) {
+ inetAddresses.addAll(Arrays.asList(InetAddress.getAllByName(result.getIps()[i])));
+ }
+ Log.d(TAG, "浣跨敤ipv4鍦板潃" + inetAddresses);
+ }
+ if (inetAddresses.size() == 0) {
+ Log.d(TAG, "httpdns 鏈繑鍥濱P锛岃蛋localdns");
+ return Dns.SYSTEM.lookup(hostname);
+ }
+ return inetAddresses;
+ }
+ })
+ .build();
+ }
+
+ @Override
+ public void updateHttpDnsConfig(boolean async, RequestIpType requestIpType) {
+ this.async = async;
+ this.type = requestIpType;
+ }
+
+ @Override
+ public String httpGet(String url) throws Exception {
+ Log.d(TAG, "浣跨敤okhttp 璇锋眰" + url + " 寮傛鎺ュ彛 " + async + " ip绫诲瀷 " + type.name());
+ Response response = client.newCall(new Request.Builder().url(url).build()).execute();
+ int code = response.code();
+ String body = response.body().string();
+ Log.d(TAG, "浣跨敤okhttp 璇锋眰缁撴灉 code " + code + " body " + body);
+ if (code != HttpURLConnection.HTTP_OK) {
+ throw new Exception("璇锋眰澶辫触 code " + code + " body " + body);
+ }
+ return body;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/utils/SpUtil.java b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/utils/SpUtil.java
new file mode 100644
index 0000000..2ab142a
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/utils/SpUtil.java
@@ -0,0 +1,28 @@
+package com.newsdk.ams.httpdns.demo.utils;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+public class SpUtil {
+
+ public static void readSp(Context context, String name, OnGetSp onGetSp) {
+ SharedPreferences sp = context.getSharedPreferences(name, Context.MODE_PRIVATE);
+ onGetSp.onGetSp(sp);
+ }
+
+ public static void writeSp(Context context, String name, OnGetSpEditor onGetSpEditor) {
+ SharedPreferences sp = context.getSharedPreferences(name, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sp.edit();
+ onGetSpEditor.onGetSpEditor(editor);
+ editor.commit();
+ }
+
+ public interface OnGetSp {
+ void onGetSp(SharedPreferences sp);
+ }
+
+ public interface OnGetSpEditor {
+ void onGetSpEditor(SharedPreferences.Editor editor);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/utils/ThreadUtil.java b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/utils/ThreadUtil.java
new file mode 100644
index 0000000..d7cb983
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/utils/ThreadUtil.java
@@ -0,0 +1,95 @@
+package com.newsdk.ams.httpdns.demo.utils;
+
+import android.util.Log;
+
+import com.newsdk.sdk.android.httpdns.HTTPDNSResult;
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+import com.newsdk.sdk.android.httpdns.SyncService;
+import com.newsdk.ams.httpdns.demo.MyApp;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class ThreadUtil {
+
+ public static void multiThreadTest(
+ final String[] validHosts,
+ final int hostCount,
+ final int threadCount,
+ final int executeTime,
+ final boolean async,
+ final RequestIpType type
+ ) {
+ new Thread(() -> runMultiThreadTest(validHosts, hostCount, threadCount, executeTime, async, type)).start();
+ }
+
+ private static void runMultiThreadTest(
+ String[] validHosts,
+ int hostCount,
+ int threadCount,
+ int executeTime,
+ boolean async,
+ RequestIpType type
+ ) {
+ int validCount = Math.min(validHosts.length, hostCount);
+ Log.d(MyApp.TAG, "Start multiThreadTest, threads=" + threadCount
+ + ", executeTimeMs=" + executeTime
+ + ", hostCount=" + hostCount
+ + ", validHostCount=" + validCount
+ + ", async=" + async
+ + ", ipType=" + type.name());
+
+ ArrayList hosts = new ArrayList<>(hostCount);
+ for (int i = 0; i < hostCount - validCount; i++) {
+ hosts.add("test" + i + ".cloudxdr.com");
+ }
+ hosts.addAll(Arrays.asList(validHosts).subList(0, validCount));
+
+ ExecutorService pool = Executors.newFixedThreadPool(threadCount);
+ CountDownLatch done = new CountDownLatch(threadCount);
+
+ for (int i = 0; i < threadCount; i++) {
+ pool.execute(() -> {
+ Random random = new Random(Thread.currentThread().getId());
+ long begin = System.currentTimeMillis();
+ int requestCount = 0;
+ int successCount = 0;
+
+ while (System.currentTimeMillis() - begin < executeTime) {
+ String host = hosts.get(random.nextInt(hosts.size()));
+ try {
+ HTTPDNSResult result;
+ if (async) {
+ result = MyApp.getInstance().getService().getIpsByHostAsync(host, type);
+ } else {
+ result = ((SyncService) MyApp.getInstance().getService()).getByHost(host, type);
+ }
+ if (result != null && result.getIps() != null && result.getIps().length > 0) {
+ successCount++;
+ }
+ } catch (Throwable t) {
+ Log.w(MyApp.TAG, "multiThreadTest request failed: " + t.getMessage());
+ }
+ requestCount++;
+ }
+
+ Log.w(MyApp.TAG, "multiThreadTest thread=" + Thread.currentThread().getId()
+ + ", requestCount=" + requestCount
+ + ", successCount=" + successCount);
+ done.countDown();
+ });
+ }
+
+ try {
+ done.await();
+ } catch (InterruptedException ignored) {
+ } finally {
+ pool.shutdownNow();
+ }
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/utils/Util.java b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/utils/Util.java
new file mode 100644
index 0000000..65b4281
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/java/com/newsdk/ams/httpdns/demo/utils/Util.java
@@ -0,0 +1,25 @@
+package com.newsdk.ams.httpdns.demo.utils;
+
+import com.newsdk.sdk.android.httpdns.HTTPDNSResult;
+
+import java.lang.reflect.Field;
+
+public class Util {
+ /**
+ * 鑾峰彇ttl锛?
+ * 姝ゆ柟娉曟槸鐢ㄤ簬娴嬭瘯鑷畾涔塼tl鏄惁鐢熸晥
+ */
+ public static int getTtl(HTTPDNSResult result) {
+ try {
+ Field ttlField = HTTPDNSResult.class.getDeclaredField("ttl");
+ ttlField.setAccessible(true);
+ return ttlField.getInt(result);
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ return -1;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/drawable/new_bg.9.png b/HttpDNSSDK/sdk/android/app/src/main/res/drawable/new_bg.9.png
new file mode 100644
index 0000000..5be6ad4
Binary files /dev/null and b/HttpDNSSDK/sdk/android/app/src/main/res/drawable/new_bg.9.png differ
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/layout/activity_base.xml b/HttpDNSSDK/sdk/android/app/src/main/res/layout/activity_base.xml
new file mode 100644
index 0000000..4ec412c
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/layout/activity_base.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/layout/activity_webview.xml b/HttpDNSSDK/sdk/android/app/src/main/res/layout/activity_webview.xml
new file mode 100644
index 0000000..eb9ec73
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/layout/activity_webview.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_autocomplete_button.xml b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_autocomplete_button.xml
new file mode 100644
index 0000000..2bd73c6
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_autocomplete_button.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_autocomplete_edittext_button.xml b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_autocomplete_edittext_button.xml
new file mode 100644
index 0000000..780f212
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_autocomplete_edittext_button.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_edit_button.xml b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_edit_button.xml
new file mode 100644
index 0000000..5452f2f
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_edit_button.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_edit_edit_button.xml b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_edit_edit_button.xml
new file mode 100644
index 0000000..0a548ce
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_edit_edit_button.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_four_button.xml b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_four_button.xml
new file mode 100644
index 0000000..e2c2762
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_four_button.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_one_button.xml b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_one_button.xml
new file mode 100644
index 0000000..b44d423
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_one_button.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_three_button.xml b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_three_button.xml
new file mode 100644
index 0000000..f62cd51
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_three_button.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_two_button.xml b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_two_button.xml
new file mode 100644
index 0000000..f7b03f6
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/layout/item_two_button.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-hdpi/back.png b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-hdpi/back.png
new file mode 100644
index 0000000..e34da76
Binary files /dev/null and b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-hdpi/back.png differ
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
Binary files /dev/null and b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..9a078e3
Binary files /dev/null and b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
Binary files /dev/null and b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..efc028a
Binary files /dev/null and b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
Binary files /dev/null and b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..3af2608
Binary files /dev/null and b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
Binary files /dev/null and b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..9bec2e6
Binary files /dev/null and b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
Binary files /dev/null and b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..34947cd
Binary files /dev/null and b/HttpDNSSDK/sdk/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/values/colors.xml b/HttpDNSSDK/sdk/android/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..3ab3e9c
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/values/strings.xml b/HttpDNSSDK/sdk/android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..86dc3ff
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,31 @@
+
+ 閵嗘劙妯嬮柌灞肩隘HttpDns閵嗘厪emo缁嬪绨
+ Settings
+ 閺咁噣鈧俺袙閺
+ 鐟欙絾鐎藉ǎ妯虹杺閸╃喎鎮
+ 鐟欙絾鐎絘pple閸╃喎鎮
+ 鐟欙絾鐎界挒鍡欐憵閸╃喎鎮
+ HTTPS瀵偓閸
+ 鐠佸墽鐤嗙搾鍛
+ 閸忎浇顔忔潻鍥ㄦ埂閸╃喎鎮
+ 瀵偓閸氼垱瀵旀稊鍛缂傛挸鐡
+ 闂勫秶楠囩粵鏍殣
+ 妫板嫯袙閺
+ region
+ 閸氬本顒炵憴锝嗙€
+ 閸氬本顒炵憴锝嗙€介獮璺哄絺
+ 楠炶泛褰傜憴锝嗙€
+
+ 閸忓厖绨幋鎴滄粦
+ 鐢喖濮稉顓炵妇
+ 濞撳懘娅庤ぐ鎾冲濞戝牊浼
+
+ All Rights Reserved.
+ 闂冨潡鍣锋禍?鏉烆垯娆?閺堝妾洪崗顒€寰冮悧鍫熸綀閹碘偓閺
+ Copyright 婕?2009 - 2016 New.com
+ 1.1.3
+ Q : 娴犫偓娑斿牊妲搁悽銊﹀煕娴f捇鐛橠emo閿涚剠nA : 閻劍鍩涙担鎾荤崣Demo鐏忚鲸妲搁梼鍧楀櫡娴滄垵閽╅崣棰佽礋閹劏鍤滈崝銊ュ灡瀵よ櫣娈戦妴浣烘暏閺夈儰缍嬫瀛抰tpDns閺堝秴濮熼崪灞藉冀妫e牆缂撶拋顔炬暏閻ㄥ嫪绔存稉顏勭毈Demo閿涘矁顔€閹劋缍嬫灞肩┒閹规灚鈧線鐝弫鍫㈡畱HttpDns閺堝秴濮熼妴淇搉\nQ : 婵″倷缍嶉懕鏃傞兇閹存垳婊戦敍鐒卬A : App Demo閻╃鍙ч梻顕€顣介敍宀冾嚞閹兼粎鍌ㄩ柦澶愭嫟缂囥倕褰块敍?1777313
+
+
+
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/values/styles.xml b/HttpDNSSDK/sdk/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..131d99a
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
diff --git a/HttpDNSSDK/sdk/android/app/src/main/res/xml/network_security_config.xml b/HttpDNSSDK/sdk/android/app/src/main/res/xml/network_security_config.xml
new file mode 100644
index 0000000..f904668
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/app/src/main/res/xml/network_security_config.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/HttpDNSSDK/sdk/android/build.gradle b/HttpDNSSDK/sdk/android/build.gradle
new file mode 100644
index 0000000..e639565
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/build.gradle
@@ -0,0 +1,12 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+plugins {
+ id 'com.android.application' version '7.3.1' apply false
+ id 'com.android.library' version '7.3.1' apply false
+ id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
+}
+
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/HttpDNSSDK/sdk/android/demo/build.gradle b/HttpDNSSDK/sdk/android/demo/build.gradle
new file mode 100644
index 0000000..85f9ec7
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/build.gradle
@@ -0,0 +1,128 @@
+plugins {
+ id 'com.android.application'
+ id 'org.jetbrains.kotlin.android'
+ id 'kotlin-kapt'
+}
+
+gradle.ext {
+ httpVersion = '2.3.4'
+}
+
+android {
+ namespace 'com.newsdk.ams.httpdns.demo'
+ compileSdk 34
+
+ defaultConfig {
+ applicationId "com.newsdk.ams.httpdns.demo"
+ minSdkVersion 26
+ targetSdkVersion 34
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+ buildConfigField "String", "HTTPDNS_VERSION", "\"${gradle.httpVersion}\""
+ buildConfigField "String", "ACCOUNT_ID", "\"replace-with-your-accountId\""
+ buildConfigField "String", "SECRET_KEY", "\"replace-with-your-secret\""
+ buildConfigField "String", "AES_SECRET_KEY", "\"replace-with-your-aes-secret\""
+ buildConfigField "String", "SERVICE_URL", "\"\""
+ }
+
+ buildTypes {
+
+ debug {
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+
+ release {
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+
+ forTest {
+ // Keep this flavor to avoid BuildVariants errors when switching httpdns-sdk to end2end tests.
+ initWith release
+ debuggable true
+ }
+ }
+
+ variantFilter { variant ->
+ def names = variant.flavors*.name
+ def type = variant.buildType.name
+ // To check for a certain build type, use variant.buildType.name == ""
+ if ((names.contains("normal") && type.contains("forTest"))
+ || (names.contains("intl") && type.contains("forTest"))
+ || (names.contains("end2end") && type.contains("release"))
+ || (names.contains("end2end") && type.contains("debug"))
+ ) {
+ // Gradle ignores any variants that satisfy the conditions above.
+ setIgnore(true)
+ }
+ }
+
+ testOptions {
+ unitTests {
+ all {
+ jvmArgs '-noverify'
+ systemProperty 'robolectric.logging.enable', true
+ }
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+ buildFeatures {
+ viewBinding = true
+ dataBinding = true
+ }
+
+ flavorDimensions += "version"
+
+ productFlavors {
+ normal {
+
+ }
+
+ intl {
+
+ }
+
+ end2end {
+ // Keep this flavor to avoid BuildVariants errors when switching httpdns-sdk to end2end tests.
+ }
+ }
+
+}
+
+dependencies {
+
+ implementation 'androidx.core:core-ktx:1.7.0'
+ implementation 'androidx.appcompat:appcompat:1.6.1'
+ implementation 'com.google.android.material:material:1.9.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1'
+ implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
+ implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
+
+ implementation("com.squareup.okhttp3:okhttp:4.10.0")
+ implementation 'com.squareup.okhttp3:logging-interceptor:4.10.0'
+ implementation project(path: ':httpdns-sdk')
+
+ implementation('com.newsdk:fastjson:1.1.73.android@jar')
+// implementation('com.emas.hybrid:emas-hybrid-android:1.1.0.4-public-SNAPSHOT') {
+// exclude group: 'com.android.support', module: 'appcompat-v7'
+// exclude group: 'com.taobao.android', module: 'thin_so_release'
+// }
+
+ implementation 'com.newsdk.ams:new-android-tool:1.1.0'
+
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'com.android.support.test:runner:1.0.2'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+}
diff --git a/HttpDNSSDK/sdk/android/demo/gradle.properties b/HttpDNSSDK/sdk/android/demo/gradle.properties
new file mode 100644
index 0000000..4b5db44
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/gradle.properties
@@ -0,0 +1,19 @@
+## Project-wide Gradle settings.
+#
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+#
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+#
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+#Sat Jun 11 21:37:51 CST 2016
+org.gradle.jvmargs=-Xmx1536m
+android.enableD8=true
+android.useAndroidX=true
+android.enableJetifier=true
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/proguard-rules.pro b/HttpDNSSDK/sdk/android/demo/proguard-rules.pro
new file mode 100644
index 0000000..e482c46
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/proguard-rules.pro
@@ -0,0 +1,22 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
+-keep class com.newsdk.sdk.android.httpdns.**{*;}
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/androidTest/java/com/newsdk/ams/emas/demo/ExampleInstrumentedTest.kt b/HttpDNSSDK/sdk/android/demo/src/androidTest/java/com/newsdk/ams/emas/demo/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..c9df783
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/androidTest/java/com/newsdk/ams/emas/demo/ExampleInstrumentedTest.kt
@@ -0,0 +1,25 @@
+package com.newsdk.ams.emas.demo
+
+import android.support.test.InstrumentationRegistry
+import android.support.test.runner.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.newsdk.ams.emas.demo", appContext.packageName)
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/AndroidManifest.xml b/HttpDNSSDK/sdk/android/demo/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..8a5c7c6
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/AndroidManifest.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/BatchResolveCacheHolder.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/BatchResolveCacheHolder.kt
new file mode 100644
index 0000000..a9ac61c
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/BatchResolveCacheHolder.kt
@@ -0,0 +1,93 @@
+package com.newsdk.ams.emas.demo
+import org.json.JSONArray
+import org.json.JSONException
+import org.json.JSONObject
+object BatchResolveCacheHolder {
+ var batchResolveV4List: MutableList = mutableListOf()
+ var batchResolveV6List: MutableList = mutableListOf()
+ var batchResolveBothList: MutableList = mutableListOf()
+ var batchResolveAutoList: MutableList = mutableListOf()
+ fun convertBatchResolveCacheData(cacheData: String?) {
+ if (cacheData == null) {
+ batchResolveBothList.add("www.baidu.com")
+ batchResolveBothList.add("m.baidu.com")
+ batchResolveBothList.add("demo.cloudxdr.com")
+ batchResolveBothList.add("www.taobao.com")
+ batchResolveBothList.add("www.163.com")
+ batchResolveBothList.add("www.sohu.com")
+ batchResolveBothList.add("www.sina.com.cn")
+ batchResolveBothList.add("www.douyin.com")
+ batchResolveBothList.add("www.qq.com")
+ batchResolveBothList.add("www.chinaamc.com")
+ batchResolveBothList.add("m.chinaamc.com")
+ return
+ }
+ try {
+ val jsonObject = JSONObject(cacheData)
+ val v4Array = jsonObject.optJSONArray("v4")
+ val v6Array = jsonObject.optJSONArray("v6")
+ val bothArray = jsonObject.optJSONArray("both")
+ val autoArray = jsonObject.optJSONArray("auto")
+ if (v4Array != null) {
+ var length = v4Array.length()
+ --length
+ while (length >= 0) {
+ batchResolveV4List.add(0, v4Array.getString(length))
+ --length
+ }
+ }
+ if (v6Array != null) {
+ var length = v6Array.length()
+ --length
+ while (length >= 0) {
+ batchResolveV6List.add(0, v6Array.getString(length))
+ --length
+ }
+ }
+ if (bothArray != null) {
+ var length = bothArray.length()
+ --length
+ while (length >= 0) {
+ batchResolveBothList.add(0, bothArray.getString(length))
+ --length
+ }
+ }
+ if (autoArray != null) {
+ var length = autoArray.length()
+ --length
+ while (length >= 0) {
+ batchResolveAutoList.add(0, autoArray.getString(length))
+ --length
+ }
+ }
+ } catch (e: JSONException) {
+ e.printStackTrace()
+ }
+ }
+ fun convertBatchResolveString(): String {
+ val jsonObject = JSONObject()
+ val v4Array = JSONArray()
+ val v6Array = JSONArray()
+ val bothArray = JSONArray()
+ val autoArray = JSONArray()
+ for (host in batchResolveV4List) {
+ v4Array.put(host)
+ }
+ jsonObject.put("v4", v4Array)
+ for (host in batchResolveV6List) {
+ v6Array.put(host)
+ }
+ jsonObject.put("v6", v6Array)
+ for (host in batchResolveBothList) {
+ bothArray.put(host)
+ }
+ jsonObject.put("both", bothArray)
+ for (host in batchResolveAutoList) {
+ autoArray.put(host)
+ }
+ jsonObject.put("auto", autoArray)
+ return jsonObject.toString()
+ }
+}
+
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/HttpDnsApplication.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/HttpDnsApplication.kt
new file mode 100644
index 0000000..2af75b0
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/HttpDnsApplication.kt
@@ -0,0 +1,17 @@
+package com.newsdk.ams.emas.demo
+
+import android.app.Application
+
+/**
+ * @author allen.wy
+ * @date 2023/5/24
+ */
+class HttpDnsApplication : Application() {
+
+ override fun onCreate() {
+ super.onCreate()
+ }
+
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/HttpDnsServiceHolder.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/HttpDnsServiceHolder.kt
new file mode 100644
index 0000000..dafec0f
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/HttpDnsServiceHolder.kt
@@ -0,0 +1,38 @@
+package com.newsdk.ams.emas.demo
+
+import android.content.Context
+import android.text.TextUtils
+import com.newsdk.ams.emas.demo.constant.KEY_ENABLE_AUTH_MODE
+import com.newsdk.ams.emas.demo.constant.KEY_SECRET_KEY_SET_BY_CONFIG
+import com.newsdk.sdk.android.httpdns.HttpDns
+import com.newsdk.sdk.android.httpdns.HttpDnsService
+import com.newsdk.ams.httpdns.demo.BuildConfig
+
+/**
+ * @author allen.wy
+ * @date 2023/6/6
+ */
+object HttpDnsServiceHolder {
+
+ fun getHttpDnsService(context: Context) : HttpDnsService? {
+ val dnsService = if (!TextUtils.isEmpty(BuildConfig.ACCOUNT_ID)) {
+ val secretKeySetByConfig = getAccountPreference(context).getBoolean(KEY_SECRET_KEY_SET_BY_CONFIG, true)
+ if (secretKeySetByConfig) {
+ HttpDns.getService(BuildConfig.ACCOUNT_ID)
+ } else {
+ val authMode = getAccountPreference(context).getBoolean(KEY_ENABLE_AUTH_MODE, true)
+ if (authMode && !TextUtils.isEmpty(BuildConfig.SECRET_KEY)) HttpDns.getService(
+ context,
+ BuildConfig.ACCOUNT_ID, BuildConfig.SECRET_KEY
+ ) else HttpDns.getService(
+ context,
+ BuildConfig.ACCOUNT_ID
+ )
+ }
+ } else null
+
+ return dnsService
+ }
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/MainActivity.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/MainActivity.kt
new file mode 100644
index 0000000..2ac302b
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/MainActivity.kt
@@ -0,0 +1,52 @@
+package com.newsdk.ams.emas.demo
+
+import android.os.Bundle
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import androidx.navigation.findNavController
+import androidx.navigation.ui.AppBarConfiguration
+import androidx.navigation.ui.setupActionBarWithNavController
+import com.newsdk.ams.httpdns.demo.R
+import com.newsdk.ams.httpdns.demo.databinding.ActivityMainBinding
+import com.google.android.material.bottomnavigation.BottomNavigationView
+
+class MainActivity : AppCompatActivity() {
+ object HttpDns {
+ var inited = false
+ }
+
+ private lateinit var binding: ActivityMainBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ val navView: BottomNavigationView = binding.navView
+
+ val navController = findNavController(R.id.nav_host_fragment_activity_main)
+ // Passing each menu ID as a set of Ids because each
+ // menu should be considered as top level destinations.
+ val appBarConfiguration = AppBarConfiguration(
+ setOf(
+ R.id.navigation_basic,
+ R.id.navigation_resolve,
+ R.id.navigation_best_practice,
+ R.id.navigation_information
+ )
+ )
+ setupActionBarWithNavController(navController, appBarConfiguration)
+
+ navView.setOnItemSelectedListener {
+ if (HttpDns.inited) {
+ navController.navigate(it.itemId)
+ true
+ } else {
+ Toast.makeText(this, R.string.init_tip, Toast.LENGTH_SHORT).show()
+ false
+ }
+ }
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/PreResolveCacheHolder.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/PreResolveCacheHolder.kt
new file mode 100644
index 0000000..c194f0f
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/PreResolveCacheHolder.kt
@@ -0,0 +1,93 @@
+package com.newsdk.ams.emas.demo
+
+import org.json.JSONArray
+import org.json.JSONException
+import org.json.JSONObject
+
+object PreResolveCacheHolder {
+ var preResolveV4List: MutableList = mutableListOf()
+ var preResolveV6List: MutableList = mutableListOf()
+ var preResolveBothList: MutableList = mutableListOf()
+ var preResolveAutoList: MutableList = mutableListOf()
+
+ fun convertPreResolveCacheData(cacheData: String?) {
+ if (cacheData == null) {
+ return
+ }
+ try {
+ val jsonObject = JSONObject(cacheData)
+ val v4Array = jsonObject.optJSONArray("v4")
+ val v6Array = jsonObject.optJSONArray("v6")
+ val bothArray = jsonObject.optJSONArray("both")
+ val autoArray = jsonObject.optJSONArray("auto")
+
+ if (v4Array != null) {
+ var length = v4Array.length()
+ --length
+ while (length >= 0) {
+ preResolveV4List.add(0, v4Array.getString(length))
+ --length
+ }
+ }
+
+ if (v6Array != null) {
+ var length = v6Array.length()
+ --length
+ while (length >= 0) {
+ preResolveV6List.add(0, v6Array.getString(length))
+ --length
+ }
+ }
+
+ if (bothArray != null) {
+ var length = bothArray.length()
+ --length
+ while (length >= 0) {
+ preResolveBothList.add(0, bothArray.getString(length))
+ --length
+ }
+ }
+
+ if (autoArray != null) {
+ var length = autoArray.length()
+ --length
+ while (length >= 0) {
+ preResolveAutoList.add(0, autoArray.getString(length))
+ --length
+ }
+ }
+ } catch (e: JSONException) {
+ e.printStackTrace()
+ }
+ }
+
+ fun convertPreResolveString(): String {
+ val jsonObject = JSONObject()
+ val v4Array = JSONArray()
+ val v6Array = JSONArray()
+ val bothArray = JSONArray()
+ val autoArray = JSONArray()
+ for (host in preResolveV4List) {
+ v4Array.put(host)
+ }
+ jsonObject.put("v4", v4Array)
+
+ for (host in preResolveV6List) {
+ v6Array.put(host)
+ }
+ jsonObject.put("v6", v6Array)
+
+ for (host in preResolveBothList) {
+ bothArray.put(host)
+ }
+ jsonObject.put("both", bothArray)
+
+ for (host in preResolveAutoList) {
+ autoArray.put(host)
+ }
+ jsonObject.put("auto", autoArray)
+
+ return jsonObject.toString()
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/SingleLiveData.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/SingleLiveData.kt
new file mode 100644
index 0000000..5f63f7d
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/SingleLiveData.kt
@@ -0,0 +1,48 @@
+package com.newsdk.ams.emas.demo
+
+import android.util.Log
+import androidx.annotation.MainThread
+import androidx.annotation.Nullable
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.Observer
+import java.util.concurrent.atomic.AtomicBoolean
+
+/**
+ * @author allen.wy
+ * @date 2023/5/18
+ */
+class SingleLiveData : MutableLiveData() {
+
+ private val mPending = AtomicBoolean(false)
+
+ @MainThread
+ override fun observe(owner: LifecycleOwner, observer: Observer) {
+
+ if (hasActiveObservers()) {
+ Log.w("SingleLiveData", "Multiple observers registered but only one will be notified of changes.")
+ }
+
+ // Observe the internal MutableLiveData
+ super.observe(owner, Observer { t ->
+ if (mPending.compareAndSet(true, false)) {
+ observer.onChanged(t)
+ }
+ })
+ }
+
+ @MainThread
+ override fun setValue(@Nullable t: T?) {
+ mPending.set(true)
+ super.setValue(t)
+ }
+
+ /**
+ * Used for cases where T is Void, to make calls cleaner.
+ */
+ @MainThread
+ fun call() {
+ value = null
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/TtlCacheHolder.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/TtlCacheHolder.kt
new file mode 100644
index 0000000..89f8965
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/TtlCacheHolder.kt
@@ -0,0 +1,51 @@
+package com.newsdk.ams.emas.demo
+
+import com.newsdk.sdk.android.httpdns.CacheTtlChanger
+import org.json.JSONException
+import org.json.JSONObject
+
+/**
+ * @author allen.wy
+ * @date 2023/6/6
+ */
+object TtlCacheHolder {
+ var ttlCache = mutableMapOf()
+
+ val cacheTtlChanger = CacheTtlChanger { host, _, ttl ->
+ if (ttlCache[host] != null) ttlCache[host]!! else ttl
+ }
+
+ fun convertTtlCacheData(cacheData: String?) {
+ if (cacheData == null) {
+ return
+ }
+ try {
+ val jsonObject = JSONObject(cacheData)
+ val it = jsonObject.keys()
+ while (it.hasNext()) {
+ val host = it.next()
+ ttlCache[host] = jsonObject.getInt(host)
+ }
+ } catch (e: JSONException) {
+ e.printStackTrace()
+ }
+ }
+
+
+ fun MutableMap?.toJsonString(): String? {
+ if (this == null) {
+ return null
+ }
+ val jsonObject = JSONObject()
+ for (host in this.keys) {
+ try {
+ jsonObject.put(host, this[host])
+ } catch (e: JSONException) {
+ e.printStackTrace()
+ }
+ }
+ return jsonObject.toString()
+ }
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/Util.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/Util.kt
new file mode 100644
index 0000000..8007e2e
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/Util.kt
@@ -0,0 +1,141 @@
+package com.newsdk.ams.emas.demo
+
+import android.content.Context
+import android.content.SharedPreferences
+import com.newsdk.sdk.android.httpdns.ranking.IPRankingBean
+import com.newsdk.ams.httpdns.demo.BuildConfig
+import org.json.JSONArray
+import org.json.JSONException
+import org.json.JSONObject
+import java.io.BufferedReader
+import java.io.IOException
+
+/**
+ * @author allen.wy
+ * @date 2023/6/5
+ */
+fun String?.toHostList(): MutableList? {
+ if (this == null) {
+ return null
+ }
+ try {
+ val array = JSONArray(this)
+ val list = mutableListOf()
+ for (i in 0 until array.length()) {
+ list.add(array.getString(i))
+ }
+ return list
+ } catch (e: JSONException) {
+ e.printStackTrace()
+ }
+ return null
+}
+
+fun String?.toTagList(): MutableList? {
+ if (this == null) {
+ return null
+ }
+
+ try {
+ val array = JSONArray(this)
+ val list = mutableListOf()
+ for (i in 0 until array.length()) {
+ list.add(array.getString(i))
+ }
+ return list
+ } catch (e: JSONException) {
+ e.printStackTrace()
+ }
+ return null
+}
+
+fun String?.toIPRankingList(): MutableList? {
+ if (this == null) {
+ return null
+ }
+ try {
+ val jsonObject = JSONObject(this)
+ val list = mutableListOf()
+ val it = jsonObject.keys()
+ while (it.hasNext()) {
+ val host = it.next()
+ list.add(
+ IPRankingBean(
+ host,
+ jsonObject.getInt(host)
+ )
+ )
+ }
+ return list
+ } catch (e: JSONException) {
+ e.printStackTrace()
+ }
+ return null
+}
+
+fun String?.toTtlCacheMap(): MutableMap? {
+ if (this == null) {
+ return null
+ }
+ try {
+ val jsonObject = JSONObject(this)
+ val map = mutableMapOf()
+ val it = jsonObject.keys()
+ while (it.hasNext()) {
+ val host = it.next()
+ val ttl = jsonObject.getInt(host)
+ map[host] = ttl
+ }
+ return map
+ } catch (e: JSONException) {
+ e.printStackTrace()
+ }
+
+ return null
+}
+
+fun String?.toBlackList(): MutableList? {
+ if (this == null) {
+ return null
+ }
+ try {
+ val array = JSONArray(this)
+ val list = mutableListOf()
+ for (i in 0 until array.length()) {
+ list.add(array.getString(i))
+ }
+ return list
+ } catch (e: JSONException) {
+ e.printStackTrace()
+ }
+ return null
+}
+
+fun getAccountPreference(context: Context): SharedPreferences {
+ return context.getSharedPreferences(
+ "New_httpdns_${BuildConfig.ACCOUNT_ID}",
+ Context.MODE_PRIVATE
+ )
+}
+
+fun convertPreResolveList(preResolveHostList: List?): String? {
+ if (preResolveHostList == null) {
+ return null
+ }
+ val array = JSONArray()
+ for (host in preResolveHostList) {
+ array.put(host)
+ }
+ return array.toString()
+}
+
+@Throws(IOException::class)
+fun readStringFrom(streamReader: BufferedReader): StringBuilder {
+ val sb = StringBuilder()
+ var line: String?
+ while (streamReader.readLine().also { line = it } != null) {
+ sb.append(line)
+ }
+ return sb
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/constant/Constant.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/constant/Constant.kt
new file mode 100644
index 0000000..dd1f11b
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/constant/Constant.kt
@@ -0,0 +1,55 @@
+package com.newsdk.ams.emas.demo.constant
+
+/**
+ * @author allen.wy
+ * @date 2023/5/24
+ */
+
+const val KEY_ENABLE_AUTH_MODE = "enable_auth_mode"
+
+const val KEY_SECRET_KEY_SET_BY_CONFIG = "secret_key_set_by_config"
+
+const val KEY_ENABLE_ENCRYPT_MODE = "enable_encrypt_mode"
+
+const val KEY_ENABLE_EXPIRED_IP = "enable_expired_ip"
+
+const val KEY_ENABLE_CACHE_IP = "enable_cache_ip"
+
+const val KEY_CACHE_EXPIRE_TIME = "cache_expire_time"
+
+const val KEY_ENABLE_HTTPS = "enable_https"
+
+const val KEY_ENABLE_DEGRADE = "enable_degrade"
+
+const val KEY_ENABLE_AUTO_REFRESH = "enable_auto_refresh"
+
+const val KEY_ENABLE_LOG = "enable_log";
+
+const val KEY_REGION = "region";
+
+const val KEY_TIMEOUT = "timeout"
+
+const val KEY_IP_RANKING_ITEMS = "ip_ranking_items"
+
+const val KEY_TTL_CHANGER = "ttl_changer"
+
+const val KEY_TAGS = "tags"
+
+const val KEY_HOST_WITH_FIXED_IP = "host_with_fixed_ip"
+
+const val KEY_HOST_BLACK_LIST = "host_black_list"
+
+const val KEY_ASYNC_RESOLVE = "async_resolve"
+
+const val KEY_SDNS_RESOLVE = "sdns_resolve"
+
+const val KEY_RESOLVE_IP_TYPE = "resolve_ip_type"
+
+const val KEY_RESOLVE_METHOD = "resolve_method"
+
+const val KEY_PRE_RESOLVE_HOST_LIST = "pre_resolve_host_list"
+
+const val KEY_SDNS_GLOBAL_PARAMS = "sdns_global_params"
+
+const val KEY_BATCH_RESOLVE_HOST_LIST = "batch_resolve_host_list"
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/HttpURLConnectionRequest.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/HttpURLConnectionRequest.kt
new file mode 100644
index 0000000..02682b7
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/HttpURLConnectionRequest.kt
@@ -0,0 +1,139 @@
+package com.newsdk.ams.emas.demo.net
+
+import android.content.Context
+import android.util.Log
+import com.newsdk.ams.emas.demo.HttpDnsServiceHolder
+import com.newsdk.ams.emas.demo.readStringFrom
+import com.newsdk.ams.emas.demo.ui.resolve.Response
+import com.newsdk.sdk.android.httpdns.HTTPDNSResult
+import com.newsdk.sdk.android.httpdns.HttpDnsCallback
+import com.newsdk.sdk.android.httpdns.NetType
+import com.newsdk.sdk.android.httpdns.RequestIpType
+import com.newsdk.sdk.android.httpdns.net.HttpDnsNetworkDetector
+import java.io.BufferedReader
+import java.io.InputStream
+import java.io.InputStreamReader
+import java.net.HttpURLConnection
+import java.net.URL
+import java.util.concurrent.CountDownLatch
+import javax.net.ssl.HostnameVerifier
+import javax.net.ssl.HttpsURLConnection
+
+/**
+ * @author allen.wy
+ * @date 2023/5/26
+ */
+class HttpURLConnectionRequest(private val context: Context, private val requestIpType: RequestIpType, private val resolveMethod: String,
+ private val isSdns: Boolean, private val sdnsParams: Map?, private val cacheKey: String): IRequest {
+
+ override fun get(url: String): Response {
+ val conn: HttpURLConnection = getConnection(url)
+ val inputStream: InputStream?
+ val streamReader: BufferedReader?
+ return if (conn.responseCode != HttpURLConnection.HTTP_OK) {
+ inputStream = conn.errorStream
+ var errStr: String? = null
+ if (inputStream != null) {
+ streamReader = BufferedReader(InputStreamReader(inputStream, "UTF-8"))
+ errStr = readStringFrom(streamReader).toString()
+ }
+ throw Exception("Status Code : " + conn.responseCode + " Msg : " + errStr)
+ } else {
+ inputStream = conn.inputStream
+ streamReader = BufferedReader(InputStreamReader(inputStream, "UTF-8"))
+ val responseStr: String = readStringFrom(streamReader).toString()
+ Response(conn.responseCode, responseStr)
+ }
+ }
+
+ private fun getConnection(url: String): HttpURLConnection {
+ val host = URL(url).host
+ val dnsService = HttpDnsServiceHolder.getHttpDnsService(context)
+
+ var ipURL: String? = null
+ dnsService?.let {
+ //鏇挎崲涓烘渶鏂扮殑api
+ Log.d("HttpURLConnection", "start lookup $host via $resolveMethod")
+ var httpDnsResult = HTTPDNSResult("", null, null, null, false, false)
+ if (resolveMethod == "getHttpDnsResultForHostSync(String host, RequestIpType type)") {
+ httpDnsResult = if (isSdns) {
+ dnsService.getHttpDnsResultForHostSync(host, requestIpType, sdnsParams, cacheKey)
+ } else {
+ dnsService.getHttpDnsResultForHostSync(host, requestIpType)
+ }
+ } else if (resolveMethod == "getHttpDnsResultForHostAsync(String host, RequestIpType type, HttpDnsCallback callback)") {
+ val lock = CountDownLatch(1)
+ if (isSdns) {
+ dnsService.getHttpDnsResultForHostAsync(host, requestIpType, sdnsParams, cacheKey, HttpDnsCallback {
+ httpDnsResult = it
+ lock.countDown()
+ })
+ } else {
+ dnsService.getHttpDnsResultForHostAsync(host, requestIpType, HttpDnsCallback {
+ httpDnsResult = it
+ lock.countDown()
+ })
+ }
+ lock.await()
+ } else if (resolveMethod == "getHttpDnsResultForHostSyncNonBlocking(String host, RequestIpType type)") {
+ httpDnsResult = if (isSdns) {
+ dnsService.getHttpDnsResultForHostSyncNonBlocking(host, requestIpType, sdnsParams, cacheKey)
+ } else {
+ dnsService.getHttpDnsResultForHostSyncNonBlocking(host, requestIpType)
+ }
+ }
+
+ Log.d("HttpURLConnection", "httpdns $host 瑙f瀽缁撴灉 $httpDnsResult")
+ val ipStackType = HttpDnsNetworkDetector.getInstance().getNetType(context)
+ val isV6 = ipStackType == NetType.v6 || ipStackType == NetType.both
+ val isV4 = ipStackType == NetType.v4 || ipStackType == NetType.both
+
+ if (httpDnsResult.ipv6s != null && httpDnsResult.ipv6s.isNotEmpty() && isV6) {
+ ipURL = url.replace(host, "[" + httpDnsResult.ipv6s[0] + "]")
+ } else if (httpDnsResult.ips != null && httpDnsResult.ips.isNotEmpty() && isV4) {
+ ipURL = url.replace(host, httpDnsResult.ips[0])
+ }
+ }
+
+ val conn: HttpURLConnection = URL(ipURL ?: url).openConnection() as HttpURLConnection
+ conn.setRequestProperty("Host", host)
+
+ conn.connectTimeout = 30000
+ conn.readTimeout = 30000
+ conn.instanceFollowRedirects = false
+
+ if (conn is HttpsURLConnection) {
+ val sslSocketFactory = TLSSNISocketFactory(conn)
+ // SNI鍦烘櫙锛屽垱寤篠SLSocket
+ conn.sslSocketFactory = sslSocketFactory
+ // https鍦烘櫙锛岃瘉涔︽牎楠?
+ conn.hostnameVerifier = HostnameVerifier { _, session ->
+ val requestHost = conn.getRequestProperty("Host") ?:conn.getURL().host
+ HttpsURLConnection.getDefaultHostnameVerifier().verify(requestHost, session)
+ }
+ }
+
+ val responseCode = conn.responseCode
+ if (needRedirect(responseCode)) {
+ //涓存椂閲嶅畾鍚戝拰姘镐箙閲嶅畾鍚憀ocation鐨勫ぇ灏忓啓鏈夊尯鍒?
+ var location = conn.getHeaderField("Location")
+ if (location == null) {
+ location = conn.getHeaderField("location")
+ }
+ if (!(location!!.startsWith("http://") || location.startsWith("https://"))) {
+ //鏌愪簺鏃跺€欎細鐪佺暐host锛屽彧杩斿洖鍚庨潰鐨刾ath锛屾墍浠ラ渶瑕佽ˉ鍏╱rl
+ val originalUrl = URL(url)
+ location = (originalUrl.protocol + "://"
+ + originalUrl.host + location)
+ }
+ return getConnection(location)
+ }
+ return conn
+ }
+
+ private fun needRedirect(code: Int): Boolean {
+ return code in 300..399
+ }
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/IRequest.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/IRequest.kt
new file mode 100644
index 0000000..8bfbb3d
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/IRequest.kt
@@ -0,0 +1,12 @@
+package com.newsdk.ams.emas.demo.net
+
+import com.newsdk.ams.emas.demo.ui.resolve.Response
+
+/**
+ * @author allen.wy
+ * @date 2023/5/26
+ */
+interface IRequest {
+ fun get(url: String): Response
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/OkHttpClientSingleton.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/OkHttpClientSingleton.kt
new file mode 100644
index 0000000..ad30ce4
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/OkHttpClientSingleton.kt
@@ -0,0 +1,150 @@
+package com.newsdk.ams.emas.demo.net
+
+import android.content.Context
+import android.util.Log
+import com.newsdk.ams.emas.demo.HttpDnsServiceHolder
+import com.newsdk.sdk.android.httpdns.HTTPDNSResult
+import com.newsdk.sdk.android.httpdns.HttpDnsCallback
+import com.newsdk.sdk.android.httpdns.NetType
+import com.newsdk.sdk.android.httpdns.RequestIpType
+import com.newsdk.sdk.android.httpdns.net.HttpDnsNetworkDetector
+import okhttp3.ConnectionPool
+import okhttp3.Dns
+import okhttp3.OkHttpClient
+import okhttp3.logging.HttpLoggingInterceptor
+import java.lang.ref.WeakReference
+import java.net.InetAddress
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+
+/**
+ * @author allen.wy
+ * @date 2023/6/14
+ */
+ class OkHttpClientSingleton private constructor(context: Context
+) {
+
+ private val mContext = WeakReference(context)
+
+ private var mRequestIpType = RequestIpType.v4
+ private var mResolveMethod: String = "getHttpDnsResultForHostSync(String host, RequestIpType type)"
+ private var mIsSdns: Boolean = false
+ private var mSdnsParams: Map? = null
+ private var mCacheKey: String? = null
+
+ private val tag: String = "httpdns:hOkHttpClientSingleton"
+
+ companion object {
+ @Volatile
+ private var instance: OkHttpClientSingleton? = null
+
+ fun getInstance(context: Context): OkHttpClientSingleton {
+ if (instance != null) {
+ return instance!!
+ }
+
+ return synchronized(this) {
+ if (instance != null) {
+ instance!!
+ } else {
+ instance = OkHttpClientSingleton(context)
+ instance!!
+ }
+ }
+ }
+ }
+
+ fun updateConfig(requestIpType: RequestIpType, resolveMethod: String, isSdns: Boolean, params: Map?, cacheKey: String): OkHttpClientSingleton {
+ mRequestIpType = requestIpType
+ mResolveMethod = resolveMethod
+ mIsSdns = isSdns
+ mSdnsParams = params
+ mCacheKey = cacheKey
+ return this
+ }
+
+ fun getOkHttpClient(): OkHttpClient {
+ val loggingInterceptor = HttpLoggingInterceptor(OkHttpLog())
+ loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
+
+ return OkHttpClient.Builder()
+ .connectionPool(ConnectionPool(0, 10 * 1000, TimeUnit.MICROSECONDS))
+ .hostnameVerifier { _, _ ->true }
+ .dns(object : Dns {
+ override fun lookup(hostname: String): List {
+ Log.d(tag, "start lookup $hostname via $mResolveMethod")
+ val dnsService = HttpDnsServiceHolder.getHttpDnsService(mContext.get()!!)
+ //淇敼涓烘渶鏂扮殑閫氫織鏄撴噦鐨刟pi
+ var httpDnsResult: HTTPDNSResult? = null
+ val inetAddresses = mutableListOf()
+ if (mResolveMethod == "getHttpDnsResultForHostSync(String host, RequestIpType type)") {
+ httpDnsResult = if (mIsSdns) {
+ dnsService?.getHttpDnsResultForHostSync(hostname, mRequestIpType, mSdnsParams, mCacheKey)
+ } else {
+ dnsService?.getHttpDnsResultForHostSync(hostname, mRequestIpType)
+ }
+ } else if (mResolveMethod == "getHttpDnsResultForHostAsync(String host, RequestIpType type, HttpDnsCallback callback)") {
+ val lock = CountDownLatch(1)
+ if (mIsSdns) {
+ dnsService?.getHttpDnsResultForHostAsync(
+ hostname,
+ mRequestIpType,
+ mSdnsParams,
+ mCacheKey,
+ HttpDnsCallback {
+ httpDnsResult = it
+ lock.countDown()
+ })
+ } else {
+ dnsService?.getHttpDnsResultForHostAsync(
+ hostname,
+ mRequestIpType,
+ HttpDnsCallback {
+ httpDnsResult = it
+ lock.countDown()
+ })
+ }
+ lock.await()
+ } else if (mResolveMethod == "getHttpDnsResultForHostSyncNonBlocking(String host, RequestIpType type)") {
+ httpDnsResult = if (mIsSdns) {
+ dnsService?.getHttpDnsResultForHostSyncNonBlocking(hostname, mRequestIpType, mSdnsParams, mCacheKey)
+ } else {
+ dnsService?.getHttpDnsResultForHostSyncNonBlocking(hostname, mRequestIpType)
+ }
+ }
+
+ Log.d(tag, "httpdns $hostname 瑙f瀽缁撴灉 $httpDnsResult")
+ httpDnsResult?.let { processDnsResult(it, inetAddresses) }
+
+ if (inetAddresses.isEmpty()) {
+ Log.d(tag, "httpdns 鏈繑鍥濱P锛岃蛋local dns")
+ return Dns.SYSTEM.lookup(hostname)
+ }
+ return inetAddresses
+ }
+ })
+ .addNetworkInterceptor(loggingInterceptor)
+ .build()
+ }
+
+ fun processDnsResult(httpDnsResult: HTTPDNSResult, inetAddresses: MutableList) {
+ val ipStackType = HttpDnsNetworkDetector.getInstance().getNetType(mContext.get())
+ val isV6 = ipStackType == NetType.v6 || ipStackType == NetType.both
+ val isV4 = ipStackType == NetType.v4 || ipStackType == NetType.both
+
+ if (httpDnsResult.ipv6s != null && httpDnsResult.ipv6s.isNotEmpty() && isV6) {
+ for (i in httpDnsResult.ipv6s.indices) {
+ inetAddresses.addAll(
+ InetAddress.getAllByName(httpDnsResult.ipv6s[i]).toList()
+ )
+ }
+ } else if (httpDnsResult.ips != null && httpDnsResult.ips.isNotEmpty() && isV4) {
+ for (i in httpDnsResult.ips.indices) {
+ inetAddresses.addAll(
+ InetAddress.getAllByName(httpDnsResult.ips[i]).toList()
+ )
+ }
+ }
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/OkHttpLog.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/OkHttpLog.kt
new file mode 100644
index 0000000..7326906
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/OkHttpLog.kt
@@ -0,0 +1,11 @@
+package com.newsdk.ams.emas.demo.net
+
+import android.util.Log
+import okhttp3.logging.HttpLoggingInterceptor
+
+class OkHttpLog: HttpLoggingInterceptor.Logger {
+ override fun log(message: String) {
+ Log.d("Okhttp", message)
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/OkHttpRequest.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/OkHttpRequest.kt
new file mode 100644
index 0000000..269e5e3
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/OkHttpRequest.kt
@@ -0,0 +1,27 @@
+package com.newsdk.ams.emas.demo.net
+
+import android.content.Context
+import com.newsdk.ams.emas.demo.ui.resolve.Response
+import com.newsdk.sdk.android.httpdns.RequestIpType
+
+/**
+ * @author allen.wy
+ * @date 2023/5/25
+ */
+class OkHttpRequest constructor(
+ private val context: Context,
+ private val requestIpType: RequestIpType,
+ private val resolveMethod: String,
+ private val mIsSdns: Boolean,
+ private val mSdnsParams: Map?,
+ private val mCacheKey: String
+) : IRequest {
+
+ override fun get(url: String): Response {
+ val request = okhttp3.Request.Builder().url(url).build()
+ OkHttpClientSingleton.getInstance(context).updateConfig(requestIpType, resolveMethod, mIsSdns, mSdnsParams, mCacheKey).getOkHttpClient().newCall(request).execute()
+ .use { response -> return Response(response.code, response.body?.string()) }
+ }
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/TLSSNISocketFactory.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/TLSSNISocketFactory.kt
new file mode 100644
index 0000000..2a8e9e9
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/net/TLSSNISocketFactory.kt
@@ -0,0 +1,84 @@
+package com.newsdk.ams.emas.demo.net
+
+import android.net.SSLCertificateSocketFactory
+import android.os.Build
+import java.net.InetAddress
+import java.net.Socket
+import javax.net.ssl.*
+
+/**
+ * @author allen.wy
+ * @date 2023/5/26
+ */
+class TLSSNISocketFactory(connection: HttpsURLConnection): SSLSocketFactory() {
+
+ private var mConnection: HttpsURLConnection
+ private var hostnameVerifier: HostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier()
+
+ init {
+ mConnection = connection
+ }
+
+ override fun createSocket(plainSocket: Socket?, host: String?, port: Int, autoClose: Boolean): Socket? {
+ var peerHost: String? = mConnection.getRequestProperty("Host")
+ if (peerHost == null) peerHost = host
+ val address = plainSocket!!.inetAddress
+ if (autoClose) {
+ // we don't need the plainSocket
+ plainSocket.close()
+ }
+
+ // create and connect SSL socket, but don't do hostname/certificate verification yet
+ // create and connect SSL socket, but don't do hostname/certificate verification yet
+ val sslSocketFactory =
+ SSLCertificateSocketFactory.getDefault(0) as SSLCertificateSocketFactory
+ val ssl = sslSocketFactory.createSocket(address, port) as SSLSocket
+
+ // enable TLSv1.1/1.2 if available
+
+ // enable TLSv1.1/1.2 if available
+ ssl.enabledProtocols = ssl.supportedProtocols
+ // set up SNI before the handshake
+
+ // set up SNI before the handshake
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ sslSocketFactory.setHostname(ssl, peerHost)
+ }
+
+ // verify hostname and certificate
+
+ // verify hostname and certificate
+ val session = ssl.session
+
+ if (!hostnameVerifier.verify(peerHost, session)) throw SSLPeerUnverifiedException(
+ "Cannot verify hostname: $peerHost"
+ )
+
+ return ssl
+ }
+
+ override fun createSocket(host: String?, port: Int): Socket? {
+ return null
+ }
+
+ override fun createSocket(host: String?, port: Int, inetAddress: InetAddress?, localPort: Int): Socket? {
+ return null
+ }
+
+ override fun createSocket(host: InetAddress?, port: Int): Socket? {
+ return null
+ }
+
+ override fun createSocket(host: InetAddress?, port: Int, localHost: InetAddress?, localPot: Int): Socket? {
+ return null
+ }
+
+ override fun getDefaultCipherSuites(): Array {
+ return arrayOfNulls(0)
+ }
+
+ override fun getSupportedCipherSuites(): Array {
+ return arrayOfNulls(0)
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/basic/BasicSettingFragment.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/basic/BasicSettingFragment.kt
new file mode 100644
index 0000000..58c9b68
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/basic/BasicSettingFragment.kt
@@ -0,0 +1,179 @@
+package com.newsdk.ams.emas.demo.ui.basic
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.inputmethod.EditorInfo
+import android.widget.Toast
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.widget.AppCompatEditText
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.newsdk.ams.emas.demo.constant.KEY_REGION
+import com.newsdk.ams.emas.demo.getAccountPreference
+import com.newsdk.ams.emas.demo.ui.info.list.ListActivity
+import com.newsdk.ams.emas.demo.ui.info.list.kListItemTag
+import com.newsdk.ams.httpdns.demo.R
+import com.newsdk.ams.httpdns.demo.databinding.FragmentBasicSettingBinding
+
+class BasicSettingFragment : Fragment(), IBasicShowDialog {
+
+ private var _binding: FragmentBasicSettingBinding? = null
+
+ private val binding get() = _binding!!
+ private lateinit var viewModel: BasicSettingViewModel
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ viewModel =
+ ViewModelProvider(this,)[BasicSettingViewModel::class.java]
+ viewModel.showDialog = this
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+
+ _binding = FragmentBasicSettingBinding.inflate(inflater, container, false)
+ binding.lifecycleOwner = this
+ val root: View = binding.root
+ viewModel.initData()
+
+ binding.viewModel = viewModel
+ binding.jumpToAddTag.setOnClickListener {
+ val intent = Intent(activity, ListActivity::class.java)
+ intent.putExtra("list_type", kListItemTag)
+ startActivity(intent)
+ }
+ return root
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+
+ override fun showSelectRegionDialog() {
+ val builder = activity?.let { act -> AlertDialog.Builder(act) }
+ builder?.apply {
+ setTitle(R.string.select_region)
+ val china = getString(R.string.china)
+ val chinaHK = getString(R.string.china_hk)
+ val singapore = getString(R.string.singapore)
+ val germany = getString(R.string.germany)
+ val america = getString(R.string.america)
+ val pre = getString(R.string.pre)
+ val items = arrayOf(china, chinaHK, singapore, germany, america, pre)
+ var region = ""
+ val preferences = activity?.let { getAccountPreference(it) }
+ val index = when (preferences?.getString(KEY_REGION, "cn")) {
+ "hk" -> 1
+ "sg" -> 2
+ "de" -> 3
+ "us" -> 4
+ "pre" -> 5
+ else -> 0
+ }
+ setSingleChoiceItems(items, index) { _, which ->
+ region = when (which) {
+ 1 -> "hk"
+ 2 -> "sg"
+ 3 -> "de"
+ 4 -> "us"
+ 5 -> "pre"
+ else -> "cn"
+ }
+ }
+ setPositiveButton(getString(R.string.confirm)) { dialog, _ ->
+ viewModel.saveRegion(region)
+ dialog.dismiss()
+ }
+ setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ }
+ builder?.show()
+ }
+
+ override fun showSetTimeoutDialog() {
+ val input = LayoutInflater.from(activity).inflate(R.layout.dialog_input, null)
+ val editText = input.findViewById(R.id.add_input)
+ editText.hint = getString(R.string.timeout_hint)
+ editText.inputType = EditorInfo.TYPE_CLASS_NUMBER
+
+ val builder = activity?.let { act -> AlertDialog.Builder(act) }
+ builder?.apply {
+ setTitle(getString(R.string.set_timeout))
+ setView(input)
+ setPositiveButton(R.string.confirm) { dialog, _ ->
+ when (val timeout = editText.text.toString()) {
+ "" -> Toast.makeText(activity, R.string.timeout_empty, Toast.LENGTH_SHORT)
+ .show()
+ else -> viewModel.saveTimeout(timeout.toInt())
+ }
+ dialog.dismiss()
+ }
+ setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ show()
+ }
+
+ }
+
+ override fun showInputHostDialog() {
+ val input = LayoutInflater.from(activity).inflate(R.layout.dialog_input, null)
+ val editText = input.findViewById(R.id.add_input)
+ editText.hint = getString(R.string.clear_cache_hint)
+
+ val builder = activity?.let { act -> AlertDialog.Builder(act) }
+ builder?.apply {
+ setTitle(getString(R.string.clear_host_cache))
+ setView(input)
+ setPositiveButton(R.string.confirm) { dialog, _ ->
+ viewModel.clearDnsCache(editText.text.toString())
+ dialog.dismiss()
+ }
+ setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ show()
+ }
+ }
+
+ override fun showAddPreResolveDialog() {
+ val input = LayoutInflater.from(activity).inflate(R.layout.dialog_input, null)
+ val editText = input.findViewById(R.id.add_input)
+ editText.hint = getString(R.string.add_pre_resolve_hint)
+
+ val builder = activity?.let { act -> AlertDialog.Builder(act) }
+ builder?.apply {
+ setTitle(getString(R.string.add_pre_resolve))
+ setView(input)
+ setPositiveButton(R.string.confirm) { dialog, _ ->
+ when (val host = editText.text.toString()) {
+ "" -> Toast.makeText(activity, R.string.pre_resolve_host_is_empty, Toast.LENGTH_SHORT)
+ .show()
+ else -> viewModel.addPreResolveDomain(host)
+ }
+ dialog.dismiss()
+ }
+ setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ show()
+ }
+ }
+
+ override fun onHttpDnsInit() {
+ activity?.runOnUiThread(Runnable {
+ _binding?.initHttpdns?.setText(R.string.inited_httpdns)
+ _binding?.initHttpdns?.isClickable = false
+ })
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/basic/BasicSettingViewModel.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/basic/BasicSettingViewModel.kt
new file mode 100644
index 0000000..a2b14c4
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/basic/BasicSettingViewModel.kt
@@ -0,0 +1,369 @@
+package com.newsdk.ams.emas.demo.ui.basic
+
+import android.app.Application
+import android.text.TextUtils
+import android.util.Log
+import android.widget.CompoundButton
+import android.widget.Toast
+import androidx.lifecycle.AndroidViewModel
+import com.newsdk.ams.emas.demo.*
+import com.newsdk.ams.emas.demo.constant.*
+import com.newsdk.sdk.android.httpdns.HttpDns
+import com.newsdk.sdk.android.httpdns.HttpDnsService
+import com.newsdk.sdk.android.httpdns.InitConfig
+import com.newsdk.sdk.android.httpdns.NotUseHttpDnsFilter
+import com.newsdk.sdk.android.httpdns.RequestIpType
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog
+import com.newsdk.ams.httpdns.demo.BuildConfig
+import com.newsdk.ams.httpdns.demo.R
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import org.json.JSONException
+import org.json.JSONObject
+
+
+class BasicSettingViewModel(application: Application) : AndroidViewModel(application) {
+
+ companion object {
+ private const val DAY_MILLS = 24 * 60 * 60 * 1000
+ }
+
+ private val preferences = getAccountPreference(getApplication())
+
+ private var dnsService: HttpDnsService? = null
+
+ var secretKeySetByConfig = true
+
+ /**
+ * 鏄惁寮€鍚壌鏉冩ā寮?
+ */
+ var enableAuthMode = true
+
+ /**
+ * 鏄惁寮€鍚姞瀵嗘ā寮?
+ */
+ var enableEncryptMode = true
+
+ /**
+ * 鏄惁鍏佽杩囨湡IP
+ */
+ var enableExpiredIP = false
+
+ /**
+ * 鏄惁寮€鍚湰鍦扮紦瀛?
+ */
+ var enableCacheIP = false
+
+ /**
+ * 鏄惁鍏佽HTTPS
+ */
+ var enableHttps = false
+
+ /**
+ * 鏄惁寮€鍚檷绾?
+ */
+ var enableDegrade = false
+
+ /**
+ * 鏄惁鍏佽缃戠粶鍒囨崲鑷姩鍒锋柊
+ */
+ var enableAutoRefresh = false
+
+ /**
+ * 鏄惁鍏佽鎵撳嵃鏃ュ織
+ */
+ var enableLog = false
+
+ /**
+ * 褰撳墠Region
+ */
+ var currentRegion = SingleLiveData().apply {
+ value = ""
+ }
+
+ /**
+ * 褰撳墠瓒呮椂
+ */
+ var currentTimeout = SingleLiveData().apply {
+ value = "2000ms"
+ }
+
+ var cacheExpireTime = SingleLiveData().apply {
+ value = "0"
+ }
+
+ var showDialog: IBasicShowDialog? = null
+
+ fun initData() {
+ secretKeySetByConfig = preferences.getBoolean(KEY_SECRET_KEY_SET_BY_CONFIG, true)
+ enableAuthMode = preferences.getBoolean(KEY_ENABLE_AUTH_MODE, true)
+ enableEncryptMode = preferences.getBoolean(KEY_ENABLE_ENCRYPT_MODE, true)
+ enableExpiredIP = preferences.getBoolean(KEY_ENABLE_EXPIRED_IP, false)
+ enableCacheIP = preferences.getBoolean(KEY_ENABLE_CACHE_IP, false)
+ cacheExpireTime.value = preferences.getString(KEY_CACHE_EXPIRE_TIME, "0")
+ enableHttps = preferences.getBoolean(KEY_ENABLE_HTTPS, false)
+ enableDegrade = preferences.getBoolean(KEY_ENABLE_DEGRADE, false)
+ enableAutoRefresh = preferences.getBoolean(KEY_ENABLE_AUTO_REFRESH, false)
+ enableLog = preferences.getBoolean(KEY_ENABLE_LOG, false)
+ when (preferences.getString(KEY_REGION, "cn")) {
+ "cn" -> currentRegion.value = getString(R.string.china)
+ "hk" -> currentRegion.value = getString(R.string.china_hk)
+ "sg" -> currentRegion.value = getString(R.string.singapore)
+ "de" -> currentRegion.value = getString(R.string.germany)
+ "us" -> currentRegion.value = getString(R.string.america)
+ "pre" -> currentRegion.value = getString(R.string.pre)
+ }
+ currentTimeout.value = "${preferences.getInt(KEY_TIMEOUT, 2000)}ms"
+
+ if (MainActivity.HttpDns.inited) {
+ dnsService = HttpDnsServiceHolder.getHttpDnsService(getApplication())
+ showDialog?.onHttpDnsInit()
+ }
+ }
+
+ fun toggleSecretKeySet(button: CompoundButton, checked: Boolean) {
+ secretKeySetByConfig = checked
+ val editor = preferences.edit()
+ editor.putBoolean(KEY_SECRET_KEY_SET_BY_CONFIG, checked)
+ editor.apply()
+ }
+
+ fun toggleAuthMode(button: CompoundButton, checked: Boolean) {
+ enableAuthMode = checked
+ val editor = preferences.edit()
+ editor.putBoolean(KEY_ENABLE_AUTH_MODE, checked)
+ editor.apply()
+ }
+
+ fun toggleEncryptMode(button: CompoundButton, checked: Boolean) {
+ enableEncryptMode = checked
+ val editor = preferences.edit()
+ editor.putBoolean(KEY_ENABLE_ENCRYPT_MODE, checked)
+ editor.apply()
+ }
+
+ fun toggleEnableExpiredIp(button: CompoundButton, checked: Boolean) {
+ enableExpiredIP = checked
+ val editor = preferences.edit()
+ editor.putBoolean(KEY_ENABLE_EXPIRED_IP, checked)
+ editor.apply()
+ }
+
+ fun toggleEnableCacheIp(button: CompoundButton, checked: Boolean) {
+ enableCacheIP = checked
+ val editor = preferences.edit()
+ editor.putBoolean(KEY_ENABLE_CACHE_IP, checked)
+ editor.apply()
+ }
+
+ fun toggleEnableHttps(button: CompoundButton, checked: Boolean) {
+ enableHttps = checked
+ val editor = preferences.edit()
+ editor.putBoolean(KEY_ENABLE_HTTPS, checked)
+ editor.apply()
+ }
+
+ fun toggleEnableDegrade(button: CompoundButton, checked: Boolean) {
+ enableDegrade = checked
+ val editor = preferences.edit()
+ editor.putBoolean(KEY_ENABLE_DEGRADE, checked)
+ editor.apply()
+ }
+
+ fun toggleEnableAutoRefresh(button: CompoundButton, checked: Boolean) {
+ enableAutoRefresh = checked
+ val editor = preferences.edit()
+ editor.putBoolean(KEY_ENABLE_AUTO_REFRESH, checked)
+ editor.apply()
+ }
+
+ fun toggleEnableLog(button: CompoundButton, checked: Boolean) {
+ enableLog = checked
+ val editor = preferences.edit()
+ editor.putBoolean(KEY_ENABLE_LOG, checked)
+ editor.apply()
+ HttpDnsLog.enable(checked)
+ }
+
+ fun setRegion() {
+ //寮圭獥閫夋嫨region
+ showDialog?.showSelectRegionDialog()
+ }
+
+ fun saveRegion(region: String) {
+ currentRegion.value = when (region) {
+ "cn" -> getString(R.string.china)
+ "hk" -> getString(R.string.china_hk)
+ "sg" -> getString(R.string.singapore)
+ "de" -> getString(R.string.germany)
+ "pre" -> getString(R.string.pre)
+ else -> getString(R.string.china)
+ }
+ val editor = preferences.edit()
+ editor.putString(KEY_REGION, region)
+ editor.apply()
+ dnsService?.setRegion(region)
+ }
+
+ fun setTimeout() {
+ showDialog?.showSetTimeoutDialog()
+ }
+
+ fun saveTimeout(timeout: Int) {
+ currentTimeout.value = "${timeout}ms"
+ val editor = preferences.edit()
+ editor.putInt(KEY_TIMEOUT, timeout)
+ editor.apply()
+ }
+
+ fun showClearCacheDialog() {
+ showDialog?.showInputHostDialog()
+ }
+
+ fun clearDnsCache(host: String) {
+ if (TextUtils.isEmpty(host)) {
+ dnsService?.cleanHostCache(null)
+ } else {
+ dnsService?.cleanHostCache(mutableListOf(host) as ArrayList)
+ }
+ }
+
+ fun batchResolveHosts() {
+ dnsService?.setPreResolveHosts(BatchResolveCacheHolder.batchResolveV4List, RequestIpType.v4)
+ dnsService?.setPreResolveHosts(BatchResolveCacheHolder.batchResolveV6List, RequestIpType.v6)
+ dnsService?.setPreResolveHosts(BatchResolveCacheHolder.batchResolveAutoList, RequestIpType.auto)
+ dnsService?.setPreResolveHosts(BatchResolveCacheHolder.batchResolveBothList, RequestIpType.both)
+ }
+
+ fun showAddPreResolveDialog() {
+ showDialog?.showAddPreResolveDialog()
+ }
+
+ fun initHttpDns() {
+ if (!TextUtils.isEmpty(BuildConfig.ACCOUNT_ID)) {
+ CoroutineScope(Dispatchers.Default).launch {
+ withContext(Dispatchers.IO) {
+ val aesSecretKey = if (enableEncryptMode && !TextUtils.isEmpty(BuildConfig.AES_SECRET_KEY)) BuildConfig.AES_SECRET_KEY else ""
+ val secretKey = if (enableAuthMode && !TextUtils.isEmpty(BuildConfig.SECRET_KEY)) BuildConfig.SECRET_KEY else ""
+ val enableExpiredIp = preferences.getBoolean(KEY_ENABLE_EXPIRED_IP, false)
+ val enableCacheIp = preferences.getBoolean(KEY_ENABLE_CACHE_IP, false)
+ val enableHttpDns = preferences.getBoolean(KEY_ENABLE_HTTPS, false)
+ val serviceUrl = BuildConfig.SERVICE_URL.trim()
+ val timeout = preferences.getInt(KEY_TIMEOUT, 2000)
+ val region = preferences.getString(KEY_REGION, "cn") ?: "cn"
+ val enableDegradationLocalDns = preferences.getBoolean(KEY_ENABLE_DEGRADE, false);
+ //鑷畾涔塼tl
+ val ttlCacheStr = preferences.getString(KEY_TTL_CHANGER, null)
+ TtlCacheHolder.convertTtlCacheData(ttlCacheStr)
+ //IP鎺㈡祴
+ val ipRankingItemJson = preferences.getString(KEY_IP_RANKING_ITEMS, null)
+ //涓荤珯鍩熷悕
+ val hostListWithFixedIpJson =
+ preferences.getString(KEY_HOST_WITH_FIXED_IP, null)
+ val tagsJson = preferences.getString(KEY_TAGS, null)
+ //棰勮В鏋?
+ val preResolveHostList = preferences.getString(KEY_PRE_RESOLVE_HOST_LIST, null)
+ preResolveHostList?.let { Log.d("httpdns:HttpDnsApplication", "pre resolve list: $it") }
+ PreResolveCacheHolder.convertPreResolveCacheData(preResolveHostList)
+
+ //鎵归噺瑙f瀽
+ val batchResolveHostList = preferences.getString(KEY_BATCH_RESOLVE_HOST_LIST, null)
+ BatchResolveCacheHolder.convertBatchResolveCacheData(batchResolveHostList)
+
+ val sdnsGlobalParamStr = preferences.getString(KEY_SDNS_GLOBAL_PARAMS, "")
+ var sdnsGlobalParams: MutableMap? = null
+ if (!TextUtils.isEmpty(sdnsGlobalParamStr)) {
+ try {
+ val sdnsJson = JSONObject(sdnsGlobalParamStr)
+ val keys = sdnsJson.keys()
+ sdnsGlobalParams = mutableMapOf()
+ while (keys.hasNext()) {
+ val key = keys.next()
+ sdnsGlobalParams[key] = sdnsJson.getString(key)
+ }
+ } catch (e: JSONException) {
+
+ }
+ }
+
+ val cacheExpireTimeTemp = cacheExpireTime.value?.toLong() ?: 0
+
+ HttpDnsLog.enable(preferences.getBoolean(KEY_ENABLE_LOG, false))
+ val builder = InitConfig.Builder()
+ .setEnableCacheIp(enableCacheIp, cacheExpireTimeTemp * DAY_MILLS)
+ .setEnableExpiredIp(enableExpiredIp)
+ .setTimeoutMillis(timeout)
+ .setEnableDegradationLocalDns(enableDegradationLocalDns)
+ .setIPRankingList(ipRankingItemJson.toIPRankingList())
+ .configCacheTtlChanger(TtlCacheHolder.cacheTtlChanger)
+ .configHostWithFixedIp(hostListWithFixedIpJson.toHostList())
+ .setNotUseHttpDnsFilter(NotUseHttpDnsFilter { host ->
+ val blackListStr = preferences.getString(KEY_HOST_BLACK_LIST, null)
+ blackListStr?.let {
+ return@NotUseHttpDnsFilter blackListStr.contains(host)
+ }
+ return@NotUseHttpDnsFilter false
+ })
+ .setSdnsGlobalParams(sdnsGlobalParams)
+ .setBizTags(tagsJson.toTagList())
+ .setAesSecretKey(aesSecretKey)
+
+ if (!TextUtils.isEmpty(serviceUrl)) {
+ // Prefer fixed service URL mode: https://host:port
+ builder.setServiceUrl(serviceUrl)
+ } else {
+ builder.setEnableHttps(enableHttpDns)
+ builder.setRegion(region)
+ }
+
+ if (secretKeySetByConfig) {
+ builder.setContext(this@BasicSettingViewModel.getApplication())
+ builder.setSecretKey(secretKey)
+ }
+ HttpDns.init(BuildConfig.ACCOUNT_ID, builder.build())
+ dnsService = HttpDnsServiceHolder.getHttpDnsService(getApplication())
+ dnsService?.setPreResolveHosts(PreResolveCacheHolder.preResolveV4List)
+ dnsService?.setPreResolveHosts(PreResolveCacheHolder.preResolveV6List, RequestIpType.v6)
+ dnsService?.setPreResolveHosts(PreResolveCacheHolder.preResolveBothList, RequestIpType.both)
+ dnsService?.setPreResolveHosts(PreResolveCacheHolder.preResolveAutoList, RequestIpType.auto)
+ showDialog?.onHttpDnsInit()
+ MainActivity.HttpDns.inited = true
+ }
+ }
+ }
+ }
+
+ fun addPreResolveDomain(host: String) {
+ val preResolveHostListStr = preferences.getString(KEY_PRE_RESOLVE_HOST_LIST, null)
+ val hostList: MutableList = if (preResolveHostListStr == null) {
+ mutableListOf()
+ } else {
+ preResolveHostListStr.toHostList()!!
+ }
+
+ if (hostList.contains(host)) {
+ Toast.makeText(
+ getApplication(),
+ getString(R.string.pre_resolve_host_duplicate, host),
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ hostList.add(host)
+ }
+
+ val editor = preferences.edit()
+ editor.putString(KEY_PRE_RESOLVE_HOST_LIST, convertPreResolveList(hostList))
+ editor.apply()
+ }
+
+ private fun getString(resId: Int): String {
+ return getApplication().getString(resId)
+ }
+
+ private fun getString(resId: Int, vararg args: String): String {
+ return getApplication().getString(resId, *args)
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/basic/IBasicShowDialog.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/basic/IBasicShowDialog.kt
new file mode 100644
index 0000000..ceb234d
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/basic/IBasicShowDialog.kt
@@ -0,0 +1,18 @@
+package com.newsdk.ams.emas.demo.ui.basic
+
+/**
+ * @author allen.wy
+ * @date 2023/5/24
+ */
+interface IBasicShowDialog {
+ fun showSelectRegionDialog()
+
+ fun showSetTimeoutDialog()
+
+ fun showInputHostDialog()
+
+ fun showAddPreResolveDialog()
+
+ fun onHttpDnsInit()
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/InfoFragment.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/InfoFragment.kt
new file mode 100644
index 0000000..1a91215
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/InfoFragment.kt
@@ -0,0 +1,95 @@
+package com.newsdk.ams.emas.demo.ui.info
+
+import android.content.Intent
+import android.os.Bundle
+import android.text.TextUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.newsdk.ams.emas.demo.ui.info.list.*
+import com.newsdk.ams.httpdns.demo.BuildConfig
+import com.newsdk.ams.httpdns.demo.databinding.FragmentInfoBinding
+
+class InfoFragment : Fragment() {
+
+ private var _binding: FragmentInfoBinding? = null
+
+ private val binding get() = _binding!!
+
+ private lateinit var viewModel: InfoViewModel
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ viewModel = ViewModelProvider(this)[InfoViewModel::class.java]
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ _binding = FragmentInfoBinding.inflate(inflater, container, false)
+ binding.viewModel = viewModel
+ binding.lifecycleOwner = this
+
+ viewModel.initData()
+
+ binding.infoPkgName.text = activity?.packageName
+ binding.infoSecretView.apply {
+ visibility = if (TextUtils.isEmpty(BuildConfig.SECRET_KEY)) View.GONE else View.VISIBLE
+ }
+
+ binding.jumpToPreResolve.setOnClickListener {
+ val intent = Intent(activity, ListActivity::class.java)
+ intent.putExtra("list_type", kListItemPreResolve)
+ startActivity(intent)
+ }
+
+ binding.jumpToIpRanking.setOnClickListener {
+ val intent = Intent(activity, ListActivity::class.java)
+ intent.putExtra("list_type", kListItemTypeIPRanking)
+ startActivity(intent)
+ }
+
+ binding.jumpToHostFiexIp.setOnClickListener {
+ val intent = Intent(activity, ListActivity::class.java)
+ intent.putExtra("list_type", kListItemTypeHostWithFixedIP)
+ startActivity(intent)
+ }
+
+ binding.jumpToHostBlackList.setOnClickListener {
+ val intent = Intent(activity, ListActivity::class.java)
+ intent.putExtra("list_type", kListItemTypeBlackList)
+ startActivity(intent)
+ }
+
+ binding.jumpToTtlCache.setOnClickListener {
+ val intent = Intent(activity, ListActivity::class.java)
+ intent.putExtra("list_type", kListItemTypeCacheTtl)
+ startActivity(intent)
+ }
+
+ binding.jumpToSdnsGlobalParams.setOnClickListener {
+ val intent = Intent(activity, SdnsGlobalSettingActivity::class.java)
+ startActivity(intent)
+ }
+
+ binding.jumpToBatchResolve.setOnClickListener {
+ val intent = Intent(activity, ListActivity::class.java)
+ intent.putExtra("list_type", kListItemBatchResolve)
+ startActivity(intent)
+ }
+
+ return binding.root
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/InfoViewModel.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/InfoViewModel.kt
new file mode 100644
index 0000000..333ba9a
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/InfoViewModel.kt
@@ -0,0 +1,63 @@
+package com.newsdk.ams.emas.demo.ui.info
+
+import android.app.Application
+import android.widget.Toast
+import androidx.lifecycle.AndroidViewModel
+import com.newsdk.ams.emas.demo.HttpDnsApplication
+import com.newsdk.ams.emas.demo.HttpDnsServiceHolder
+import com.newsdk.ams.emas.demo.SingleLiveData
+import com.newsdk.ams.emas.demo.getAccountPreference
+import com.newsdk.sdk.android.httpdns.NetType
+import com.newsdk.sdk.android.httpdns.net.HttpDnsNetworkDetector
+import com.newsdk.ams.httpdns.demo.BuildConfig
+import com.newsdk.ams.httpdns.demo.R
+
+
+class InfoViewModel(application: Application) : AndroidViewModel(application) {
+
+ /**
+ * 璐︽埛ID
+ */
+ val accountId = SingleLiveData().apply {
+ value = ""
+ }
+
+ /**
+ * 璐︽埛secret
+ */
+ val secretKey = SingleLiveData()
+
+ val currentIpStackType = SingleLiveData().apply {
+ value = "V4"
+ }
+
+ fun initData() {
+ currentIpStackType.value = when (HttpDnsNetworkDetector.getInstance().getNetType(getApplication())) {
+ NetType.v4 -> "V4"
+ NetType.v6 -> "V6"
+ NetType.both -> "V4&V6"
+ else -> getApplication().getString(R.string.unknown)
+ }
+
+ accountId.value = BuildConfig.ACCOUNT_ID
+ secretKey.value = BuildConfig.SECRET_KEY
+ }
+
+ fun clearDnsCache() {
+ val httpdnsService = HttpDnsServiceHolder.getHttpDnsService(getApplication())
+ var i = 0;
+ while (i < 500) {
+ httpdnsService?.cleanHostCache(null)
+ ++i
+ }
+ }
+
+ fun clearAllCache() {
+ val preferences = getAccountPreference(getApplication())
+ preferences.edit().clear().apply()
+ Toast.makeText(getApplication(), R.string.all_cache_cleared, Toast.LENGTH_SHORT).show()
+ }
+
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/SdnsGlobalSettingActivity.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/SdnsGlobalSettingActivity.kt
new file mode 100644
index 0000000..b7099b4
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/SdnsGlobalSettingActivity.kt
@@ -0,0 +1,46 @@
+package com.newsdk.ams.emas.demo.ui.info
+
+import android.os.Bundle
+import android.text.TextUtils
+import androidx.appcompat.app.AppCompatActivity
+import com.newsdk.ams.emas.demo.constant.KEY_SDNS_GLOBAL_PARAMS
+import com.newsdk.ams.emas.demo.getAccountPreference
+import com.newsdk.ams.httpdns.demo.R
+import com.newsdk.ams.httpdns.demo.databinding.ActivitySdnsGlobalSettingBinding
+import org.json.JSONException
+import org.json.JSONObject
+
+class SdnsGlobalSettingActivity: AppCompatActivity() {
+ private lateinit var binding: ActivitySdnsGlobalSettingBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val preferences = getAccountPreference(this)
+
+ binding = ActivitySdnsGlobalSettingBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ binding.toolbar.title = getString(R.string.input_the_sdns_params)
+
+ val params = preferences.getString(KEY_SDNS_GLOBAL_PARAMS, "")
+ binding.sdnsParamsInputLayout.editText?.setText(params)
+ binding.toolbar.setNavigationOnClickListener {
+ val sdnsParamsStr = binding.sdnsParamsInputLayout.editText?.text.toString()
+ if (!TextUtils.isEmpty(sdnsParamsStr)) {
+ try {
+ val sdnsJson = JSONObject(sdnsParamsStr)
+ preferences.edit().putString(KEY_SDNS_GLOBAL_PARAMS, sdnsParamsStr).apply()
+ onBackPressed()
+ } catch (e: JSONException) {
+ binding.sdnsParamsInputLayout.error = getString(R.string.input_the_sdns_params_error)
+ }
+ } else {
+ preferences.edit().putString(KEY_SDNS_GLOBAL_PARAMS, "").apply()
+ onBackPressed()
+ }
+ }
+ }
+
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListActivity.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListActivity.kt
new file mode 100644
index 0000000..e0cf1ed
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListActivity.kt
@@ -0,0 +1,353 @@
+package com.newsdk.ams.emas.demo.ui.info.list
+
+import android.content.Context
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.MenuItem
+import android.view.View
+import android.view.inputmethod.EditorInfo
+import android.widget.RadioButton
+import android.widget.RadioGroup
+import android.widget.Toast
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.AppCompatEditText
+import androidx.lifecycle.ViewModelProvider
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.newsdk.ams.httpdns.demo.R
+import com.newsdk.ams.httpdns.demo.databinding.ActivityListBinding
+
+class ListActivity : AppCompatActivity(), ListAdapter.OnDeleteListener {
+
+ private lateinit var binding: ActivityListBinding
+
+ private val infoList: MutableList = mutableListOf()
+ private lateinit var listAdapter: ListAdapter
+ private var listType: Int = kListItemTypeIPRanking
+
+ private lateinit var viewModel: ListViewModel
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ var title = ""
+ intent?.let {
+ listType = intent.getIntExtra("list_type", kListItemTypeIPRanking)
+ title = when (listType) {
+ kListItemTypeCacheTtl -> getString(R.string.ttl_cache_list)
+ kListItemTypeHostWithFixedIP -> getString(R.string.host_fixed_ip_list)
+ kListItemPreResolve -> getString(R.string.pre_resolve_list)
+ kListItemTypeBlackList -> getString(R.string.host_black_list)
+ kListItemBatchResolve -> getString(R.string.batch_resolve_list)
+ kListItemTag -> getString(R.string.add_tag)
+ else -> getString(R.string.ip_probe_list)
+ }
+ }
+ viewModel = ViewModelProvider(this)[ListViewModel::class.java]
+
+ binding = ActivityListBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ binding.infoListToolbar.title = title
+ setSupportActionBar(binding.infoListToolbar)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)//娣诲姞榛樿鐨勮繑鍥炲浘鏍?
+ supportActionBar?.setHomeButtonEnabled(true)
+
+ binding.infoListView.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
+
+ viewModel.initData(listType, infoList)
+
+ listAdapter = ListAdapter(this, infoList, this)
+ binding.infoListView.adapter = listAdapter
+
+ binding.fab.setOnClickListener {
+ showAddDialog()
+ }
+ }
+
+ private fun showAddDialog() {
+ when (listType) {
+ kListItemTag -> {
+ val input = LayoutInflater.from(this).inflate(R.layout.dialog_input, null)
+ val editText = input.findViewById(R.id.add_input)
+ editText.hint = getString(R.string.add_tag_hint)
+
+ val builder = AlertDialog.Builder(this)
+ builder.setTitle(getString(R.string.add_tag))
+ .setView(input)
+ .setPositiveButton(R.string.confirm) { dialog, _ ->
+ when (val host = editText.text.toString()) {
+ "" -> Toast.makeText(
+ this@ListActivity,
+ R.string.host_fixed_ip_empty,
+ Toast.LENGTH_SHORT
+ ).show()
+ else -> {
+ viewModel.toAddTag(host, listAdapter)
+ }
+ }
+ dialog.dismiss()
+ }
+ .setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ .show()
+ }
+ kListItemTypeHostWithFixedIP -> {
+ val input = LayoutInflater.from(this).inflate(R.layout.dialog_input, null)
+ val editText = input.findViewById(R.id.add_input)
+ editText.hint = getString(R.string.add_host_fixed_ip_hint)
+
+ val builder = AlertDialog.Builder(this)
+ builder.setTitle(getString(R.string.add_host_fixed_ip))
+ .setView(input)
+ .setPositiveButton(R.string.confirm) { dialog, _ ->
+ when (val host = editText.text.toString()) {
+ "" -> Toast.makeText(
+ this@ListActivity,
+ R.string.host_fixed_ip_empty,
+ Toast.LENGTH_SHORT
+ ).show()
+ else -> {
+ viewModel.toAddHostWithFixedIP(host, listAdapter)
+ }
+ }
+ dialog.dismiss()
+ }
+ .setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ .show()
+ }
+ kListItemTypeBlackList -> {
+ val input = LayoutInflater.from(this).inflate(R.layout.dialog_input, null)
+ val editText = input.findViewById(R.id.add_input)
+ editText.hint = getString(R.string.add_host_to_black_list_hint)
+
+ val builder = AlertDialog.Builder(this)
+ builder.setTitle(getString(R.string.add_host_to_black_list))
+ .setView(input)
+ .setPositiveButton(R.string.confirm) { dialog, _ ->
+ when (val host = editText.text.toString()) {
+ "" -> Toast.makeText(
+ this@ListActivity,
+ R.string.host_to_black_list_empty,
+ Toast.LENGTH_SHORT
+ ).show()
+ else -> {
+ viewModel.toAddHostInBlackList(host, listAdapter)
+ }
+ }
+ dialog.dismiss()
+ }
+ .setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ .show()
+ }
+ kListItemPreResolve -> {
+ val input = LayoutInflater.from(this).inflate(R.layout.dialog_input_3, null)
+ val editText = input.findViewById(R.id.add_input)
+ editText.hint = getString(R.string.add_pre_resolve_hint)
+ val ipTypeGroup = input.findViewById(R.id.ip_type)
+
+ var view = createIpTypeRadio(this)
+ view.text = "IPv4"
+ view.isChecked = true
+ view.tag = 0
+ ipTypeGroup.addView(view)
+
+ view = createIpTypeRadio(this)
+ view.text = "IPv6"
+ view.tag = 1
+ ipTypeGroup.addView(view)
+
+ view = createIpTypeRadio(this)
+ view.text = "IPv4&IPv6"
+ view.tag = 2
+ ipTypeGroup.addView(view)
+
+ view = createIpTypeRadio(this)
+ view.text = "鑷姩鍒ゆ柇IP绫诲瀷"
+ view.tag = 3
+ ipTypeGroup.addView(view)
+
+ val builder = AlertDialog.Builder(this)
+ builder.setTitle(getString(R.string.add_pre_resolve))
+ .setView(input)
+ .setPositiveButton(R.string.confirm) { dialog, _ ->
+ when (val host = editText.text.toString()) {
+ "" -> Toast.makeText(
+ this@ListActivity,
+ R.string.pre_resolve_host_is_empty,
+ Toast.LENGTH_SHORT
+ ).show()
+ else -> {
+ viewModel.toAddPreResolveHost(host, listAdapter, ipTypeGroup.findViewById(ipTypeGroup.checkedRadioButtonId).tag as Int)
+ }
+ }
+ dialog.dismiss()
+ }
+ .setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ .show()
+ }
+ kListItemBatchResolve -> {
+ val input = LayoutInflater.from(this).inflate(R.layout.dialog_input_3, null)
+ val editText = input.findViewById(R.id.add_input)
+ editText.hint = getString(R.string.add_batch_resolve_hint)
+ val ipTypeGroup = input.findViewById(R.id.ip_type)
+ var view = createIpTypeRadio(this)
+ view.text = "IPv4"
+ view.isChecked = true
+ view.tag = 0
+ ipTypeGroup.addView(view)
+ view = createIpTypeRadio(this)
+ view.text = "IPv6"
+ view.tag = 1
+ ipTypeGroup.addView(view)
+ view = createIpTypeRadio(this)
+ view.text = "IPv4&IPv6"
+ view.tag = 2
+ ipTypeGroup.addView(view)
+ view = createIpTypeRadio(this)
+ view.text = "鑷姩鍒ゆ柇IP绫诲瀷"
+ view.tag = 3
+ ipTypeGroup.addView(view)
+ val builder = AlertDialog.Builder(this)
+ builder.setTitle(getString(R.string.add_batch_resolve))
+ .setView(input)
+ .setPositiveButton(R.string.confirm) { dialog, _ ->
+ when (val host = editText.text.toString()) {
+ "" -> Toast.makeText(
+ this@ListActivity,
+ R.string.batch_resolve_host_is_empty,
+ Toast.LENGTH_SHORT
+ ).show()
+ else -> {
+ viewModel.toAddBatchResolveHost(host, listAdapter, ipTypeGroup.findViewById(ipTypeGroup.checkedRadioButtonId).tag as Int)
+ }
+ }
+ dialog.dismiss()
+ }
+ .setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ .show()
+ }
+ else -> {
+ val isTtl = listType == kListItemTypeCacheTtl
+ val input = LayoutInflater.from(this).inflate(R.layout.dialog_input_2, null)
+ val hostEditText = input.findViewById(R.id.input_content_1)
+ val intEditText = input.findViewById(R.id.input_content_2)
+ intEditText.inputType = EditorInfo.TYPE_CLASS_NUMBER
+
+ hostEditText.hint =
+ getString(if (isTtl) R.string.add_ttl_host_hint else R.string.add_ip_probe_host_hint)
+ intEditText.hint =
+ getString(if (isTtl) R.string.add_ttl_ttl_hint else R.string.add_ip_probe_port_hint)
+
+ val builder = AlertDialog.Builder(this)
+ builder.setTitle(getString(if (isTtl) R.string.add_custom_ttl else R.string.add_ip_probe))
+ .setView(input)
+ .setPositiveButton(R.string.confirm) { dialog, _ ->
+ when (val host = hostEditText.text.toString()) {
+ "" -> Toast.makeText(
+ this@ListActivity,
+ R.string.host_is_empty,
+ Toast.LENGTH_SHORT
+ ).show()
+ else -> {
+ when (val intValue = intEditText.text.toString()) {
+ "" -> Toast.makeText(
+ this@ListActivity,
+ if (isTtl) R.string.ttl_is_empty else R.string.port_is_empty,
+ Toast.LENGTH_SHORT
+ ).show()
+ else -> {
+ try {
+ if (isTtl) {
+ viewModel.toSaveTtlCache(
+ host,
+ intValue.toInt(),
+ listAdapter
+ )
+ } else {
+ viewModel.toSaveIPProbe(
+ host,
+ intValue.toInt(),
+ listAdapter
+ )
+ }
+ } catch (e: NumberFormatException) {
+ Toast.makeText(
+ this@ListActivity,
+ R.string.ttl_is_not_number,
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+ }
+ }
+ }
+ dialog.dismiss()
+ }
+ .setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ .show()
+ }
+ }
+ }
+
+ fun createIpTypeRadio(context: Context): RadioButton {
+ val btn = RadioButton(context)
+ btn.id = View.generateViewId()
+ val params = RadioGroup.LayoutParams(RadioGroup.LayoutParams.MATCH_PARENT, RadioGroup.LayoutParams.WRAP_CONTENT)
+ btn.layoutParams = params
+
+ return btn
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ if (item.itemId == android.R.id.home) {
+ finish()
+ return true
+ }
+ return super.onOptionsItemSelected(item)
+ }
+
+ override fun onTagDeleted(position: Int) {
+ viewModel.onTagDeleted(position)
+ }
+
+ override fun onHostWithFixedIPDeleted(position: Int) {
+ //鍙兘閲嶅惎鐢熸晥
+ viewModel.onHostWithFixedIPDeleted(position)
+ }
+
+ override fun onIPRankingItemDeleted(position: Int) {
+ viewModel.onIPProbeItemDeleted(position)
+ }
+
+ override fun onTtlDeleted(host: String) {
+ viewModel.onTtlDeleted(host)
+ }
+
+ override fun onPreResolveDeleted(host: String, intValue: Int) {
+ Log.d("httpdns", "onPreResolveDeleted")
+ viewModel.onPreResolveDeleted(host, intValue)
+ }
+
+ override fun onHostBlackListDeleted(position: Int) {
+ viewModel.onHostBlackListDeleted(position)
+ }
+
+ override fun onBatchResolveDeleted(host: String, intValue: Int) {
+ viewModel.onBatchResolveDeleted(host, intValue)
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListAdapter.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListAdapter.kt
new file mode 100644
index 0000000..d88e383
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListAdapter.kt
@@ -0,0 +1,151 @@
+package com.newsdk.ams.emas.demo.ui.info.list
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.newsdk.ams.httpdns.demo.R
+import com.newsdk.ams.httpdns.demo.databinding.InfoListItemBinding;
+
+/**
+ * @author allen.wy
+ * @date 2023/6/5
+ */
+class ListAdapter(private val context: Context,
+ private val itemList: MutableList,
+ private val deleteListener: OnDeleteListener) :
+ RecyclerView.Adapter() {
+
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
+ val binding = InfoListItemBinding.inflate(LayoutInflater.from(context))
+ return ListViewHolder(context, binding)
+ }
+
+ override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
+ if (itemList.isEmpty()) {
+ return
+ }
+ holder.setItemValue(itemList[position]) {
+ when (itemList[holder.adapterPosition].type) {
+ kListItemTag -> deleteListener.onTagDeleted(holder.adapterPosition)
+ kListItemTypeHostWithFixedIP -> deleteListener.onHostWithFixedIPDeleted(holder.adapterPosition)
+ kListItemTypeBlackList -> deleteListener.onHostBlackListDeleted(holder.adapterPosition)
+ kListItemTypeCacheTtl -> deleteListener.onTtlDeleted(itemList[holder.adapterPosition].content)
+ kListItemPreResolve -> deleteListener.onPreResolveDeleted(itemList[holder.adapterPosition].content, itemList[holder.adapterPosition].intValue)
+ kListItemBatchResolve -> deleteListener.onBatchResolveDeleted(itemList[holder.adapterPosition].content, itemList[holder.adapterPosition].intValue)
+ else -> deleteListener.onIPRankingItemDeleted(holder.adapterPosition)
+ }
+ itemList.removeAt(holder.adapterPosition)
+ notifyItemRemoved(holder.adapterPosition)
+ }
+ }
+
+ override fun getItemCount(): Int {
+ return itemList.size
+ }
+
+ fun addItemData(item: ListItem) {
+ itemList.add(item)
+ notifyItemInserted(itemList.size - 1)
+ }
+
+ fun getPositionByContent(content: String): Int {
+ for (index in itemList.indices) {
+ if (content == itemList[index].content) {
+ return index
+ }
+ }
+ return -1
+ }
+
+ fun updateItemByPosition(content:String, intValue: Int, position: Int) {
+ itemList[position].content = content
+ itemList[position].intValue = intValue
+ notifyItemChanged(position)
+ }
+
+ class ListViewHolder(private val context: Context, private val binding: InfoListItemBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+
+
+ fun setItemValue(listItem: ListItem, onDeleteListener: View.OnClickListener) {
+ when (listItem.type) {
+ kListItemTag -> {
+ binding.hostFixedIpContainer.visibility = View.VISIBLE
+ binding.hostAndPortOrTtlContainer.visibility = View.GONE
+ binding.preHostOrWithFixedIp.text = listItem.content
+ }
+ kListItemTypeIPRanking -> {
+ binding.hostFixedIpContainer.visibility = View.GONE
+ binding.hostAndPortOrTtlContainer.visibility = View.VISIBLE
+ binding.hostValue.text = listItem.content
+ binding.portOrTtlValue.text = listItem.intValue.toString()
+ binding.portOrTtlIndicate.text = context.getString(R.string.port)
+ }
+ kListItemTypeCacheTtl -> {
+ binding.hostFixedIpContainer.visibility = View.GONE
+ binding.hostAndPortOrTtlContainer.visibility = View.VISIBLE
+ binding.hostValue.text = listItem.content
+ binding.portOrTtlValue.text = listItem.intValue.toString()
+ binding.portOrTtlIndicate.text = context.getString(R.string.ttl)
+ }
+ kListItemTypeHostWithFixedIP -> {
+ binding.hostFixedIpContainer.visibility = View.VISIBLE
+ binding.hostAndPortOrTtlContainer.visibility = View.GONE
+ binding.preHostOrWithFixedIp.text = listItem.content
+ }
+ kListItemTypeBlackList -> {
+ binding.hostFixedIpContainer.visibility = View.VISIBLE
+ binding.hostAndPortOrTtlContainer.visibility = View.GONE
+ binding.preHostOrWithFixedIp.text = listItem.content
+ }
+ kListItemPreResolve -> {
+ binding.hostFixedIpContainer.visibility = View.GONE
+ binding.hostAndPortOrTtlContainer.visibility = View.VISIBLE
+ binding.hostValue.text = listItem.content
+ binding.portOrTtlValue.text = when (listItem.intValue) {
+ 0 -> "IPv4"
+ 1 -> "IPv6"
+ 2 -> "IPv4&IPv6"
+ else -> "鑷姩鍒ゆ柇IP绫诲瀷"
+ }
+ binding.portOrTtlIndicate.text = context.getString(R.string.ip_type)
+ }
+ kListItemBatchResolve -> {
+ binding.hostFixedIpContainer.visibility = View.GONE
+ binding.hostAndPortOrTtlContainer.visibility = View.VISIBLE
+ binding.hostValue.text = listItem.content
+ binding.portOrTtlValue.text = when (listItem.intValue) {
+ 0 -> "IPv4"
+ 1 -> "IPv6"
+ 2 -> "IPv4&IPv6"
+ else -> "鑷姩鍒ゆ柇IP绫诲瀷"
+ }
+ binding.portOrTtlIndicate.text = context.getString(R.string.ip_type)
+ }
+ }
+
+ binding.slideDeleteMenu.setOnClickListener(onDeleteListener)
+ binding.slideDeleteMenu2.setOnClickListener(onDeleteListener)
+ }
+ }
+
+ interface OnDeleteListener {
+ fun onTagDeleted(position: Int)
+
+ fun onHostWithFixedIPDeleted(position: Int)
+
+ fun onIPRankingItemDeleted(position: Int)
+
+ fun onTtlDeleted(host: String)
+
+ fun onPreResolveDeleted(host: String, intValue: Int)
+
+ fun onHostBlackListDeleted(position: Int)
+
+ fun onBatchResolveDeleted(host: String, intValue: Int)
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListItem.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListItem.kt
new file mode 100644
index 0000000..3ddb54d
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListItem.kt
@@ -0,0 +1,9 @@
+package com.newsdk.ams.emas.demo.ui.info.list
+
+/**
+ * @author allen.wy
+ * @date 2023/6/5
+ */
+
+data class ListItem(var type: Int, var content: String, var intValue: Int)
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListItemType.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListItemType.kt
new file mode 100644
index 0000000..e213255
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListItemType.kt
@@ -0,0 +1,21 @@
+package com.newsdk.ams.emas.demo.ui.info.list
+
+/**
+ * @author allen.wy
+ * @date 2023/6/5
+ */
+
+const val kListItemTypeIPRanking = 0x01
+
+const val kListItemTypeCacheTtl = 0x02
+
+const val kListItemTypeHostWithFixedIP = 0x03
+
+const val kListItemPreResolve = 0x04
+
+const val kListItemTypeBlackList = 0x05
+
+const val kListItemBatchResolve = 0x06
+
+const val kListItemTag = 0x07
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListViewModel.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListViewModel.kt
new file mode 100644
index 0000000..f9b3fe1
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/info/list/ListViewModel.kt
@@ -0,0 +1,407 @@
+package com.newsdk.ams.emas.demo.ui.info.list
+
+import android.app.Application
+import android.content.SharedPreferences
+import android.widget.Toast
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.viewModelScope
+import com.newsdk.ams.emas.demo.*
+import com.newsdk.ams.emas.demo.TtlCacheHolder.toJsonString
+import com.newsdk.ams.emas.demo.constant.KEY_BATCH_RESOLVE_HOST_LIST
+import com.newsdk.ams.emas.demo.constant.KEY_HOST_BLACK_LIST
+import com.newsdk.ams.emas.demo.constant.KEY_HOST_WITH_FIXED_IP
+import com.newsdk.ams.emas.demo.constant.KEY_IP_RANKING_ITEMS
+import com.newsdk.ams.emas.demo.constant.KEY_PRE_RESOLVE_HOST_LIST
+import com.newsdk.ams.emas.demo.constant.KEY_TAGS
+import com.newsdk.ams.emas.demo.constant.KEY_TTL_CHANGER
+import com.newsdk.sdk.android.httpdns.ranking.IPRankingBean
+import com.newsdk.ams.httpdns.demo.R
+import kotlinx.coroutines.launch
+import org.json.JSONArray
+import org.json.JSONException
+import org.json.JSONObject
+
+/**
+ * @author allen.wy
+ * @date 2023/6/6
+ */
+class ListViewModel(application: Application) : AndroidViewModel(application) {
+
+ private var hostFixedIpList: MutableList = mutableListOf()
+ private var ipRankingList: MutableList = mutableListOf()
+ private var hostBlackList: MutableList = mutableListOf()
+ private var tagsList: MutableList = mutableListOf()
+
+ private lateinit var preferences: SharedPreferences
+
+ fun initData(listType: Int, infoList: MutableList) {
+ preferences = getAccountPreference(getApplication())
+ viewModelScope.launch {
+ when (listType) {
+ kListItemTag -> {
+ val tagStr = preferences.getString(KEY_TAGS, null)
+ val list = tagStr.toTagList()
+ list?.let {
+ tagsList.addAll(list)
+ for (tag in tagsList) {
+ infoList.add(ListItem(kListItemTag, tag, 0))
+ }
+ }
+ }
+ kListItemTypeHostWithFixedIP -> {
+ val hostFixedIpStr = preferences.getString(KEY_HOST_WITH_FIXED_IP, null)
+ val list = hostFixedIpStr.toHostList()
+ list?.let {
+ hostFixedIpList.addAll(list)
+ for (host in hostFixedIpList) {
+ infoList.add(ListItem(kListItemTypeHostWithFixedIP, host, 0))
+ }
+ }
+ }
+ kListItemTypeBlackList -> {
+ val hostBlackListStr = preferences.getString(KEY_HOST_BLACK_LIST, null)
+ val list = hostBlackListStr.toBlackList()
+ list?.let {
+ hostBlackList.addAll(list)
+ for (host in hostBlackList) {
+ infoList.add(ListItem(kListItemTypeBlackList, host, 0))
+ }
+ }
+ }
+ kListItemTypeCacheTtl -> {
+ val ttlCacheStr = preferences.getString(KEY_TTL_CHANGER, null)
+ val map = ttlCacheStr.toTtlCacheMap()
+ map?.let {
+ TtlCacheHolder.ttlCache.putAll(map)
+ for ((host, ttl) in TtlCacheHolder.ttlCache) {
+ infoList.add(ListItem(kListItemTypeCacheTtl, host, ttl))
+ }
+ }
+ }
+ kListItemPreResolve -> {
+ for (host in PreResolveCacheHolder.preResolveV4List) {
+ infoList.add(ListItem(kListItemPreResolve, host, 0))
+ }
+
+ for (host in PreResolveCacheHolder.preResolveV6List) {
+ infoList.add(ListItem(kListItemPreResolve, host, 1))
+ }
+
+ for (host in PreResolveCacheHolder.preResolveBothList) {
+ infoList.add(ListItem(kListItemPreResolve, host, 2))
+ }
+
+ for (host in PreResolveCacheHolder.preResolveAutoList) {
+ infoList.add(ListItem(kListItemPreResolve, host, 3))
+ }
+ }
+ kListItemBatchResolve -> {
+ for (host in BatchResolveCacheHolder.batchResolveV4List) {
+ infoList.add(ListItem(kListItemBatchResolve, host, 0))
+ }
+ for (host in BatchResolveCacheHolder.batchResolveV6List) {
+ infoList.add(ListItem(kListItemBatchResolve, host, 1))
+ }
+ for (host in BatchResolveCacheHolder.batchResolveBothList) {
+ infoList.add(ListItem(kListItemBatchResolve, host, 2))
+ }
+ for (host in BatchResolveCacheHolder.batchResolveAutoList) {
+ infoList.add(ListItem(kListItemBatchResolve, host, 3))
+ }
+ }
+ else -> {
+ val ipRankingListStr = preferences.getString(KEY_IP_RANKING_ITEMS, null)
+ val rankingList = ipRankingListStr.toIPRankingList()
+ rankingList?.let {
+ ipRankingList.addAll(rankingList)
+ for (rankingItem in ipRankingList) {
+ infoList.add(
+ ListItem(
+ kListItemTypeIPRanking,
+ rankingItem.hostName,
+ rankingItem.port
+ )
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fun toAddTag(tag: String, listAdapter: ListAdapter) {
+ tagsList.add(tag)
+ saveTags()
+
+ listAdapter.addItemData(
+ ListItem(
+ kListItemTag,
+ tag,
+ 0
+ )
+ )
+ }
+
+ fun toAddHostWithFixedIP(host: String, listAdapter: ListAdapter) {
+ if (hostFixedIpList.contains(host)) {
+ Toast.makeText(
+ getApplication(),
+ getString(R.string.host_fixed_ip_duplicate, host),
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ hostFixedIpList.add(host)
+ saveHostWithFixedIP()
+ listAdapter.addItemData(
+ ListItem(
+ kListItemTypeHostWithFixedIP,
+ host,
+ 0
+ )
+ )
+ }
+ }
+
+ fun toAddHostInBlackList(host: String, listAdapter: ListAdapter) {
+ if (hostBlackList.contains(host)) {
+ Toast.makeText(
+ getApplication(),
+ getString(R.string.host_black_list_duplicate, host),
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ hostBlackList.add(host)
+ saveHostInBlackList()
+ listAdapter.addItemData(
+ ListItem(
+ kListItemTypeBlackList,
+ host,
+ 0
+ )
+ )
+ }
+ }
+
+ private fun saveTags() {
+ viewModelScope.launch {
+ val array = JSONArray()
+ for (tag in tagsList) {
+ array.put(tag)
+ }
+ val tagStr = array.toString()
+ val editor = preferences.edit()
+ editor.putString(KEY_TAGS, tagStr)
+ editor.apply()
+ }
+ }
+
+ private fun saveHostWithFixedIP() {
+ viewModelScope.launch {
+ val array = JSONArray()
+ for (host in hostFixedIpList) {
+ array.put(host)
+ }
+ val hostStr = array.toString()
+ val editor = preferences.edit()
+ editor.putString(KEY_HOST_WITH_FIXED_IP, hostStr)
+ editor.apply()
+ }
+ }
+
+ private fun saveHostInBlackList() {
+ viewModelScope.launch {
+ val array = JSONArray()
+ for (host in hostBlackList) {
+ array.put(host)
+ }
+
+ preferences.edit()
+ .putString(KEY_HOST_BLACK_LIST, array.toString())
+ .apply()
+ }
+ }
+
+ fun toSaveIPProbe(host: String, port: Int, listAdapter: ListAdapter) {
+ val ipProbeItem =
+ IPRankingBean(host, port)
+ if (ipRankingList.contains(ipProbeItem)) {
+ Toast.makeText(
+ getApplication(),
+ getString(R.string.ip_probe_item_duplicate, host, port.toString()),
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ ipRankingList.add(ipProbeItem)
+ saveIPProbe()
+ listAdapter.addItemData(
+ ListItem(
+ kListItemTypeIPRanking,
+ host,
+ port
+ )
+ )
+ }
+ }
+
+ private fun saveIPProbe() {
+ viewModelScope.launch {
+ val jsonObject = JSONObject()
+ for (item in ipRankingList) {
+ try {
+ jsonObject.put(item.hostName, item.port)
+ } catch (e: JSONException) {
+ e.printStackTrace()
+ }
+ }
+ val ipProbeStr = jsonObject.toString()
+ val editor = preferences.edit()
+ editor.putString(KEY_IP_RANKING_ITEMS, ipProbeStr)
+ editor.apply()
+ }
+ }
+
+ fun toSaveTtlCache(host: String, ttl: Int, listAdapter: ListAdapter) {
+ viewModelScope.launch {
+ val editor = preferences.edit()
+ editor.putString(KEY_TTL_CHANGER, TtlCacheHolder.ttlCache.toJsonString())
+ editor.apply()
+ }
+ if (TtlCacheHolder.ttlCache.containsKey(host)) {
+ val position = listAdapter.getPositionByContent(host)
+ if (position != -1) {
+ listAdapter.updateItemByPosition(host, ttl, position)
+ }
+ } else {
+ listAdapter.addItemData(
+ ListItem(kListItemTypeCacheTtl, host, ttl)
+ )
+ }
+ TtlCacheHolder.ttlCache[host] = ttl
+ }
+
+ fun toAddPreResolveHost(host: String, listAdapter: ListAdapter, type: Int) {
+ val list: MutableList = when (type) {
+ 0 -> PreResolveCacheHolder.preResolveV4List
+ 1 -> PreResolveCacheHolder.preResolveV6List
+ 2 -> PreResolveCacheHolder.preResolveBothList
+ else -> PreResolveCacheHolder.preResolveAutoList
+ }
+
+ if (list.contains(host)) {
+ Toast.makeText(
+ getApplication(),
+ getString(R.string.pre_resolve_host_duplicate, host),
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ list.add(host)
+ savePreResolveHost()
+ listAdapter.addItemData(
+ ListItem(
+ kListItemPreResolve,
+ host,
+ type
+ )
+ )
+ }
+ }
+
+ fun toAddBatchResolveHost(host: String, listAdapter: ListAdapter, type: Int) {
+ val list: MutableList = when (type) {
+ 0 -> BatchResolveCacheHolder.batchResolveV4List
+ 1 -> BatchResolveCacheHolder.batchResolveV6List
+ 2 -> BatchResolveCacheHolder.batchResolveBothList
+ else -> BatchResolveCacheHolder.batchResolveAutoList
+ }
+ if (list.contains(host)) {
+ Toast.makeText(
+ getApplication(),
+ getString(R.string.batch_resolve_host_duplicate, host),
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ list.add(host)
+ saveBatchResolveHost()
+ listAdapter.addItemData(
+ ListItem(
+ kListItemBatchResolve,
+ host,
+ type
+ )
+ )
+ }
+ }
+
+ private fun savePreResolveHost() {
+ viewModelScope.launch {
+ val editor = preferences.edit()
+ editor.putString(KEY_PRE_RESOLVE_HOST_LIST, PreResolveCacheHolder.convertPreResolveString())
+ editor.apply()
+ }
+ }
+
+ private fun saveBatchResolveHost() {
+ viewModelScope.launch {
+ val editor = preferences.edit()
+ editor.putString(KEY_BATCH_RESOLVE_HOST_LIST, BatchResolveCacheHolder.convertBatchResolveString())
+ editor.apply()
+ }
+ }
+
+ fun onTagDeleted(position: Int) {
+ tagsList.removeAt(position)
+ saveTags()
+ }
+
+ fun onHostWithFixedIPDeleted(position: Int) {
+ //鍙兘閲嶅惎鐢熸晥
+ val deletedHost = hostFixedIpList.removeAt(position)
+ saveHostWithFixedIP()
+ }
+
+ fun onIPProbeItemDeleted(position: Int) {
+ ipRankingList.removeAt(position)
+ saveIPProbe()
+ }
+
+ fun onTtlDeleted(host: String) {
+ TtlCacheHolder.ttlCache.remove(host)
+ viewModelScope.launch {
+ val editor = preferences.edit()
+ editor.putString(KEY_TTL_CHANGER, TtlCacheHolder.ttlCache.toJsonString())
+ editor.apply()
+ }
+ }
+
+ fun onPreResolveDeleted(host: String, intValue: Int) {
+ val list = when (intValue) {
+ 0 -> PreResolveCacheHolder.preResolveV4List
+ 1 -> PreResolveCacheHolder.preResolveV6List
+ 2 -> PreResolveCacheHolder.preResolveBothList
+ else -> PreResolveCacheHolder.preResolveAutoList
+ }
+ list.remove(host)
+ savePreResolveHost()
+ }
+
+ fun onBatchResolveDeleted(host: String, intValue: Int) {
+ val list = when (intValue) {
+ 0 -> BatchResolveCacheHolder.batchResolveV4List
+ 1 -> BatchResolveCacheHolder.batchResolveV6List
+ 2 -> BatchResolveCacheHolder.batchResolveBothList
+ else -> BatchResolveCacheHolder.batchResolveAutoList
+ }
+ list.remove(host)
+ saveBatchResolveHost()
+ }
+
+ fun onHostBlackListDeleted(position: Int) {
+ hostBlackList.removeAt(position)
+ saveHostInBlackList()
+ }
+
+ private fun getString(resId: Int, vararg args: String): String {
+ return getApplication().getString(resId, *args)
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/BestPracticeFragment.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/BestPracticeFragment.kt
new file mode 100644
index 0000000..36a287a
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/BestPracticeFragment.kt
@@ -0,0 +1,68 @@
+package com.newsdk.ams.emas.demo.ui.practice
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.newsdk.ams.httpdns.demo.R
+import com.newsdk.ams.httpdns.demo.databinding.FragmentBestPracticeBinding
+
+/**
+ * @author allen.wy
+ * @date 2023/6/14
+ */
+class BestPracticeFragment : Fragment(), IBestPracticeShowDialog {
+
+ private var _binding: FragmentBestPracticeBinding? = null
+
+ private val binding get() = _binding!!
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ _binding = FragmentBestPracticeBinding.inflate(inflater, container, false)
+
+ val viewModel = ViewModelProvider(this)[BestPracticeViewModel::class.java]
+ viewModel.showDialog = this
+
+ binding.viewModel = viewModel
+ binding.openHttpdnsWebview.setOnClickListener {
+ val intent = Intent(activity, HttpDnsWebviewGetActivity::class.java)
+ startActivity(intent)
+ }
+
+// binding.openHttpdnsWebviewPost.setOnClickListener {
+// val intent = Intent(activity, HttpDnsWVWebViewActivity::class.java)
+// startActivity(intent)
+// }
+
+ return binding.root
+ }
+
+ override fun showResponseDialog(message: String) {
+ val builder = activity?.let { act -> AlertDialog.Builder(act) }
+ builder?.apply {
+ setTitle(R.string.sni_request)
+ setMessage(message)
+ setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
+ }
+ builder?.show()
+ }
+
+ override fun showNoNetworkDialog() {
+ val builder = activity?.let { act -> AlertDialog.Builder(act) }
+ builder?.apply {
+ setTitle(R.string.tips)
+ setMessage(R.string.network_not_connect)
+ setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
+ }
+ builder?.show()
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/BestPracticeViewModel.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/BestPracticeViewModel.kt
new file mode 100644
index 0000000..d7b25ea
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/BestPracticeViewModel.kt
@@ -0,0 +1,127 @@
+package com.newsdk.ams.emas.demo.ui.practice
+
+import android.app.Application
+import android.util.Log
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.viewModelScope
+import com.newsdk.ams.emas.demo.HttpDnsServiceHolder
+import com.newsdk.ams.emas.demo.net.TLSSNISocketFactory
+import com.newsdk.ams.emas.demo.readStringFrom
+import com.newsdk.sdk.android.httpdns.NetType
+import com.newsdk.sdk.android.httpdns.RequestIpType
+import com.newsdk.sdk.android.httpdns.net.HttpDnsNetworkDetector
+import com.alibaba.sdk.android.tool.NetworkUtils
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import java.io.BufferedReader
+import java.io.InputStream
+import java.io.InputStreamReader
+import java.net.HttpURLConnection
+import java.net.URL
+import javax.net.ssl.HostnameVerifier
+import javax.net.ssl.HttpsURLConnection
+
+/**
+ * @author allen.wy
+ * @date 2023/6/15
+ */
+class BestPracticeViewModel(application: Application) : AndroidViewModel(application) {
+
+
+ var showDialog: IBestPracticeShowDialog? = null
+
+
+ fun sniRequest() {
+ if (!NetworkUtils.isNetworkConnected(getApplication())) {
+ showDialog?.showNoNetworkDialog()
+ return
+ }
+ val testUrl = "https://suggest.taobao.com/sug?code=utf-8&q=phone"
+ viewModelScope.launch(Dispatchers.IO) {
+ recursiveRequest(testUrl) { message ->
+ withContext(Dispatchers.Main) {
+ showDialog?.showResponseDialog(
+ message
+ )
+ }
+ }
+ }
+ }
+
+
+ private suspend fun recursiveRequest(url: String, callback: suspend (message: String) -> Unit) {
+ val host = URL(url).host
+ var ipURL: String? = null
+ val dnsService = HttpDnsServiceHolder.getHttpDnsService(getApplication())
+ dnsService?.let {
+ val httpDnsResult = dnsService.getIpsByHostAsync(host, RequestIpType.both)
+ Log.d("httpdns", "$host 瑙f瀽缁撴灉 $httpDnsResult")
+ val ipStackType = HttpDnsNetworkDetector.getInstance().getNetType(getApplication())
+ val isV6 = ipStackType == NetType.v6 || ipStackType == NetType.both
+ val isV4 = ipStackType == NetType.v4 || ipStackType == NetType.both
+
+ if (httpDnsResult.ipv6s != null && httpDnsResult.ipv6s.isNotEmpty() && isV6) {
+ ipURL = url.replace(host, "[" + httpDnsResult.ipv6s[0] + "]")
+ } else if (httpDnsResult.ips != null && httpDnsResult.ips.isNotEmpty() && isV4) {
+ ipURL = url.replace(host, httpDnsResult.ips[0])
+ }
+ }
+
+ val conn: HttpsURLConnection =
+ URL(ipURL ?: url).openConnection() as HttpsURLConnection
+ conn.setRequestProperty("Host", host)
+ conn.connectTimeout = 30000
+ conn.readTimeout = 30000
+ conn.instanceFollowRedirects = false
+
+ //璁剧疆SNI
+ val sslSocketFactory = TLSSNISocketFactory(conn)
+ // SNI鍦烘櫙锛屽垱寤篠SLSocket
+ conn.sslSocketFactory = sslSocketFactory
+ conn.hostnameVerifier = HostnameVerifier { _, session ->
+ val requestHost = conn.getRequestProperty("Host") ?: conn.url.host
+ HttpsURLConnection.getDefaultHostnameVerifier().verify(requestHost, session)
+ }
+ val code = conn.responseCode
+ if (needRedirect(code)) {
+ //涓存椂閲嶅畾鍚戝拰姘镐箙閲嶅畾鍚憀ocation鐨勫ぇ灏忓啓鏈夊尯鍒?
+ var location = conn.getHeaderField("Location")
+ if (location == null) {
+ location = conn.getHeaderField("location")
+ }
+ if (!(location!!.startsWith("http://") || location.startsWith("https://"))) {
+ //鏌愪簺鏃跺€欎細鐪佺暐host锛屽彧杩斿洖鍚庨潰鐨刾ath锛屾墍浠ラ渶瑕佽ˉ鍏╱rl
+ val originalUrl = URL(url)
+ location = (originalUrl.protocol + "://"
+ + originalUrl.host + location)
+ }
+ recursiveRequest(location, callback)
+ } else {
+ val inputStream: InputStream?
+ val streamReader: BufferedReader?
+ if (code != HttpURLConnection.HTTP_OK) {
+ inputStream = conn.errorStream
+ var errMsg: String? = null
+ if (inputStream != null) {
+ streamReader = BufferedReader(InputStreamReader(inputStream, "UTF-8"))
+ errMsg = readStringFrom(streamReader).toString()
+ }
+ Log.d("httpdns", "SNI request error: $errMsg")
+ callback("$code - $errMsg")
+ } else {
+ inputStream = conn.inputStream
+ streamReader = BufferedReader(InputStreamReader(inputStream, "UTF-8"))
+ val body: String = readStringFrom(streamReader).toString()
+ Log.d("httpdns", "SNI request response: $body")
+ callback("$code - $body")
+ }
+ }
+ }
+
+ private fun needRedirect(code: Int): Boolean {
+ return code in 300..399
+ }
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/HttpDnsWebviewGetActivity.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/HttpDnsWebviewGetActivity.kt
new file mode 100644
index 0000000..c7d7900
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/HttpDnsWebviewGetActivity.kt
@@ -0,0 +1,199 @@
+package com.newsdk.ams.emas.demo.ui.practice
+
+import android.os.Bundle
+import android.text.TextUtils
+import android.util.Log
+import android.view.MenuItem
+import android.webkit.*
+import androidx.appcompat.app.AppCompatActivity
+import com.newsdk.ams.emas.demo.HttpDnsServiceHolder
+import com.newsdk.ams.httpdns.demo.R
+import com.newsdk.ams.httpdns.demo.databinding.ActivityHttpDnsWebviewBinding
+import java.io.IOException
+import java.net.*
+import javax.net.ssl.*
+
+
+class HttpDnsWebviewGetActivity : AppCompatActivity() {
+
+ private lateinit var binding: ActivityHttpDnsWebviewBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ binding = ActivityHttpDnsWebviewBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ binding.webviewToolbar.title = getString(R.string.httpdns_webview_best_practice)
+ setSupportActionBar(binding.webviewToolbar)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)//娣诲姞榛樿鐨勮繑鍥炲浘鏍?
+ supportActionBar?.setHomeButtonEnabled(true)
+
+ binding.httpdnsWebview.webViewClient = object : WebViewClient() {
+
+ override fun shouldInterceptRequest(
+ view: WebView?,
+ request: WebResourceRequest?
+ ): WebResourceResponse? {
+
+ val url = request?.url.toString()
+ val schema = request?.url?.scheme?.trim()
+ val method = request?.method
+ if ("get" != method && "GET" != method) {
+ return super.shouldInterceptRequest(view, request)
+ }
+
+ schema?.let {
+ if (!schema.startsWith("https") && !schema.startsWith("http")) {
+ return super.shouldInterceptRequest(view, request)
+ }
+ val headers = request.requestHeaders
+ try {
+ val urlConnection = recursiveRequest(url, headers)
+ ?: return super.shouldInterceptRequest(view, request)
+
+ val contentType = urlConnection.contentType
+ val mimeType = contentType?.split(";")?.get(0)
+ if (TextUtils.isEmpty(mimeType)) {
+ //鏃爉imeType寰楄姹備笉鎷︽埅
+ return super.shouldInterceptRequest(view, request)
+ }
+ val charset = getCharset(contentType)
+ val httpURLConnection = urlConnection as HttpURLConnection
+ val statusCode = httpURLConnection.responseCode
+ var response = httpURLConnection.responseMessage
+ val headerFields = httpURLConnection.headerFields
+ val isBinaryResource =
+ mimeType!!.startsWith("image") || mimeType.startsWith("audio") || mimeType.startsWith(
+ "video"
+ )
+ if (!TextUtils.isEmpty(charset) || isBinaryResource) {
+ val resourceResponse = WebResourceResponse(
+ mimeType,
+ charset,
+ httpURLConnection.inputStream
+ )
+ if (TextUtils.isEmpty(response)) {
+ response = "OK"
+ }
+ resourceResponse.setStatusCodeAndReasonPhrase(statusCode, response)
+ val responseHeader: MutableMap = HashMap()
+ for ((key) in headerFields) {
+ // HttpUrlConnection鍙兘鍖呭惈key涓簄ull鐨勬姤澶达紝鎸囧悜璇ttp璇锋眰鐘舵€佺爜
+ responseHeader[key] = httpURLConnection.getHeaderField(key)
+ }
+ resourceResponse.responseHeaders = responseHeader
+ return resourceResponse
+ } else {
+ return super.shouldInterceptRequest(view, request)
+ }
+ } catch (e: Exception) {
+ Log.e("httpdns", Log.getStackTraceString(e))
+ }
+ }
+
+ return super.shouldInterceptRequest(view, request)
+ }
+ }
+ binding.httpdnsWebview.loadUrl("https://demo.cloudxdr.com")
+ }
+
+ private fun getCharset(contentType: String?): String? {
+ if (contentType == null) {
+ return null
+ }
+ val fields = contentType.split(";")
+ if (fields.size <= 1) {
+ return null
+ }
+ var charset = fields[1]
+ if (!charset.contains("=")) {
+ return null
+ }
+ charset = charset.substring(charset.indexOf("=") + 1)
+ return charset
+ }
+
+ private fun recursiveRequest(path: String, headers: Map?): URLConnection? {
+ try {
+ val url = URL(path)
+ val httpdnsService = HttpDnsServiceHolder.getHttpDnsService(this@HttpDnsWebviewGetActivity)
+ ?: return null
+ val hostIP: String? = httpdnsService.getIpByHostAsync(url.host) ?: return null
+ val newUrl = if (hostIP == null) path else path.replaceFirst(url.host, hostIP)
+ val urlConnection: HttpURLConnection = URL(newUrl).openConnection() as HttpURLConnection
+ if (headers != null) {
+ for ((key, value) in headers) {
+ urlConnection.setRequestProperty(key, value)
+ }
+ }
+ urlConnection.setRequestProperty("Host", url.host)
+ urlConnection.connectTimeout = 30000
+ urlConnection.readTimeout = 30000
+ urlConnection.instanceFollowRedirects = false
+ if (urlConnection is HttpsURLConnection) {
+ val sniFactory = SNISocketFactory(urlConnection)
+ urlConnection.sslSocketFactory = sniFactory
+ urlConnection.hostnameVerifier = HostnameVerifier { _, session ->
+ var host: String? = urlConnection.getRequestProperty("Host")
+ if (null == host) {
+ host = urlConnection.getURL().host
+ }
+ HttpsURLConnection.getDefaultHostnameVerifier().verify(host, session)
+ }
+ }
+
+ val responseCode = urlConnection.responseCode
+ if (responseCode in 300..399) {
+ if (containCookie(headers)) {
+ return null
+ }
+
+ var location: String? = urlConnection.getHeaderField("Location")
+ if (location == null) {
+ location = urlConnection.getHeaderField("location")
+ }
+
+ return if (location != null) {
+ if (!(location.startsWith("http://") || location.startsWith("https://"))) {
+ //鏌愪簺鏃跺€欎細鐪佺暐host锛屽彧杩斿洖鍚庨潰鐨刾ath锛屾墍浠ラ渶瑕佽ˉ鍏╱rl
+ val originalUrl = URL(path)
+ location = (originalUrl.protocol + "://" + originalUrl.host + location)
+ }
+ recursiveRequest(location, headers)
+ } else {
+ null
+ }
+ } else {
+ return urlConnection
+ }
+ } catch (e: MalformedURLException) {
+ Log.e("httpdns", Log.getStackTraceString(e))
+ } catch (e: IOException) {
+ Log.e("httpdns", Log.getStackTraceString(e))
+ }
+ return null
+ }
+
+ private fun containCookie(headers: Map?): Boolean {
+ if (headers == null) {
+ return false
+ }
+ for ((key) in headers) {
+ if (key.contains("Cookie")) {
+ return true
+ }
+ }
+ return false
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ if (item.itemId == android.R.id.home) {
+ finish()
+ return true
+ }
+ return super.onOptionsItemSelected(item)
+ }
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/IBestPracticeShowDialog.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/IBestPracticeShowDialog.kt
new file mode 100644
index 0000000..e065376
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/IBestPracticeShowDialog.kt
@@ -0,0 +1,12 @@
+package com.newsdk.ams.emas.demo.ui.practice
+
+/**
+ * @author allen.wy
+ * @date 2023/6/15
+ */
+interface IBestPracticeShowDialog {
+ fun showResponseDialog( message: String)
+
+ fun showNoNetworkDialog()
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/SNISocketFactory.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/SNISocketFactory.kt
new file mode 100644
index 0000000..a83c196
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/practice/SNISocketFactory.kt
@@ -0,0 +1,82 @@
+package com.newsdk.ams.emas.demo.ui.practice
+
+import android.net.SSLCertificateSocketFactory
+import java.net.InetAddress
+import java.net.Socket
+import javax.net.ssl.*
+
+/**
+ * @author allen.wy
+ * @date 2023/6/14
+ */
+class SNISocketFactory(private val conn: HttpsURLConnection) : SSLSocketFactory() {
+ private val hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier()
+
+ override fun createSocket(
+ plainSocket: Socket?,
+ host: String?,
+ port: Int,
+ autoClose: Boolean
+ ): Socket {
+ var peerHost: String? = conn.getRequestProperty("Host")
+ if (peerHost == null) {
+ peerHost = host
+ }
+ val address = plainSocket?.inetAddress
+ if (autoClose) {
+ plainSocket?.close()
+ }
+ val sslSocketFactory: SSLCertificateSocketFactory =
+ SSLCertificateSocketFactory.getDefault(0) as SSLCertificateSocketFactory
+ val ssl: SSLSocket =
+ sslSocketFactory.createSocket(address, port) as SSLSocket
+
+ ssl.enabledProtocols = ssl.supportedProtocols
+
+ // set up SNI before the handshake
+ sslSocketFactory.setHostname(ssl, peerHost)
+ // verify hostname and certificate
+ val session: SSLSession = ssl.session
+
+ if (!hostnameVerifier.verify(peerHost, session)
+ ) throw SSLPeerUnverifiedException("Cannot verify hostname: $peerHost")
+
+ return ssl
+ }
+
+ override fun createSocket(host: String?, port: Int): Socket? {
+ return null
+ }
+
+ override fun createSocket(
+ host: String?,
+ port: Int,
+ localHost: InetAddress?,
+ localPort: Int
+ ): Socket? {
+ return null
+ }
+
+ override fun createSocket(host: InetAddress?, port: Int): Socket? {
+ return null
+ }
+
+ override fun createSocket(
+ address: InetAddress?,
+ port: Int,
+ localAddress: InetAddress?,
+ localPort: Int
+ ): Socket? {
+ return null
+ }
+
+ override fun getDefaultCipherSuites(): Array {
+ return arrayOf()
+ }
+
+ override fun getSupportedCipherSuites(): Array {
+ return arrayOf()
+ }
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/IResolveShowDialog.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/IResolveShowDialog.kt
new file mode 100644
index 0000000..d7a314c
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/IResolveShowDialog.kt
@@ -0,0 +1,18 @@
+package com.newsdk.ams.emas.demo.ui.resolve
+
+/**
+ * @author allen.wy
+ * @date 2023/5/26
+ */
+interface IResolveShowDialog {
+ fun showSelectResolveIpTypeDialog()
+
+ fun showRequestResultDialog(response: Response)
+
+ fun showRequestFailedDialog(e: Throwable)
+
+ fun showResolveMethodDialog()
+
+ fun showRequestNumberDialog()
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/NetRequestType.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/NetRequestType.kt
new file mode 100644
index 0000000..8f3bdbb
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/NetRequestType.kt
@@ -0,0 +1,12 @@
+package com.newsdk.ams.emas.demo.ui.resolve
+
+/**
+ * @author allen.wy
+ * @date 2023/5/26
+ */
+enum class NetRequestType {
+ OKHTTP,
+
+ HTTP_URL_CONNECTION
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/ResolveFragment.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/ResolveFragment.kt
new file mode 100644
index 0000000..3f53771
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/ResolveFragment.kt
@@ -0,0 +1,233 @@
+package com.newsdk.ams.emas.demo.ui.resolve
+
+import android.os.Bundle
+import android.text.TextUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.newsdk.ams.emas.demo.constant.KEY_RESOLVE_IP_TYPE
+import com.newsdk.ams.emas.demo.constant.KEY_RESOLVE_METHOD
+import com.newsdk.ams.emas.demo.getAccountPreference
+import com.newsdk.ams.httpdns.demo.R
+import com.newsdk.ams.httpdns.demo.databinding.FragmentResolveBinding
+import org.json.JSONException
+import org.json.JSONObject
+
+
+class ResolveFragment : Fragment(), IResolveShowDialog {
+
+ private var _binding: FragmentResolveBinding? = null
+
+ private val binding get() = _binding!!
+ private lateinit var viewModel: ResolveViewModel
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ viewModel = ViewModelProvider(this)[ResolveViewModel::class.java]
+ viewModel.showDialog = this
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+
+ _binding = FragmentResolveBinding.inflate(inflater, container, false)
+ viewModel.initData()
+ binding.lifecycleOwner = this
+ binding.viewModel = viewModel
+ binding.sdnsParamsInputLayout.visibility = if (viewModel.isSdns.value!!) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+ binding.sdnsCacheKeyInputLayout.visibility = if (viewModel.isSdns.value!!) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+
+ binding.enableSdnsResolve.setOnCheckedChangeListener{_, isChecked ->
+ viewModel.toggleSdns(isChecked)
+
+ binding.sdnsParamsInputLayout.visibility = if (viewModel.isSdns.value!!) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+ binding.sdnsCacheKeyInputLayout.visibility = if (viewModel.isSdns.value!!) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+ }
+
+ binding.startResolve.setOnClickListener {
+ binding.resolveHostInputLayout.error = ""
+ //1. 鏍¢獙鍩熷悕鏄惁濉啓
+ val host = binding.resolveHostInputLayout.editText?.text.toString()
+ if (TextUtils.isEmpty(host)) {
+ binding.resolveHostInputLayout.error = getString(R.string.resolve_host_empty)
+ return@setOnClickListener
+ }
+ var sdnsParams: MutableMap? = null
+ //2. 鏍¢獙sdns鍙傛暟
+ if (viewModel.isSdns.value!!) {
+ val sdnsParamsStr = binding.sdnsParamsInputLayout.editText?.text.toString()
+ if (!TextUtils.isEmpty(sdnsParamsStr)) {
+ try {
+ val sdnsJson = JSONObject(sdnsParamsStr)
+ val keys = sdnsJson.keys()
+ sdnsParams = HashMap()
+ while (keys.hasNext()) {
+ val key = keys.next()
+ sdnsParams[key] = sdnsJson.getString(key)
+ }
+ } catch (e: JSONException) {
+ binding.sdnsParamsInputLayout.error = getString(R.string.input_the_sdns_params_error)
+ }
+ }
+ }
+
+ var api = binding.requestApiInputLayout.editText?.text.toString()
+
+ val cacheKey = binding.sdnsCacheKeyInputLayout.editText?.text.toString()
+ if (!api.startsWith("/")) {
+ api = "/$api"
+ }
+ var index: Int = 0
+ do {
+ viewModel.startToResolve(host, api, sdnsParams, cacheKey)
+ ++index
+ } while (index < viewModel.requestNum.value!!)
+ }
+
+ return binding.root
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+
+ override fun showSelectResolveIpTypeDialog() {
+ val builder = activity?.let { act -> AlertDialog.Builder(act) }
+ builder?.apply {
+ setTitle(R.string.select_resolve_ip_type)
+ val items = arrayOf("IPv4", "IPv6", "IPv4&IPv6", getString(R.string.auto_get_ip_type))
+ val preferences = activity?.let { getAccountPreference(it) }
+ val index = when (preferences?.getString(KEY_RESOLVE_IP_TYPE, "IPv4")) {
+ "IPv4" -> 0
+ "IPv6" -> 1
+ "IPv4&IPv6" -> 2
+ else -> 3
+ }
+ var resolvedIpType = "IPv4"
+ setSingleChoiceItems(items, index) { _, which ->
+ resolvedIpType = when (which) {
+ 0 -> "IPv4"
+ 1 -> "IPv6"
+ 2 -> "IPv4&IPv6"
+ else -> "Auto"
+ }
+ }
+ setPositiveButton(getString(R.string.confirm)) { dialog, _ ->
+ viewModel.saveResolveIpType(resolvedIpType)
+ dialog.dismiss()
+ }
+ setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ }
+ builder?.show()
+ }
+
+ override fun showRequestResultDialog(response: Response) {
+ val code = response.code
+ val body = response.body
+ val builder = activity?.let { act -> AlertDialog.Builder(act) }
+ builder?.apply {
+ setTitle(R.string.response_title)
+ val message = if (code == 200 && !TextUtils.isEmpty(body)) {
+ if (body!!.length <= 100) "$code - $body" else "$code - ${getString(R.string.body_large_see_log)}"
+ } else {
+ code.toString()
+ }
+ setMessage(message)
+ setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
+ }
+ builder?.show()
+ }
+
+ override fun showRequestFailedDialog(e: Throwable) {
+ val builder = activity?.let { act -> AlertDialog.Builder(act) }
+ builder?.apply {
+ setTitle(R.string.response_title)
+ setMessage(getString(R.string.request_exception, e.message))
+ setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
+ }
+ builder?.show()
+ }
+
+ override fun showResolveMethodDialog() {
+ val builder = activity?.let { act -> AlertDialog.Builder(act) }
+ builder?.apply {
+ setTitle(R.string.select_resolve_method)
+ val items = arrayOf("Sync", "Async", "Sync NonBlocking")
+ val preferences = activity?.let { getAccountPreference(it) }
+
+ var resolvedMethod = preferences?.getString(KEY_RESOLVE_METHOD, "getHttpDnsResultForHostSync(String host, RequestIpType type)").toString()
+ val index = when (resolvedMethod) {
+ "getHttpDnsResultForHostSync(String host, RequestIpType type)" -> 0
+ "getHttpDnsResultForHostAsync(String host, RequestIpType type, HttpDnsCallback callback)" -> 1
+ "getHttpDnsResultForHostSyncNonBlocking(String host, RequestIpType type)" -> 2
+ else -> 3
+ }
+ setSingleChoiceItems(items, index) { _, which ->
+ resolvedMethod = when (which) {
+ 0 -> "getHttpDnsResultForHostSync(String host, RequestIpType type)"
+ 1 -> "getHttpDnsResultForHostAsync(String host, RequestIpType type, HttpDnsCallback callback)"
+ 2 -> "getHttpDnsResultForHostSyncNonBlocking(String host, RequestIpType type)"
+ else -> "getHttpDnsResultForHostSync(String host, RequestIpType type)"
+ }
+ }
+
+ setPositiveButton(getString(R.string.confirm)) { dialog, _ ->
+ viewModel.saveResolveMethod(resolvedMethod)
+ dialog.dismiss()
+ }
+ setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ }
+ builder?.show()
+ }
+
+ override fun showRequestNumberDialog() {
+ val builder = activity?.let { act -> AlertDialog.Builder(act) }
+ builder?.apply {
+ setTitle(R.string.select_request_num)
+ val items = arrayOf("1", "2", "3", "4", "5")
+
+ val index = viewModel.requestNum.value!! - 1
+ var num = viewModel.requestNum.value
+ setSingleChoiceItems(items, index) { _, which ->
+ num = which + 1
+ }
+
+ setPositiveButton(getString(R.string.confirm)) { dialog, _ ->
+ viewModel.saveRequestNumber(num!!)
+ dialog.dismiss()
+ }
+ setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+ }
+ builder?.show()
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/ResolveViewModel.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/ResolveViewModel.kt
new file mode 100644
index 0000000..fc19c5e
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/ResolveViewModel.kt
@@ -0,0 +1,153 @@
+package com.newsdk.ams.emas.demo.ui.resolve
+
+import android.app.Application
+import android.util.Log
+import android.widget.RadioGroup
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.viewModelScope
+import com.newsdk.ams.emas.demo.HttpDnsApplication
+import com.newsdk.ams.emas.demo.SingleLiveData
+import com.newsdk.ams.emas.demo.constant.KEY_RESOLVE_IP_TYPE
+import com.newsdk.ams.emas.demo.constant.KEY_RESOLVE_METHOD
+import com.newsdk.ams.emas.demo.constant.KEY_SDNS_RESOLVE
+import com.newsdk.ams.emas.demo.getAccountPreference
+import com.newsdk.ams.emas.demo.net.HttpURLConnectionRequest
+import com.newsdk.ams.emas.demo.net.OkHttpRequest
+import com.newsdk.sdk.android.httpdns.RequestIpType
+import com.newsdk.ams.httpdns.demo.R
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+
+class ResolveViewModel(application: Application) : AndroidViewModel(application) {
+
+ private val preferences = getAccountPreference(getApplication())
+
+ val currentIpType = SingleLiveData().apply {
+ value = "IPv4"
+ }
+
+ val requestNum = SingleLiveData().apply {
+ value = 1
+ }
+
+ val currentResolveMethod = SingleLiveData().apply {
+ value = "getHttpDnsResultForHostSync(String host, RequestIpType type)"
+ }
+
+ val isSdns = SingleLiveData().apply {
+ value = false
+ }
+
+ var showDialog:IResolveShowDialog? = null
+
+ private var requestType: NetRequestType = NetRequestType.OKHTTP
+ private var schemaType: SchemaType = SchemaType.HTTPS
+
+ fun initData() {
+ isSdns.value = preferences.getBoolean(KEY_SDNS_RESOLVE, false)
+ val ipType = preferences.getString(KEY_RESOLVE_IP_TYPE, "IPv4")
+ currentIpType.value = when(ipType) {
+ "Auto" -> getApplication().getString(R.string.auto_get_ip_type)
+ else -> ipType
+ }
+
+ currentResolveMethod.value = preferences.getString(KEY_RESOLVE_METHOD, "getHttpDnsResultForHostSync(String host, RequestIpType type)")
+ requestNum.value = 1
+ }
+
+ fun onNetRequestTypeChanged(radioGroup: RadioGroup, id: Int) {
+ requestType = when(id) {
+ R.id.http_url_connection -> NetRequestType.HTTP_URL_CONNECTION
+ else -> NetRequestType.OKHTTP
+ }
+ }
+
+ fun toggleSdns(checked: Boolean) {
+ isSdns.value = checked
+ viewModelScope.launch {
+ val editor = preferences.edit()
+ editor.putBoolean(KEY_SDNS_RESOLVE, checked)
+ editor.apply()
+ }
+ }
+
+ fun onSchemaTypeChanged(radioGroup: RadioGroup, id: Int) {
+ schemaType = when(id) {
+ R.id.schema_http -> SchemaType.HTTP
+ else -> SchemaType.HTTPS
+ }
+ }
+
+ fun setResolveIpType() {
+ showDialog?.showSelectResolveIpTypeDialog()
+ }
+
+ fun setResolveMethod() {
+ showDialog?.showResolveMethodDialog()
+ }
+
+ fun setRequestNumber() {
+ showDialog?.showRequestNumberDialog()
+ }
+
+ fun saveResolveIpType(ipType: String) {
+ viewModelScope.launch {
+ val editor = preferences.edit()
+ editor.putString(KEY_RESOLVE_IP_TYPE, ipType)
+ editor.apply()
+ }
+ currentIpType.value = when (ipType) {
+ "Auto" -> getApplication().getString(R.string.auto_get_ip_type)
+ else -> ipType
+ }
+ }
+
+ fun saveResolveMethod(resolveMethod: String) {
+ viewModelScope.launch {
+ val editor = preferences.edit()
+ editor.putString(KEY_RESOLVE_METHOD, resolveMethod)
+ editor.apply()
+ }
+
+ currentResolveMethod.value = resolveMethod
+ }
+
+ fun saveRequestNumber(num: Int) {
+ requestNum.value = num
+ }
+
+ fun startToResolve(host: String, api: String, sdnsParams: Map?, cacheKey: String) {
+ val requestUrl = if (schemaType == SchemaType.HTTPS) "https://$host$api" else "http://$host$api"
+ val requestIpType = when (currentIpType.value) {
+ "IPv4" -> RequestIpType.v4
+ "IPv6" -> RequestIpType.v6
+ "IPv4&IPv6" -> RequestIpType.both
+ else -> RequestIpType.auto
+ }
+ Log.d("httpdns", "api: ${currentResolveMethod.value}, " + "requestIp: $requestIpType")
+
+ val requestClient = if (requestType == NetRequestType.OKHTTP) OkHttpRequest(getApplication(), requestIpType,
+ currentResolveMethod.value!!, isSdns.value!!, sdnsParams, cacheKey
+ ) else HttpURLConnectionRequest(getApplication(), requestIpType, currentResolveMethod.value!!, isSdns.value!!, sdnsParams, cacheKey)
+
+ viewModelScope.launch(Dispatchers.IO) {
+ try {
+ Log.d("httpdns", "before request $requestUrl");
+ val response = requestClient.get(requestUrl)
+ withContext(Dispatchers.Main) {
+ showDialog?.showRequestResultDialog(response)
+ }
+ } catch (e: Exception) {
+ Log.e("httpdns", Log.getStackTraceString(e))
+ withContext(Dispatchers.Main) {
+ showDialog?.showRequestFailedDialog(e)
+ }
+ }
+ }
+ }
+
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/Response.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/Response.kt
new file mode 100644
index 0000000..b8b3026
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/Response.kt
@@ -0,0 +1,8 @@
+package com.newsdk.ams.emas.demo.ui.resolve
+
+/**
+ * @author allen.wy
+ * @date 2023/6/14
+ */
+data class Response(val code: Int, val body: String?)
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/SchemaType.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/SchemaType.kt
new file mode 100644
index 0000000..766cfa7
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/ui/resolve/SchemaType.kt
@@ -0,0 +1,12 @@
+package com.newsdk.ams.emas.demo.ui.resolve
+
+/**
+ * @author allen.wy
+ * @date 2023/6/7
+ */
+enum class SchemaType {
+ HTTPS,
+
+ HTTP
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/widget/SwipeLayout.kt b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/widget/SwipeLayout.kt
new file mode 100644
index 0000000..f0917de
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/java/com/newsdk/ams/emas/demo/widget/SwipeLayout.kt
@@ -0,0 +1,364 @@
+package com.newsdk.ams.emas.demo.widget
+
+import android.content.Context
+import android.graphics.PointF
+import android.util.AttributeSet
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewConfiguration
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import android.widget.Scroller
+import com.newsdk.ams.httpdns.demo.R
+import java.lang.ref.WeakReference
+import kotlin.math.abs
+
+/**
+ * @author allen.wy
+ * @date 2023/6/5
+ */
+class SwipeLayout(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
+ ViewGroup(context, attrs, defStyleAttr) {
+ private val mMatchParentChildren = mutableListOf()
+ private var menuViewResId = 0
+ private var contentViewResId = 0
+ private var menuView: View? = null
+ private var contentView: View? = null
+ private var contentViewLayoutParam: MarginLayoutParams? = null
+ private var isSwiping = false
+ private var lastP: PointF? = null
+ private var firstP: PointF? = null
+ private var fraction = 0.2f
+ private var scaledTouchSlop = 0
+ private var scroller: Scroller? = null
+ private var finalDistanceX = 0f
+
+ constructor(context: Context) : this(context, null)
+ constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
+
+ /**
+ * 鍒濆鍖栨柟娉?
+ *
+ * @param context
+ * @param attrs
+ * @param defStyleAttr
+ */
+ private fun init(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {
+ //鍒涘缓杈呭姪瀵硅薄
+ val viewConfiguration = ViewConfiguration.get(context)
+ scaledTouchSlop = viewConfiguration.scaledTouchSlop
+ scroller = Scroller(context)
+ //1銆佽幏鍙栭厤缃殑灞炴€у€?
+ val typedArray = context.theme
+ .obtainStyledAttributes(attrs, R.styleable.SwipeLayout, defStyleAttr, 0)
+ try {
+ val indexCount: Int = typedArray.indexCount
+ for (i in 0 until indexCount) {
+ when (typedArray.getIndex(i)) {
+ R.styleable.SwipeLayout_menuView -> {
+ menuViewResId =
+ typedArray.getResourceId(R.styleable.SwipeLayout_menuView, -1)
+ }
+ R.styleable.SwipeLayout_contentView -> {
+ contentViewResId =
+ typedArray.getResourceId(R.styleable.SwipeLayout_contentView, -1)
+ }
+ R.styleable.SwipeLayout_fraction -> {
+ fraction = typedArray.getFloat(R.styleable.SwipeLayout_fraction, 0.5f)
+ }
+ }
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ } finally {
+ typedArray.recycle()
+ }
+ }
+
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+ //鑾峰彇childView鐨勪釜鏁?
+ isClickable = true
+ var count = childCount
+ val measureMatchParentChildren =
+ MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
+ MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY
+ mMatchParentChildren.clear()
+ var maxHeight = 0
+ var maxWidth = 0
+ var childState = 0
+ for (i in 0 until count) {
+ val child: View = getChildAt(i)
+ if (child.visibility != View.GONE) {
+ measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0)
+ val lp = child.layoutParams as MarginLayoutParams
+ maxWidth =
+ maxWidth.coerceAtLeast(child.measuredWidth + lp.leftMargin + lp.rightMargin)
+ maxHeight =
+ maxHeight.coerceAtLeast(child.measuredHeight + lp.topMargin + lp.bottomMargin)
+ childState = combineMeasuredStates(childState, child.measuredState)
+ if (measureMatchParentChildren) {
+ if (lp.width == LayoutParams.MATCH_PARENT ||
+ lp.height == LayoutParams.MATCH_PARENT
+ ) {
+ mMatchParentChildren.add(child)
+ }
+ }
+ }
+ }
+ // Check against our minimum height and width
+ maxHeight = maxHeight.coerceAtLeast(suggestedMinimumHeight)
+ maxWidth = maxWidth.coerceAtLeast(suggestedMinimumWidth)
+ setMeasuredDimension(
+ resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
+ resolveSizeAndState(
+ maxHeight, heightMeasureSpec,
+ childState shl MEASURED_HEIGHT_STATE_SHIFT
+ )
+ )
+ count = mMatchParentChildren.size
+ if (count < 1) {
+ return
+ }
+ for (i in 0 until count) {
+ val child: View = mMatchParentChildren[i]
+ val lp = child.layoutParams as MarginLayoutParams
+ val childWidthMeasureSpec = if (lp.width == LayoutParams.MATCH_PARENT) {
+ val width = 0.coerceAtLeast(
+ measuredWidth - lp.leftMargin - lp.rightMargin
+ )
+ MeasureSpec.makeMeasureSpec(
+ width, MeasureSpec.EXACTLY
+ )
+ } else {
+ getChildMeasureSpec(
+ widthMeasureSpec,
+ lp.leftMargin + lp.rightMargin,
+ lp.width
+ )
+ }
+ val childHeightMeasureSpec = if (lp.height == FrameLayout.LayoutParams.MATCH_PARENT) {
+ val height = 0.coerceAtLeast(
+ measuredHeight - lp.topMargin - lp.bottomMargin
+ )
+ MeasureSpec.makeMeasureSpec(
+ height, MeasureSpec.EXACTLY
+ )
+ } else {
+ getChildMeasureSpec(
+ heightMeasureSpec,
+ lp.topMargin + lp.bottomMargin,
+ lp.height
+ )
+ }
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec)
+ }
+ }
+
+ override fun generateLayoutParams(attrs: AttributeSet?): LayoutParams {
+ return MarginLayoutParams(context, attrs)
+ }
+
+ override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
+ val count = childCount
+ val left = 0 + paddingLeft
+ val top = 0 + paddingTop
+ for (i in 0 until count) {
+ val child: View = getChildAt(i)
+ if (menuView == null && child.id == menuViewResId) {
+ menuView = child
+ menuView!!.isClickable = true
+ } else if (contentView == null && child.id == contentViewResId) {
+ contentView = child
+ contentView!!.isClickable = true
+ }
+ }
+ //甯冨眬contentView
+ val cRight: Int
+ if (contentView != null) {
+ contentViewLayoutParam = contentView!!.layoutParams as MarginLayoutParams?
+ val cTop = top + contentViewLayoutParam!!.topMargin
+ val cLeft = left + contentViewLayoutParam!!.leftMargin
+ cRight = left + contentViewLayoutParam!!.leftMargin + contentView!!.measuredWidth
+ val cBottom: Int = cTop + contentView!!.measuredHeight
+ contentView!!.layout(cLeft, cTop, cRight, cBottom)
+ }
+
+ if (menuView != null) {
+ val rightViewLp = menuView!!.layoutParams as MarginLayoutParams
+ val lTop = top + rightViewLp.topMargin
+ val lLeft =
+ contentView!!.right + contentViewLayoutParam!!.rightMargin + rightViewLp.leftMargin
+ val lRight: Int = lLeft + menuView!!.measuredWidth
+ val lBottom: Int = lTop + menuView!!.measuredHeight
+ menuView!!.layout(lLeft, lTop, lRight, lBottom)
+ }
+ }
+
+ private var result: State? = null
+
+ init {
+ init(context, attrs, defStyleAttr)
+ }
+
+ override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
+ when (ev.action) {
+ MotionEvent.ACTION_DOWN -> {
+ isSwiping = false
+ if (lastP == null) {
+ lastP = PointF()
+ }
+ lastP!!.set(ev.rawX, ev.rawY)
+ if (firstP == null) {
+ firstP = PointF()
+ }
+ firstP!!.set(ev.rawX, ev.rawY)
+ if (viewCache != null) {
+ if (viewCache!!.get() != this) {
+ viewCache!!.get()!!.handlerSwipeMenu(State.CLOSE)
+ }
+ parent.requestDisallowInterceptTouchEvent(true)
+ }
+ }
+ MotionEvent.ACTION_MOVE -> run {
+ val distanceX: Float = lastP!!.x - ev.rawX
+ val distanceY: Float = lastP!!.y - ev.rawY
+ if (abs(distanceY) > scaledTouchSlop && abs(distanceY) > abs(distanceX)) {
+ return@run
+ }
+ scrollBy(distanceX.toInt(), 0)
+ //瓒婄晫淇
+ if (scrollX < 0) {
+ scrollTo(0, 0)
+ } else if (scrollX > 0) {
+ if (scrollX > menuView!!.right - contentView!!.right - contentViewLayoutParam!!.rightMargin) {
+ scrollTo(
+ menuView!!.right - contentView!!.right - contentViewLayoutParam!!.rightMargin,
+ 0
+ )
+ }
+ }
+ //褰撳浜庢按骞虫粦鍔ㄦ椂锛岀姝㈢埗绫绘嫤鎴?
+ if (abs(distanceX) > scaledTouchSlop) {
+ parent.requestDisallowInterceptTouchEvent(true)
+ }
+ lastP!!.set(ev.rawX, ev.rawY)
+ }
+ MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
+ finalDistanceX = firstP!!.x - ev.rawX
+ if (abs(finalDistanceX) > scaledTouchSlop) {
+ isSwiping = true
+ }
+ result = isShouldOpen()
+ handlerSwipeMenu(result)
+ }
+ else -> {}
+ }
+ return super.dispatchTouchEvent(ev)
+ }
+
+ override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
+ when (event.action) {
+ MotionEvent.ACTION_DOWN -> {}
+ MotionEvent.ACTION_MOVE -> {
+ //婊戝姩鏃舵嫤鎴偣鍑绘椂闂?
+ if (abs(finalDistanceX) > scaledTouchSlop) {
+ return true
+ }
+ }
+ MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
+ //婊戝姩鍚庝笉瑙﹀彂contentView鐨勭偣鍑讳簨浠?
+ if (isSwiping) {
+ isSwiping = false
+ finalDistanceX = 0f
+ return true
+ }
+ }
+ }
+ return super.onInterceptTouchEvent(event)
+ }
+
+ /**
+ * 鑷姩璁剧疆鐘舵€?
+ *
+ * @param result
+ */
+ private fun handlerSwipeMenu(result: State?) {
+ if (result === State.RIGHT_OPEN) {
+ viewCache = WeakReference(this)
+ scroller!!.startScroll(
+ scrollX,
+ 0,
+ menuView!!.right - contentView!!.right - contentViewLayoutParam!!.rightMargin - scrollX,
+ 0
+ )
+ mStateCache = result
+ } else {
+ scroller!!.startScroll(scrollX, 0, -scrollX, 0)
+ viewCache = null
+ mStateCache = null
+ }
+ invalidate()
+ }
+
+ override fun computeScroll() {
+ //鍒ゆ柇Scroller鏄惁鎵ц瀹屾瘯锛?
+ if (scroller!!.computeScrollOffset()) {
+ scrollTo(scroller!!.currX, scroller!!.currY)
+ invalidate()
+ }
+ }
+
+ /**
+ * 鏍规嵁褰撳墠鐨剆crollX鐨勫€煎垽鏂澗寮€鎵嬪悗搴斿浜庝綍绉嶇姸鎬?
+ *
+ * @param
+ * @param scrollX
+ * @return
+ */
+ private fun isShouldOpen(): State? {
+ if (scaledTouchSlop >= abs(finalDistanceX)) {
+ return mStateCache
+ }
+ if (finalDistanceX < 0) {
+ //鍏抽棴鍙宠竟
+ if (scrollX > 0 && menuView != null) {
+ return State.CLOSE
+ }
+ } else if (finalDistanceX > 0) {
+ //寮€鍚彸杈?
+ if (scrollX > 0 && menuView != null) {
+ if (abs(menuView!!.width * fraction) < abs(scrollX)) {
+ return State.RIGHT_OPEN
+ }
+ }
+ }
+ return State.CLOSE
+ }
+
+ override fun onDetachedFromWindow() {
+ if (this == viewCache?.get()) {
+ viewCache!!.get()!!.handlerSwipeMenu(State.CLOSE)
+ }
+ super.onDetachedFromWindow()
+ }
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ if (this == viewCache?.get()) {
+ viewCache!!.get()!!.handlerSwipeMenu(mStateCache)
+ }
+ }
+
+
+ companion object {
+ var viewCache: WeakReference? = null
+ private set
+ private var mStateCache: State? = null
+ }
+
+ enum class State {
+ RIGHT_OPEN, CLOSE
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/drawable-v24/ic_launcher_foreground.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_add.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_add.xml
new file mode 100644
index 0000000..4d6df25
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_add.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_arrow_left.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_arrow_left.xml
new file mode 100644
index 0000000..8cd0048
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_arrow_left.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_arrow_right.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_arrow_right.xml
new file mode 100644
index 0000000..f90c9f8
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_arrow_right.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_back.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_back.xml
new file mode 100644
index 0000000..ac46ad9
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_back.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_dns.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_dns.xml
new file mode 100644
index 0000000..1e5f0c0
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_dns.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_home_black_24dp.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_home_black_24dp.xml
new file mode 100644
index 0000000..f8bb0b5
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_home_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_httpdns.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_httpdns.xml
new file mode 100644
index 0000000..e5ac938
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_httpdns.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_information.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_information.xml
new file mode 100644
index 0000000..bc0ebe5
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_information.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_practice.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_practice.xml
new file mode 100644
index 0000000..e8c29f5
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/drawable/ic_practice.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/layout/activity_http_dns_webview.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/activity_http_dns_webview.xml
new file mode 100644
index 0000000..880dea8
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/activity_http_dns_webview.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/layout/activity_list.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/activity_list.xml
new file mode 100644
index 0000000..d60a58b
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/activity_list.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/layout/activity_main.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..6b1ea89
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/activity_main.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/layout/activity_sdns_global_setting.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/activity_sdns_global_setting.xml
new file mode 100644
index 0000000..44defbd
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/activity_sdns_global_setting.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/layout/dialog_input.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/dialog_input.xml
new file mode 100644
index 0000000..c58ff19
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/dialog_input.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/layout/dialog_input_2.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/dialog_input_2.xml
new file mode 100644
index 0000000..3a83b52
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/dialog_input_2.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/layout/dialog_input_3.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/dialog_input_3.xml
new file mode 100644
index 0000000..bd855dd
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/dialog_input_3.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/layout/fragment_basic_setting.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/fragment_basic_setting.xml
new file mode 100644
index 0000000..f5d47ba
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/fragment_basic_setting.xml
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/layout/fragment_best_practice.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/fragment_best_practice.xml
new file mode 100644
index 0000000..4cd9adb
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/fragment_best_practice.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/layout/fragment_info.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/fragment_info.xml
new file mode 100644
index 0000000..d019018
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/fragment_info.xml
@@ -0,0 +1,378 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FragmentBestPracticeBinding
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/layout/fragment_resolve.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/fragment_resolve.xml
new file mode 100644
index 0000000..04950c0
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/fragment_resolve.xml
@@ -0,0 +1,336 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/layout/info_list_item.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/info_list_item.xml
new file mode 100644
index 0000000..a544b66
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/layout/info_list_item.xml
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/menu/bottom_nav_menu.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/menu/bottom_nav_menu.xml
new file mode 100644
index 0000000..6ecb2b6
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/menu/bottom_nav_menu.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-hdpi/ic_launcher.png b/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0ece4ca
Binary files /dev/null and b/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-mdpi/ic_launcher.png b/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..0150452
Binary files /dev/null and b/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-xhdpi/ic_launcher.png b/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..954b048
Binary files /dev/null and b/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png b/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..dabb239
Binary files /dev/null and b/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d32c9ba
Binary files /dev/null and b/HttpDNSSDK/sdk/android/demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/navigation/mobile_navigation.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/navigation/mobile_navigation.xml
new file mode 100644
index 0000000..8cdd575
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/navigation/mobile_navigation.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/values-land/dimens.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/values-land/dimens.xml
new file mode 100644
index 0000000..22d7f00
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/values-land/dimens.xml
@@ -0,0 +1,3 @@
+
+ 48dp
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/values-night/themes.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000..8e73a51
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/values-night/themes.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/values-w1240dp/dimens.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/values-w1240dp/dimens.xml
new file mode 100644
index 0000000..d73f4a3
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/values-w1240dp/dimens.xml
@@ -0,0 +1,3 @@
+
+ 200dp
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/values-w600dp/dimens.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/values-w600dp/dimens.xml
new file mode 100644
index 0000000..22d7f00
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/values-w600dp/dimens.xml
@@ -0,0 +1,3 @@
+
+ 48dp
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/values-zh-rCN/strings.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..1e0b26a
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,138 @@
+
+
+ 闃块噷浜慔ttpDNS瀹樻柟Demo
+ 鍩虹璁剧疆
+ HttpDNS瑙f瀽
+ 鏈€浣冲疄璺
+ 淇℃伅
+
+ 寮€鍚壌鏉冩ā寮
+ SecretKey閫氳繃config閰嶇疆
+ 寮€鍚姞瀵嗘ā寮
+ 鍏佽杩囨湡IP
+ 寮€鍚寔涔呭寲缂撳瓨IP
+ 缂撳瓨杩囨湡鏃堕棿
+ 缂撳瓨杩囨湡鏃堕棿鐨勫崟浣嶆槸澶?
+ 寮€鍚疕TTPS
+ 鍏佽闄嶇骇
+ 缃戠粶鍒囨崲鑷姩鍒锋柊
+ 鍏佽SDK鎵撳嵃鏃ュ織
+ 瓒呮椂鏃堕棿
+ 璇峰厛鍒濆鍖朒ttpDns
+ 宸茬粡鍒濆鍖
+
+ 涓浗
+ 涓浗棣欐腐
+ 鏂板姞鍧
+ 寰峰浗
+ 缇庡浗
+ 棰勫彂
+
+ 閫夋嫨Region
+ 纭
+ 鍙栨秷
+ 璇疯緭鍏ヨ秴鏃舵椂闂达紝姣涓哄崟浣
+ 璁剧疆瓒呮椂
+ 瓒呮椂鏃堕棿涓虹┖
+
+ 鎺㈡祴IP鍒楄〃
+ 鑷畾涔塗TL缂撳瓨鍒楄〃
+ 涓荤珯鍩熷悕鍒楄〃
+ 鍩熷悕榛戝悕鍗曞垪琛
+ 鑷畾涔夎В鏋愬叏灞€鍙傛暟
+ 鎵归噺瑙f瀽鍩熷悕
+
+ HttpDNS鐗堟湰鍙
+ 鏈煡
+ 褰撳墠鎵€杩炴帴缃戠粶鐨勭綉缁滄爤绫诲瀷
+ 娓呯┖鎸囧畾鍩熷悕缂撳瓨
+ 璇疯緭鍏ヨ娓呯┖缂撳瓨鐨勫煙鍚
+ 缃戠粶璇锋眰绫诲瀷
+ 寮傛瑙f瀽鑾峰彇IP
+ 鑷畾涔夊煙鍚嶈В鏋
+ 瑕佽В鏋愮殑IP绫诲瀷
+ 浣跨敤鐨勮В鏋愭柟娉
+ 骞跺彂璇锋眰娆℃暟
+
+ 閫夋嫨IP绫诲瀷
+ 閫夋嫨瑙f瀽鏂规硶
+ 閫夋嫨骞跺彂璇锋眰娆℃暟
+ 鑷姩鍒ゆ柇IP绫诲瀷
+ 娣诲姞棰勮В鏋愬煙鍚
+ 璇疯緭鍏ヨ棰勮В鏋愮殑鍩熷悕
+ 棰勮В鏋愬煙鍚嶅垪琛
+ 娣诲姞Tag
+ %s鍩熷悕宸茬粡琚坊鍔犺嚦棰勮В鏋愬垪琛紝璇峰嬁閲嶅娣诲姞
+ 鍒濆鍖朒ttpDns
+ 鎵归噺瑙f瀽鍩熷悕鍒楄〃
+ 璇疯緭鍏ヨ鎵归噺瑙f瀽鐨勫煙鍚
+ 璇疯緭鍏ヨ鎵归噺瑙f瀽鐨勫煙鍚
+ %s鍩熷悕宸茬粡琚坊鍔犺嚦鎵归噺瑙f瀽鍒楄〃锛岃鍕块噸澶嶆坊鍔
+
+ 鍩熷悕锛
+ 绔彛锛
+ TTL鏃堕暱:
+
+ 璇疯緭鍏ヤ富绔欏煙鍚
+ 娣诲姞涓荤珯鍩熷悕
+ 涓荤珯鍩熷悕涓虹┖
+ %s涓荤珯鍩熷悕宸茬粡琚坊鍔狅紝璇峰嬁閲嶅娣诲姞
+
+ 璇疯緭鍏ユ爣绛
+
+ 璇疯緭鍏ヤ笉浣跨敤HttpDns瑙f瀽鐨勫煙鍚
+ 娣诲姞涓嶄娇鐢℉ttpDns鐨勫煙鍚
+ 鍩熷悕涓虹┖
+ %s鍩熷悕宸茬粡鍦ㄩ粦鍚嶅崟涓紝璇峰嬁閲嶅娣诲姞
+
+ 璇疯緭鍏ユ帰娴婭P鐨勫煙鍚
+ 璇疯緭鍏ユ帰娴婭P鐨勭鍙
+ 娣诲姞IP鎺㈡祴
+ 绔彛鍙蜂负绌
+ %s:%s宸茬粡琚坊鍔犺嚦IP鎺㈡祴鍒楄〃锛岃鍕块噸澶嶆坊鍔
+
+ 鍩熷悕涓虹┖
+ 棰勮В鏋愮殑鍩熷悕涓虹┖
+ 鎵归噺瑙f瀽鐨勫煙鍚嶄负绌
+
+ 璇疯緭鍏ョ紦瀛樼殑鍩熷悕
+ 璇疯緭鍏ョ紦瀛樼殑ttl鏃堕棿锛屽崟浣嶏細绉
+ 娣诲姞鑷畾涔塗TL
+ TTL鏃堕棿涓虹┖
+ 璇疯緭鍏ユ纭牸寮忕殑TTL鏃堕暱
+
+ 鍒犻櫎
+ 娓呴櫎鎵€鏈塇ttpDNS閰嶇疆缂撳瓨
+ 鎵€鏈塇ttpDNS閰嶇疆缂撳瓨閮藉凡娓呴櫎
+ 娓呯┖Dns缂撳瓨锛?00娆★級
+
+ 鑷畾涔夎В鏋愮殑鍙傛暟
+ json瀵硅薄鏍煎紡
+ 鑷畾涔夎В鏋愮殑鍙傛暟蹇呴』鏄痡son瀵硅薄
+
+ 鑷畾涔夎В鏋愮殑cache key
+ Cache key鐢ㄤ簬鍞竴鏍囪瘑缂撳瓨涓殑瑙f瀽缁撴灉
+
+ 瑕佽В鏋愮殑鍩熷悕
+ 渚嬪锛歞emo.cloudxdr.com
+ 瑕佽姹傜殑鎺ュ彛
+ 渚嬪: /document_detail/434554.html
+
+ 瑙f瀽骞惰姹
+ 鍩熷悕涓嶈兘涓虹┖
+ 鍩熷悕涓嶈兘鏄疘P鍦板潃
+ 璇疯緭鍏ユ纭牸寮忕殑鍩熷悕
+ Schema绫诲瀷
+ HttpDNS WebView 鎷︽埅GET璇锋眰
+ HttpDNS WebView POST璇锋眰閫氳繃Native鍙戦€
+ HttpDNS IP鐩磋繛鏂规
+
+ 濂界殑
+ 璇锋眰缁撴灉
+ Body璇烽€氳繃鏃ュ織鏌ョ湅锛屽叧閿瓧涓篽ttpdns
+ IP鐩磋繛鏂规
+
+ 鎻愮ず
+ 缃戠粶鏈繛鎺ワ紝璇锋鏌ョ綉缁
+ 璇锋眰寮傚父: %s
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/values/attrs.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..9f1387a
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/values/attrs.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/values/colors.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/values/colors.xml
new file mode 100644
index 0000000..2583807
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/values/colors.xml
@@ -0,0 +1,13 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
+ #e6e6e6
+ #1B58F4
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/values/dimens.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..0cd1a2a
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/values/dimens.xml
@@ -0,0 +1,11 @@
+
+
+ 16dp
+ 16dp
+
+
+ 1.0
+ 8dp
+ 8dp
+ 16dp
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/values/strings.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/values/strings.xml
new file mode 100644
index 0000000..7fb2d6a
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/values/strings.xml
@@ -0,0 +1,141 @@
+
+ New Cloud HttpDNS Demo
+ Basic Settings
+ HttpDNS Resolve
+ Best Practice
+ Information
+ Please init HttpDns first
+
+ Enable Auth Mode
+ Secret key is in config
+ Enable Encrypt Mode
+ Enable Expired IP
+ Enable Cache IP
+ cache expire time
+ the unit of cache expire time is day.
+ Enable HTTPS
+ Enable Degrade
+ Enable Automatic Refresh
+ Enable Log
+ Timeout
+
+ China
+ China-HongKong
+ Singapore
+ Germany
+ America
+ Pre
+
+ Choose Region
+ Confirm
+ Cancel
+ Please input timeout, ms unit
+ Set Timeout
+ Timeout is empty
+ Probe IP List
+ TTL Cache List
+ Host with fixed IP List
+ Host black list
+ Custom DNS global params
+ Batch resolve hosts
+
+ HttpDNS Version
+ Unknown
+ IP stack type of current network
+ Clear the cached DNS record
+ Please input the domain name which you want to clear the cache
+ Network request type
+ Asynchronously resolve host
+ Custom resolve host
+ Resolve IP Type
+ Resolve Method
+ Number of concurrent requests
+
+ Select IP Type
+ Select resolve Method
+ Select number of concurrent requests
+ Get IP automatically
+ Add Pre-Resolve Domain
+ Please input the domain you want to pre-resolve
+ Pre-Resolve Domain List
+ Add Tag
+ The host %s is already added to pre-resolve List
+ Init HttpDns
+ HttpDns Inited
+ Batch resolve domain list
+ Please input the domain you want to batch resolve
+ Add batch resolve domain
+ The host %s is already added to batch resolve List
+
+ Host:
+ Port:
+ Ttl:
+
+ Please input the host with fixed IP
+ Add Host with fixed IP
+ Host with fixed IP is empty
+ The host %s is already added to fixed IP List
+
+ Please input the tag
+
+ Please input the host not use HttpDns
+ Add Host not use HttpDns
+ Host not use HttpDns is empty
+ The host %s is already added to Black List
+
+ Please input the host of IP Probe
+ Please input the port of IP Probe
+ Add IP probe
+ Port is empty
+ The ip probe item - %s:%s is already added
+
+ Host is empty
+ Pre-Resolve Host is empty
+ Batch resolve host is empty
+
+ Please input the host of custom TTL
+ Please input the ttl, unit is second
+ Add custom ttl
+ TTL is empty
+ Please input correct ttl value
+
+ Delete
+ Clear all HttpDNS config cache
+ All HttpDNDS config cache have been cleared
+ Clear Dns Cache (500)
+
+ The sdns params
+ json object format
+ The sdns params must be json object
+
+ The sdns cache key
+ The cache key is the uniquely identifies of the cache dns result
+
+ The Host will be resolved
+ eg: demo.cloudxdr.com
+ The API to be requested
+ eg: /document_detail/434554.html
+
+ Resolve and request
+ The host can not be empty
+ The input host can not be an IP
+ The input a valid host
+ Schema Type
+ HttpDNS WebView intercept GET request
+ HttpDNS WebView POST request forward to native
+ HttpDNS Request By IP Address
+
+ OK
+ Response
+ Check the logs to get the response body with the keyword httpdns
+
+ Request By IP Address
+
+ Tips
+ Network has issues, please check the network
+
+ Request exception: %s
+
+
+
+
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/values/styles.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/values/styles.xml
new file mode 100644
index 0000000..e54b557
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/values/styles.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/values/themes.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/values/themes.xml
new file mode 100644
index 0000000..ff5d71e
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/values/themes.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/main/res/xml/network_security_config.xml b/HttpDNSSDK/sdk/android/demo/src/main/res/xml/network_security_config.xml
new file mode 100644
index 0000000..dca93c0
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/main/res/xml/network_security_config.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/demo/src/test/java/com/newsdk/ams/emas/demo/ExampleUnitTest.kt b/HttpDNSSDK/sdk/android/demo/src/test/java/com/newsdk/ams/emas/demo/ExampleUnitTest.kt
new file mode 100644
index 0000000..d48306b
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/demo/src/test/java/com/newsdk/ams/emas/demo/ExampleUnitTest.kt
@@ -0,0 +1,18 @@
+package com.newsdk.ams.emas.demo
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/gradle.properties b/HttpDNSSDK/sdk/android/gradle.properties
new file mode 100644
index 0000000..c2a0c52
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/gradle.properties
@@ -0,0 +1,16 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+#android.enableR8=false
+
+android.useAndroidX=true
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/gradle/wrapper/gradle-wrapper.jar b/HttpDNSSDK/sdk/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/HttpDNSSDK/sdk/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/HttpDNSSDK/sdk/android/gradle/wrapper/gradle-wrapper.properties b/HttpDNSSDK/sdk/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..b1159fc
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/HttpDNSSDK/sdk/android/gradlew b/HttpDNSSDK/sdk/android/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/HttpDNSSDK/sdk/android/gradlew.bat b/HttpDNSSDK/sdk/android/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/build.gradle b/HttpDNSSDK/sdk/android/httpdns-sdk/build.gradle
new file mode 100644
index 0000000..12a62dd
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/build.gradle
@@ -0,0 +1,129 @@
+plugins {
+ id 'com.android.library'
+ id 'maven-publish'
+}
+apply from: 'version.gradle'
+
+
+android {
+ compileSdk 33
+ defaultConfig {
+ minSdkVersion 19
+ targetSdkVersion 33
+ versionCode 1
+ versionName httpdnsDebugVersion
+ setProperty("archivesBaseName", "new-android-httpdns-$versionName")
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ buildConfigField "String", "VERSION_NAME", "\"${httpdnsDebugVersion}\""
+
+ }
+ buildTypes {
+ release {
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+
+ debug {
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile("proguard-android.txt"), 'proguard-rules.pro'
+ }
+
+ forTest {
+ initWith release
+ debuggable true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-for-test.pro'
+ }
+ }
+
+ flavorDimensions += "version"
+
+ productFlavors {
+ normal {
+
+ }
+
+ intl {
+
+ }
+
+ end2end {
+
+ }
+ }
+
+ variantFilter { variant ->
+ def names = variant.flavors*.name
+ def type = variant.buildType.name
+ // To check for a certain build type, use variant.buildType.name == ""
+ if ((names.contains("normal") && type.contains("forTest"))
+ || (names.contains("intl") && type.contains("forTest"))
+ || (names.contains("end2end") && type.contains("release"))
+ || (names.contains("end2end") && type.contains("debug"))
+ ) {
+ // Gradle ignores any variants that satisfy the conditions above.
+ setIgnore(true)
+ }
+ }
+
+ testOptions {
+ unitTests {
+ all {
+ jvmArgs '-noverify'
+ systemProperty 'robolectric.logging.enable', true
+ }
+ }
+ }
+
+ lintOptions {
+ abortOnError false
+ }
+}
+
+android.libraryVariants.all { variant ->
+ if (variant.name == "normalRelease") {
+ def sdkVersion = variant.mergedFlavor.versionName ?: httpdnsDebugVersion
+ variant.outputs.all { output ->
+ outputFileName = "new--android-httpdns-v${sdkVersion}.aar"
+ }
+ }
+}
+
+dependencies {
+
+ //noinspection GradleDependency 高版本 jdk和androidx有一些依赖,暂时不升级
+ testEnd2endImplementation "org.robolectric:robolectric:3.8"
+ //noinspection GradleDependency
+ testEnd2endImplementation 'junit:junit:4.12'
+ //noinspection GradleDependency
+ testEnd2endImplementation 'org.mockito:mockito-core:2.15.0'
+ testEnd2endImplementation 'com.squareup.okhttp3:mockwebserver:3.9.0'
+
+ implementation "com.newsdk.ams:new-android-logger:${loggerVersion}"
+ implementation "com.newsdk.ams:new-android-crashdefend:${crashDefendVersion}"
+ implementation "com.newsdk.ams:new-android-ipdetector:${ipdetectorVersion}"
+}
+
+ext.getIntlVersion = { version ->
+ if (version.endsWith("-SNAPSHOT")) {
+ return version.replace("-SNAPSHOT", "-intl-SNAPSHOT");
+ } else {
+ return version + "-intl";
+ }
+}
+
+task copyDependencies {
+ doLast {
+ def config = configurations.findByName("normalReleaseRuntimeClasspath")
+ if (config != null) {
+ config.resolvedConfiguration.resolvedArtifacts.each { artifact ->
+ def file = artifact.file
+ if (file.name.contains("new-android")) {
+ copy {
+ from file
+ into 'build/outputs/dependencies'
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/proguard-rules-for-test.pro b/HttpDNSSDK/sdk/android/httpdns-sdk/proguard-rules-for-test.pro
new file mode 100644
index 0000000..4ccca54
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/proguard-rules-for-test.pro
@@ -0,0 +1,50 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/ryan/Downloads/adt-bundle-mac-x86_64-20131030/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+-optimizationpasses 3
+-dontoptimize
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-verbose
+-overloadaggressively
+#-allowaccessmodification
+-useuniqueclassmembernames
+
+-keeppackagenames com.newsdk.sdk.android.httpdns
+-keep class com.newsdk.sdk.android.httpdns.HttpDns{*;}
+-keep class com.newsdk.sdk.android.httpdns.HttpDnsService{*;}
+-keep class com.newsdk.sdk.android.httpdns.SyncService{*;}
+-keep class com.newsdk.sdk.android.httpdns.RequestIpType{*;}
+-keep class com.newsdk.sdk.android.httpdns.net64.Net64Service{*;}
+-keep class com.newsdk.sdk.android.httpdns.DegradationFilter{*;}
+-keep class com.newsdk.sdk.android.httpdns.ranking.IPRankingBean{*;}
+-keep class com.newsdk.sdk.android.httpdns.ILogger{*;}
+-keepclasseswithmembers class com.newsdk.sdk.android.httpdns.log.HttpDnsLog {
+ public static *** setLogger(***);
+ public static *** removeLogger(***);
+ public static *** enable(***);
+}
+-keep class com.newsdk.sdk.android.httpdns.HTTPDNSResult{*;}
+-keep class com.newsdk.sdk.android.httpdns.ApiForTest{*;}
+-keep class com.newsdk.sdk.android.httpdns.test.** {*;}
+-keep class com.newsdk.sdk.android.httpdns.resolve.ResolveHostResponse{*;}
+
+
+-keep class com.newsdk.sdk.android.httpdns.utils.CommonUtil{
+ public ;
+ public ;
+}
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/proguard-rules.pro b/HttpDNSSDK/sdk/android/httpdns-sdk/proguard-rules.pro
new file mode 100644
index 0000000..8466ec6
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/proguard-rules.pro
@@ -0,0 +1,70 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/ryan/Downloads/adt-bundle-mac-x86_64-20131030/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+-optimizationpasses 3
+-dontoptimize
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-verbose
+-overloadaggressively
+#-allowaccessmodification
+-useuniqueclassmembernames
+
+-dontwarn com.newsdk.sdk.android.httpdns.net.HttpDnsNetworkDetector
+
+-keeppackagenames com.newsdk.sdk.android.httpdns
+-flattenpackagehierarchy com.newsdk.sdk.android.httpdns
+-keep class com.newsdk.sdk.android.httpdns.HttpDns{*;}
+-keep interface com.newsdk.sdk.android.httpdns.HttpDnsService{*;}
+-keep class com.newsdk.sdk.android.httpdns.impl.ErrorImpl{*;}
+-keep interface com.newsdk.sdk.android.httpdns.SyncService{*;}
+-keep class com.newsdk.sdk.android.httpdns.InitConfig{*;}
+-keep class com.newsdk.sdk.android.httpdns.InitConfig$Builder{*;}
+-keep class com.newsdk.sdk.android.httpdns.RequestIpType{*;}
+-keep interface com.newsdk.sdk.android.httpdns.DegradationFilter{*;}
+-keep interface com.newsdk.sdk.android.httpdns.NotUseHttpDnsFilter{*;}
+-keep interface com.newsdk.sdk.android.httpdns.HttpDnsCallback{*;}
+-keep class com.newsdk.sdk.android.httpdns.ranking.IPRankingBean{*;}
+-keep interface com.newsdk.sdk.android.httpdns.ILogger{*;}
+-keep interface com.newsdk.sdk.android.httpdns.CacheTtlChanger{*;}
+-keep class com.newsdk.sdk.android.httpdns.NetType{*;}
+-keepclasseswithmembers class com.newsdk.sdk.android.httpdns.log.HttpDnsLog {
+ public static *** setLogger(***);
+ public static *** removeLogger(***);
+ public static *** enable(***);
+}
+-keep class com.newsdk.sdk.android.httpdns.HTTPDNSResult{*;}
+-keepclasseswithmembers class com.newsdk.sdk.android.httpdns.HttpDnsSettings {
+ public static *** setDailyReport(***);
+ public static *** setNetworkChecker(***);
+}
+
+-keep class com.newsdk.sdk.android.httpdns.net.HttpDnsNetworkDetector {
+ public ;
+ public ;
+}
+
+-keep class com.newsdk.sdk.android.httpdns.network.**{*;}
+
+-keep interface com.newsdk.sdk.android.httpdns.HttpDnsSettings$NetworkChecker{*;}
+-keep interface com.newsdk.sdk.android.httpdns.HttpDnsSettings$NetworkDetector{*;}
+-keep class com.newsdk.sdk.android.httpdns.utils.CommonUtil{
+ public ;
+ public ;
+}
+-keep enum com.newsdk.sdk.android.httpdns.Region {*;}
+-keep class com.newsdk.sdk.android.httpdns.exception.InitException{*;}
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/ApiForTest.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/ApiForTest.java
new file mode 100644
index 0000000..9db5a90
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/ApiForTest.java
@@ -0,0 +1,78 @@
+package com.newsdk.sdk.android.httpdns;
+
+import com.newsdk.sdk.android.httpdns.ranking.IPRankingTask;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * @author zonglin.nzl
+ * @date 2020/10/15
+ */
+public interface ApiForTest {
+
+ /**
+ * 鎸囧畾鍒濆鏈嶅姟ip
+ * @param region
+ * @param ips
+ * @param ports
+ * @param ipv6s
+ * @param v6Ports
+ */
+ void setInitServer(String region, String[] ips, int[] ports, String[] ipv6s, int[] v6Ports);
+
+ /**
+ * 鎸囧畾httpdns浣跨敤鐨勭嚎绋嬫睜
+ * @param scheduledExecutorService
+ */
+ void setThread(ScheduledExecutorService scheduledExecutorService);
+
+ /**
+ * 鎸囧畾 娴嬭瘯浣跨敤鐨剆ocket factory
+ * @param speedTestSocketFactory
+ */
+ void setSocketFactory(IPRankingTask.SpeedTestSocketFactory speedTestSocketFactory);
+
+ /**
+ * 鎸囧畾璋冨害鎺ュ彛鐨勮皟鐢ㄩ棿姝囷紝閬垮厤姝e父鐨勯棿姝囪繃闀挎棤娉曟祴璇?
+ * @param timeInterval
+ */
+ void setUpdateServerTimeInterval(int timeInterval);
+
+ /**
+ * 鎸囧畾 sniff妯″紡鐨?璇锋眰闂存瓏
+ * @param timeInterval
+ */
+ void setSniffTimeInterval(int timeInterval);
+
+ /**
+ * 鑾峰彇httpdns鐨勭嚎绋嬫睜鐢ㄤ簬鎺у埗寮傚父鎿嶄綔
+ *
+ * @return
+ */
+ ExecutorService getWorker();
+
+ /**
+ * 璁剧疆鍏滃簳鐨勮皟搴p
+ *
+ * @param defaultServerIps
+ * @param ports
+ */
+ void setDefaultUpdateServer(String[] defaultServerIps, int[] ports);
+
+ /**
+ * 璁剧疆ipv6鐨勫厹搴曡皟搴P
+ *
+ * @param defaultServerIps
+ * @param ports
+ */
+ void setDefaultUpdateServerIpv6(String[] defaultServerIps, int[] ports);
+
+ /**
+ * 璁剧疆娴嬭瘯鐢ㄧ殑缃戠粶detector
+ *
+ * @param networkDetector
+ */
+ void setNetworkDetector(HttpDnsSettings.NetworkDetector networkDetector);
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/BeforeHttpDnsServiceInit.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/BeforeHttpDnsServiceInit.java
new file mode 100644
index 0000000..e9a2596
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/BeforeHttpDnsServiceInit.java
@@ -0,0 +1,12 @@
+package com.newsdk.sdk.android.httpdns;
+
+/**
+ * 娴嬭瘯鐢ㄧ殑鍒濆鍖栨帴鍙?
+ * @author zonglin.nzl
+ * @date 1/14/22
+ */
+public interface BeforeHttpDnsServiceInit {
+
+ void beforeInit(HttpDnsService service);
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/HttpDns.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/HttpDns.java
new file mode 100644
index 0000000..f576edc
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/HttpDns.java
@@ -0,0 +1,86 @@
+package com.newsdk.sdk.android.httpdns;
+
+import android.content.Context;
+
+import com.newsdk.sdk.android.httpdns.impl.HttpDnsInstanceHolder;
+import com.newsdk.sdk.android.httpdns.impl.InstanceCreator;
+import com.newsdk.sdk.android.httpdns.net.NetworkStateManager;
+import com.newsdk.sdk.android.httpdns.network.HttpDnsAdapterOptions;
+import com.newsdk.sdk.android.httpdns.network.HttpDnsHttpAdapter;
+import com.newsdk.sdk.android.httpdns.utils.CommonUtil;
+
+/**
+ * Httpdns瀹炰緥绠$悊
+ */
+public class HttpDns {
+
+ private static HttpDnsInstanceHolder sHolder = new HttpDnsInstanceHolder(new InstanceCreator());
+
+ /**
+ * 鑾峰彇HttpDnsService瀵硅薄
+ *
+ * @param applicationContext 褰撳墠APP鐨凜ontext
+ * @param accountID HttpDns鎺у埗鍙板垎閰嶇殑AccountID
+ * @return
+ */
+ public synchronized static HttpDnsService getService(final Context applicationContext, final String accountID) {
+ return sHolder.get(applicationContext, accountID, null);
+ }
+
+ /**
+ * 鑾峰彇HttpDnsService瀵硅薄锛屽苟鍚敤閴存潈鍔熻兘
+ *
+ * @param applicationContext 褰撳墠APP鐨凜ontext
+ * @param accountID HttpDns鎺у埗鍙板垎閰嶇殑AccountID
+ * @param secretKey 鐢ㄦ埛閴存潈绉侀挜
+ * @return
+ */
+ public synchronized static HttpDnsService getService(final Context applicationContext, final String accountID, final String secretKey) {
+ return sHolder.get(applicationContext, accountID, secretKey);
+ }
+
+ /**
+ * 鑾峰彇HttpDnsService瀵硅薄锛屽垵濮嬪寲鏃朵笉浼犲叆浠讳綍鍙傛暟锛岄潬缁熶竴鎺ュ叆鏈嶅姟鑾峰彇鐩稿叧鍙傛暟
+ *
+ * @param applicationContext 褰撳墠APP鐨凜ontext
+ * @return
+ */
+ public synchronized static HttpDnsService getService(final Context applicationContext) {
+ return sHolder.get(applicationContext, CommonUtil.getAccountId(applicationContext), CommonUtil.getSecretKey(applicationContext));
+ }
+
+ /**
+ * 鍚敤鎴栬€呯鐢╤ttpdns锛岀悊璁轰笂杩欎釜鏄唴閮ㄦ帴鍙o紝涓嶇粰澶栭儴浣跨敤鐨?
+ * 浣嗘槸宸茬粡瀵瑰鏆撮湶锛屾墍浠ヤ繚鐣?
+ *
+ * @param enabled
+ * @deprecated 鍚敤绂佺敤搴旇璋冪敤瀹炰緥鐨勬柟娉曪紝鑰屼笉鏄帶鍒跺叏閮ㄥ疄渚嬬殑鏂规硶
+ */
+ @Deprecated
+ public synchronized static void switchDnsService(boolean enabled) {
+ // do nothing as deprecated
+ }
+
+ /**
+ * 閲嶇疆httpdns锛岀敤浜庝竴浜涙ā鎷熷簲鐢ㄩ噸鍚殑鍦烘櫙
+ */
+ public static void resetInstance() {
+ sHolder = new HttpDnsInstanceHolder(new InstanceCreator());
+ NetworkStateManager.getInstance().reset();
+ }
+
+ /**
+ * Build official IP-direct + empty-SNI adapter.
+ */
+ public static HttpDnsHttpAdapter buildHttpClientAdapter(HttpDnsService service) {
+ return new HttpDnsHttpAdapter(service);
+ }
+
+ /**
+ * Build official IP-direct + empty-SNI adapter with options.
+ */
+ public static HttpDnsHttpAdapter buildHttpClientAdapter(HttpDnsService service, HttpDnsAdapterOptions options) {
+ return new HttpDnsHttpAdapter(service, options);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/InitManager.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/InitManager.java
new file mode 100644
index 0000000..1e80732
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/InitManager.java
@@ -0,0 +1,35 @@
+package com.newsdk.sdk.android.httpdns;
+
+import java.util.HashMap;
+
+/**
+ * 澧炲姞鍒濆鍖栭€昏緫鐨勫崟渚?
+ * 鐢ㄤ簬鍦ㄦ祴璇曠敤鐨刪ttpdns瀹炰緥涓鍔犳祴璇曢渶瑕佺殑鍒濆鍖栭€昏緫
+ * @author zonglin.nzl
+ * @date 1/14/22
+ */
+public class InitManager {
+
+ private static class Holder {
+ private static final InitManager instance = new InitManager();
+ }
+
+ public static InitManager getInstance() {
+ return Holder.instance;
+ }
+
+ private InitManager() {
+ }
+
+ private HashMap initThings = new HashMap<>();
+
+
+ public void add(String accountId, BeforeHttpDnsServiceInit beforeHttpDnsServiceInit) {
+ initThings.put(accountId, beforeHttpDnsServiceInit);
+ }
+
+ public BeforeHttpDnsServiceInit getAndRemove(String accountId) {
+ return initThings.remove(accountId);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsServiceTestImpl.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsServiceTestImpl.java
new file mode 100644
index 0000000..0a79d5c
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsServiceTestImpl.java
@@ -0,0 +1,87 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import android.content.Context;
+
+import com.newsdk.sdk.android.httpdns.ApiForTest;
+import com.newsdk.sdk.android.httpdns.BeforeHttpDnsServiceInit;
+import com.newsdk.sdk.android.httpdns.HttpDnsSettings;
+import com.newsdk.sdk.android.httpdns.InitManager;
+import com.newsdk.sdk.android.httpdns.ranking.IPRankingTask;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * 娴嬭瘯鏃?浣跨敤鐨刪ttpdns 瀹炰緥
+ * 澧炲姞浜嗕竴浜涚敤浜庢祴璇曠殑api鍜屾満鍒?
+ * @author zonglin.nzl
+ * @date 2020/10/16
+ */
+public class HttpDnsServiceTestImpl extends HttpDnsServiceImpl implements ApiForTest {
+ public HttpDnsServiceTestImpl(Context context, String accountId, String secret) {
+ super(context, accountId, secret);
+ }
+
+ @Override
+ protected void beforeInit() {
+ super.beforeInit();
+ // 閫氳繃InitManager 鍦╤ttpdns鍒濆鍖栦箣鍓?杩涜涓€浜涙祴璇曢渶瑕佸墠缃伐浣?
+ BeforeHttpDnsServiceInit init = InitManager.getInstance().getAndRemove(mHttpDnsConfig.getAccountId());
+
+ if (init != null) {
+ init.beforeInit(this);
+ }
+ }
+
+ @Override
+ protected void initCrashDefend(Context context, HttpDnsConfig config) {
+ // do nothing for test
+ mHttpDnsConfig.crashDefend(false);
+ }
+
+ @Override
+ public void setInitServer(String region, String[] ips, int[] ports, String[] ipv6s, int[] v6Ports) {
+ mHttpDnsConfig.setInitServers(region, ips, ports, ipv6s, v6Ports);
+ }
+
+ @Override
+ public void setThread(ScheduledExecutorService scheduledExecutorService) {
+ mHttpDnsConfig.setWorker(scheduledExecutorService);
+ }
+
+ @Override
+ public void setSocketFactory(IPRankingTask.SpeedTestSocketFactory speedTestSocketFactory) {
+ mIpIPRankingService.setSocketFactory(speedTestSocketFactory);
+ }
+
+ @Override
+ public void setUpdateServerTimeInterval(int timeInterval) {
+ mScheduleService.setTimeInterval(timeInterval);
+ }
+
+ @Override
+ public void setSniffTimeInterval(int timeInterval) {
+ mRequestHandler.setSniffTimeInterval(timeInterval);
+ }
+
+ @Override
+ public ExecutorService getWorker() {
+ return mHttpDnsConfig.mWorker;
+ }
+
+ @Override
+ public void setDefaultUpdateServer(String[] defaultServerIps, int[] ports) {
+ mHttpDnsConfig.setDefaultUpdateServer(defaultServerIps, ports);
+ }
+
+ @Override
+ public void setDefaultUpdateServerIpv6(String[] defaultServerIps, int[] ports) {
+ mHttpDnsConfig.setDefaultUpdateServerIpv6(defaultServerIps, ports);
+ }
+
+ @Override
+ public void setNetworkDetector(HttpDnsSettings.NetworkDetector networkDetector) {
+ mHttpDnsConfig.setNetworkDetector(networkDetector);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/impl/InstanceCreator.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/impl/InstanceCreator.java
new file mode 100644
index 0000000..40e877b
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/end2end/java/com/newsdk/sdk/android/httpdns/impl/InstanceCreator.java
@@ -0,0 +1,18 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import android.content.Context;
+
+import com.newsdk.sdk.android.httpdns.HttpDnsService;
+
+/**
+ * 鏀逛负浣跨敤娴嬭瘯瀹炰緥
+ * @author zonglin.nzl
+ * @date 2020/12/4
+ */
+public class InstanceCreator implements HttpDnsCreator {
+ @Override
+ public HttpDnsService create(Context context, String accountId, String secretKey) {
+ return new HttpDnsServiceTestImpl(context.getApplicationContext(), accountId, secretKey);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/intl/java/com/newsdk/sdk/android/httpdns/HttpDns.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/intl/java/com/newsdk/sdk/android/httpdns/HttpDns.java
new file mode 100644
index 0000000..8e15668
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/intl/java/com/newsdk/sdk/android/httpdns/HttpDns.java
@@ -0,0 +1,104 @@
+package com.newsdk.sdk.android.httpdns;
+
+import com.newsdk.sdk.android.httpdns.impl.HttpDnsInstanceHolder;
+import com.newsdk.sdk.android.httpdns.impl.InstanceCreator;
+import com.newsdk.sdk.android.httpdns.network.HttpDnsAdapterOptions;
+import com.newsdk.sdk.android.httpdns.network.HttpDnsHttpAdapter;
+import com.newsdk.sdk.android.httpdns.utils.CommonUtil;
+
+import android.content.Context;
+
+/**
+ * Httpdns瀹炰緥绠$悊
+ */
+public class HttpDns {
+
+ private static final HttpDnsInstanceHolder HOLDER = new HttpDnsInstanceHolder(
+ new InstanceCreator());
+
+ /**
+ * 鑾峰彇HttpDnsService瀵硅薄
+ * @param accountId HttpDns鎺у埗鍙板垎閰嶇殑AccountID
+ * @return
+ */
+ public synchronized static HttpDnsService getService(final String accountId) {
+ return HOLDER.get(null, accountId, null);
+ }
+
+ /**
+ * 鑾峰彇HttpDnsService瀵硅薄
+ * 璇ユ柟娉曞凡寮冪敤锛屽缓璁娇鐢▄@link HttpDns#getService(String)}鏂规硶
+ * @param applicationContext 褰撳墠APP鐨凜ontext
+ * @param accountID HttpDns鎺у埗鍙板垎閰嶇殑AccountID
+ * @return
+ */
+ @Deprecated
+ public synchronized static HttpDnsService getService(final Context applicationContext,
+ final String accountID) {
+ return HOLDER.get(applicationContext, accountID, null);
+ }
+
+ /**
+ * 鑾峰彇HttpDnsService瀵硅薄锛屽苟鍚敤閴存潈鍔熻兘
+ * 璇ユ柟娉曞凡寮冪敤锛屽缓璁娇鐢▄@link HttpDns#getService(String)}鏂规硶
+ * @param applicationContext 褰撳墠APP鐨凜ontext
+ * @param accountID HttpDns鎺у埗鍙板垎閰嶇殑AccountID
+ * @param secretKey 鐢ㄦ埛閴存潈绉侀挜
+ * @return
+ */
+ @Deprecated
+ public synchronized static HttpDnsService getService(final Context applicationContext,
+ final String accountID,
+ final String secretKey) {
+ return HOLDER.get(applicationContext, accountID, secretKey);
+ }
+
+ /**
+ * 鑾峰彇HttpDnsService瀵硅薄锛屽垵濮嬪寲鏃朵笉浼犲叆浠讳綍鍙傛暟锛岄潬缁熶竴鎺ュ叆鏈嶅姟鑾峰彇鐩稿叧鍙傛暟
+ * 璇ユ柟娉曞凡寮冪敤锛屽缓璁娇鐢▄@link HttpDns#getService(String)}鏂规硶
+ * @param applicationContext 褰撳墠APP鐨凜ontext
+ * @return
+ */
+ @Deprecated
+ public synchronized static HttpDnsService getService(final Context applicationContext) {
+ return HOLDER.get(applicationContext, CommonUtil.getAccountId(applicationContext),
+ CommonUtil.getSecretKey(applicationContext));
+ }
+
+ /**
+ * 鍒濆鍖栨柟娉曪紝璇ユ柟娉曚富瑕佹槸淇濆瓨{@link InitConfig}锛屼笉浼氱湡姝h繘琛屽垵濮嬪寲銆傜湡姝e垵濮嬪寲鏄湪{@link HttpDns#getService(Context, String, String)}涓?
+ * 杩欎箞瀹炵幇涓昏鏄负浜嗗吋瀹箋@link InitConfig.Builder#buildFor(String)}鏂规硶锛屾柊瀹㈡埛浣跨敤璇ユ柟娉曞拰鏃х殑鏂规硶鍔熻兘涓€鑷?
+ * @param accountId HttpDns鎺у埗鍙板垎閰嶇殑AccountID
+ * @param config {@link InitConfig}
+ */
+ public static void init(String accountId, InitConfig config) {
+ InitConfig.addConfig(accountId, config);
+ }
+
+ /**
+ * Build official IP-direct + empty-SNI adapter.
+ */
+ public static HttpDnsHttpAdapter buildHttpClientAdapter(HttpDnsService service) {
+ return new HttpDnsHttpAdapter(service);
+ }
+
+ /**
+ * Build official IP-direct + empty-SNI adapter with options.
+ */
+ public static HttpDnsHttpAdapter buildHttpClientAdapter(HttpDnsService service, HttpDnsAdapterOptions options) {
+ return new HttpDnsHttpAdapter(service, options);
+ }
+
+ /**
+ * 鍚敤鎴栬€呯鐢╤ttpdns锛岀悊璁轰笂杩欎釜鏄唴閮ㄦ帴鍙o紝涓嶇粰澶栭儴浣跨敤鐨?
+ * 浣嗘槸宸茬粡瀵瑰鏆撮湶锛屾墍浠ヤ繚鐣?
+ *
+ * @param enabled
+ * @deprecated 鍚敤绂佺敤搴旇璋冪敤瀹炰緥鐨勬柟娉曪紝鑰屼笉鏄帶鍒跺叏閮ㄥ疄渚嬬殑鏂规硶
+ */
+ @Deprecated
+ public synchronized static void switchDnsService(boolean enabled) {
+ // do nothing as deprecated
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/intl/java/com/newsdk/sdk/android/httpdns/impl/InstanceCreator.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/intl/java/com/newsdk/sdk/android/httpdns/impl/InstanceCreator.java
new file mode 100644
index 0000000..cf5fdf2
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/intl/java/com/newsdk/sdk/android/httpdns/impl/InstanceCreator.java
@@ -0,0 +1,13 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import com.newsdk.sdk.android.httpdns.HttpDnsService;
+
+import android.content.Context;
+
+public class InstanceCreator implements HttpDnsCreator {
+ @Override
+ public HttpDnsService create(Context context, String accountId, String secretKey) {
+ return new IntlImpl(context, accountId, secretKey);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/intl/java/com/newsdk/sdk/android/httpdns/impl/IntlImpl.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/intl/java/com/newsdk/sdk/android/httpdns/impl/IntlImpl.java
new file mode 100644
index 0000000..9f95b85
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/intl/java/com/newsdk/sdk/android/httpdns/impl/IntlImpl.java
@@ -0,0 +1,10 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import android.content.Context;
+
+public class IntlImpl extends HttpDnsServiceImpl {
+ public IntlImpl(Context context, String accountId, String secret) {
+ super(context, accountId, secret);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/AndroidManifest.xml b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a799256
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/CacheTtlChanger.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/CacheTtlChanger.java
new file mode 100644
index 0000000..c410372
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/CacheTtlChanger.java
@@ -0,0 +1,19 @@
+package com.newsdk.sdk.android.httpdns;
+
+/**
+ * 淇敼ttl鏃堕暱鐨勬帴鍙?
+ * 鐢ㄤ簬鐢ㄦ埛瀹氬埗ttl锛屼互鎺у埗缂撳瓨鐨勬椂闀?
+ */
+public interface CacheTtlChanger {
+
+ /**
+ * 鏍规嵁 鍩熷悕 ip绫诲瀷 鍜?鏈嶅姟鐨則tl 杩斿洖 瀹氬埗鐨則tl
+ *
+ * @param host 鍩熷悕
+ * @param type ip绫诲瀷
+ * @param ttl 鏈嶅姟涓嬪彂鐨則tl 鍗曚綅绉?
+ * @return 瀹氬埗鐨則tl 鍗曚綅绉?
+ */
+ int changeCacheTtl(String host, RequestIpType type, int ttl);
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/DegradationFilter.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/DegradationFilter.java
new file mode 100644
index 0000000..0717d30
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/DegradationFilter.java
@@ -0,0 +1,14 @@
+package com.newsdk.sdk.android.httpdns;
+
+/**
+ * 闄嶇骇鍒ゆ柇寮€鍏虫帴鍙?
+ */
+@Deprecated
+public interface DegradationFilter {
+ /**
+ * 鏄惁搴旇涓嶄娇鐢╤ttpdns
+ *
+ */
+ boolean shouldDegradeHttpDNS(String hostName);
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HTTPDNSResult.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HTTPDNSResult.java
new file mode 100644
index 0000000..00b6cee
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HTTPDNSResult.java
@@ -0,0 +1,151 @@
+package com.newsdk.sdk.android.httpdns;
+
+import android.text.TextUtils;
+
+import com.newsdk.sdk.android.httpdns.cache.HostRecord;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * sdns鐨勮В鏋愮粨鏋?
+ */
+public class HTTPDNSResult {
+ String host;
+ String[] ips;
+ String[] ipv6s;
+ String extra;
+ long queryTime;
+ int ttl;
+ boolean fromDB;
+ boolean fromLocalDns;
+
+ public HTTPDNSResult(String host) {
+ this.host = host;
+ this.ips = Constants.NO_IPS;
+ this.ipv6s = Constants.NO_IPS;
+ this.extra = "";
+ queryTime = 0;
+ ttl = 0;
+ fromDB = false;
+ fromLocalDns = false;
+ }
+
+ public HTTPDNSResult(String host, String[] ips, String[] ipv6s, String extra, boolean expired, boolean isFromDB) {
+ this.host = host;
+ this.ips = ips;
+ this.ipv6s = ipv6s;
+ this.extra = extra;
+ this.queryTime = System.currentTimeMillis();
+ this.ttl = 60;
+ this.fromDB = isFromDB;
+ fromLocalDns = false;
+ }
+
+ public HTTPDNSResult (String host, String[] ips, String[] ipv6s, String extra, boolean expired, boolean isFromDB, boolean isFromLocalDns) {
+ this(host, ips, ipv6s, extra, expired, isFromDB);
+ fromLocalDns = isFromLocalDns;
+ }
+
+ public static HTTPDNSResult empty(String host) {
+ return new HTTPDNSResult(host, new String[0], new String[0], "", false, false);
+ }
+
+ public void update(HostRecord record) {
+ if (record.getHost().equals(host)) {
+ if (record.getType() == RequestIpType.v4.ordinal()) {
+ ips = record.getIps();
+ } else if (record.getType() == RequestIpType.v6.ordinal()) {
+ ipv6s = record.getIps();
+ }
+ extra = TextUtils.isEmpty(record.getExtra()) ? "" : record.getExtra();
+ queryTime = record.getQueryTime();
+ ttl = record.getTtl();
+ fromDB = record.isFromDB();
+ }
+ }
+
+ public void update(List records) {
+ String extra = null;
+ long queryTime = System.currentTimeMillis();
+ int ttl = Integer.MAX_VALUE;
+ boolean fromDB = false;
+
+ for (HostRecord record : records) {
+ if (record.getHost().equals(host)) {
+ if (record.getType() == RequestIpType.v4.ordinal()) {
+ ips = record.getIps();
+ } else if (record.getType() == RequestIpType.v6.ordinal()) {
+ ipv6s = record.getIps();
+ }
+ if (record.getExtra() != null && !record.getExtra().isEmpty()) {
+ extra = record.getExtra();
+ }
+ if (queryTime > record.getQueryTime()) {
+ queryTime = record.getQueryTime();
+ }
+ if (ttl > record.getTtl()) {
+ ttl = record.getTtl();
+ }
+ fromDB |= record.isFromDB();
+ }
+ }
+ this.extra = TextUtils.isEmpty(extra) ? "" : extra;
+ this.queryTime = queryTime;
+ this.ttl = ttl;
+ this.fromDB = fromDB;
+ }
+
+ @Override
+ public String toString() {
+ String sb = "host:"
+ + host
+ + ", ips:"
+ + Arrays.toString(ips)
+ + ", ipv6s:"
+ + Arrays.toString(ipv6s)
+ + ", extras:"
+ + extra
+ + ", expired:"
+ + isExpired()
+ + ", fromDB:"
+ + fromDB
+ + ", from Local Dns:"
+ + fromLocalDns;
+ return sb;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public String[] getIps() {
+ return ips;
+ }
+
+ public String[] getIpv6s() {
+ return ipv6s;
+ }
+
+ public String getExtras() {
+ return extra;
+ }
+
+ public int getTtl() {
+ return ttl;
+ }
+
+ public boolean isExpired() {
+ return !fromLocalDns && Math.abs(System.currentTimeMillis() - queryTime) > ttl * 1000L;
+ }
+
+ public boolean isFromDB() {
+ return fromDB;
+ }
+
+ public boolean isFromLocalDns() {
+ return fromLocalDns;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HTTPDNSResultWrapper.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HTTPDNSResultWrapper.java
new file mode 100644
index 0000000..e8eea38
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HTTPDNSResultWrapper.java
@@ -0,0 +1,62 @@
+package com.newsdk.sdk.android.httpdns;
+
+import android.text.TextUtils;
+
+import com.newsdk.sdk.android.httpdns.cache.HostRecord;
+
+import java.util.List;
+
+/**
+ * 瀵硅В鏋愮粨鏋滆繘琛屽皝瑁咃紝鐢ㄤ簬鍙娴嬫暟鎹殑涓€浜涜В鏋愭暟鎹惡甯︼紝涓嶅澶栭€忓嚭
+ */
+public class HTTPDNSResultWrapper {
+ private final HTTPDNSResult mHTTPDNSResult;
+ private String mServerIp;
+
+ public HTTPDNSResultWrapper(String host) {
+ mHTTPDNSResult = new HTTPDNSResult(host);
+ }
+
+ public HTTPDNSResult getHTTPDNSResult() {
+ return mHTTPDNSResult;
+ }
+
+ public void update(HostRecord record) {
+ mHTTPDNSResult.update(record);
+ mServerIp = record.getServerIp();
+ }
+
+ public void update(List records) {
+ mHTTPDNSResult.update(records);
+
+ for (HostRecord record : records) {
+ if (record.getHost().equals(mHTTPDNSResult.getHost())) {
+ if (!TextUtils.isEmpty(record.getServerIp())) {
+ mServerIp = record.getServerIp();
+ }
+ }
+ }
+ }
+
+ public boolean isExpired() {
+ return mHTTPDNSResult.isExpired();
+ }
+
+ public String[] getIps() {
+ return mHTTPDNSResult.getIps();
+ }
+
+ public String[] getIpv6s() {
+ return mHTTPDNSResult.getIpv6s();
+ }
+
+ public String getServerIp() {
+ return mServerIp;
+ }
+
+ @Override
+ public String toString() {
+ return mHTTPDNSResult.toString();
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HttpDnsCallback.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HttpDnsCallback.java
new file mode 100644
index 0000000..e4d99b1
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HttpDnsCallback.java
@@ -0,0 +1,6 @@
+package com.newsdk.sdk.android.httpdns;
+
+public interface HttpDnsCallback {
+ void onHttpDnsCompleted(HTTPDNSResult result);
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HttpDnsService.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HttpDnsService.java
new file mode 100644
index 0000000..97349f1
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HttpDnsService.java
@@ -0,0 +1,316 @@
+package com.newsdk.sdk.android.httpdns;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * HttpDns鏈嶅姟鎺ュ彛
+ */
+public interface HttpDnsService {
+ /**
+ * 璁剧疆棰勮В鏋愬煙鍚嶅垪琛紝榛樿瑙f瀽ipv4
+ *
+ * @param hostList 棰勮В鏋愮殑host鍩熷悕鍒楄〃
+ */
+ void setPreResolveHosts(List hostList);
+
+ /**
+ * 璁剧疆棰勮В鏋愬煙鍚嶅垪琛ㄥ拰瑙f瀽鐨刬p绫诲瀷
+ *
+ * @param hostList 棰勮В鏋愮殑host鍒楄〃
+ * @param requestIpType {@link RequestIpType} 缃戠粶鏍堢被鍨嬶紝v4,v6,both,auto(鏍规嵁褰撳墠璁惧鎵€杩炵殑缃戠粶鑷姩鍒ゆ柇缃戠粶鏍?
+ */
+ void setPreResolveHosts(List hostList, RequestIpType requestIpType);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ *
+ * @param host 濡倃emo.cloudxdr.com
+ * @return 杩斿洖ip, 濡傛灉娌″緱鍒拌В鏋愮粨鏋? 鍒欒繑鍥瀗ull
+ * @deprecated 璇ユ帴鍙e凡搴熷純锛屽悗缁増鏈彲鑳戒細琚垹闄わ紝璇蜂娇鐢▄@link #getIPv4ForHostAsync(String)}
+ */
+ @Deprecated
+ String getIpByHostAsync(String host);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛锛屽彧鏌ヨv4鍦板潃锛岄鍏堟煡璇㈢紦瀛? 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @return 杩斿洖v4鍦板潃
+ */
+ @Deprecated
+ String getIPv4ForHostAsync(String host);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛, 鑾峰彇ipv4鍒楄〃
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @return 杩斿洖v4鍦板潃鐨凷tring 鏁扮粍, 濡傛灉娌″緱鍒拌В鏋愮粨鏋? 鍒橲tring 鏁扮粍鐨勯暱搴︿负0
+ * @deprecated 璇ユ帴鍙e凡搴熷純锛屽悗缁増鏈彲鑳戒細琚垹闄わ紝璇蜂娇鐢▄@link #getIPv4ListForHostAsync(String)}
+ */
+ @Deprecated
+ String[] getIpsByHostAsync(String host);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛, 鑾峰彇ipv4鍒楄〃
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @return 杩斿洖v4鍦板潃鍒楄〃
+ */
+ @Deprecated
+ String[] getIPv4ListForHostAsync(String host);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛锛岃幏鍙栧崟涓猧pv6, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @return 杩斿洖v6鍦板潃
+ * @deprecated 璇ユ帴鍙e凡搴熷純锛屽悗缁増鏈彲鑳戒細琚垹闄わ紝璇蜂娇鐢▄@link #getIPv6ForHostAsync(String)}
+ */
+ @Deprecated
+ String getIPv6ByHostAsync(String host);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛锛岃幏鍙栧崟涓猧pv6, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @return 杩斿洖v6鍦板潃
+ */
+ @Deprecated
+ String getIPv6ForHostAsync(String host);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛锛岃幏鍙杋pv6鍒楄〃, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @return 杩斿洖v6鍦板潃鐨凷tring 鏁扮粍, 濡傛灉娌″緱鍒拌В鏋愮粨鏋? 鍒橲tring 鏁扮粍鐨勯暱搴︿负0
+ * @deprecated 璇ユ帴鍙e凡搴熷純锛屽悗缁増鏈彲鑳戒細琚垹闄わ紝璇蜂娇鐢▄@link #getIPv6ListForHostASync(String)}
+ */
+ @Deprecated
+ String[] getIPv6sByHostAsync(String host);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛锛岃幏鍙杋pv6鍒楄〃, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @return 杩斿洖v6鍦板潃鐨凷tring 鏁扮粍, 濡傛灉娌″緱鍒拌В鏋愮粨鏋? 鍒橲tring 鏁扮粍鐨勯暱搴︿负0
+ */
+ @Deprecated
+ String[] getIPv6ListForHostASync(String host);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛锛岃幏鍙杋pv4ipv6鍒楄〃
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @return {@link HTTPDNSResult}
+ * @deprecated 璇ユ帴鍙e凡搴熷純锛屽悗缁増鏈彲鑳戒細琚垹闄わ紝璇蜂娇鐢▄@link #getHttpDnsResultForHostAsync(String)}
+ */
+ @Deprecated
+ HTTPDNSResult getAllByHostAsync(String host);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛锛岃幏鍙杋pv4 + ipv6鍒楄〃, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @return {@link HTTPDNSResult}
+ */
+ @Deprecated
+ HTTPDNSResult getHttpDnsResultForHostAsync(String host);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛锛岃幏鍙杋pv4 + ipv6鍒楄〃, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ * 鏀寔 鎸囧畾瑙f瀽IP绫诲瀷
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @param type {@link RequestIpType} 缃戠粶鏍堢被鍨嬶紝v4,v6,both,auto(鏍规嵁褰撳墠璁惧鎵€杩炵殑缃戠粶鑷姩鍒ゆ柇缃戠粶鏍?
+ * @return {@link HTTPDNSResult}
+ * @deprecated 璇ユ帴鍙e凡搴熷純锛屽悗缁増鏈彲鑳戒細琚垹闄わ紝璇蜂娇鐢▄@link #getHttpDnsResultForHostAsync(String, RequestIpType)}
+ */
+ @Deprecated
+ HTTPDNSResult getIpsByHostAsync(String host, RequestIpType type);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛锛岃幏鍙杋pv4 + ipv6鍒楄〃, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ * 鏀寔 鎸囧畾瑙f瀽IP绫诲瀷
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @param type {@link RequestIpType} 缃戠粶鏍堢被鍨嬶紝v4,v6,both,auto(鏍规嵁褰撳墠璁惧鎵€杩炵殑缃戠粶鑷姩鍒ゆ柇缃戠粶鏍?
+ * @return {@link HTTPDNSResult}
+ */
+ @Deprecated
+ HTTPDNSResult getHttpDnsResultForHostAsync(String host, RequestIpType type);
+
+ /***
+ * 鏍℃App绛惧悕鏃堕棿
+ * @param time time涓篹poch鏃堕棿鎴筹紝1970骞?鏈?鏃ヤ互鏉ョ殑绉掓暟
+ */
+ void setAuthCurrentTime(long time);
+
+ /**
+ * 鑾峰彇浼氳瘽id
+ *
+ * @return sid
+ */
+ String getSessionId();
+
+ //浠ヤ笅閽堝SDNS
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛, 鑾峰彇ipv4 + ipv6 鍒楄〃,棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ * 鏀寔閰嶇疆sdns鍙傛暟
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @return {@link HTTPDNSResult}
+ * @deprecated 璇ユ帴鍙e凡搴熷純锛屽悗缁増鏈彲鑳戒細琚垹闄わ紝璇蜂娇鐢▄@link #getHttpDnsResultForHostAsync(String, Map, String)}
+ */
+ @Deprecated
+ HTTPDNSResult getIpsByHostAsync(String host, Map params, String cacheKey);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛, 鑾峰彇ipv4 + ipv6鍒楄〃, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ * 鏀寔閰嶇疆sdns鍙傛暟
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @param params
+ * @param cacheKey
+ * @return {@link HTTPDNSResult}
+ */
+ @Deprecated
+ HTTPDNSResult getHttpDnsResultForHostAsync(String host, Map params,
+ String cacheKey);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛, 鑾峰彇ipv4 + ipv6鍒楄〃, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ * 鏀寔閰嶇疆sdns鍙傛暟
+ * 鏀寔鎸囧畾瑙f瀽绫诲瀷
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @param type {@link RequestIpType} 缃戠粶鏍堢被鍨嬶紝v4,v6,both,auto(鏍规嵁褰撳墠璁惧鎵€杩炵殑缃戠粶鑷姩鍒ゆ柇缃戠粶鏍?
+ * @param params
+ * @param cacheKey
+ * @return {@link HTTPDNSResult}
+ * @deprecated 璇ユ帴鍙e凡搴熷純锛屽悗缁増鏈彲鑳戒細琚垹闄わ紝璇蜂娇鐢▄@link #getHttpDnsResultForHostAsync(String, RequestIpType,
+ * Map, String)}
+ */
+ @Deprecated
+ HTTPDNSResult getIpsByHostAsync(String host, RequestIpType type, Map params,
+ String cacheKey);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛, 鑾峰彇ipv4 + ipv6鍒楄〃, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ * 鏀寔閰嶇疆sdns鍙傛暟
+ * 鏀寔鎸囧畾瑙f瀽绫诲瀷
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @param type {@link RequestIpType} 缃戠粶鏍堢被鍨嬶紝v4,v6,both,auto(鏍规嵁褰撳墠璁惧鎵€杩炵殑缃戠粶鑷姩鍒ゆ柇缃戠粶鏍?
+ * @param params 鑷畾涔夎В鏋愬弬鏁?
+ * @param cacheKey 缂撳瓨鐨刱ey
+ * @return {@link HTTPDNSResult}
+ */
+ @Deprecated
+ HTTPDNSResult getHttpDnsResultForHostAsync(String host, RequestIpType type, Map params, String cacheKey);
+
+ /**
+ * 鍚屾瑙f瀽鎺ュ彛锛屾敮鎸佹寚瀹氳В鏋愮被鍨?
+ * 鏀寔閰嶇疆sdns鍙傛暟
+ * 闇€瑕佹敞鎰忕殑鍦版柟:
+ * 1. 璇ユ柟娉曞繀椤诲湪瀛愮嚎绋嬩腑鎵ц锛屽鏋滃湪涓荤嚎绋嬩腑璋冪敤璇ユ柟娉曪紝鏂规硶鍐呴儴浼氳嚜鍔ㄥ垏鎹㈡垚寮傛鎵ц
+ * 2. 鍚屾鎺ュ彛浼氶樆濉炲綋鍓嶅瓙绾跨▼锛岄樆濉炴椂闀垮彲浠ラ€氳繃{@link InitConfig.Builder#setTimeout(int)}璁剧疆锛?
+ * 涓嶈繃闃诲鏃堕暱鐨勪笂闄愭槸5s锛屽鏋滆缃殑瓒呮椂鏃堕暱瓒呰繃5s鍒欐棤鏁?
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕鍒楄〃
+ * @param type {@link RequestIpType}
+ * @param params 鑷畾涔夎В鏋愬弬鏁?
+ * @param cacheKey 缂撳瓨鐨刱ey
+ * @return {@link HTTPDNSResult}
+ */
+ HTTPDNSResult getHttpDnsResultForHostSync(String host, RequestIpType type, Map params, String cacheKey);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛, 鑾峰彇ipv4 + ipv6鍒楄〃, 閫氳繃鍥炶皟杩斿洖瑙f瀽缁撴灉锛岄鍏堟煡璇㈢紦瀛? 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ * 鏀寔閰嶇疆sdns鍙傛暟
+ * 鏀寔鎸囧畾瑙f瀽绫诲瀷
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @param type {@link RequestIpType} 缃戠粶鏍堢被鍨嬶紝v4,v6,both,auto(鏍规嵁褰撳墠璁惧鎵€杩炵殑缃戠粶鑷姩鍒ゆ柇缃戠粶鏍?
+ * @param params 鑷畾涔夎В鏋愬弬鏁?
+ * @param cacheKey 缂撳瓨鐨刱ey
+ */
+ void getHttpDnsResultForHostAsync(String host, RequestIpType type, Map params, String cacheKey, HttpDnsCallback callback);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛, 鑾峰彇ipv4 + ipv6鍒楄〃, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ * 鏀寔閰嶇疆sdns鍙傛暟
+ * 鏀寔鎸囧畾瑙f瀽绫诲瀷
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @param type {@link RequestIpType} 缃戠粶鏍堢被鍨嬶紝v4,v6,both,auto(鏍规嵁褰撳墠璁惧鎵€杩炵殑缃戠粶鑷姩鍒ゆ柇缃戠粶鏍?
+ * @param params 鑷畾涔夎В鏋愬弬鏁?
+ * @param cacheKey 缂撳瓨鐨刱ey
+ */
+ HTTPDNSResult getHttpDnsResultForHostSyncNonBlocking(String host, RequestIpType type, Map params, String cacheKey);
+
+ //浠ヤ笂閽堝SDNS
+
+ /**
+ * 璁剧疆region锛屾捣澶栬妭鐐?
+ * 鍥藉唴鐗堥粯璁ゆ槸涓浗澶ч檰鑺傜偣锛屽浗闄呯増榛樿鏄柊鍔犲潯鑺傜偣
+ *
+ * @param region sg(鏂板鍧?, hk(涓浗棣欐腐), ""(涓浗澶ч檰), de(寰峰浗), us(缇庡浗)
+ */
+ @Deprecated
+ void setRegion(String region);
+
+ /**
+ * 璁剧疆region
+ * 鍥藉唴鐗堥粯璁ゆ槸涓浗澶ч檰鑺傜偣
+ *
+ * @param region {@link Region}
+ */
+ void setRegion(Region region);
+
+ /**
+ * 绔嬪嵆娓呴櫎鍩熷悕绔晶鍐呭瓨鍜屾湰鍦扮紦瀛樸€?
+ * 鍚庣画璋冪敤寮傛鎺ュ彛锛屼細鍏堣繑鍥炵┖锛岃Е鍙戝煙鍚嶈В鏋?
+ *
+ * @param hosts host鍩熷悕鍒楄〃
+ */
+ void cleanHostCache(ArrayList hosts);
+
+ /**
+ * 鍚屾瑙f瀽鎺ュ彛锛屾敮鎸佹寚瀹氳В鏋愮被鍨?
+ * 闇€瑕佹敞鎰忕殑鍦版柟:
+ * 1. 璇ユ柟娉曞繀椤诲湪瀛愮嚎绋嬩腑鎵ц锛屽鏋滃湪涓荤嚎绋嬩腑璋冪敤璇ユ柟娉曪紝鏂规硶鍐呴儴浼氳嚜鍔ㄥ垏鎹㈡垚寮傛鎵ц
+ * 2. 鍚屾鎺ュ彛浼氶樆濉炲綋鍓嶅瓙绾跨▼锛岄樆濉炴椂闀垮彲浠ラ€氳繃{@link InitConfig.Builder#setTimeout(int)}璁剧疆锛?
+ * 涓嶈繃闃诲鏃堕暱鐨勪笂闄愭槸5s锛屽鏋滆缃殑瓒呮椂鏃堕暱瓒呰繃5s鍒欐棤鏁?
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕鍒楄〃
+ * @param type {@link RequestIpType}
+ * @return {@link HTTPDNSResult}
+ */
+ HTTPDNSResult getHttpDnsResultForHostSync(String host, RequestIpType type);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛锛屾牴鎹畉ype鑾峰彇ip, 閫氳繃鍥炶皟杩斿洖瑙f瀽缁撴灉锛岄鍏堟煡璇㈢紦瀛? 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰
+ * 鏀寔 鎸囧畾瑙f瀽IP绫诲瀷
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @param type {@link RequestIpType} 缃戠粶鏍堢被鍨嬶紝v4,v6,both,auto(鏍规嵁褰撳墠璁惧鎵€杩炵殑缃戠粶鑷姩鍒ゆ柇缃戠粶鏍?
+ */
+ void getHttpDnsResultForHostAsync(String host, RequestIpType type, HttpDnsCallback callback);
+
+ /**
+ * 寮傛瑙f瀽鎺ュ彛锛屾牴鎹畉ype鑾峰彇ip, 棣栧厛鏌ヨ缂撳瓨, 鑻ュ瓨鍦ㄥ垯杩斿洖缁撴灉, 鑻ヤ笉瀛樺湪杩斿洖null 骞朵笖杩涜寮傛鍩熷悕瑙f瀽璇锋眰锛堜笉浼氶€氳繃鍥炶皟缁欒皟鐢ㄦ柟锛?
+ * 鏀寔 鎸囧畾瑙f瀽IP绫诲瀷
+ *
+ * @param host 瑕佽В鏋愮殑host鍩熷悕
+ * @param type {@link RequestIpType} 缃戠粶鏍堢被鍨嬶紝v4,v6,both,auto(鏍规嵁褰撳墠璁惧鎵€杩炵殑缃戠粶鑷姩鍒ゆ柇缃戠粶鏍?
+ * @return {@link HTTPDNSResult}
+ */
+ HTTPDNSResult getHttpDnsResultForHostSyncNonBlocking(String host, RequestIpType type);
+}
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HttpDnsSettings.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HttpDnsSettings.java
new file mode 100644
index 0000000..675250d
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HttpDnsSettings.java
@@ -0,0 +1,48 @@
+package com.newsdk.sdk.android.httpdns;
+
+import android.content.Context;
+
+public class HttpDnsSettings {
+
+ private static boolean sDailyReport = true;
+
+ public static void setDailyReport(boolean dailyReport) {
+ HttpDnsSettings.sDailyReport = dailyReport;
+ }
+
+ public static boolean isDailyReport() {
+ return sDailyReport;
+ }
+
+ private static NetworkChecker checker = new NetworkChecker() {
+ @Override
+ public boolean isIpv6Only() {
+ return false;
+ }
+ };
+
+ @Deprecated
+ public static void setNetworkChecker(NetworkChecker checker) {
+ HttpDnsSettings.checker = checker;
+ }
+
+ @Deprecated
+ public static NetworkChecker getChecker() {
+ return checker;
+ }
+
+ /**
+ * 闇€瑕佸閮ㄦ敞鍏ョ殑涓€浜涚綉缁滅幆澧冨垽鏂?
+ */
+ public interface NetworkChecker {
+ boolean isIpv6Only();
+ }
+
+ /**
+ * 鑾峰彇缃戠粶绫诲瀷鐨勬帴鍙?
+ */
+ public interface NetworkDetector {
+ NetType getNetType(Context context);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HttpDnsV1Client.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HttpDnsV1Client.java
new file mode 100644
index 0000000..ce8e19d
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/HttpDnsV1Client.java
@@ -0,0 +1,91 @@
+package com.newsdk.sdk.android.httpdns;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.newsdk.sdk.android.httpdns.network.HttpDnsAdapterOptions;
+import com.newsdk.sdk.android.httpdns.network.HttpDnsHttpAdapter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public final class HttpDnsV1Client {
+ private HttpDnsV1Client() {
+ }
+
+ public static HttpDnsService init(Context context,
+ String appId,
+ String serviceUrl,
+ String signSecret) {
+ InitConfig.Builder builder = new InitConfig.Builder()
+ .setContext(context)
+ .setServiceUrl(serviceUrl);
+
+ if (!TextUtils.isEmpty(signSecret)) {
+ builder.setSecretKey(signSecret);
+ }
+
+ builder.buildFor(appId);
+ if (!TextUtils.isEmpty(signSecret)) {
+ return HttpDns.getService(context, appId, signSecret);
+ }
+ return HttpDns.getService(context, appId);
+ }
+
+ public static HttpDnsService init(Context context,
+ String appId,
+ String primaryServiceHost,
+ String backupServiceHost,
+ int servicePort,
+ String signSecret) {
+ InitConfig.Builder builder = new InitConfig.Builder()
+ .setContext(context)
+ .setEnableHttps(true)
+ .setPrimaryServiceHost(primaryServiceHost)
+ .setServicePort(servicePort > 0 ? servicePort : 443);
+
+ if (!TextUtils.isEmpty(backupServiceHost)) {
+ builder.setBackupServiceHost(backupServiceHost);
+ }
+ if (!TextUtils.isEmpty(signSecret)) {
+ builder.setSecretKey(signSecret);
+ }
+
+ builder.buildFor(appId);
+ if (!TextUtils.isEmpty(signSecret)) {
+ return HttpDns.getService(context, appId, signSecret);
+ }
+ return HttpDns.getService(context, appId);
+ }
+
+ public static HTTPDNSResult resolveHost(HttpDnsService service,
+ String host,
+ String qtype,
+ String cip) {
+ if (service == null) {
+ return HTTPDNSResult.empty(host);
+ }
+ RequestIpType requestIpType = RequestIpType.auto;
+ if ("AAAA".equalsIgnoreCase(qtype)) {
+ requestIpType = RequestIpType.v6;
+ }
+
+ Map params = null;
+ if (!TextUtils.isEmpty(cip)) {
+ params = new HashMap<>();
+ params.put("cip", cip);
+ }
+
+ return service.getHttpDnsResultForHostSyncNonBlocking(host, requestIpType, params, host);
+ }
+
+ public static HttpDnsHttpAdapter buildHttpClientAdapter(HttpDnsService service) {
+ return HttpDns.buildHttpClientAdapter(service);
+ }
+
+ public static HttpDnsHttpAdapter buildHttpClientAdapter(HttpDnsService service,
+ HttpDnsAdapterOptions options) {
+ return HttpDns.buildHttpClientAdapter(service, options);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/ILogger.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/ILogger.java
new file mode 100644
index 0000000..4dc4dcf
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/ILogger.java
@@ -0,0 +1,13 @@
+package com.newsdk.sdk.android.httpdns;
+
+/**
+ * 鏃ュ織鎺ュ彛
+ */
+public interface ILogger {
+
+ /**
+ * 鏃ュ織杈撳嚭
+ */
+ void log(String msg);
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/InitConfig.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/InitConfig.java
new file mode 100644
index 0000000..3764702
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/InitConfig.java
@@ -0,0 +1,552 @@
+package com.newsdk.sdk.android.httpdns;
+
+import android.app.Application;
+import android.content.Context;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.newsdk.sdk.android.httpdns.exception.InitException;
+import com.newsdk.sdk.android.httpdns.ranking.IPRankingBean;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+/**
+ * 鍒濆鍖栭厤缃?
+ * 涔嬪墠鐨勫垵濮嬪寲鏂瑰紡锛屾瘡涓厤缃兘鏄崟鐙缃殑锛屾湁鍙兘閫犳垚涓€浜涙椂搴忎笂鐨勯棶棰?
+ * 鎵€浠ュ鍔犵粺涓€鍒濆鍖栭厤缃殑鏂规硶锛岀敱鍐呴儴鍥哄畾鍒濆鍖栭€昏緫锛岄伩鍏嶆椂搴忛棶棰?
+ */
+public class InitConfig {
+
+ private static final Map configs = new ConcurrentHashMap<>();
+
+ static void addConfig(String accountId, InitConfig config) {
+ configs.put(accountId, config);
+ }
+
+ public static final String NOT_SET = null;
+
+ public static InitConfig getInitConfig(String accountId) {
+ return configs.get(accountId);
+ }
+
+ public static void removeConfig(String accountId) {
+ if (accountId == null || accountId.isEmpty()) {
+ configs.clear();
+ } else {
+ configs.remove(accountId);
+ }
+ }
+
+ private final boolean mEnableExpiredIp;
+ private final boolean mEnableCacheIp;
+ private final long mExpiredThresholdMillis;
+ private final int mTimeout;
+ private final boolean mEnableHttps;
+ private final List mIPRankingList;
+ private final String mRegion;
+ private final CacheTtlChanger mCacheTtlChanger;
+ private final List mHostListWithFixedIp;
+ private final boolean mResolveAfterNetworkChange;
+ private final DegradationFilter mDegradationFilter;
+ private final NotUseHttpDnsFilter mNotUseHttpDnsFilter;
+ private final boolean mEnableCrashDefend;
+ private final Map mSdnsGlobalParams;
+ private final boolean mEnableDegradationLocalDns;
+ private final boolean mEnableObservable;
+ private final String mBizTags;
+ private final String aesSecretKey;
+ private final String secretKey;
+ private final String primaryServiceHost;
+ private final String backupServiceHost;
+ private final int servicePort;
+ private final Context context;
+
+ private InitConfig(Builder builder) {
+ mEnableExpiredIp = builder.enableExpiredIp;
+ mEnableCacheIp = builder.enableCacheIp;
+ mExpiredThresholdMillis = builder.expiredThresholdMillis;
+ mTimeout = builder.timeout;
+ mEnableHttps = builder.enableHttps;
+ mIPRankingList = builder.ipRankingList;
+ mRegion = builder.region;
+ mCacheTtlChanger = builder.cacheTtlChanger;
+ mHostListWithFixedIp = builder.hostListWithFixedIp;
+ mResolveAfterNetworkChange = builder.resolveAfterNetworkChange;
+ mDegradationFilter = builder.degradationFilter;
+ mNotUseHttpDnsFilter = builder.notUseHttpDnsFilter;
+ mEnableCrashDefend = builder.enableCrashDefend;
+ mSdnsGlobalParams = builder.sdnsGlobalParams;
+ mEnableDegradationLocalDns = builder.enableDegradationLocalDns;
+ mEnableObservable = builder.enableObservable;
+ mBizTags = builder.bizTags;
+ aesSecretKey = builder.aesSecretKey;
+ primaryServiceHost = builder.primaryServiceHost;
+ backupServiceHost = builder.backupServiceHost;
+ servicePort = builder.servicePort;
+ context = builder.context;
+ secretKey = builder.secretKey;
+ }
+
+ public boolean isEnableExpiredIp() {
+ return mEnableExpiredIp;
+ }
+
+ public boolean isEnableCacheIp() {
+ return mEnableCacheIp;
+ }
+
+ public long getExpiredThresholdMillis() {
+ return mExpiredThresholdMillis;
+ }
+
+ public boolean isResolveAfterNetworkChange() {
+ return mResolveAfterNetworkChange;
+ }
+
+ public int getTimeout() {
+ return mTimeout;
+ }
+
+ public boolean isEnableHttps() {
+ return mEnableHttps;
+ }
+
+ public boolean isEnableDegradationLocalDns() {
+ return mEnableDegradationLocalDns;
+ }
+
+ public List getIPRankingList() {
+ return mIPRankingList;
+ }
+
+ public String getRegion() {
+ return mRegion;
+ }
+
+ public CacheTtlChanger getCacheTtlChanger() {
+ return mCacheTtlChanger;
+ }
+
+ public List getHostListWithFixedIp() {
+ return mHostListWithFixedIp;
+ }
+
+ @Deprecated
+ public DegradationFilter getDegradationFilter() {
+ return mDegradationFilter;
+ }
+
+ public NotUseHttpDnsFilter getNotUseHttpDnsFilter() {
+ return mNotUseHttpDnsFilter;
+ }
+
+ public boolean isEnableCrashDefend() {
+ return mEnableCrashDefend;
+ }
+
+ public Map getSdnsGlobalParams() {
+ return mSdnsGlobalParams;
+ }
+
+ public boolean isEnableObservable() {
+ return mEnableObservable;
+ }
+
+ public String getBizTags() {
+ return mBizTags;
+ }
+
+ public String getAesSecretKey() {
+ return aesSecretKey;
+ }
+
+ public String getPrimaryServiceHost() {
+ return primaryServiceHost;
+ }
+
+ public String getBackupServiceHost() {
+ return backupServiceHost;
+ }
+
+ public int getServicePort() {
+ return servicePort;
+ }
+
+ public Context getContext() {return context;}
+
+ public String getSecretKey() {
+ return secretKey;
+ }
+
+ public static class Builder {
+ private boolean enableExpiredIp = Constants.DEFAULT_ENABLE_EXPIRE_IP;
+ private boolean enableCacheIp = Constants.DEFAULT_ENABLE_CACHE_IP;
+ private long expiredThresholdMillis = 0L;
+ private int timeout = Constants.DEFAULT_TIMEOUT;
+ private boolean enableDegradationLocalDns = Constants.DEFAULT_ENABLE_DEGRADATION_LOCAL_DNS;
+ private boolean enableHttps = Constants.DEFAULT_ENABLE_HTTPS;
+ private List ipRankingList = null;
+ private String region = NOT_SET;
+ private CacheTtlChanger cacheTtlChanger = null;
+ private List hostListWithFixedIp = null;
+ private boolean resolveAfterNetworkChange = true;
+ private DegradationFilter degradationFilter = null;
+ private NotUseHttpDnsFilter notUseHttpDnsFilter = null;
+ private boolean enableCrashDefend = false;
+ private boolean enableObservable = true;
+ private Map sdnsGlobalParams = null;
+ private String bizTags = null;
+ private String aesSecretKey = null;
+ private String primaryServiceHost = null;
+ private String backupServiceHost = null;
+ private int servicePort = -1;
+ private Context context = null;
+ private String secretKey = null;
+
+ /**
+ * 璁剧疆鏄惁鍏佽杩斿洖瓒呰繃ttl 鐨刬p
+ * @param enableExpiredIp 鏄惁鍏佽杩斿洖瓒呰繃ttl 鐨刬p
+ * @return {@link Builder}
+ */
+ public Builder setEnableExpiredIp(boolean enableExpiredIp) {
+ this.enableExpiredIp = enableExpiredIp;
+ return this;
+ }
+
+ /**
+ * 璁剧疆鏄惁鍏佽浣跨敤DB缂撳瓨锛岄粯璁や笉鍏佽
+ * @param enableCacheIp 鏄惁鍏佽浣跨敤DB缂撳瓨
+ * @return {@link Builder}
+ */
+ public Builder setEnableCacheIp(boolean enableCacheIp) {
+ this.enableCacheIp = enableCacheIp;
+ return this;
+ }
+
+ public Builder setEnableCacheIp(boolean enableCacheIp, long expiredThresholdMillis) {
+ this.enableCacheIp = enableCacheIp;
+ if (expiredThresholdMillis >= 0 && expiredThresholdMillis <= DateUtils.YEAR_IN_MILLIS) {
+ this.expiredThresholdMillis = expiredThresholdMillis;
+ }
+
+ return this;
+ }
+
+ /**
+ * 璁剧疆璇锋眰瓒呮椂鏃堕棿,鍗曚綅ms,榛樿涓?s
+ * @param timeoutMillis 瓒呮椂鏃堕棿锛屽崟浣峬s
+ * @return {@link Builder}
+ */
+ public Builder setTimeoutMillis(int timeoutMillis) {
+ timeout = timeoutMillis;
+ return this;
+ }
+
+ /**
+ * 璁剧疆璇锋眰瓒呮椂鏃堕棿,鍗曚綅ms,榛樿涓?s
+ * @param timeout 瓒呮椂鏃堕棿锛屽崟浣峬s
+ * @return {@link Builder}
+ */
+ @Deprecated
+ public Builder setTimeout(int timeout) {
+ this.timeout = timeout;
+ return this;
+ }
+
+ /**
+ * 璁剧疆寮€鍚?鍏抽棴闄嶇骇鍒癓ocal Dns锛屽湪httpdns瑙f瀽澶辫触鎴栬€呭煙鍚嶈杩囨护涓嶈蛋httpdns鐨勬椂鍊欙紝寮€鍚檷绾т細璧發ocal dns瑙f瀽
+ * @param enableDegradation true, 寮€鍚?锝?false, 鍏抽棴
+ * @return {@link Builder}
+ */
+ public Builder setEnableDegradationLocalDns(boolean enableDegradation) {
+ enableDegradationLocalDns = enableDegradation;
+ return this;
+ }
+
+ /**
+ * 璁剧疆HTTPDNS鍩熷悕瑙f瀽璇锋眰绫诲瀷(HTTP/HTTPS)锛岃嫢涓嶈皟鐢ㄨ鎺ュ彛锛岄粯璁や负HTTP璇锋眰
+ * @param enableHttps 鏄惁浣跨敤https
+ * @return {@link Builder}
+ */
+ public Builder setEnableHttps(boolean enableHttps) {
+ this.enableHttps = enableHttps;
+ return this;
+ }
+
+ /**
+ * 璁剧疆瑕佹帰娴嬬殑鍩熷悕鍒楄〃,榛樿鍙細瀵筰pv4鐨勫湴鍧€杩涜ip浼橀€?
+ * @param ipRankingList {@link IPRankingBean}
+ * @return {@link Builder}
+ */
+ public Builder setIPRankingList(List ipRankingList) {
+ this.ipRankingList = ipRankingList;
+ return this;
+ }
+
+ @Deprecated
+ public Builder setRegion(String region) {
+ this.region = region;
+ return this;
+ }
+
+ public Builder setRegion(Region region) {
+ if (region != null) {
+ this.region = region.getRegion();
+ }
+
+ return this;
+ }
+
+ /**
+ * 閰嶇疆鑷畾涔塼tl鐨勯€昏緫
+ *
+ * @param cacheTtlChanger 淇敼ttl鐨勬帴鍙?
+ */
+ public Builder configCacheTtlChanger(CacheTtlChanger cacheTtlChanger) {
+ this.cacheTtlChanger = cacheTtlChanger;
+ return this;
+ }
+
+ /**
+ * 閰嶇疆涓荤珯鍩熷悕鍒楄〃
+ *
+ * @param hostListWithFixedIp 涓荤珯鍩熷悕鍒楄〃
+ */
+ public Builder configHostWithFixedIp(List hostListWithFixedIp) {
+ this.hostListWithFixedIp = hostListWithFixedIp;
+ return this;
+ }
+
+ /**
+ * 璁剧疆缃戠粶鍒囨崲鏃舵槸鍚﹁嚜鍔ㄥ埛鏂版墍鏈夊煙鍚嶈В鏋愮粨鏋滐紝榛樿鑷姩鍒锋柊
+ * @param enable 鏄惁鍏佽鑷姩鍒锋柊鍩熷悕瑙f瀽缁撴灉
+ * @return {@link Builder}
+ */
+ public Builder setPreResolveAfterNetworkChanged(boolean enable) {
+ resolveAfterNetworkChange = enable;
+ return this;
+ }
+
+ /**
+ * 璁剧疆闄嶇骇绛栫暐, 鐢ㄦ埛鍙畾鍒惰鍒欓檷绾т负鍘熺敓DNS瑙f瀽鏂瑰紡
+ * @param filter {@link DegradationFilter}
+ * @return {@link Builder}
+ */
+ @Deprecated
+ public Builder setDegradationFilter(DegradationFilter filter) {
+ degradationFilter = filter;
+ return this;
+ }
+
+ /**
+ * 璁剧疆涓嶄娇鐢℉ttpDns鐨勭瓥鐣? 鐢ㄦ埛鍙畾鍒惰鍒欐寚瀹氫笉璧癶ttpdns鐨勫煙鍚?
+ * @param filter {@link NotUseHttpDnsFilter}
+ * @return {@link Builder}
+ */
+ public Builder setNotUseHttpDnsFilter(NotUseHttpDnsFilter filter) {
+ notUseHttpDnsFilter = filter;
+ return this;
+ }
+
+ /**
+ * 鏄惁寮€鍚痵dk鍐呴儴鐨勫穿婧冧繚鎶ゆ満鍒讹紝榛樿鏄叧闂殑
+ * @param enabled 寮€鍚?鍏抽棴
+ * @return {@link Builder}
+ */
+ public Builder enableCrashDefend(boolean enabled) {
+ enableCrashDefend = enabled;
+ return this;
+ }
+
+ /**
+ * 璁剧疆sdns鍏ㄥ眬鍙傛暟锛堣鍏ㄥ眬鍙傛暟涓嶅奖鍝嶅紓姝ヨВ鏋愪换鍔★紝鍙敤浜庤В鏋愭帴鍙h皟鐢ㄦ椂杩涜鍙傛暟鍚堝苟锛?
+ * @param params sdn鐨勫叏灞€鍙傛暟
+ * @return {@link Builder}
+ */
+ public Builder setSdnsGlobalParams(Map params) {
+ sdnsGlobalParams = params;
+ return this;
+ }
+
+ public Builder enableObservable(boolean enabled) {
+ enableObservable = enabled;
+ return this;
+ }
+
+ public Builder setBizTags(List tags) {
+ if (tags == null) {
+ return this;
+ }
+
+ if (tags.size() > 5) {
+ throw new InitException("The number of tags cannot be greater than 5");
+ }
+
+ Pattern p = Pattern.compile("[^a-zA-Z0-9-]");
+ Matcher matcher;
+ StringBuilder tmpTag = new StringBuilder();
+ for (int i = 0; i != tags.size(); ++i) {
+ String tag = tags.get(i);
+ if (TextUtils.isEmpty(tag)) {
+ continue;
+ }
+
+ matcher = p.matcher(tag);
+ if (matcher.find()) {
+ throw new InitException("tag can only contain a-z and A-Z and 0-9 and -");
+ }
+
+ if (tmpTag.indexOf(tag) != -1) {
+ //鍘婚噸
+ continue;
+ }
+
+ tmpTag.append(tag);
+ if (i != tags.size() - 1) {
+ tmpTag.append(",");
+ }
+ }
+
+ int lastCommaIndex = tmpTag.lastIndexOf(",");
+ //鏈€鍚庝竴浣嶉€楀彿瑕佸幓鎺?
+ if (lastCommaIndex == tmpTag.length() - 1) {
+ tmpTag.deleteCharAt(lastCommaIndex);
+ }
+
+ if (tmpTag.length() > 64) {
+ throw new InitException("The length of all tags cannot be greater than 64");
+ }
+
+ bizTags = tmpTag.toString();
+ return this;
+ }
+
+ /**
+ * 璁剧疆aes鍔犲瘑瀵嗛挜
+ * @param aesSecretKey 鍔犲瘑瀵嗛挜
+ * @return {@link Builder}
+ */
+ public Builder setAesSecretKey(String aesSecretKey) {
+ this.aesSecretKey = aesSecretKey;
+ return this;
+ }
+
+ /**
+ * 璁剧疆涓绘湇鍔″煙鍚嶃€? */
+ public Builder setPrimaryServiceHost(String host) {
+ this.primaryServiceHost = host;
+ return this;
+ }
+
+ /**
+ * 璁剧疆澶囨湇鍔″煙鍚嶃€? */
+ public Builder setBackupServiceHost(String host) {
+ this.backupServiceHost = host;
+ return this;
+ }
+
+ /**
+ * Configure HTTPDNS endpoint with URL, e.g. "https://example.com:8445".
+ * This sets scheme/host/port in one call and clears backup host.
+ */
+ public Builder setServiceUrl(String serviceUrl) {
+ if (TextUtils.isEmpty(serviceUrl)) {
+ throw new InitException("serviceUrl should not be empty");
+ }
+
+ String raw = serviceUrl.trim();
+ if (raw.isEmpty()) {
+ throw new InitException("serviceUrl should not be empty");
+ }
+
+ String normalized = raw;
+ if (!raw.startsWith("http://") && !raw.startsWith("https://")) {
+ normalized = "https://" + raw;
+ }
+
+ try {
+ URI uri = new URI(normalized);
+ String host = uri.getHost();
+ if (TextUtils.isEmpty(host)) {
+ throw new InitException("invalid serviceUrl host: " + serviceUrl);
+ }
+
+ this.primaryServiceHost = host;
+ this.backupServiceHost = null;
+
+ if (uri.getPort() > 0) {
+ this.servicePort = uri.getPort();
+ }
+
+ String scheme = uri.getScheme();
+ this.enableHttps = !"http".equalsIgnoreCase(scheme);
+ } catch (URISyntaxException e) {
+ throw new InitException("invalid serviceUrl: " + serviceUrl);
+ }
+ return this;
+ }
+
+ /**
+ * 鎵归噺璁剧疆鏈嶅姟鍩熷悕锛屾敮鎸佷富澶囦袱涓€? */
+ public Builder setServiceHosts(List hosts) {
+ if (hosts != null && hosts.size() > 0) {
+ this.primaryServiceHost = hosts.get(0);
+ }
+ if (hosts != null && hosts.size() > 1) {
+ this.backupServiceHost = hosts.get(1);
+ }
+ return this;
+ }
+
+ /**
+ * 璁剧疆鏈嶅姟绔彛锛岄粯璁?-1 琛ㄧず浣跨敤鍗忚榛樿绔彛銆? */
+ public Builder setServicePort(int port) {
+ this.servicePort = port;
+ return this;
+ }
+
+ /**
+ * 璁剧疆context
+ * @param context 涓婁笅鏂?
+ * @return {@link Builder}
+ */
+ public Builder setContext(Context context) {
+ if (context instanceof Application) {
+ this.context = context;
+ } else {
+ if (context != null) {
+ this.context = context.getApplicationContext();
+ }
+ }
+ return this;
+ }
+
+ /**
+ * 璁剧疆鍔犵瀵嗛挜
+ * @param secretKey 鍔犵瀵嗛挜
+ * @return {@link Builder}
+ */
+ public Builder setSecretKey(String secretKey) {
+ this.secretKey = secretKey;
+ return this;
+ }
+
+ public InitConfig build() {
+ return new InitConfig(this);
+ }
+
+ public InitConfig buildFor(String accountId) {
+ InitConfig config = new InitConfig(this);
+ addConfig(accountId, config);
+ return config;
+ }
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/NetType.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/NetType.java
new file mode 100644
index 0000000..45ff534
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/NetType.java
@@ -0,0 +1,12 @@
+package com.newsdk.sdk.android.httpdns;
+
+/**
+ * 缃戠粶绫诲瀷
+ */
+public enum NetType {
+ none,
+ v4,
+ v6,
+ both
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/NotUseHttpDnsFilter.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/NotUseHttpDnsFilter.java
new file mode 100644
index 0000000..50a9a42
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/NotUseHttpDnsFilter.java
@@ -0,0 +1,15 @@
+package com.newsdk.sdk.android.httpdns;
+
+/**
+ * 涓嶄娇鐢℉ttpDns鐨勯厤缃帴鍙?
+ */
+public interface NotUseHttpDnsFilter {
+ /**
+ * 鏄惁搴旇涓嶄娇鐢╤ttpdns
+ * @param hostName 鍩熷悕
+ * @return true 涓嶈蛋httpdns瑙f瀽 锝?false 璧癶ttpdns瑙f瀽
+ *
+ */
+ boolean notUseHttpDns(String hostName);
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/Region.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/Region.java
new file mode 100644
index 0000000..be76cb8
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/Region.java
@@ -0,0 +1,21 @@
+package com.newsdk.sdk.android.httpdns;
+
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+public enum Region {
+ DEFAULT(""),
+ HK(Constants.REGION_HK),
+ SG(Constants.REGION_SG),
+ DE(Constants.REGION_DE),
+ US(Constants.REGION_US);
+
+ private final String region;
+ Region(String region) {
+ this.region = region;
+ }
+
+ public String getRegion() {
+ return region;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/RequestIpType.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/RequestIpType.java
new file mode 100644
index 0000000..ae600a9
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/RequestIpType.java
@@ -0,0 +1,18 @@
+package com.newsdk.sdk.android.httpdns;
+
+/**
+ * 璇锋眰鐨刬p绫诲瀷
+ */
+public enum RequestIpType {
+ v4,
+ v6,
+ /**
+ * 琛ㄧず 涓や釜閮借
+ */
+ both,
+ /**
+ * 琛ㄧず鏍规嵁缃戠粶鎯呭喌鑷姩鍒ゆ柇
+ */
+ auto
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/SyncService.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/SyncService.java
new file mode 100644
index 0000000..30ccff0
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/SyncService.java
@@ -0,0 +1,14 @@
+package com.newsdk.sdk.android.httpdns;
+
+public interface SyncService {
+ /**
+ * 鍚屾瑙f瀽鎺ュ彛锛屽繀椤诲湪瀛愮嚎绋嬩腑鎵ц锛屽惁鍒欐病鏈夋晥鏋?
+ *
+ * @deprecated 璇ユ帴鍙e凡搴熷純锛屽悗缁増鏈彲鑳戒細鍒犻櫎锛岃浣跨敤
+ * {@link HttpDnsService#getHttpDnsResultForHostSync(String, RequestIpType)}
+ */
+ @Deprecated
+ HTTPDNSResult getByHost(String host, RequestIpType type);
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/cache/HostRecord.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/cache/HostRecord.java
new file mode 100644
index 0000000..27658b6
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/cache/HostRecord.java
@@ -0,0 +1,184 @@
+package com.newsdk.sdk.android.httpdns.cache;
+
+import java.util.Arrays;
+
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+import com.newsdk.sdk.android.httpdns.utils.CommonUtil;
+
+/**
+ * ip瑙f瀽缁撴灉璁板綍
+ * 娉ㄦ剰璁$畻hash 鍜?equal瀹炵幇锛屾病鏈変娇鐢╢romDB瀛楁
+ */
+public class HostRecord {
+ private long id = -1;
+ private String region;
+ private String host;
+ private String[] ips;
+ private int type;
+ private int ttl;
+ private long queryTime;
+ private String extra;
+ private String cacheKey;
+ private boolean fromDB = false;
+ private String serverIp;
+ private String noIpCode;
+
+ public static HostRecord create(String region, String host, RequestIpType type, String extra,
+ String cacheKey, String[] ips, int ttl, String serverIp, String noIpCode) {
+ HostRecord record = new HostRecord();
+ record.region = region;
+ record.host = host;
+ record.type = type.ordinal();
+ record.ips = ips;
+ record.ttl = ttl;
+ record.queryTime = System.currentTimeMillis();
+ record.extra = extra;
+ record.cacheKey = cacheKey;
+ record.serverIp = serverIp;
+ record.noIpCode = noIpCode;
+ return record;
+ }
+
+ public boolean isExpired() {
+ return System.currentTimeMillis() > queryTime + ttl * 1000L;
+ }
+
+ public void setFromDB(boolean fromDB) {
+ this.fromDB = fromDB;
+ }
+
+ public boolean isFromDB() {
+ return fromDB;
+ }
+
+ public String getRegion() {
+ return region;
+ }
+
+ public void setRegion(String region) {
+ this.region = region;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public String[] getIps() {
+ return ips;
+ }
+
+ public void setIps(String[] ips) {
+ this.ips = ips;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public void setType(int type) {
+ this.type = type;
+ }
+
+ public int getTtl() {
+ return ttl;
+ }
+
+ public void setTtl(int ttl) {
+ this.ttl = ttl;
+ }
+
+ public long getQueryTime() {
+ return queryTime;
+ }
+
+ public void setQueryTime(long queryTime) {
+ this.queryTime = queryTime;
+ }
+
+ public String getExtra() {
+ return extra;
+ }
+
+ public void setExtra(String extra) {
+ this.extra = extra;
+ }
+
+ public String getCacheKey() {
+ return cacheKey;
+ }
+
+ public void setCacheKey(String cacheKey) {
+ this.cacheKey = cacheKey;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public void setServerIp(String ip) {
+ serverIp = ip;
+ }
+
+ public String getServerIp() {
+ return serverIp;
+ }
+
+ public void setNoIpCode(String noIpCode) {
+ this.noIpCode = noIpCode;
+ }
+
+ public String getNoIpCode() {
+ return noIpCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {return true;}
+ if (o == null || getClass() != o.getClass()) {return false;}
+ HostRecord that = (HostRecord)o;
+ return id == that.id &&
+ type == that.type &&
+ ttl == that.ttl &&
+ queryTime == that.queryTime &&
+ region.equals(that.region) &&
+ host.equals(that.host) &&
+ Arrays.equals(ips, that.ips) &&
+ CommonUtil.equals(extra, that.extra) &&
+ CommonUtil.equals(cacheKey, that.cacheKey) &&
+ CommonUtil.equals(noIpCode, that.noIpCode);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Arrays.hashCode(
+ new Object[] {id, region, host, type, ttl, queryTime, extra, cacheKey, noIpCode});
+ result = 31 * result + Arrays.hashCode(ips);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "HostRecord{" +
+ "id=" + id +
+ ", region='" + region + '\'' +
+ ", host='" + host + '\'' +
+ ", ips=" + Arrays.toString(ips) +
+ ", type=" + type +
+ ", ttl=" + ttl +
+ ", queryTime=" + queryTime +
+ ", extra='" + extra + '\'' +
+ ", cacheKey='" + cacheKey + '\'' +
+ ", fromDB=" + fromDB +
+ ", noIpCode=" + noIpCode +
+ '}';
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/cache/RecordDBHelper.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/cache/RecordDBHelper.java
new file mode 100644
index 0000000..70e4948
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/cache/RecordDBHelper.java
@@ -0,0 +1,261 @@
+package com.newsdk.sdk.android.httpdns.cache;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog;
+import com.newsdk.sdk.android.httpdns.utils.CommonUtil;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+/**
+ * 鏁版嵁搴撳瓨鍙栨搷浣?
+ */
+public class RecordDBHelper extends SQLiteOpenHelper {
+
+ private static final String DB_NAME = "aliclound_httpdns_v3_";
+ private static final int DB_VERSION = 0x03;
+
+ static class HOST {
+
+ static final String TABLE_NAME = "host";
+
+ static final String COL_ID = "id";
+
+ static final String COL_REGION = "region";
+
+ static final String COL_HOST = "host";
+
+ static final String COL_IPS = "ips";
+
+ static final String COL_TYPE = "type";
+
+ static final String COL_TIME = "time";
+
+ static final String COL_TTL = "ttl";
+
+ static final String COL_EXTRA = "extra";
+
+ static final String COL_CACHE_KEY = "cache_key";
+
+ // 鏃х増鏈?鐢ㄤ簬瀛樺偍缃戠粶鏍囪瘑鐨勫瓧娈碉紝鐢变簬鍚堣鐨勫奖鍝嶏紝鍒犻櫎浜嗙浉鍏充唬鐮侊紝姝ゅ瓧娈靛彉涓哄浐瀹氬瓧娈碉紝鐩墠宸茬粡娌℃湁鎰忎箟
+ static final String COL_SP = "sp";
+
+ static final String COL_NO_IP_CODE = "no_ip_code";
+
+ static final String CREATE_HOST_TABLE_SQL = "CREATE TABLE " + TABLE_NAME + " ("
+ + COL_ID + " INTEGER PRIMARY KEY,"
+ + COL_REGION + " TEXT,"
+ + COL_HOST + " TEXT,"
+ + COL_IPS + " TEXT,"
+ + COL_TYPE + " INTEGER,"
+ + COL_TIME + " INTEGER,"
+ + COL_TTL + " INTEGER,"
+ + COL_EXTRA + " TEXT,"
+ + COL_CACHE_KEY + " TEXT,"
+ + COL_SP + " TEXT,"
+ + COL_NO_IP_CODE + " TEXT"
+ + ");";
+ }
+
+ private final String mAccountId;
+ private final Object mLock = new Object();
+ private SQLiteDatabase mDb;
+
+ public RecordDBHelper(Context context, String accountId) {
+ super(context, DB_NAME + accountId + ".db", null, DB_VERSION);
+ this.mAccountId = accountId;
+ }
+
+ private SQLiteDatabase getDB() {
+ if (mDb == null) {
+ try {
+ mDb = getWritableDatabase();
+ } catch (Exception e) {
+ }
+ }
+ return mDb;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ if (mDb != null) {
+ try {
+ mDb.close();
+ } catch (Exception ignored) {
+ }
+ }
+ super.finalize();
+ }
+
+ /**
+ * 浠庢暟鎹簱鑾峰彇鍏ㄩ儴鏁版嵁
+ *
+ * @param region
+ * @return
+ */
+ public List readFromDb(String region) {
+ synchronized (mLock) {
+ ArrayList hosts = new ArrayList<>();
+
+ SQLiteDatabase db = null;
+ Cursor cursor = null;
+ try {
+ db = getDB();
+ cursor = db.query(HOST.TABLE_NAME, null, HOST.COL_REGION + " = ?",
+ new String[] {region}, null, null, null);
+ if (cursor != null && cursor.getCount() > 0) {
+ cursor.moveToFirst();
+ do {
+ HostRecord hostRecord = new HostRecord();
+ hostRecord.setId(cursor.getLong(cursor.getColumnIndex(HOST.COL_ID)));
+ hostRecord.setRegion(
+ cursor.getString(cursor.getColumnIndex(HOST.COL_REGION)));
+ hostRecord.setHost(cursor.getString(cursor.getColumnIndex(HOST.COL_HOST)));
+ hostRecord.setIps(CommonUtil.parseStringArray(
+ cursor.getString(cursor.getColumnIndex(HOST.COL_IPS))));
+ hostRecord.setType(cursor.getInt(cursor.getColumnIndex(HOST.COL_TYPE)));
+ hostRecord.setTtl(cursor.getInt(cursor.getColumnIndex(HOST.COL_TTL)));
+ hostRecord.setQueryTime(
+ cursor.getLong(cursor.getColumnIndex(HOST.COL_TIME)));
+ hostRecord.setExtra(
+ cursor.getString(cursor.getColumnIndex(HOST.COL_EXTRA)));
+ hostRecord.setCacheKey(
+ cursor.getString(cursor.getColumnIndex(HOST.COL_CACHE_KEY)));
+ hostRecord.setFromDB(true);
+ hostRecord.setNoIpCode(cursor.getString(cursor.getColumnIndex(HOST.COL_NO_IP_CODE)));
+ hosts.add(hostRecord);
+ } while (cursor.moveToNext());
+ }
+ } catch (Exception e) {
+ HttpDnsLog.w("read from db fail " + mAccountId, e);
+ } finally {
+ try {
+ if (cursor != null) {
+ cursor.close();
+ }
+ } catch (Exception ignored) {
+ }
+ }
+ return hosts;
+ }
+ }
+
+ /**
+ * 浠庢暟鎹簱鍒犻櫎鏁版嵁
+ */
+ public void delete(List records) {
+ if (records == null || records.isEmpty()) {
+ return;
+ }
+
+ synchronized (mLock) {
+ SQLiteDatabase db = null;
+ try {
+ db = getDB();
+ db.beginTransaction();
+ for (HostRecord record : records) {
+ db.delete(HOST.TABLE_NAME, HOST.COL_ID + " = ? ",
+ new String[] {String.valueOf(record.getId())});
+ }
+ db.setTransactionSuccessful();
+ } catch (Exception e) {
+ HttpDnsLog.w("delete record fail " + mAccountId, e);
+ } finally {
+ if (db != null) {
+ try {
+ db.endTransaction();
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 鏇存柊鏁版嵁
+ */
+ public void insertOrUpdate(List records) {
+ synchronized (mLock) {
+ SQLiteDatabase db = null;
+ try {
+ db = getDB();
+ db.beginTransaction();
+ for (HostRecord record : records) {
+ ContentValues cv = new ContentValues();
+ cv.put(HOST.COL_REGION, record.getRegion());
+ cv.put(HOST.COL_HOST, record.getHost());
+ cv.put(HOST.COL_IPS, CommonUtil.translateStringArray(record.getIps()));
+ cv.put(HOST.COL_CACHE_KEY, record.getCacheKey());
+ cv.put(HOST.COL_EXTRA, record.getExtra());
+ cv.put(HOST.COL_TIME, record.getQueryTime());
+ cv.put(HOST.COL_TYPE, record.getType());
+ cv.put(HOST.COL_TTL, record.getTtl());
+ cv.put(HOST.COL_NO_IP_CODE, record.getNoIpCode());
+
+ if (record.getId() != -1) {
+ db.update(HOST.TABLE_NAME, cv, HOST.COL_ID + " = ?",
+ new String[] {String.valueOf(record.getId())});
+ } else {
+ long id = db.insert(HOST.TABLE_NAME, null, cv);
+ record.setId(id);
+ }
+ }
+ db.setTransactionSuccessful();
+ } catch (Exception e) {
+ HttpDnsLog.w("insertOrUpdate record fail " + mAccountId, e);
+ } finally {
+ if (db != null) {
+ try {
+ db.endTransaction();
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ try {
+ db.execSQL(HOST.CREATE_HOST_TABLE_SQL);
+ } catch (Exception e) {
+ HttpDnsLog.w("create db fail " + mAccountId, e);
+ }
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (oldVersion != newVersion) {
+ try {
+ db.beginTransaction();
+ db.execSQL("DROP TABLE IF EXISTS " + HOST.TABLE_NAME + ";");
+ db.setTransactionSuccessful();
+ db.endTransaction();
+ onCreate(db);
+ } catch (Exception e) {
+ HttpDnsLog.w("upgrade db fail " + mAccountId, e);
+ }
+ }
+ }
+
+ @Override
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (oldVersion != newVersion) {
+ try {
+ db.beginTransaction();
+ db.execSQL("DROP TABLE IF EXISTS " + HOST.TABLE_NAME + ";");
+ db.setTransactionSuccessful();
+ db.endTransaction();
+ onCreate(db);
+ } catch (Exception e) {
+ HttpDnsLog.w("downgrade db fail " + mAccountId, e);
+ }
+ }
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/ConfigCacheHelper.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/ConfigCacheHelper.java
new file mode 100644
index 0000000..7a4d3f9
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/ConfigCacheHelper.java
@@ -0,0 +1,66 @@
+package com.newsdk.sdk.android.httpdns.config;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import com.newsdk.sdk.android.httpdns.impl.HttpDnsConfig;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+/**
+ * 杈呭姪閰嶇疆鐨勭紦瀛樺啓鍏ュ拰璇诲彇
+ */
+public class ConfigCacheHelper {
+
+ private final AtomicBoolean mSaving = new AtomicBoolean(false);
+
+ public void restoreFromCache(Context context, HttpDnsConfig config) {
+ SharedPreferences sp = context.getSharedPreferences(
+ Constants.CONFIG_CACHE_PREFIX + config.getAccountId(), Context.MODE_PRIVATE);
+ SpCacheItem[] items = config.getCacheItem();
+ for (SpCacheItem item : items) {
+ item.restoreFromCache(sp);
+ }
+ }
+
+ public void saveConfigToCache(Context context, HttpDnsConfig config) {
+ if (mSaving.compareAndSet(false, true)) {
+ try {
+ config.getWorker().execute(new WriteCacheTask(context, config, this));
+ } catch (Exception ignored) {
+ mSaving.set(false);
+ }
+ }
+ }
+
+ static class WriteCacheTask implements Runnable {
+
+ private final Context mContext;
+ private final HttpDnsConfig mHttpDnsConfig;
+ private final ConfigCacheHelper mCacheHelper;
+
+ public WriteCacheTask(Context context, HttpDnsConfig config, ConfigCacheHelper helper) {
+ this.mContext = context;
+ this.mHttpDnsConfig = config;
+ this.mCacheHelper = helper;
+ }
+
+ @Override
+ public void run() {
+ mCacheHelper.mSaving.set(false);
+
+ SharedPreferences.Editor editor = mContext.getSharedPreferences(
+ Constants.CONFIG_CACHE_PREFIX + mHttpDnsConfig.getAccountId(),
+ Context.MODE_PRIVATE)
+ .edit();
+ SpCacheItem[] items = mHttpDnsConfig.getCacheItem();
+ for (SpCacheItem item : items) {
+ item.saveToCache(editor);
+ }
+ // 铏界劧鎻愮ず寤鸿浣跨敤apply锛屼絾鏄疄璺佃瘉鏄庯紝apply鏄妸鍐欐枃浠舵搷浣滄帹杩熷埌浜嗕竴浜涚晫闈㈠垏鎹㈢瓑鏃舵満锛屽弽鑰屽奖鍝嶄簡UI绾跨▼銆備笉濡傜洿鎺ュ湪瀛愮嚎绋嬪啓鏂囦欢
+ editor.commit();
+ }
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/RegionServer.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/RegionServer.java
new file mode 100644
index 0000000..4080678
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/RegionServer.java
@@ -0,0 +1,118 @@
+package com.newsdk.sdk.android.httpdns.config;
+
+import com.newsdk.sdk.android.httpdns.utils.CommonUtil;
+
+import java.util.Arrays;
+
+public class RegionServer {
+ /**
+ * HttpDns鐨勬湇鍔P
+ */
+ private String[] mServerIps;
+ /**
+ * HttpDns鐨勬湇鍔$鍙o紝绾夸笂閮芥槸榛樿绔彛 80 鎴栬€?443
+ * 姝ゅ鏄负浜嗘祴璇曞満鏅寚瀹氱鍙?
+ * 涓嬫爣鍜寋@link #mServerIps} 瀵瑰簲
+ * 濡傛灉涓簄ull 琛ㄧず娌℃湁鎸囧畾绔彛
+ */
+ private int[] mPorts;
+ private String mRegion;
+
+ private String[] mIpv6ServerIps;
+ private int[] mIpv6Ports;
+
+ public RegionServer(String[] serverIps, int[] ports, String[] ipv6ServerIps, int[] ipv6Ports, String region) {
+ this.mServerIps = serverIps == null ? new String[0] : serverIps;
+ this.mPorts = ports;
+ this.mRegion = region;
+ this.mIpv6ServerIps = ipv6ServerIps == null ? new String[0] : ipv6ServerIps;
+ this.mIpv6Ports = ipv6Ports;
+ }
+
+ public String[] getServerIps() {
+ return mServerIps;
+ }
+
+ public int[] getPorts() {
+ return mPorts;
+ }
+
+ public String getRegion() {
+ return mRegion;
+ }
+
+ public String[] getIpv6ServerIps() {
+ return mIpv6ServerIps;
+ }
+
+ public int[] getIpv6Ports() {
+ return mIpv6Ports;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ RegionServer that = (RegionServer) o;
+ return Arrays.equals(mServerIps, that.mServerIps) &&
+ Arrays.equals(mPorts, that.mPorts) &&
+ Arrays.equals(mIpv6ServerIps, that.mIpv6ServerIps) &&
+ Arrays.equals(mIpv6Ports, that.mIpv6Ports) &&
+ CommonUtil.equals(mRegion, that.mRegion);
+ }
+
+ public boolean serverEquals(RegionServer that) {
+ return Arrays.equals(mServerIps, that.mServerIps) &&
+ Arrays.equals(mPorts, that.mPorts) &&
+ Arrays.equals(mIpv6ServerIps, that.mIpv6ServerIps) &&
+ Arrays.equals(mIpv6Ports, that.mIpv6Ports) &&
+ CommonUtil.equals(mRegion, that.mRegion);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Arrays.hashCode(new Object[]{mRegion});
+ result = 31 * result + Arrays.hashCode(mServerIps);
+ result = 31 * result + Arrays.hashCode(mPorts);
+ result = 31 * result + Arrays.hashCode(mIpv6ServerIps);
+ result = 31 * result + Arrays.hashCode(mIpv6Ports);
+ return result;
+ }
+
+ public boolean updateIpv6(String[] ips, int[] ports) {
+ boolean same = CommonUtil.isSameServer(this.mIpv6ServerIps, this.mIpv6Ports, ips, ports);
+ if (same) {
+ return false;
+ }
+ this.mIpv6ServerIps = ips;
+ this.mIpv6Ports = ports;
+ return true;
+ }
+
+ public boolean updateRegionAndIpv4(String region, String[] ips, int[] ports) {
+ boolean same = CommonUtil.isSameServer(this.mServerIps, this.mPorts, ips, ports);
+ if (same && region.equals(this.mRegion)) {
+ return false;
+ }
+ this.mRegion = region;
+ this.mServerIps = ips;
+ this.mPorts = ports;
+ return true;
+ }
+
+
+ public boolean updateAll(String region, String[] ips, int[] ports, String[] ipv6s, int[] v6ports) {
+ boolean same = CommonUtil.isSameServer(this.mServerIps, this.mPorts, ips, ports);
+ boolean v6same = CommonUtil.isSameServer(this.mIpv6ServerIps, this.mIpv6Ports, ipv6s, v6ports);
+ if (same && v6same && region.equals(this.mRegion)) {
+ return false;
+ }
+ this.mRegion = region;
+ this.mServerIps = ips;
+ this.mPorts = ports;
+ this.mIpv6ServerIps = ipv6s;
+ this.mIpv6Ports = v6ports;
+ return true;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/ServerConfig.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/ServerConfig.java
new file mode 100644
index 0000000..648d8ac
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/ServerConfig.java
@@ -0,0 +1,393 @@
+package com.newsdk.sdk.android.httpdns.config;
+
+import java.util.Arrays;
+
+import com.newsdk.sdk.android.httpdns.impl.HttpDnsConfig;
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog;
+import com.newsdk.sdk.android.httpdns.utils.CommonUtil;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+import android.content.SharedPreferences;
+import android.text.TextUtils;
+
+/**
+ * 鏈嶅姟鑺傜偣閰嶇疆
+ * 缁存姢 鏈嶅姟鑺傜偣鐨勪竴浜涚姸鎬?
+ */
+public class ServerConfig extends RegionServer implements SpCacheItem {
+
+ private final HttpDnsConfig mHttpDnsConfig;
+ private int mLastOkServerIndex = 0;
+ private int mCurrentServerIndex = 0;
+ private long mServerIpsLastUpdatedTime = 0;
+
+ private int mLastOkServerIndexForV6 = 0;
+ private int mCurrentServerIndexForV6 = 0;
+
+ public ServerConfig(HttpDnsConfig config, String[] serverIps, int[] ports, String[] ipv6ServerIps, int[] ipv6Ports) {
+ super(serverIps, ports, ipv6ServerIps, ipv6Ports, config.getRegion());
+ mHttpDnsConfig = config;
+ }
+
+ /**
+ * 鑾峰彇褰撳墠浣跨敤鐨勬湇鍔P
+ */
+ public String getServerIp() {
+ final String[] serverIps = getServerIps();
+ if (serverIps == null || mCurrentServerIndex >= serverIps.length
+ || mCurrentServerIndex < 0) {
+ return null;
+ }
+ return serverIps[mCurrentServerIndex];
+ }
+
+ /**
+ * 鑾峰彇褰撳墠浣跨敤鐨勬湇鍔P ipv6
+ */
+ public String getServerIpForV6() {
+ final String[] serverIps = getIpv6ServerIps();
+ if (serverIps == null || mCurrentServerIndexForV6 >= serverIps.length
+ || mCurrentServerIndexForV6 < 0) {
+ return null;
+ }
+ return serverIps[mCurrentServerIndexForV6];
+ }
+
+ /**
+ * 鑾峰彇褰撳墠浣跨敤鐨勬湇鍔$鍙?
+ */
+ public int getPort() {
+ final int[] ports = getPorts();
+ if (ports == null || mCurrentServerIndex >= ports.length || mCurrentServerIndex < 0) {
+ return CommonUtil.getPort(-1, mHttpDnsConfig.getSchema());
+ }
+ return CommonUtil.getPort(ports[mCurrentServerIndex], mHttpDnsConfig.getSchema());
+ }
+
+ /**
+ * 鑾峰彇褰撳墠浣跨敤鐨勬湇鍔$鍙?
+ */
+ public int getPortForV6() {
+ final int[] ports = getIpv6Ports();
+ if (ports == null || mCurrentServerIndexForV6 >= ports.length
+ || mCurrentServerIndexForV6 < 0) {
+ return CommonUtil.getPort(-1, mHttpDnsConfig.getSchema());
+ }
+ return CommonUtil.getPort(ports[mCurrentServerIndexForV6], mHttpDnsConfig.getSchema());
+ }
+
+ /**
+ * 鏄惁搴旇鏇存柊鏈嶅姟IP
+ */
+ public boolean shouldUpdateServerIp() {
+ return System.currentTimeMillis() - mServerIpsLastUpdatedTime >= 24 * 60 * 60 * 1000;
+ }
+
+ /**
+ * 璁剧疆鏈嶅姟IP
+ *
+ * @return false 琛ㄧず 鍓嶅悗鏈嶅姟涓€鐩达紝娌℃湁鏇存柊
+ */
+ public synchronized boolean setServerIps(String region, String[] serverIps, int[] ports,
+ String[] serverV6Ips, int[] v6Ports) {
+ region = CommonUtil.fixRegion(region);
+ if (serverIps == null || serverIps.length == 0) {
+ serverIps = mHttpDnsConfig.getInitServer().getServerIps();
+ ports = mHttpDnsConfig.getInitServer().getPorts();
+ }
+ if (serverV6Ips == null || serverV6Ips.length == 0) {
+ serverV6Ips = mHttpDnsConfig.getInitServer().getIpv6ServerIps();
+ v6Ports = mHttpDnsConfig.getInitServer().getIpv6Ports();
+ }
+ boolean changed = updateRegionAndIpv4(region, serverIps, ports);
+ boolean v6changed = updateIpv6(serverV6Ips, v6Ports);
+ if (changed) {
+ this.mLastOkServerIndex = 0;
+ this.mCurrentServerIndex = 0;
+ }
+ if (v6changed) {
+ this.mLastOkServerIndexForV6 = 0;
+ this.mCurrentServerIndexForV6 = 0;
+ }
+ if (!CommonUtil.isSameServer(serverIps, ports,
+ mHttpDnsConfig.getInitServer().getServerIps(),
+ mHttpDnsConfig.getInitServer().getPorts())
+ || !CommonUtil.isSameServer(serverV6Ips, v6Ports,
+ mHttpDnsConfig.getInitServer().getIpv6ServerIps(),
+ mHttpDnsConfig.getInitServer().getIpv6Ports())) {
+ // 闈炲垵濮嬪寲IP锛屾墠璁や负鏄湡姝g殑鏇存柊浜嗘湇鍔P
+ this.mServerIpsLastUpdatedTime = System.currentTimeMillis();
+ // 闈炲垵濮婭P鎵嶆湁缂撳瓨鐨勫繀瑕?
+ mHttpDnsConfig.saveToCache();
+ }
+ return changed || v6changed;
+ }
+
+ public synchronized void updateServerIpv4sRank(String[] sortedIps, int[] ports) {
+ String[] serverIps = getServerIps();
+ int[] serverPorts = getPorts();
+ String region = getRegion();
+
+ //瀵规瘮鍜屽綋鍓嶇殑region server鏄惁鏄悓涓€鎵癸紝閬垮厤娴嬮€熷畬宸茬粡琚洿鏂?
+ if (serverIps.length != sortedIps.length) {
+ //ip鏁伴噺涓嶄竴鑷达紝鏁版嵁宸茬粡琚洿鏂?
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("abort rank server ip count changed, current ips: " + Arrays.toString(serverIps)
+ + ", sorted ips: " + Arrays.toString(sortedIps));
+ }
+ return;
+ }
+
+ boolean contain;
+ //濡傛灉鎺掑簭鐨刬p閮藉湪褰撳墠Server ip鍒楄〃涓紝璁や负鏄竴鎵规湇鍔p锛宨p鍜岀鍙i渶瑕佷竴璧峰垽鏂?
+ for (int i = 0; i != sortedIps.length; ++i) {
+ contain = isContainServiceIp(serverIps, serverPorts, sortedIps[i], ports == null ? -1 : ports[i]);
+ if (!contain) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("abort rank server ip as changed, current ips: " + Arrays.toString(serverIps)
+ + ", ports: " + Arrays.toString(serverPorts)
+ + ", sorted ips: " + Arrays.toString(sortedIps)
+ + ", ports: " + Arrays.toString(ports)
+ );
+ }
+
+ return;
+ }
+ }
+
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("update ranked server ips: " + Arrays.toString(sortedIps)
+ + ", ports: " + Arrays.toString(ports));
+ }
+ //浠呮洿鏂板唴瀛?
+ boolean changed = updateRegionAndIpv4(region, sortedIps, ports);
+ if (changed) {
+ this.mLastOkServerIndex = 0;
+ this.mCurrentServerIndex = 0;
+ }
+ }
+
+ public synchronized void updateServerIpv6sRank(String[] sortedIps, int[] ports) {
+ //鍜屽綋鍓峣p杩涜瀵规瘮锛岀湅鐪嬫槸涓嶆槸宸茬粡琚洿鏂颁簡锛屽鏋滆鏇存柊浜嗛偅姝ゆ鎺掑簭缁撴灉涓嶄娇鐢?
+ String[] serverIps = getIpv6ServerIps();
+ int[] serverPorts = getIpv6Ports();
+
+ //瀵规瘮鍜屽綋鍓嶇殑region server鏄惁鏄悓涓€鎵癸紝閬垮厤娴嬮€熷畬宸茬粡琚洿鏂?
+ if (serverIps.length != sortedIps.length) {
+ //ip鏁伴噺涓嶄竴鑷达紝鏁版嵁宸茬粡琚洿鏂?
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("abort rank server ip count changed, current ipv6s: " + Arrays.toString(serverIps)
+ + ", sorted ipv6s: " + Arrays.toString(sortedIps));
+ }
+ return;
+ }
+
+ boolean contain;
+ //濡傛灉鎺掑簭鐨刬p閮藉湪褰撳墠Server ip鍒楄〃涓紝璁や负鏄竴鎵规湇鍔p
+ for (int i = 0; i != sortedIps.length; ++i) {
+ contain = isContainServiceIp(serverIps, serverPorts, sortedIps[i], ports == null ? -1 : ports[i]);
+ if (!contain) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("abort rank server ip as changed, current ipv6s: " + Arrays.toString(serverIps)
+ + ", ports: " + Arrays.toString(serverPorts)
+ + ", sorted ipv6s: " + Arrays.toString(sortedIps)
+ + ", ports: " + Arrays.toString(ports)
+ );
+ }
+
+ return;
+ }
+ }
+
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("update ranked server ipv6s: " + Arrays.toString(sortedIps)
+ + ", ports: " + Arrays.toString(ports));
+ }
+
+ //浠呮洿鏂板唴瀛?
+ boolean v6changed = updateIpv6(sortedIps, ports);
+ if (v6changed) {
+ mLastOkServerIndexForV6 = 0;
+ mCurrentServerIndexForV6 = 0;
+ }
+ }
+
+ private boolean isContainServiceIp(String[] sourceIps, int[] sourcePorts, String targetIp, int targetPort) {
+ if (sourceIps == null || sourceIps.length == 0) {
+ return false;
+ }
+
+ for (int i = 0; i != sourceIps.length; ++i) {
+ if (TextUtils.equals(sourceIps[i], targetIp)) {
+ if (sourcePorts == null) {
+ return targetPort <= 0;
+ }
+
+ if (i < sourcePorts.length) {
+ if (sourcePorts[i] == targetPort) {
+ return true;
+ }
+ } else {
+ if (targetPort <= 0) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * 鍒囨崲鍩熷悕瑙f瀽鏈嶅姟
+ *
+ * @param ip 璇锋眰澶辫触鐨勬湇鍔P
+ * @param port 璇锋眰澶辫触鐨勬湇鍔$鍙?
+ * @return 鏄惁鍒囨崲鍥炰簡鏈€寮€濮嬬殑鏈嶅姟銆傚綋璇锋眰鍒囨崲鐨刬p鍜宲ort涓嶆槸褰撳墠ip鍜宲ort鏃讹紝璇存槑杩欎釜鍒囨崲璇锋眰鏄棤鏁堢殑锛屼笉鍒囨崲锛岃繑鍥瀎alse 璁や负娌℃湁鍒囨崲鍥炴渶寮€濮嬬殑ip
+ */
+ public boolean shiftServer(String ip, int port) {
+ return shiftServerV4(ip, port);
+ }
+
+ private boolean shiftServerV4(String ip, int port) {
+ final String[] serverIps = getServerIps();
+ final int[] ports = getPorts();
+ if (serverIps == null) {
+ return false;
+ }
+ if (!(ip.equals(serverIps[mCurrentServerIndex]) && (ports == null
+ || ports[mCurrentServerIndex] == port))) {
+ return false;
+ }
+ mCurrentServerIndex++;
+ if (mCurrentServerIndex >= serverIps.length) {
+ mCurrentServerIndex = 0;
+ }
+ return mCurrentServerIndex == mLastOkServerIndex;
+ }
+
+ public boolean shiftServerV6(String ip, int port) {
+ final String[] serverIps = getIpv6ServerIps();
+ final int[] ports = getIpv6Ports();
+ if (serverIps == null) {
+ return false;
+ }
+ if (!(ip.equals(serverIps[mCurrentServerIndexForV6]) && (ports == null
+ || ports[mCurrentServerIndexForV6] == port))) {
+ return false;
+ }
+ mCurrentServerIndexForV6++;
+ if (mCurrentServerIndexForV6 >= serverIps.length) {
+ mCurrentServerIndexForV6 = 0;
+ }
+ return mCurrentServerIndexForV6 == mLastOkServerIndexForV6;
+ }
+
+ /**
+ * 鏍囪褰撳墠濂界敤鐨勫煙鍚嶈В鏋愭湇鍔?
+ *
+ * @return 鏍囪鎴愬姛涓庡惁
+ */
+ public boolean markOkServer(String serverIp, int port) {
+ final String[] serverIps = getServerIps();
+ final int[] ports = getPorts();
+ if (serverIps == null) {
+ return false;
+ }
+ if (serverIps[mCurrentServerIndex].equals(serverIp) && (ports == null
+ || ports[mCurrentServerIndex] == port)) {
+ if (mLastOkServerIndex != mCurrentServerIndex) {
+ mLastOkServerIndex = mCurrentServerIndex;
+ mHttpDnsConfig.saveToCache();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 鏍囪褰撳墠濂界敤鐨勫煙鍚嶈В鏋愭湇鍔?
+ *
+ * @return 鏍囪鎴愬姛涓庡惁
+ */
+ public boolean markOkServerV6(String serverIp, int port) {
+ final String[] serverIps = getIpv6ServerIps();
+ final int[] ports = getIpv6Ports();
+ if (serverIps == null) {
+ return false;
+ }
+ if (serverIps[mCurrentServerIndexForV6].equals(serverIp) && (ports == null
+ || ports[mCurrentServerIndexForV6] == port)) {
+ if (mLastOkServerIndexForV6 != mCurrentServerIndexForV6) {
+ mLastOkServerIndexForV6 = mCurrentServerIndexForV6;
+ mHttpDnsConfig.saveToCache();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {return true;}
+ if (o == null || getClass() != o.getClass()) {return false;}
+ if (!super.equals(o)) {return false;}
+ ServerConfig that = (ServerConfig)o;
+ return mLastOkServerIndex == that.mLastOkServerIndex &&
+ mCurrentServerIndex == that.mCurrentServerIndex &&
+ mLastOkServerIndexForV6 == that.mLastOkServerIndexForV6 &&
+ mCurrentServerIndexForV6 == that.mCurrentServerIndexForV6 &&
+ mServerIpsLastUpdatedTime == that.mServerIpsLastUpdatedTime &&
+ mHttpDnsConfig.equals(that.mHttpDnsConfig);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(
+ new Object[] {super.hashCode(), mHttpDnsConfig, mLastOkServerIndex,
+ mCurrentServerIndex,
+ mLastOkServerIndexForV6, mCurrentServerIndexForV6, mServerIpsLastUpdatedTime});
+ }
+
+ @Override
+ public void restoreFromCache(SharedPreferences sp) {
+ String cachedServerRegion = sp.getString(Constants.CONFIG_CURRENT_SERVER_REGION,
+ getRegion());
+ //鍒濆鍖杛egion鍜岀紦瀛榮erver region涓€鑷寸殑鎯呭喌锛屼娇鐢ㄧ紦瀛樼殑鏈嶅姟IP銆傚惁鍒欏垵濮嬪寲鐨剅egion浼樺厛绾ф洿楂?
+ if (CommonUtil.regionEquals(cachedServerRegion, getRegion())) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("restore service ip of " + (TextUtils.isEmpty(cachedServerRegion) ? "default" : cachedServerRegion));
+ }
+ String[] serverIps = CommonUtil.parseStringArray(sp.getString(Constants.CONFIG_KEY_SERVERS,
+ CommonUtil.translateStringArray(getServerIps())));
+ int[] ports = CommonUtil.parsePorts(
+ sp.getString(Constants.CONFIG_KEY_PORTS, CommonUtil.translateIntArray(getPorts())));
+ String[] serverV6Ips = CommonUtil.parseStringArray(
+ sp.getString(Constants.CONFIG_KEY_SERVERS_IPV6,
+ CommonUtil.translateStringArray(getIpv6ServerIps())));
+ int[] v6Ports = CommonUtil.parsePorts(sp.getString(Constants.CONFIG_KEY_PORTS_IPV6,
+ CommonUtil.translateIntArray(getIpv6Ports())));
+
+ updateAll(cachedServerRegion, serverIps, ports, serverV6Ips, v6Ports);
+ mServerIpsLastUpdatedTime = sp.getLong(Constants.CONFIG_SERVERS_LAST_UPDATED_TIME, 0);
+ }
+ }
+
+ @Override
+ public void saveToCache(SharedPreferences.Editor editor) {
+ editor.putString(Constants.CONFIG_KEY_SERVERS,
+ CommonUtil.translateStringArray(getServerIps()));
+ editor.putString(Constants.CONFIG_KEY_PORTS, CommonUtil.translateIntArray(getPorts()));
+ editor.putInt(Constants.CONFIG_CURRENT_INDEX, mCurrentServerIndex);
+ editor.putInt(Constants.CONFIG_LAST_INDEX, mLastOkServerIndex);
+ editor.putString(Constants.CONFIG_KEY_SERVERS_IPV6,
+ CommonUtil.translateStringArray(getIpv6ServerIps()));
+ editor.putString(Constants.CONFIG_KEY_PORTS_IPV6,
+ CommonUtil.translateIntArray(getIpv6Ports()));
+ editor.putInt(Constants.CONFIG_CURRENT_INDEX_IPV6, mCurrentServerIndexForV6);
+ editor.putInt(Constants.CONFIG_LAST_INDEX_IPV6, mLastOkServerIndexForV6);
+ editor.putLong(Constants.CONFIG_SERVERS_LAST_UPDATED_TIME, mServerIpsLastUpdatedTime);
+ editor.putString(Constants.CONFIG_CURRENT_SERVER_REGION, getRegion());
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/SpCacheItem.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/SpCacheItem.java
new file mode 100644
index 0000000..936baa2
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/SpCacheItem.java
@@ -0,0 +1,10 @@
+package com.newsdk.sdk.android.httpdns.config;
+
+import android.content.SharedPreferences;
+
+public interface SpCacheItem {
+ void restoreFromCache(SharedPreferences sp);
+
+ void saveToCache(SharedPreferences.Editor editor);
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/AmericaRegionServer.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/AmericaRegionServer.java
new file mode 100644
index 0000000..e0f3f88
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/AmericaRegionServer.java
@@ -0,0 +1,33 @@
+package com.newsdk.sdk.android.httpdns.config.region;
+
+import com.newsdk.sdk.android.httpdns.config.RegionServer;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+public class AmericaRegionServer {
+ private static final String [] SERVER_IPS = new String [] {
+ "47.246.131.175",
+ "47.246.131.141"
+ };
+ private static final int[] PORTS = null;
+ private static final String[] IPV6_SERVER_IPS = new String [] {
+ "2404:2280:4000::2bb",
+ "2404:2280:4000::23e"
+ };
+ private static final int[] IPV6_PORTS = null;
+
+ private static final String[] UPDATE_SERVER = new String[] {
+ "resolvers-us.httpdns.Newcs.com"
+ };
+ private static final String[] IPV6_UPDATE_SERVER = new String[] {
+ "resolvers-us.httpdns.Newcs.com"
+ };
+
+ public static RegionServer getInitServer() {
+ return new RegionServer(SERVER_IPS, PORTS, IPV6_SERVER_IPS, IPV6_PORTS, Constants.REGION_US);
+ }
+
+ public static RegionServer getUpdateServer() {
+ return new RegionServer(UPDATE_SERVER, Constants.NO_PORTS, IPV6_UPDATE_SERVER, Constants.NO_PORTS, Constants.REGION_US);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/DefaultRegionServer.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/DefaultRegionServer.java
new file mode 100644
index 0000000..1b918b7
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/DefaultRegionServer.java
@@ -0,0 +1,39 @@
+package com.newsdk.sdk.android.httpdns.config.region;
+
+import com.newsdk.sdk.android.httpdns.config.RegionServer;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+public final class DefaultRegionServer {
+ private static final String [] SERVER_IPS = new String [] {
+ "203.107.1.1",
+ "203.107.1.97",
+ "203.107.1.100",
+ "203.119.238.240",
+ "106.11.25.239",
+ "59.82.99.47"
+ };
+ private static final int[] PORTS = null;
+ private static final String[] IPV6_SERVER_IPS = new String [] {
+ "2401:b180:7001::31d",
+ "2408:4003:1f40::30a",
+ "2401:b180:2000:20::10",
+ "2401:b180:2000:30::1c"
+ };
+ private static final int[] IPV6_PORTS = null;
+
+ private static final String[] UPDATE_SERVER = new String[] {
+ "resolvers-cn.httpdns.Newcs.com"
+ };
+ private static final String[] IPV6_UPDATE_SERVER = new String[] {
+ "resolvers-cn.httpdns.Newcs.com"
+ };
+
+ public static RegionServer getInitServer() {
+ return new RegionServer(SERVER_IPS, PORTS, IPV6_SERVER_IPS, IPV6_PORTS, Constants.REGION_DEFAULT);
+ }
+
+ public static RegionServer getUpdateServer() {
+ return new RegionServer(UPDATE_SERVER, Constants.NO_PORTS, IPV6_UPDATE_SERVER, Constants.NO_PORTS, Constants.REGION_DEFAULT);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/GermanyRegionServer.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/GermanyRegionServer.java
new file mode 100644
index 0000000..bd0fac3
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/GermanyRegionServer.java
@@ -0,0 +1,34 @@
+package com.newsdk.sdk.android.httpdns.config.region;
+
+import com.newsdk.sdk.android.httpdns.config.RegionServer;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+public class GermanyRegionServer {
+ private static final String [] SERVER_IPS = new String [] {
+ "47.89.80.182",
+ "47.246.146.77"
+ };
+ private static final int[] PORTS = null;
+
+ private static final String[] IPV6_SERVER_IPS = new String [] {
+ "2404:2280:3000::176",
+ "2404:2280:3000::188"
+ };
+ private static final int[] IPV6_PORTS = null;
+
+ private static final String[] UPDATE_SERVER = new String[] {
+ "resolvers-de.httpdns.Newcs.com"
+ };
+ private static final String[] IPV6_UPDATE_SERVER = new String[] {
+ "resolvers-de.httpdns.Newcs.com"
+ };
+
+ public static RegionServer getInitServer() {
+ return new RegionServer(SERVER_IPS, PORTS, IPV6_SERVER_IPS, IPV6_PORTS, Constants.REGION_DE);
+ }
+
+ public static RegionServer getUpdateServer() {
+ return new RegionServer(UPDATE_SERVER, Constants.NO_PORTS, IPV6_UPDATE_SERVER, Constants.NO_PORTS, Constants.REGION_DE);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/HongKongRegionServer.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/HongKongRegionServer.java
new file mode 100644
index 0000000..70146bc
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/HongKongRegionServer.java
@@ -0,0 +1,33 @@
+package com.newsdk.sdk.android.httpdns.config.region;
+
+import com.newsdk.sdk.android.httpdns.config.RegionServer;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+public class HongKongRegionServer {
+ private static final String[] SERVER_IPS = new String[] {
+ "47.56.234.194",
+ "47.56.119.115"
+ };
+ private static final int[] PORTS = null;
+ private static final String[] IPV6_SERVER_IPS = new String[] {
+ "240b:4000:f10::178",
+ "240b:4000:f10::188"
+ };
+ private static final int[] IPV6_PORTS = null;
+
+ private static final String[] UPDATE_SERVER = new String[] {
+ "resolvers-hk.httpdns.Newcs.com"
+ };
+ private static final String[] IPV6_UPDATE_SERVER = new String[] {
+ "resolvers-hk.httpdns.Newcs.com"
+ };
+
+ public static RegionServer getInitServer() {
+ return new RegionServer(SERVER_IPS, PORTS, IPV6_SERVER_IPS, IPV6_PORTS, Constants.REGION_HK);
+ }
+
+ public static RegionServer getUpdateServer() {
+ return new RegionServer(UPDATE_SERVER, Constants.NO_PORTS, IPV6_UPDATE_SERVER, Constants.NO_PORTS, Constants.REGION_HK);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/PreReleaseRegionServer.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/PreReleaseRegionServer.java
new file mode 100644
index 0000000..ddddcfe
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/PreReleaseRegionServer.java
@@ -0,0 +1,31 @@
+package com.newsdk.sdk.android.httpdns.config.region;
+
+import com.newsdk.sdk.android.httpdns.config.RegionServer;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+public class PreReleaseRegionServer {
+ private static final String [] SERVER_IPS = new String [] {
+ "106.11.190.18"
+ };
+ private static final int[] PORTS = null;
+ private static final String[] IPV6_SERVER_IPS = new String [] {
+ "resolvers-cn-pre.httpdns.Newcs.com"
+ };
+ private static final int[] IPV6_PORTS = null;
+
+ private static final String[] UPDATE_SERVER = new String[] {
+ "resolvers-cn-pre.httpdns.Newcs.com"
+ };
+ private static final String[] IPV6_UPDATE_SERVER = new String[] {
+ "resolvers-cn-pre.httpdns.Newcs.com"
+ };
+
+ public static RegionServer getInitServer() {
+ return new RegionServer(SERVER_IPS, PORTS, IPV6_SERVER_IPS, IPV6_PORTS, Constants.REGION_DEBUG_PRE);
+ }
+
+ public static RegionServer getUpdateServer() {
+ return new RegionServer(UPDATE_SERVER, Constants.NO_PORTS, IPV6_UPDATE_SERVER, Constants.NO_PORTS, Constants.REGION_DEBUG_PRE);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/RegionServerManager.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/RegionServerManager.java
new file mode 100644
index 0000000..3943da7
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/RegionServerManager.java
@@ -0,0 +1,77 @@
+package com.newsdk.sdk.android.httpdns.config.region;
+
+import com.newsdk.sdk.android.httpdns.config.RegionServer;
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+public class RegionServerManager {
+ public static RegionServer getInitServer(String region) {
+ RegionServer regionServer = null;
+ switch (region) {
+ case Constants.REGION_HK:
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("use hk region");
+ }
+ regionServer = HongKongRegionServer.getInitServer();
+ break;
+ case Constants.REGION_SG:
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("use sg region");
+ }
+ regionServer = SingaporeRegionServer.getInitServer();
+ break;
+ case Constants.REGION_DE:
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("use de region");
+ }
+ regionServer = GermanyRegionServer.getInitServer();
+ break;
+ case Constants.REGION_US:
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("use us region");
+ }
+ regionServer = AmericaRegionServer.getInitServer();
+ break;
+ case Constants.REGION_DEBUG_PRE:
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("use pre region");
+ }
+ regionServer = PreReleaseRegionServer.getInitServer();
+ break;
+ default:
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("use default region");
+ }
+ regionServer = DefaultRegionServer.getInitServer();
+ break;
+ }
+
+ return regionServer;
+ }
+
+ public static RegionServer getUpdateServer(String region) {
+ RegionServer regionServer = null;
+ switch (region) {
+ case Constants.REGION_HK:
+ regionServer = HongKongRegionServer.getUpdateServer();
+ break;
+ case Constants.REGION_SG:
+ regionServer = SingaporeRegionServer.getUpdateServer();
+ break;
+ case Constants.REGION_DE:
+ regionServer = GermanyRegionServer.getUpdateServer();
+ break;
+ case Constants.REGION_US:
+ regionServer = AmericaRegionServer.getUpdateServer();
+ break;
+ case Constants.REGION_DEBUG_PRE:
+ regionServer = PreReleaseRegionServer.getUpdateServer();
+ break;
+ default:
+ regionServer = DefaultRegionServer.getUpdateServer();
+ }
+
+ return regionServer;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/SingaporeRegionServer.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/SingaporeRegionServer.java
new file mode 100644
index 0000000..1679600
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/config/region/SingaporeRegionServer.java
@@ -0,0 +1,33 @@
+package com.newsdk.sdk.android.httpdns.config.region;
+
+import com.newsdk.sdk.android.httpdns.config.RegionServer;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+public class SingaporeRegionServer {
+ private static final String[] SERVER_IPS = new String[] {
+ "161.117.200.122",
+ "47.74.222.190"
+ };
+ private static final int[] PORTS = null;
+ private static final String[] IPV6_SERVER_IPS = new String[] {
+ "240b:4000:f10::178",
+ "240b:4000:f10::188"
+ };
+ private static final int[] IPV6_PORTS = null;
+
+ private static final String[] UPDATE_SERVER = new String[] {
+ "resolvers-sg.httpdns.Newcs.com"
+ };
+ private static final String[] IPV6_UPDATE_SERVER = new String[] {
+ "resolvers-sg.httpdns.Newcs.com"
+ };
+
+ public static RegionServer getInitServer() {
+ return new RegionServer(SERVER_IPS, PORTS, IPV6_SERVER_IPS, IPV6_PORTS, Constants.REGION_SG);
+ }
+
+ public static RegionServer getUpdateServer() {
+ return new RegionServer(UPDATE_SERVER, Constants.NO_PORTS, IPV6_UPDATE_SERVER, Constants.NO_PORTS, Constants.REGION_SG);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/exception/HttpDnsUncaughtExceptionHandler.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/exception/HttpDnsUncaughtExceptionHandler.java
new file mode 100644
index 0000000..a782b5b
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/exception/HttpDnsUncaughtExceptionHandler.java
@@ -0,0 +1,22 @@
+package com.newsdk.sdk.android.httpdns.exception;
+
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog;
+
+public class HttpDnsUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
+ // 澶勭悊鎵€鏈夋湭鎹曡幏寮傚父
+ public void uncaughtException(Thread thread, Throwable ex) {
+ try {
+ HttpDnsLog.e("Catch an uncaught exception, " + thread.getName() + ", error message: "
+ + ex.getMessage(), ex);
+ reportUncaughtError(ex);
+ ex.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void reportUncaughtError(Throwable ex) {
+
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/exception/InitException.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/exception/InitException.java
new file mode 100644
index 0000000..8edbefc
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/exception/InitException.java
@@ -0,0 +1,9 @@
+package com.newsdk.sdk.android.httpdns.exception;
+
+public class InitException extends RuntimeException {
+
+ public InitException(String msg) {
+ super(msg);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/AESEncryptService.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/AESEncryptService.java
new file mode 100644
index 0000000..01ace2d
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/AESEncryptService.java
@@ -0,0 +1,164 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import android.text.TextUtils;
+
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog;
+import com.newsdk.sdk.android.httpdns.utils.CommonUtil;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
+import java.util.Arrays;
+
+/**
+ * AES 加密解密工具类
+ * @author renwei
+ * @date 2025/3/26
+ */
+public class AESEncryptService {
+ private static final int GCM_IV_LENGTH = 12;
+ private static final int CBC_IV_LENGTH = 16;
+ private static final int GCM_TAG_LENGTH = 128;
+
+ private String aesSecretKey;
+
+ /**
+ * 加密方法
+ */
+ public String encrypt(String data, EncryptionMode mode) {
+ if (EncryptionMode.PLAIN == mode) {
+ return "";
+ }
+ if (TextUtils.isEmpty(aesSecretKey)) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("aesSecretKey为空");
+ }
+ return "";
+ }
+ if (TextUtils.isEmpty(data)) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("待加密数据为空");
+ }
+ return "";
+ }
+
+ // 生成IV
+ SecureRandom random = new SecureRandom();
+ byte[] iv = new byte[mode == EncryptionMode.AES_GCM ? GCM_IV_LENGTH : CBC_IV_LENGTH];
+ random.nextBytes(iv);
+
+ String encryptStr = "";
+ try {
+ byte[] encrypted = mode == EncryptionMode.AES_GCM ? aesGcmEncrypt(data, iv) : aesCbcEncrypt(data, iv);
+ // 组合IV和密文
+ byte[] combined = new byte[iv.length + encrypted.length];
+ System.arraycopy(iv, 0, combined, 0, iv.length);
+ System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length);
+ encryptStr = CommonUtil.encodeHexString(combined);
+ } catch (Exception e) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.e("加密失败, 加密内容:" + data);
+ }
+ }
+ return encryptStr;
+ }
+
+ private byte[] aesGcmEncrypt(String plainText, byte[] iv) throws Exception {
+ byte[] key = CommonUtil.decodeHex(aesSecretKey);
+ Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ SecretKey secretKey = new SecretKeySpec(key, "AES");
+ GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv); // 认证标签长度为 128 位
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey, spec);
+ return cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
+ }
+
+ private byte[] aesCbcEncrypt(String plainText, byte[] iv) throws Exception {
+ byte[] key = CommonUtil.decodeHex(aesSecretKey);
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //
+ SecretKey secretKey = new SecretKeySpec(key, "AES");
+ IvParameterSpec ivSpec = new IvParameterSpec(iv); // IV 必须为 16 字节
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
+ return cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
+ }
+
+ /**
+ * 解密方法
+ */
+ public String decrypt(String encryptData, EncryptionMode mode) {
+ if (EncryptionMode.PLAIN == mode) {
+ return encryptData;
+ }
+ if (TextUtils.isEmpty(aesSecretKey)) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("aesSecretKey为空");
+ }
+ return "";
+ }
+ if (TextUtils.isEmpty(encryptData)) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("待解密数据为空");
+ }
+ return "";
+ }
+ String plainData = "";
+ try {
+ byte[] binaryencrypted = CommonUtil.decodeBase64(encryptData);
+ plainData = EncryptionMode.AES_GCM == mode ? aesGcmDecrypt(binaryencrypted): aesCbcDecrypt(binaryencrypted);
+ } catch (Exception e) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.e("解密失败, 待解密数据: " + encryptData);
+ }
+ }
+ return plainData;
+ }
+
+ private String aesCbcDecrypt(byte[] binaryencrypted) throws Exception {
+ byte[] key = CommonUtil.decodeHex(aesSecretKey);
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
+ IvParameterSpec ivSpec = new IvParameterSpec(Arrays.copyOfRange(binaryencrypted, 0, 16));
+ cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
+ byte[] decrypted = cipher.doFinal(Arrays.copyOfRange(binaryencrypted, 16, binaryencrypted.length));
+ return new String(decrypted, StandardCharsets.UTF_8);
+ }
+
+ private String aesGcmDecrypt(byte[] binaryencrypted) throws Exception {
+ byte[] key = CommonUtil.decodeHex(aesSecretKey);
+ SecretKey secretKey = new SecretKeySpec(key, "AES");
+ Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, Arrays.copyOfRange(binaryencrypted, 0, 12)); // 认证标签长度为 128 位
+ cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);
+ byte[] decrypted = cipher.doFinal(Arrays.copyOfRange(binaryencrypted, 12, binaryencrypted.length));
+ return new String(decrypted, StandardCharsets.UTF_8);
+ }
+
+ public Boolean isEncryptionMode(){
+ return !TextUtils.isEmpty(aesSecretKey);
+ }
+
+ public void setAesSecretKey(String aesSecretKey) {
+ this.aesSecretKey = aesSecretKey;
+ }
+
+ public enum EncryptionMode {
+ PLAIN("0"), AES_CBC("1"), AES_GCM("2");
+
+ private final String mode;
+
+ EncryptionMode(String mode) {
+ this.mode = mode;
+ }
+
+ public String getMode(){
+ return mode;
+ }
+
+ }
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/ErrorImpl.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/ErrorImpl.java
new file mode 100644
index 0000000..b8d8ab7
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/ErrorImpl.java
@@ -0,0 +1,179 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import com.newsdk.sdk.android.httpdns.HTTPDNSResult;
+import com.newsdk.sdk.android.httpdns.HttpDnsCallback;
+import com.newsdk.sdk.android.httpdns.HttpDnsService;
+import com.newsdk.sdk.android.httpdns.Region;
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+import com.newsdk.sdk.android.httpdns.SyncService;
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class ErrorImpl implements HttpDnsService, SyncService {
+
+ @Override
+ public void setPreResolveHosts(List hostList) {
+
+ }
+
+ @Override
+ public void setPreResolveHosts(List hostList, RequestIpType requestIpType) {
+
+ }
+
+ @Override
+ public String getIpByHostAsync(String host) {
+ HttpDnsLog.w("init error");
+ return null;
+ }
+
+ @Override
+ public String getIPv4ForHostAsync(String host) {
+ return null;
+ }
+
+ @Override
+ public String[] getIpsByHostAsync(String host) {
+ HttpDnsLog.w("init error");
+ return new String[0];
+ }
+
+ @Override
+ public String[] getIPv4ListForHostAsync(String host) {
+ return new String[0];
+ }
+
+ @Override
+ public String[] getIPv6sByHostAsync(String host) {
+ HttpDnsLog.w("init error");
+ return new String[0];
+ }
+
+ @Override
+ public String[] getIPv6ListForHostASync(String host) {
+ return new String[0];
+ }
+
+ @Override
+ public HTTPDNSResult getAllByHostAsync(String host) {
+ HttpDnsLog.w("init error");
+ return Constants.EMPTY;
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostAsync(String host) {
+ return Constants.EMPTY;
+ }
+
+ @Override
+ public HTTPDNSResult getIpsByHostAsync(String host, RequestIpType type) {
+ return Constants.EMPTY;
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostAsync(String host, RequestIpType type) {
+ return Constants.EMPTY;
+ }
+
+ @Override
+ public void setAuthCurrentTime(long time) {
+
+ }
+
+ @Override
+ public String getSessionId() {
+ return null;
+ }
+
+ @Override
+ public HTTPDNSResult getIpsByHostAsync(String host, Map params,
+ String cacheKey) {
+ HttpDnsLog.w("init error");
+ return Constants.EMPTY;
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostAsync(String host, Map params,
+ String cacheKey) {
+ return Constants.EMPTY;
+ }
+
+ @Override
+ public HTTPDNSResult getIpsByHostAsync(String host, RequestIpType type,
+ Map params, String cacheKey) {
+ HttpDnsLog.w("init error");
+ return Constants.EMPTY;
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostAsync(String host, RequestIpType type,
+ Map params, String cacheKey) {
+ return Constants.EMPTY;
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostSync(String host, RequestIpType type, Map params, String cacheKey) {
+ return Constants.EMPTY;
+ }
+
+ @Override
+ public void getHttpDnsResultForHostAsync(String host, RequestIpType type, Map params, String cacheKey, HttpDnsCallback callback) {
+
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostSyncNonBlocking(String host, RequestIpType type, Map params, String cacheKey) {
+ return Constants.EMPTY;
+ }
+
+ @Override
+ public void setRegion(String region) {
+
+ }
+
+ @Override
+ public void setRegion(Region region) {
+
+ }
+
+ @Override
+ public String getIPv6ByHostAsync(String host) {
+ HttpDnsLog.w("init error");
+ return null;
+ }
+
+ @Override
+ public String getIPv6ForHostAsync(String host) {
+ return null;
+ }
+
+ @Override
+ public HTTPDNSResult getByHost(String host, RequestIpType type) {
+ HttpDnsLog.w("init error");
+ return Constants.EMPTY;
+ }
+
+ @Override
+ public void cleanHostCache(ArrayList hosts) {
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostSync(String host, RequestIpType type) {
+ return Constants.EMPTY;
+ }
+
+ @Override
+ public void getHttpDnsResultForHostAsync(String host, RequestIpType type, HttpDnsCallback callback) {
+
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostSyncNonBlocking(String host, RequestIpType type) {
+ return Constants.EMPTY;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HostResolveLocker.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HostResolveLocker.java
new file mode 100644
index 0000000..4b90e9d
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HostResolveLocker.java
@@ -0,0 +1,162 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+
+public class HostResolveLocker {
+
+ private static class Recorder {
+ private final HashSet mV4ResolvingHost = new HashSet<>();
+ private final HashSet mV6ResolvingHost = new HashSet<>();
+ private final HashSet mBothResolvingHost = new HashSet<>();
+ private final HashMap mV4Latchs = new HashMap<>();
+ private final HashMap mV6Latchs = new HashMap<>();
+ private final HashMap mBothLatchs = new HashMap<>();
+ private final Object mLock = new Object();
+
+ public boolean beginResolve(String host, RequestIpType type) {
+
+ if (type == RequestIpType.both) {
+ if (mBothResolvingHost.contains(host)) {
+ // 姝e湪瑙f瀽
+ return false;
+ } else {
+ synchronized (mLock) {
+ if (mBothResolvingHost.contains(host)) {
+ // 姝e湪瑙f瀽
+ return false;
+ } else {
+ mBothResolvingHost.add(host);
+ createLatch(host, mBothLatchs);
+ return true;
+ }
+ }
+ }
+ } else if (type == RequestIpType.v4) {
+ if (mV4ResolvingHost.contains(host)) {
+ return false;
+ } else {
+ synchronized (mLock) {
+ if (mV4ResolvingHost.contains(host)) {
+ return false;
+ } else {
+ mV4ResolvingHost.add(host);
+ createLatch(host, mV4Latchs);
+ return true;
+ }
+ }
+ }
+ } else if (type == RequestIpType.v6) {
+ if (mV6ResolvingHost.contains(host)) {
+ return false;
+ } else {
+ synchronized (mLock) {
+ if (mV6ResolvingHost.contains(host)) {
+ return false;
+ } else {
+ mV6ResolvingHost.add(host);
+ createLatch(host, mV6Latchs);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private void createLatch(String host, HashMap latchs) {
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ latchs.put(host, countDownLatch);
+ }
+
+ private void countDownLatch(String host, HashMap latchs) {
+ CountDownLatch latch = latchs.get(host);
+ if (latch != null) {
+ latch.countDown();
+ }
+ }
+
+ private CountDownLatch getLatch(String host, RequestIpType type) {
+ switch (type) {
+ case v4:
+ return mV4Latchs.get(host);
+ case v6:
+ return mV6Latchs.get(host);
+ case both:
+ return mBothLatchs.get(host);
+ }
+ return null;
+ }
+
+ public void endResolve(String host, RequestIpType type) {
+ switch (type) {
+ case v4:
+ mV4ResolvingHost.remove(host);
+ countDownLatch(host, mV4Latchs);
+ break;
+ case v6:
+ mV6ResolvingHost.remove(host);
+ countDownLatch(host, mV6Latchs);
+ break;
+ case both:
+ mBothResolvingHost.remove(host);
+ countDownLatch(host, mBothLatchs);
+ break;
+ }
+ }
+
+ public boolean await(String host, RequestIpType type, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ CountDownLatch countDownLatch = getLatch(host, type);
+ if (countDownLatch != null) {
+ return countDownLatch.await(timeout, unit);
+ } else {
+ return true;
+ }
+ }
+ }
+
+ private final Object mLock = new Object();
+ private final Recorder mDefaultRecorder = new Recorder();
+ private final HashMap mRecorders = new HashMap<>();
+
+ public boolean beginResolve(String host, RequestIpType type, String cacheKey) {
+ Recorder recorder = getRecorder(cacheKey);
+ return recorder.beginResolve(host, type);
+ }
+
+ private Recorder getRecorder(String cacheKey) {
+ Recorder recorder;
+ if (cacheKey == null || cacheKey.isEmpty()) {
+ recorder = mDefaultRecorder;
+ } else {
+ recorder = mRecorders.get(cacheKey);
+ if (recorder == null) {
+ synchronized (mLock) {
+ recorder = mRecorders.get(cacheKey);
+ if (recorder == null) {
+ recorder = new Recorder();
+ mRecorders.put(cacheKey, recorder);
+ }
+ }
+ }
+ }
+ return recorder;
+ }
+
+ public void endResolve(String host, RequestIpType type, String cacheKey) {
+ Recorder recorder = getRecorder(cacheKey);
+ recorder.endResolve(host, type);
+ }
+
+ public boolean await(String host, RequestIpType type, String cacheKey, long timeout,
+ TimeUnit unit) throws InterruptedException {
+ Recorder recorder = getRecorder(cacheKey);
+ return recorder.await(host, type, timeout, unit);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HostResolveRecorder.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HostResolveRecorder.java
new file mode 100644
index 0000000..b51c814
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HostResolveRecorder.java
@@ -0,0 +1,120 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import java.util.HashMap;
+import java.util.HashSet;
+
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+
+public class HostResolveRecorder {
+ private static class Recorder {
+ private final HashSet mV4ResolvingHost = new HashSet<>();
+ private final HashSet mV6ResolvingHost = new HashSet<>();
+ private final HashSet mBothResolvingHost = new HashSet<>();
+ private final Object mLock = new Object();
+
+ public boolean beginResolve(String host, RequestIpType type) {
+
+ if (type == RequestIpType.both) {
+ if (mBothResolvingHost.contains(host) || (mV4ResolvingHost.contains(host)
+ && mV6ResolvingHost.contains(host))) {
+ // 姝e湪瑙f瀽
+ return false;
+ } else {
+ synchronized (mLock) {
+ if (mBothResolvingHost.contains(host) || (mV4ResolvingHost.contains(host)
+ && mV6ResolvingHost.contains(host))) {
+ // 姝e湪瑙f瀽
+ return false;
+ } else {
+ mBothResolvingHost.add(host);
+ return true;
+ }
+ }
+ }
+ } else if (type == RequestIpType.v4) {
+ if (mV4ResolvingHost.contains(host) || mBothResolvingHost.contains(host)) {
+ return false;
+ } else {
+ synchronized (mLock) {
+ if (mV4ResolvingHost.contains(host) || mBothResolvingHost.contains(host)) {
+ return false;
+ } else {
+ mV4ResolvingHost.add(host);
+ return true;
+ }
+ }
+ }
+ } else if (type == RequestIpType.v6) {
+ if (mV6ResolvingHost.contains(host) || mBothResolvingHost.contains(host)) {
+ return false;
+ } else {
+ synchronized (mLock) {
+ if (mV6ResolvingHost.contains(host) || mBothResolvingHost.contains(host)) {
+ return false;
+ } else {
+ mV6ResolvingHost.add(host);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public void endResolve(String host, RequestIpType type) {
+ switch (type) {
+ case v4:
+ mV4ResolvingHost.remove(host);
+ break;
+ case v6:
+ mV6ResolvingHost.remove(host);
+ break;
+ case both:
+ mBothResolvingHost.remove(host);
+ break;
+ }
+ }
+ }
+
+ private final Object mLock = new Object();
+ private final Recorder mDefaultRecorder = new Recorder();
+ private final HashMap mRecorderHashMap = new HashMap<>();
+
+ public boolean beginResolve(String host, RequestIpType type) {
+ return beginResolve(host, type, null);
+ }
+
+ public void endResolve(String host, RequestIpType type) {
+ endResolve(host, type, null);
+ }
+
+ public boolean beginResolve(String host, RequestIpType type, String cacheKey) {
+ Recorder recorder = getRecorder(cacheKey);
+ return recorder.beginResolve(host, type);
+ }
+
+ private Recorder getRecorder(String cacheKey) {
+ Recorder recorder = null;
+ if (cacheKey == null || cacheKey.isEmpty()) {
+ recorder = mDefaultRecorder;
+ } else {
+ recorder = mRecorderHashMap.get(cacheKey);
+ if (recorder == null) {
+ synchronized (mLock) {
+ recorder = mRecorderHashMap.get(cacheKey);
+ if (recorder == null) {
+ recorder = new Recorder();
+ mRecorderHashMap.put(cacheKey, recorder);
+ }
+ }
+ }
+ }
+ return recorder;
+ }
+
+ public void endResolve(String host, RequestIpType type, String cacheKey) {
+ Recorder recorder = getRecorder(cacheKey);
+ recorder.endResolve(host, type);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsConfig.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsConfig.java
new file mode 100644
index 0000000..bb6963d
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsConfig.java
@@ -0,0 +1,432 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import java.util.Arrays;
+import java.util.concurrent.ExecutorService;
+
+import com.newsdk.sdk.android.httpdns.BuildConfig;
+import com.newsdk.sdk.android.httpdns.HttpDnsSettings;
+import com.newsdk.sdk.android.httpdns.InitConfig;
+import com.newsdk.sdk.android.httpdns.config.ConfigCacheHelper;
+import com.newsdk.sdk.android.httpdns.config.RegionServer;
+import com.newsdk.sdk.android.httpdns.config.ServerConfig;
+import com.newsdk.sdk.android.httpdns.config.region.RegionServerManager;
+import com.newsdk.sdk.android.httpdns.config.SpCacheItem;
+import com.newsdk.sdk.android.httpdns.observable.ObservableConfig;
+import com.newsdk.sdk.android.httpdns.observable.ObservableConstants;
+import com.newsdk.sdk.android.httpdns.observable.ObservableManager;
+import com.newsdk.sdk.android.httpdns.request.HttpRequestConfig;
+import com.newsdk.sdk.android.httpdns.utils.CommonUtil;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+import com.newsdk.sdk.android.httpdns.utils.ThreadUtil;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.os.Build;
+
+/**
+ * httpdns鐨勯厤缃?
+ */
+public class HttpDnsConfig implements SpCacheItem {
+ private final Context mContext;
+ private boolean mEnabled = Constants.DEFAULT_SDK_ENABLE;
+ /**
+ * 鍒濆鏈嶅姟鑺傜偣
+ */
+ private RegionServer mInitServer;
+
+ /**
+ * 鍏滃簳鐨勮皟搴︽湇鍔P锛岀敤浜庡簲瀵瑰浗闄呯増鏈嶅姟IP鏈夊彲鑳戒笉绋冲畾鐨勬儏鍐?
+ */
+ private RegionServer mDefaultUpdateServer;
+
+ /**
+ * 褰撳墠鏈嶅姟鑺傜偣
+ */
+ private final ServerConfig mCurrentServer;
+
+ /**
+ * 鐢ㄦ埛鐨刟ccountId
+ */
+ private final String mAccountId;
+ /**
+ * 褰撳墠璇锋眰浣跨敤鐨剆chema
+ */
+ private String mSchema = Constants.DEFAULT_SCHEMA;
+ /**
+ * 褰撳墠region
+ */
+ private String mRegion;
+ /**
+ * 瓒呮椂鏃堕暱
+ */
+ private int mTimeout = Constants.DEFAULT_TIMEOUT;
+
+ /**
+ * 鏄惁绂佺敤鏈嶅姟锛屼互閬垮厤宕╂簝
+ */
+ private boolean mHitCrashDefend;
+ /**
+ * 鏄惁杩滅▼绂佺敤鏈嶅姟
+ */
+ private boolean mRemoteDisabled = false;
+ /**
+ * 鏄惁绂佺敤probe鑳藉姏
+ */
+ private boolean mIPRankingDisabled = false;
+ /**
+ * 鏄惁寮€鍚檷绾у埌Local Dns
+ */
+ private boolean mEnableDegradationLocalDns = Constants.DEFAULT_ENABLE_DEGRADATION_LOCAL_DNS;
+
+ /**
+ * 缃戠粶鎺㈡祴鎺ュ彛
+ */
+ private HttpDnsSettings.NetworkDetector mNetworkDetector = null;
+
+ private final ConfigCacheHelper mCacheHelper;
+
+ protected ExecutorService mWorker = ThreadUtil.createExecutorService();
+ protected ExecutorService mResolveWorker = ThreadUtil.createResolveExecutorService();
+ protected ExecutorService mDbWorker = ThreadUtil.createDBExecutorService();
+ private ObservableConfig mObservableConfig;
+ private ObservableManager mObservableManager;
+ private float mObservableSampleBenchMarks;
+ private String mBizTags;
+ private String mUA;
+
+ public HttpDnsConfig(Context context, String accountId, String secret) {
+ mContext = context;
+ mAccountId = accountId;
+ if (mContext != null) {
+ mUA = buildUA();
+ }
+
+ //region鎻愬墠璁剧疆
+ mRegion = getInitRegion(accountId);
+ mInitServer = RegionServerManager.getInitServer(mRegion);
+ mDefaultUpdateServer = RegionServerManager.getUpdateServer(mRegion);
+
+ mCurrentServer = new ServerConfig(this, mInitServer.getServerIps(), mInitServer.getPorts(), mInitServer.getIpv6ServerIps(), mInitServer.getIpv6Ports());
+ mObservableConfig = new ObservableConfig();
+ // 鍏堜粠缂撳瓨璇诲彇鏁版嵁锛屽啀璧嬪€糲acheHelper锛?閬垮厤鍦ㄨ鍙栫紦瀛樿繃绋嬩腑锛岃Е鍙戝啓缂撳瓨鎿嶄綔
+ ConfigCacheHelper helper = new ConfigCacheHelper();
+ if (context != null) {
+ helper.restoreFromCache(context, this);
+ }
+ mCacheHelper = helper;
+
+ mObservableManager = new ObservableManager(this, secret);
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ public String getAccountId() {
+ return mAccountId;
+ }
+
+ public ServerConfig getCurrentServer() {
+ return mCurrentServer;
+ }
+
+ public ObservableConfig getObservableConfig() {
+ return mObservableConfig;
+ }
+
+ public ObservableManager getObservableManager() {
+ return mObservableManager;
+ }
+
+ public float getObservableSampleBenchMarks() {
+ return mObservableSampleBenchMarks;
+ }
+
+ public void setObservableSampleBenchMarks(float benchMarks) {
+ if (mObservableSampleBenchMarks != benchMarks) {
+ mObservableSampleBenchMarks = benchMarks;
+ saveToCache();
+ }
+ }
+
+ public boolean isCurrentRegionMatch() {
+ return CommonUtil.regionEquals(mRegion, mCurrentServer.getRegion());
+ }
+
+ public boolean isAllInitServer() {
+ return mInitServer.serverEquals((RegionServer)mCurrentServer);
+ }
+
+ public String getRegion() {
+ return mRegion;
+ }
+
+ public boolean isEnabled() {
+ return mEnabled && !mHitCrashDefend && !mRemoteDisabled;
+ }
+
+ /**
+ * 鏄惁鍚敤httpdns
+ *
+ * 娉ㄦ剰鏄?姘镐箙绂佺敤锛屽洜涓虹紦瀛樼殑鍘熷洜锛屼竴鏃︾鐢紝灏辨病鏈夋満浼氬惎鐢ㄤ簡
+ */
+ public void setEnabled(boolean enabled) {
+ if (this.mEnabled != enabled) {
+ this.mEnabled = enabled;
+ saveToCache();
+ }
+ }
+
+ public int getTimeout() {
+ return mTimeout;
+ }
+
+ public void setTimeout(int timeout) {
+ if (this.mTimeout != timeout) {
+ this.mTimeout = timeout;
+ saveToCache();
+ }
+ }
+
+ public String getBizTags() {
+ return mBizTags;
+ }
+
+ public void setBizTags(String tags) {
+ mBizTags = tags;
+ }
+
+ public String getSchema() {
+ return mSchema;
+ }
+
+ public ExecutorService getWorker() {
+ return mWorker;
+ }
+
+ public ExecutorService getResolveWorker() {
+ return mResolveWorker;
+ }
+
+ public ExecutorService getDbWorker() {
+ return mDbWorker;
+ }
+
+ public void setWorker(ExecutorService worker) {
+ // 缁欐祴璇曚娇鐢?
+ this.mWorker = worker;
+ this.mDbWorker = worker;
+ mResolveWorker = worker;
+ }
+
+ /**
+ * 鍒囨崲https
+ *
+ * @return 閰嶇疆鏄惁鍙樺寲
+ */
+ public boolean setHTTPSRequestEnabled(boolean enabled) {
+ String oldSchema = mSchema;
+ if (enabled) {
+ mSchema = HttpRequestConfig.HTTPS_SCHEMA;
+ } else {
+ mSchema = HttpRequestConfig.HTTP_SCHEMA;
+ }
+ if (!mSchema.equals(oldSchema)) {
+ saveToCache();
+ }
+ return !mSchema.equals(oldSchema);
+ }
+
+ public void setEnableDegradationLocalDns(boolean enable) {
+ mEnableDegradationLocalDns = enable;
+ }
+
+ public boolean isEnableDegradationLocalDns() {
+ return mEnableDegradationLocalDns;
+ }
+
+ /**
+ * 璁剧疆鐢ㄦ埛鍒囨崲鐨剅egion
+ */
+ public boolean setRegion(String region) {
+ if (!mRegion.equals(region)) {
+ mRegion = region;
+ mInitServer = RegionServerManager.getInitServer(mRegion);
+ mDefaultUpdateServer = RegionServerManager.getUpdateServer(mRegion);
+ mCurrentServer.setServerIps(mRegion, mInitServer.getServerIps(), mInitServer.getPorts(), mInitServer.getIpv6ServerIps(), mInitServer.getIpv6Ports());
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 鑾峰彇ipv6鐨勬湇鍔¤妭鐐?
+ */
+ public String[] getIpv6ServerIps() {
+ return this.mCurrentServer.getIpv6ServerIps();
+ }
+
+ public RegionServer getInitServer() {
+ return this.mInitServer;
+ }
+
+ public RegionServer getDefaultUpdateServer() {
+ return mDefaultUpdateServer;
+ }
+
+ public String[] getDefaultIpv6UpdateServer() {
+ return mDefaultUpdateServer.getIpv6ServerIps();
+ }
+
+ public String getUA() {
+ return mUA;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {return true;}
+ if (o == null || getClass() != o.getClass()) {return false;}
+ HttpDnsConfig that = (HttpDnsConfig)o;
+ return mEnabled == that.mEnabled &&
+ mTimeout == that.mTimeout &&
+ mHitCrashDefend == that.mHitCrashDefend &&
+ mRemoteDisabled == that.mRemoteDisabled &&
+ mIPRankingDisabled == that.mIPRankingDisabled &&
+ CommonUtil.equals(mContext, that.mContext) &&
+ CommonUtil.equals(mInitServer, that.mInitServer) &&
+ CommonUtil.equals(mDefaultUpdateServer, that.mDefaultUpdateServer) &&
+ CommonUtil.equals(mCurrentServer, that.mCurrentServer) &&
+ CommonUtil.equals(mAccountId, that.mAccountId) &&
+ CommonUtil.equals(mSchema, that.mSchema) &&
+ CommonUtil.equals(mRegion, that.mRegion) &&
+ CommonUtil.equals(mCacheHelper, that.mCacheHelper) &&
+ CommonUtil.equals(mWorker, that.mWorker) &&
+ CommonUtil.equals(mResolveWorker, that.mResolveWorker) &&
+ CommonUtil.equals(mDbWorker, that.mDbWorker);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(
+ new Object[] {mContext, mEnabled, mInitServer, mDefaultUpdateServer, mCurrentServer,
+ mAccountId, mSchema, mRegion, mTimeout, mHitCrashDefend, mRemoteDisabled,
+ mIPRankingDisabled,
+ mCacheHelper, mWorker, mResolveWorker, mDbWorker});
+ }
+
+ /**
+ * 璁剧疆鍒濆鏈嶅姟IP
+ *
+ * 绾夸笂SDK 鍒濆鍖栨湇鍔P鏄唴缃啓姝荤殑銆?
+ * 鏈珹PI涓昏鐢ㄤ簬涓€浜涙祴璇曚唬鐮佷娇鐢?
+ *
+ */
+ public void setInitServers(String initRegion, String[] initIps, int[] initPorts,
+ String[] initIpv6s, int[] initV6Ports) {
+ this.mRegion = initRegion;
+ if (initIps == null) {
+ return;
+ }
+ String[] oldInitServerIps = this.mInitServer.getServerIps();
+ int[] oldInitPorts = this.mInitServer.getPorts();
+ String[] oldInitIpv6ServerIps = this.mInitServer.getIpv6ServerIps();
+ int[] oldInitIpv6Ports = this.mInitServer.getIpv6Ports();
+ this.mInitServer.updateAll(initRegion, initIps, initPorts, initIpv6s, initV6Ports);
+ if (mCurrentServer.getServerIps() == null
+ || mCurrentServer.getIpv6ServerIps() == null
+ || (CommonUtil.isSameServer(oldInitServerIps, oldInitPorts,
+ mCurrentServer.getServerIps(), mCurrentServer.getPorts())
+ && CommonUtil.isSameServer(oldInitIpv6ServerIps, oldInitIpv6Ports,
+ mCurrentServer.getIpv6ServerIps(), mCurrentServer.getIpv6Ports()))) {
+ mCurrentServer.setServerIps(initRegion, initIps, initPorts, initIpv6s, initV6Ports);
+ }
+ }
+
+ /**
+ * 璁剧疆鍏滃簳鐨勮皟搴P锛?
+ * 娴嬭瘯浠g爜浣跨敤
+ */
+ public void setDefaultUpdateServer(String[] ips, int[] ports) {
+ this.mDefaultUpdateServer.updateRegionAndIpv4(this.mInitServer.getRegion(), ips, ports);
+ }
+
+ public void setDefaultUpdateServerIpv6(String[] defaultServerIps, int[] ports) {
+ this.mDefaultUpdateServer.updateIpv6(defaultServerIps, ports);
+ }
+
+ public void crashDefend(boolean crashDefend) {
+ this.mHitCrashDefend = crashDefend;
+ }
+
+ public void remoteDisable(boolean disable) {
+ this.mRemoteDisabled = disable;
+ }
+
+ public void ipRankingDisable(boolean disable) {
+ this.mIPRankingDisabled = disable;
+ }
+
+ public boolean isIPRankingDisabled() {
+ return mIPRankingDisabled;
+ }
+
+ public HttpDnsSettings.NetworkDetector getNetworkDetector() {
+ return mNetworkDetector;
+ }
+
+ public void setNetworkDetector(HttpDnsSettings.NetworkDetector networkDetector) {
+ this.mNetworkDetector = networkDetector;
+ }
+
+ // 缂撳瓨鐩稿叧鐨?澶勭悊锛屾殏鏃舵斁杩欓噷
+
+ public void saveToCache() {
+ if (mCacheHelper != null && mContext != null) {
+ mCacheHelper.saveConfigToCache(mContext, this);
+ }
+ }
+
+ public SpCacheItem[] getCacheItem() {
+ return new SpCacheItem[] {this, mCurrentServer, mObservableConfig};
+ }
+
+ @Override
+ public void restoreFromCache(SharedPreferences sp) {
+ mEnabled = sp.getBoolean(Constants.CONFIG_ENABLE, Constants.DEFAULT_SDK_ENABLE);
+ mObservableSampleBenchMarks = sp.getFloat(Constants.CONFIG_OBSERVABLE_BENCH_MARKS, -1);
+ }
+
+ @Override
+ public void saveToCache(SharedPreferences.Editor editor) {
+ editor.putBoolean(Constants.CONFIG_ENABLE, mEnabled);
+ editor.putFloat(Constants.CONFIG_OBSERVABLE_BENCH_MARKS, mObservableSampleBenchMarks);
+ }
+
+ private String getInitRegion(String accountId) {
+ InitConfig config = InitConfig.getInitConfig(accountId);
+ if (config == null) {
+ return Constants.REGION_DEFAULT;
+ }
+
+ return CommonUtil.fixRegion(config.getRegion());
+ }
+
+ private String buildUA() {
+ if (mContext == null) {
+ return "";
+ }
+ String versionName = ObservableConstants.UNKNOWN;
+ try {
+ versionName = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName;
+ } catch (PackageManager.NameNotFoundException e) {
+
+ }
+
+ return Build.BRAND + "/" + Build.MODEL
+ + ";" + "Android" + "/" + Build.VERSION.RELEASE
+ + ";" + mContext.getPackageName() + "/" + versionName
+ + ";" + "HTTPDNS" + "/" + BuildConfig.VERSION_NAME;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsCreator.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsCreator.java
new file mode 100644
index 0000000..abe7f6a
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsCreator.java
@@ -0,0 +1,13 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import android.content.Context;
+
+import com.newsdk.sdk.android.httpdns.HttpDnsService;
+
+/**
+ * httpdns鏈嶅姟鍒涘缓鎺ュ彛
+ */
+public interface HttpDnsCreator {
+ HttpDnsService create(Context context, String accountId, String secretKey);
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsInstanceHolder.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsInstanceHolder.java
new file mode 100644
index 0000000..5f24bf0
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsInstanceHolder.java
@@ -0,0 +1,43 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import android.content.Context;
+
+import com.newsdk.sdk.android.httpdns.HttpDnsService;
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog;
+
+import java.util.HashMap;
+
+/**
+ * HttpDnsService 瀹炰緥鎸佹湁鑰?
+ */
+public class HttpDnsInstanceHolder {
+
+ private final HttpDnsCreator mHttpDnsCreator;
+ private final HashMap mInstances;
+ private final ErrorImpl mError = new ErrorImpl();
+
+
+ public HttpDnsInstanceHolder(HttpDnsCreator creator) {
+ this.mHttpDnsCreator = creator;
+ mInstances = new HashMap<>();
+ }
+
+ public HttpDnsService get(Context context, String account, String secretKey) {
+ if (account == null || account.equals("")) {
+ HttpDnsLog.e("init httpdns with emtpy account!!");
+ return mError;
+ }
+ HttpDnsService service = mInstances.get(account);
+ if (service == null) {
+
+ service = mHttpDnsCreator.create(context, account, secretKey);
+ mInstances.put(account, service);
+ } else {
+ if (service instanceof HttpDnsServiceImpl) {
+ ((HttpDnsServiceImpl) service).setSecret(secretKey);
+ }
+ }
+ return service;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsServiceImpl.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsServiceImpl.java
new file mode 100644
index 0000000..30de84b
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/HttpDnsServiceImpl.java
@@ -0,0 +1,959 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.alibaba.sdk.android.crashdefend.CrashDefendApi;
+import com.alibaba.sdk.android.crashdefend.CrashDefendCallback;
+import com.newsdk.sdk.android.httpdns.BuildConfig;
+import com.newsdk.sdk.android.httpdns.HTTPDNSResult;
+import com.newsdk.sdk.android.httpdns.HttpDnsCallback;
+import com.newsdk.sdk.android.httpdns.HttpDnsService;
+import com.newsdk.sdk.android.httpdns.HttpDnsSettings;
+import com.newsdk.sdk.android.httpdns.InitConfig;
+import com.newsdk.sdk.android.httpdns.Region;
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+import com.newsdk.sdk.android.httpdns.SyncService;
+import com.newsdk.sdk.android.httpdns.cache.RecordDBHelper;
+import com.newsdk.sdk.android.httpdns.observable.ObservableConstants;
+import com.newsdk.sdk.android.httpdns.observable.event.CleanHostCacheEvent;
+import com.newsdk.sdk.android.httpdns.resolve.HostFilter;
+import com.newsdk.sdk.android.httpdns.resolve.ResolveHostCache;
+import com.newsdk.sdk.android.httpdns.resolve.ResolveHostCacheGroup;
+import com.newsdk.sdk.android.httpdns.resolve.ResolveHostRequestHandler;
+import com.newsdk.sdk.android.httpdns.resolve.ResolveHostResultRepo;
+import com.newsdk.sdk.android.httpdns.resolve.ResolveHostService;
+import com.newsdk.sdk.android.httpdns.resolve.BatchResolveHostService;
+import com.newsdk.sdk.android.httpdns.HTTPDNSResultWrapper;
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog;
+import com.newsdk.sdk.android.httpdns.net.HttpDnsNetworkDetector;
+import com.newsdk.sdk.android.httpdns.net.NetworkStateManager;
+import com.newsdk.sdk.android.httpdns.ranking.IPRankingService;
+import com.newsdk.sdk.android.httpdns.serverip.RegionServerScheduleService;
+import com.newsdk.sdk.android.httpdns.serverip.RegionServerScheduleService.OnRegionServerIpUpdate;
+import com.newsdk.sdk.android.httpdns.serverip.ranking.RegionServerRankingService;
+import com.newsdk.sdk.android.httpdns.track.SessionTrackMgr;
+import com.newsdk.sdk.android.httpdns.utils.CommonUtil;
+import com.newsdk.sdk.android.httpdns.utils.Constants;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Looper;
+import android.text.TextUtils;
+
+/**
+ * 鍩熷悕瑙f瀽鏈嶅姟 httpdns鎺ュ彛鐨勫疄鐜?
+ */
+public class HttpDnsServiceImpl implements HttpDnsService, OnRegionServerIpUpdate,
+ NetworkStateManager.OnNetworkChange, SyncService {
+
+ protected HttpDnsConfig mHttpDnsConfig;
+ private ResolveHostResultRepo mResultRepo;
+ protected ResolveHostRequestHandler mRequestHandler;
+ protected RegionServerScheduleService mScheduleService;
+ protected IPRankingService mIpIPRankingService;
+ protected RegionServerRankingService mRegionServerRankingService;
+ protected ResolveHostService mResolveHostService;
+ protected BatchResolveHostService mBatchResolveHostService;
+ private HostFilter mFilter;
+ private SignService mSignService;
+ private AESEncryptService mAESEncryptService;
+ private boolean resolveAfterNetworkChange = true;
+ private boolean mUseCustomServiceHosts = false;
+ /**
+ * crash defend 榛樿鍏抽棴
+ */
+ private boolean mCrashDefendEnabled = false;
+ public static Context sContext;
+
+ public HttpDnsServiceImpl(Context context, final String accountId, String secret) {
+ try {
+ InitConfig config = InitConfig.getInitConfig(accountId);
+ sContext = (config != null && config.getContext() != null) ? config.getContext() : context;
+ secret = (config != null && config.getSecretKey() != null) ? config.getSecretKey() : secret;
+ mHttpDnsConfig = new HttpDnsConfig(sContext, accountId, secret);
+ if (sContext == null) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.e("init httpdns with null context!!");
+ }
+ mHttpDnsConfig.setEnabled(false);
+ return;
+ }
+ mFilter = new HostFilter();
+ mSignService = new SignService(secret);
+ mAESEncryptService = new AESEncryptService();
+ mIpIPRankingService = new IPRankingService(this.mHttpDnsConfig);
+ mRegionServerRankingService = new RegionServerRankingService(mHttpDnsConfig);
+ mResultRepo = new ResolveHostResultRepo(this.mHttpDnsConfig, this.mIpIPRankingService,
+ new RecordDBHelper(this.mHttpDnsConfig.getContext(), this.mHttpDnsConfig.getAccountId()),
+ new ResolveHostCacheGroup());
+ mScheduleService = new RegionServerScheduleService(this.mHttpDnsConfig, this);
+ mRequestHandler = new ResolveHostRequestHandler(mHttpDnsConfig, mScheduleService,
+ mSignService, mAESEncryptService);
+ HostResolveLocker asyncLocker = new HostResolveLocker();
+ mResolveHostService = new ResolveHostService(this.mHttpDnsConfig,
+ mIpIPRankingService,
+ mRequestHandler, mResultRepo, mFilter, asyncLocker);
+ mBatchResolveHostService = new BatchResolveHostService(this.mHttpDnsConfig, mResultRepo,
+ mRequestHandler,
+ mIpIPRankingService, mFilter, asyncLocker);
+ mHttpDnsConfig.setNetworkDetector(HttpDnsNetworkDetector.getInstance());
+
+ beforeInit();
+
+ setupInitConfig(accountId);
+
+ if (mCrashDefendEnabled) {
+ initCrashDefend(sContext, mHttpDnsConfig);
+ }
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.w("init fail, crash defend");
+ return;
+ }
+ NetworkStateManager.getInstance().init(sContext);
+ NetworkStateManager.getInstance().addListener(this);
+
+ tryUpdateRegionServer(sContext, accountId);
+
+ if (!mUseCustomServiceHosts) {
+ mRegionServerRankingService.rankServiceIp(mHttpDnsConfig.getCurrentServer());
+ }
+ favorInit(sContext, accountId);
+
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("httpdns service is init " + accountId);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void setupInitConfig(final String accountId) {
+ InitConfig config = InitConfig.getInitConfig(accountId);
+
+ if (config != null) {
+ // 鍏堣缃拰缃戠粶鐩稿叧鐨勫唴瀹?
+ this.mHttpDnsConfig.setTimeout(config.getTimeout());
+ this.mHttpDnsConfig.setHTTPSRequestEnabled(config.isEnableHttps());
+ mHttpDnsConfig.setBizTags(config.getBizTags());
+ mHttpDnsConfig.setEnableDegradationLocalDns(config.isEnableDegradationLocalDns());
+ // 鍐嶈缃竴浜涘彲浠ユ彁鍓嶏紝娌℃湁鍓綔鐢ㄧ殑鍐呭
+ mResolveHostService.setEnableExpiredIp(config.isEnableExpiredIp());
+ if (config.getIPRankingList() != null) {
+ mIpIPRankingService.setIPRankingList(config.getIPRankingList());
+ }
+ // 璁剧疆region 蹇呴』鍦?璇诲彇缂撳瓨涔嬪墠銆?.4.1鐗堟湰寮€濮媟egion鍒濆鍖栨彁鍓嶅埌HttpDnsConfig鍒濆鍖?
+
+ // 璁剧疆 涓荤珯鍩熷悕 闇€瑕佸湪 璇诲彇缂撳瓨涔嬪墠
+ this.mResultRepo.setHostListWhichIpFixed(config.getHostListWithFixedIp());
+ // 璁剧疆缂撳瓨鎺у埗锛屽苟璇诲彇缂撳瓨
+ mResultRepo.setCachedIPEnabled(config.isEnableCacheIp(), config.getExpiredThresholdMillis());
+ this.mResultRepo.setCacheTtlChanger(config.getCacheTtlChanger());
+ resolveAfterNetworkChange = config.isResolveAfterNetworkChange();
+
+ if (config.getDegradationFilter() != null) {
+ mFilter.setFilter(config.getDegradationFilter());
+ }
+
+ if (config.getNotUseHttpDnsFilter() != null) {
+ mFilter.setFilter(config.getNotUseHttpDnsFilter());
+ }
+
+ mHttpDnsConfig.getObservableManager().positiveEnableObservable(config.isEnableObservable());
+
+ mCrashDefendEnabled = config.isEnableCrashDefend();
+
+ mRequestHandler.setSdnsGlobalParams(config.getSdnsGlobalParams());
+ mAESEncryptService.setAesSecretKey(config.getAesSecretKey());
+ applyCustomServiceHosts(config);
+ }
+
+ }
+
+ private void applyCustomServiceHosts(InitConfig config) {
+ String primaryHost = config.getPrimaryServiceHost();
+ String backupHost = config.getBackupServiceHost();
+ ArrayList hosts = new ArrayList<>();
+ if (!TextUtils.isEmpty(primaryHost)) {
+ hosts.add(primaryHost.trim());
+ }
+ if (!TextUtils.isEmpty(backupHost) && !backupHost.trim().equalsIgnoreCase(primaryHost == null ? "" : primaryHost.trim())) {
+ hosts.add(backupHost.trim());
+ }
+ if (hosts.isEmpty()) {
+ return;
+ }
+
+ String[] serverHosts = hosts.toArray(new String[0]);
+ int[] ports = new int[serverHosts.length];
+ int servicePort = config.getServicePort();
+ Arrays.fill(ports, servicePort > 0 ? servicePort : -1);
+
+ mHttpDnsConfig.setInitServers(mHttpDnsConfig.getRegion(), serverHosts, ports, serverHosts, ports);
+ mHttpDnsConfig.setDefaultUpdateServer(serverHosts, ports);
+ mHttpDnsConfig.setDefaultUpdateServerIpv6(serverHosts, ports);
+ mHttpDnsConfig.setHTTPSRequestEnabled(true);
+ mUseCustomServiceHosts = true;
+ }
+
+ protected void beforeInit() {
+ // only for test
+ }
+
+ protected void favorInit(Context context, String accountId) {
+ // for different favor init
+ }
+
+ protected void initCrashDefend(Context context, final HttpDnsConfig config) {
+ CrashDefendApi.registerCrashDefendSdk(context, "httpdns", BuildConfig.VERSION_NAME, 2, 7,
+ new CrashDefendCallback() {
+ @Override
+ public void onSdkStart(int limitCount, int crashCount, int restoreCount) {
+ config.crashDefend(false);
+ }
+
+ @Override
+ public void onSdkStop(int limitCount, int crashCount, int restoreCount,
+ long nextRestoreInterval) {
+ config.crashDefend(true);
+ HttpDnsLog.w("sdk is not safe to run");
+ }
+
+ @Override
+ public void onSdkClosed(int restoreCount) {
+ config.crashDefend(true);
+ HttpDnsLog.e("sdk will not run any more");
+ }
+ });
+ }
+
+ public void setSecret(String secret) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ return;
+ }
+ InitConfig config = InitConfig.getInitConfig(mHttpDnsConfig.getAccountId());
+ secret = (config != null && config.getSecretKey() != null) ? config.getSecretKey() : secret;
+ this.mSignService.setSecretKey(secret);
+ }
+
+ @Override
+ public void serverIpUpdated(boolean regionUpdated) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ return;
+ }
+ if (regionUpdated) {
+ mResultRepo.clearMemoryCache();
+ }
+ mRequestHandler.resetStatus();
+
+ //鏈嶅姟IP鏇存柊锛岃Е鍙戞湇鍔P娴嬮€?
+ if (!mUseCustomServiceHosts) {
+ mRegionServerRankingService.rankServiceIp(mHttpDnsConfig.getCurrentServer());
+ }
+ }
+
+ @Override
+ public void setPreResolveHosts(List hostList) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return;
+ }
+ if (hostList == null || hostList.size() == 0) {
+ HttpDnsLog.i("setPreResolveHosts empty list");
+ return;
+ }
+ setPreResolveHosts(hostList, RequestIpType.v4);
+ }
+
+ @Override
+ public void setPreResolveHosts(List hostList, RequestIpType requestIpType) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return;
+ }
+ if (hostList == null || hostList.size() == 0) {
+ HttpDnsLog.i("setPreResolveHosts empty list");
+ return;
+ }
+ requestIpType = changeTypeWithNetType(mHttpDnsConfig.getNetworkDetector(), requestIpType);
+ mBatchResolveHostService.batchResolveHostAsync(hostList, requestIpType);
+ }
+
+ @Override
+ public String getIpByHostAsync(String host) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return null;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return null;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return null;
+ }
+ String[] ips = getIPv4ListForHostAsync(host);
+ if (ips == null || ips.length == 0) {
+ return null;
+ }
+ return ips[0];
+ }
+
+ @Override
+ public String getIPv4ForHostAsync(String host) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return null;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return null;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return null;
+ }
+ String[] ips = getIPv4ListForHostAsync(host);
+ if (ips == null || ips.length == 0) {
+ return null;
+ }
+ return ips[0];
+ }
+
+ @Override
+ public String[] getIpsByHostAsync(final String host) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return new String[0];
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return new String[0];
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return new String[0];
+ }
+ return mResolveHostService.resolveHostSyncNonBlocking(host, RequestIpType.v4, null, getCurrentNetworkKey()).getIps();
+ }
+
+ @Override
+ public String[] getIPv4ListForHostAsync(String host) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return new String[0];
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return new String[0];
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return new String[0];
+ }
+ return mResolveHostService.resolveHostSyncNonBlocking(host, RequestIpType.v4, null, getCurrentNetworkKey()).getIps();
+ }
+
+ @Override
+ public String[] getIPv6sByHostAsync(String host) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return new String[0];
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return new String[0];
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return new String[0];
+ }
+ return mResolveHostService.resolveHostSyncNonBlocking(host, RequestIpType.v6, null, getCurrentNetworkKey())
+ .getIpv6s();
+ }
+
+ @Override
+ public String[] getIPv6ListForHostASync(String host) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return new String[0];
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return new String[0];
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return new String[0];
+ }
+ return mResolveHostService.resolveHostSyncNonBlocking(host, RequestIpType.v6, null, getCurrentNetworkKey())
+ .getIpv6s();
+ }
+
+ @Override
+ public HTTPDNSResult getAllByHostAsync(String host) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ return mResolveHostService.resolveHostSyncNonBlocking(host, RequestIpType.both, null, getCurrentNetworkKey());
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostAsync(String host) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ return mResolveHostService.resolveHostSyncNonBlocking(host, RequestIpType.both, null, getCurrentNetworkKey());
+ }
+
+ @Override
+ public HTTPDNSResult getIpsByHostAsync(String host, RequestIpType type) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ type = changeTypeWithNetType(mHttpDnsConfig.getNetworkDetector(), type);
+ return mResolveHostService.resolveHostSyncNonBlocking(host, type, null, getCurrentNetworkKey());
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostAsync(String host, RequestIpType type) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ type = changeTypeWithNetType(mHttpDnsConfig.getNetworkDetector(), type);
+ return mResolveHostService.resolveHostSyncNonBlocking(host, type, null, getCurrentNetworkKey());
+ }
+
+ @Override
+ public void setAuthCurrentTime(long time) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ return;
+ }
+ mSignService.setCurrentTimestamp(time);
+ }
+
+ @Override
+ public String getSessionId() {
+ return SessionTrackMgr.getInstance().getSessionId();
+ }
+
+ @Override
+ public HTTPDNSResult getIpsByHostAsync(String host, Map params,
+ String cacheKey) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ return mResolveHostService.resolveHostSyncNonBlocking(host, RequestIpType.v4, params, cacheKey);
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostAsync(String host, Map params,
+ String cacheKey) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ return mResolveHostService.resolveHostSyncNonBlocking(host, RequestIpType.v4, params, cacheKey);
+ }
+
+ @Override
+ public HTTPDNSResult getIpsByHostAsync(String host, RequestIpType type,
+ Map params, String cacheKey) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ type = changeTypeWithNetType(mHttpDnsConfig.getNetworkDetector(), type);
+ return mResolveHostService.resolveHostSyncNonBlocking(host, type, params, cacheKey);
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostAsync(String host, RequestIpType type,
+ Map params, String cacheKey) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ type = changeTypeWithNetType(mHttpDnsConfig.getNetworkDetector(), type);
+ return mResolveHostService.resolveHostSyncNonBlocking(host, type, params, cacheKey);
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostSync(String host, RequestIpType type, Map params, String cacheKey) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ type = changeTypeWithNetType(mHttpDnsConfig.getNetworkDetector(), type);
+ if (Looper.getMainLooper() == Looper.myLooper()) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("request in main thread, use async request");
+ }
+ return mResolveHostService.resolveHostSyncNonBlocking(host, type, null, getCurrentNetworkKey());
+ }
+ return mResolveHostService.resolveHostSync(host, type, params, cacheKey);
+ }
+
+ @Override
+ public void getHttpDnsResultForHostAsync(String host, RequestIpType type, Map params, String cacheKey, HttpDnsCallback callback) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ if (callback != null) {
+ callback.onHttpDnsCompleted(Constants.EMPTY);
+ }
+ return;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ if (callback != null) {
+ callback.onHttpDnsCompleted(Constants.EMPTY);
+ }
+ return;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ if (callback != null) {
+ callback.onHttpDnsCompleted(Constants.EMPTY);
+ }
+ return;
+ }
+
+ type = changeTypeWithNetType(mHttpDnsConfig.getNetworkDetector(), type);
+ mResolveHostService.resolveHostAsync(host, type, params, cacheKey, callback);
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostSyncNonBlocking(String host, RequestIpType type, Map params, String cacheKey) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ type = changeTypeWithNetType(mHttpDnsConfig.getNetworkDetector(), type);
+ return mResolveHostService.resolveHostSyncNonBlocking(host, type, params, cacheKey);
+ }
+
+ @Override
+ public void setRegion(String region) {
+ if (mUseCustomServiceHosts) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("ignore setRegion in custom service host mode");
+ }
+ return;
+ }
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return;
+ }
+ region = CommonUtil.fixRegion(region);
+ if (CommonUtil.regionEquals(this.mHttpDnsConfig.getRegion(), region)
+ && !this.mHttpDnsConfig.isAllInitServer()) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("region " + region + " is same, do not update serverIps");
+ }
+ return;
+ }
+ boolean changed = mHttpDnsConfig.setRegion(region);
+ if (changed) {
+ mResultRepo.clearMemoryCache();
+ //region鍙樺寲锛屾湇鍔P鍙樻垚瀵瑰簲鐨勯缃甀P锛岃Е鍙戞祴閫?
+ if (!mUseCustomServiceHosts) {
+ mRegionServerRankingService.rankServiceIp(mHttpDnsConfig.getCurrentServer());
+ }
+ }
+ if (!mUseCustomServiceHosts) {
+ mScheduleService.updateRegionServerIps(region, Constants.UPDATE_REGION_SERVER_SCENES_REGION_CHANGE);
+ }
+ }
+
+ @Override
+ public void setRegion(Region region) {
+ setRegion(region == null ? "" : region.getRegion());
+ }
+
+ @Override
+ public String getIPv6ByHostAsync(String host) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return null;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return null;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return null;
+ }
+ String[] ips = getIPv6sByHostAsync(host);
+ if (ips == null || ips.length == 0) {
+ return null;
+ }
+ return ips[0];
+ }
+
+ @Override
+ public String getIPv6ForHostAsync(String host) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return null;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return null;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return null;
+ }
+ String[] ips = getIPv6sByHostAsync(host);
+ if (ips == null || ips.length == 0) {
+ return null;
+ }
+ return ips[0];
+ }
+
+ @Override
+ public void onNetworkChange(String networkType) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ return;
+ }
+ try {
+ mHttpDnsConfig.getWorker().execute(new Runnable() {
+ @Override
+ public void run() {
+ // 鑾峰彇褰撳墠缃戠粶鏍囪瘑
+ String requestNetworkKey = getCurrentNetworkKey();
+
+ // 鑾峰彇鍘嗗彶鍩熷悕
+ HashMap allHost = mResultRepo.getAllHostWithoutFixedIP();
+
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("network change to " + requestNetworkKey + ", smart resolve hosts");
+ }
+
+ // 鏅鸿兘澧為噺瑙f瀽
+ if (resolveAfterNetworkChange && mHttpDnsConfig.isEnabled()) {
+ smartBatchResolve(allHost, requestNetworkKey);
+ }
+ }
+ });
+
+ //缃戠粶鍙樺寲锛岃Е鍙戞湇鍔P娴嬮€?
+ if (!mUseCustomServiceHosts) {
+ mRegionServerRankingService.rankServiceIp(mHttpDnsConfig.getCurrentServer());
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ @Override
+ public HTTPDNSResult getByHost(String host, RequestIpType type) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ type = changeTypeWithNetType(mHttpDnsConfig.getNetworkDetector(), type);
+ if (Looper.getMainLooper() == Looper.myLooper()) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("request in main thread, use async request");
+ }
+ return mResolveHostService.resolveHostSyncNonBlocking(host, type, null, getCurrentNetworkKey());
+ }
+ return mResolveHostService.resolveHostSync(host, type, null, getCurrentNetworkKey());
+ }
+
+ private RequestIpType changeTypeWithNetType(HttpDnsSettings.NetworkDetector networkDetector,
+ RequestIpType type) {
+ if (type == RequestIpType.auto) {
+ if (networkDetector != null) {
+ switch (networkDetector.getNetType(mHttpDnsConfig.getContext())) {
+ case v4:
+ return RequestIpType.v4;
+ default:
+ return RequestIpType.both;
+ }
+ }
+ return RequestIpType.both;
+ }
+ return type;
+ }
+
+ public void cleanHostCache(ArrayList hosts) {
+ CleanHostCacheEvent cleanHostCacheEvent = new CleanHostCacheEvent();
+ if (hosts == null || hosts.size() == 0) {
+ // 娓呯悊鎵€鏈塰ost
+ mResultRepo.clear();
+ cleanHostCacheEvent.setTag(ObservableConstants.CLEAN_ALL_HOST_CACHE);
+ } else {
+ // 娓呯悊閫変腑鐨刪ost
+ cleanHostCacheEvent.setTag(ObservableConstants.CLEAN_SPECIFY_HOST_CACHE);
+ mResultRepo.clear(hosts);
+ }
+ cleanHostCacheEvent.setStatusCode(200);
+ cleanHostCacheEvent.setCostTime((int) (System.currentTimeMillis() - cleanHostCacheEvent.getTimestamp()));
+ mHttpDnsConfig.getObservableManager().addObservableEvent(cleanHostCacheEvent);
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostSync(String host, RequestIpType type) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ type = changeTypeWithNetType(mHttpDnsConfig.getNetworkDetector(), type);
+ if (Looper.getMainLooper() == Looper.myLooper()) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("request in main thread, use async request");
+ }
+ return mResolveHostService.resolveHostSyncNonBlocking(host, type, null, getCurrentNetworkKey());
+ }
+ return mResolveHostService.resolveHostSync(host, type, null, getCurrentNetworkKey());
+ }
+
+ @Override
+ public void getHttpDnsResultForHostAsync(String host, RequestIpType type, HttpDnsCallback callback) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ if (callback != null) {
+ callback.onHttpDnsCompleted(Constants.EMPTY);
+ }
+ return;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ if (callback != null) {
+ callback.onHttpDnsCompleted(Constants.EMPTY);
+ }
+ return;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ if (callback != null) {
+ callback.onHttpDnsCompleted(Constants.EMPTY);
+ }
+ return;
+ }
+
+ type = changeTypeWithNetType(mHttpDnsConfig.getNetworkDetector(), type);
+
+ mResolveHostService.resolveHostAsync(host, type, null, getCurrentNetworkKey(), callback);
+ }
+
+ @Override
+ public HTTPDNSResult getHttpDnsResultForHostSyncNonBlocking(String host, RequestIpType type) {
+ if (!mHttpDnsConfig.isEnabled()) {
+ HttpDnsLog.i("service is disabled");
+ return Constants.EMPTY;
+ }
+ if (!CommonUtil.isAHost(host)) {
+ HttpDnsLog.i("host is invalid. " + host);
+ return Constants.EMPTY;
+ }
+ if (CommonUtil.isAnIP(host)) {
+ HttpDnsLog.i("host is ip. " + host);
+ return Constants.EMPTY;
+ }
+ type = changeTypeWithNetType(mHttpDnsConfig.getNetworkDetector(), type);
+ return mResolveHostService.resolveHostSyncNonBlocking(host, type, null, getCurrentNetworkKey());
+ }
+
+ private void tryUpdateRegionServer(Context context, String accountId) {
+ if (mUseCustomServiceHosts) {
+ return;
+ }
+
+ if (mHttpDnsConfig.getCurrentServer().shouldUpdateServerIp()) {
+ mScheduleService.updateRegionServerIps(Constants.UPDATE_REGION_SERVER_SCENES_INIT);
+ } else {
+ InitConfig config = InitConfig.getInitConfig(accountId);
+ String initRegion = Constants.REGION_DEFAULT;
+ if (config != null) {
+ initRegion = CommonUtil.fixRegion(config.getRegion());
+ }
+ SharedPreferences sp = context.getSharedPreferences(
+ Constants.CONFIG_CACHE_PREFIX + accountId, Context.MODE_PRIVATE);
+ String cachedRegion = sp.getString(Constants.CONFIG_CURRENT_SERVER_REGION,
+ Constants.REGION_DEFAULT);
+
+ if (!CommonUtil.regionEquals(cachedRegion, initRegion)) {
+ mScheduleService.updateRegionServerIps(Constants.UPDATE_REGION_SERVER_SCENES_REGION_CHANGE);
+ }
+ }
+ }
+
+ /**
+ * 鏅鸿兘澧為噺瑙f瀽锛氬彧瑙f瀽褰撳墠缃戠粶鐜涓嬬己澶辩殑鍩熷悕
+ *
+ * @param allHosts 鎵€鏈夊巻鍙插煙鍚?
+ * @param requestNetworkKey 璇锋眰鏃剁殑缃戠粶鏍囪瘑
+ */
+ private void smartBatchResolve(HashMap allHosts, String requestNetworkKey) {
+ ArrayList v4List = new ArrayList<>();
+ ArrayList v6List = new ArrayList<>();
+ ArrayList bothList = new ArrayList<>();
+
+ // 妫€鏌ュ綋鍓嶇綉缁滅幆澧冧笅鏄惁闇€瑕佽В鏋?
+ for (Map.Entry entry : allHosts.entrySet()) {
+ String host = entry.getKey();
+ RequestIpType type = entry.getValue();
+
+ // 浣跨敤璇锋眰鏃剁殑缃戠粶鏍囪瘑妫€鏌ョ紦瀛?
+ if (needsResolveInNetwork(host, type, requestNetworkKey)) {
+ if (type == RequestIpType.v4) {
+ v4List.add(host);
+ } else if (type == RequestIpType.v6) {
+ v6List.add(host);
+ } else {
+ bothList.add(host);
+ }
+ }
+ }
+
+ // 浣跨敤甯︾綉缁滄爣璇嗙殑鎵归噺瑙f瀽鏂规硶
+ if (v4List.size() > 0) {
+ mBatchResolveHostService.batchResolveHostAsync(v4List, RequestIpType.v4);
+ }
+ if (v6List.size() > 0) {
+ mBatchResolveHostService.batchResolveHostAsync(v6List, RequestIpType.v6);
+ }
+ if (bothList.size() > 0) {
+ mBatchResolveHostService.batchResolveHostAsync(bothList, RequestIpType.both);
+ }
+
+ if (v4List.size() > 0 || v6List.size() > 0 || bothList.size() > 0) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("smart resolve " + (v4List.size() + v6List.size() + bothList.size()) + " hosts for network " + requestNetworkKey);
+ }
+ }
+ }
+
+ /**
+ * 妫€鏌ユ寚瀹氱綉缁滅幆澧冧笅鏄惁闇€瑕佽В鏋愬煙鍚?
+ *
+ * @param host 鍩熷悕
+ * @param type 瑙f瀽绫诲瀷
+ * @param networkKey 缃戠粶鏍囪瘑
+ * @return 鏄惁闇€瑕佽В鏋?
+ */
+ private boolean needsResolveInNetwork(String host, RequestIpType type, String networkKey) {
+ // 妫€鏌ユ寚瀹氱綉缁滅幆澧冧笅鏄惁鏈夋湁鏁堢紦瀛?
+ ResolveHostCache cache = mResultRepo.getCacheGroup().getCache(networkKey);
+ HTTPDNSResultWrapper result = cache.getResult(host, type);
+ return result == null || result.isExpired();
+ }
+
+ /**
+ * 鑾峰彇褰撳墠缃戠粶鏍囪瘑锛岀敤浜庣綉缁滈殧绂荤紦瀛?
+ *
+ * @return 褰撳墠缃戠粶鏍囪瘑
+ */
+ private String getCurrentNetworkKey() {
+ return NetworkStateManager.getInstance().getCurrentNetworkKey();
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/SignService.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/SignService.java
new file mode 100644
index 0000000..b063a55
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/impl/SignService.java
@@ -0,0 +1,141 @@
+package com.newsdk.sdk.android.httpdns.impl;
+
+import android.text.TextUtils;
+
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog;
+
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+public class SignService {
+ private static final String ALGORITHM = "HmacSHA256";
+ public static final int EXPIRATION_TIME = 10 * 60;
+
+ private static final String SDNS_PREFIX = "sdns-";
+ private static final Set includeParamKeys = new HashSet<>();
+
+ private String mSecretKey;
+
+ private long mOffset = 0L;
+
+ public SignService(String secretKey) {
+ mSecretKey = secretKey;
+ includeParamKeys.addAll(Arrays.asList("id", "m", "dn", "cip", "q", "enc", "exp", "tags", "v"));
+ }
+
+ /**
+ * 设置密钥
+ */
+ public void setSecretKey(String secretKey) {
+ mSecretKey = secretKey;
+ }
+
+ /**
+ * 使用 HMAC-SHA256 生成十六进制格式的签名
+ */
+ public String sign(Map param) {
+ if (TextUtils.isEmpty(mSecretKey)) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("secretKey为空");
+ }
+ return "";
+ }
+
+ String signStr;
+ try {
+ signStr = generateV2SignContent(param);
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("signStr:" + signStr);
+ }
+ signStr = hmacSha256(signStr);
+ } catch (Exception e) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.e("sign fail.", e);
+ }
+ signStr = "";
+ }
+ return signStr;
+ }
+
+ /**
+ * 鏂扮増 /resolve 璇锋眰绛惧悕锛? * appId|lower(domain)|upper(qtype)|exp|nonce
+ */
+ public String signResolve(String appId, String domain, String qtype, String exp, String nonce) {
+ if (TextUtils.isEmpty(mSecretKey)
+ || TextUtils.isEmpty(appId)
+ || TextUtils.isEmpty(domain)
+ || TextUtils.isEmpty(qtype)
+ || TextUtils.isEmpty(exp)
+ || TextUtils.isEmpty(nonce)) {
+ return "";
+ }
+ String raw = appId + "|" + domain.toLowerCase() + "|" + qtype.toUpperCase() + "|" + exp + "|" + nonce;
+ try {
+ return hmacSha256(raw);
+ } catch (Exception e) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.e("sign resolve fail.", e);
+ }
+ return "";
+ }
+ }
+
+ private static String generateV2SignContent(Map map) {
+ Map sortedMap = new TreeMap<>();
+ for(Map.Entry entry : map.entrySet()) {
+ String paramKey = entry.getKey();
+ String paramValue = entry.getValue();
+ if (includeParamKeys.contains(paramKey) || paramKey.startsWith(SDNS_PREFIX)) {
+ if(!TextUtils.isEmpty(paramValue)) {
+ sortedMap.put(paramKey, paramValue);
+ }
+ }
+ }
+ StringBuilder signContent = new StringBuilder();
+ for (Map.Entry entry : sortedMap.entrySet()) {
+ if (signContent.length() > 0) {
+ signContent.append("&");
+ }
+ signContent.append(entry.getKey()).append("=").append(entry.getValue());
+ }
+ return signContent.toString();
+ }
+
+ private String hmacSha256(String content)
+ throws NoSuchAlgorithmException, InvalidKeyException {
+ Mac mac = Mac.getInstance(ALGORITHM);
+ mac.init(new SecretKeySpec(mSecretKey.getBytes(StandardCharsets.UTF_8), ALGORITHM));
+ byte[] signedBytes = mac.doFinal(content.getBytes(StandardCharsets.UTF_8));
+ StringBuilder sb = new StringBuilder(signedBytes.length * 2);
+ for (byte b : signedBytes) {
+ String h = Integer.toHexString(b & 0xff);
+ if (h.length() == 1) {
+ sb.append('0');
+ }
+ sb.append(h);
+ }
+ return sb.toString();
+ }
+
+ public void setCurrentTimestamp(long serverTime) {
+ mOffset = serverTime - System.currentTimeMillis() / 1000;
+ }
+
+ public String getExpireTime(){
+ return Long.toString(System.currentTimeMillis() / 1000 + EXPIRATION_TIME + mOffset);
+ }
+
+ public Boolean isSignMode(){
+ return !TextUtils.isEmpty(mSecretKey);
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/log/HttpDnsLog.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/log/HttpDnsLog.java
new file mode 100644
index 0000000..8754430
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/log/HttpDnsLog.java
@@ -0,0 +1,145 @@
+package com.newsdk.sdk.android.httpdns.log;
+
+import java.util.HashSet;
+
+import com.newsdk.sdk.android.httpdns.ILogger;
+
+import android.util.Log;
+
+/**
+ * 鏃ュ織宸ュ叿绫?
+ */
+public class HttpDnsLog {
+
+ public static final String TAG = "httpdns";
+ private static boolean printToLogcat = false;
+ private static final HashSet LOGGERS = new HashSet<>();
+
+ /**
+ * 璁剧疆鏃ュ織鎺ュ彛
+ * 涓嶅彈{@link #printToLogcat} 鎺у埗
+ */
+ public static void setLogger(ILogger logger) {
+ if (logger != null) {
+ LOGGERS.add(logger);
+ }
+ }
+
+ /**
+ * 绉婚櫎鏃ュ織鎺ュ彛
+ */
+ public static void removeLogger(ILogger logger) {
+ if (logger != null) {
+ LOGGERS.remove(logger);
+ }
+ }
+
+ /**
+ * logcat寮€鍏?
+ *
+ * @param enable
+ */
+ public static void enable(boolean enable) {
+ HttpDnsLog.printToLogcat = enable;
+ }
+
+ public static boolean isPrint() {
+ return HttpDnsLog.printToLogcat;
+ }
+
+ public static void e(String errLog) {
+ if (HttpDnsLog.printToLogcat) {
+ Log.e(TAG, errLog);
+ }
+ if (HttpDnsLog.LOGGERS.size() > 0) {
+ for (ILogger logger : HttpDnsLog.LOGGERS) {
+ logger.log("[E]" + errLog);
+ }
+ }
+ }
+
+ public static void i(String infoLog) {
+ if (HttpDnsLog.printToLogcat) {
+ Log.i(TAG, infoLog);
+ }
+ if (HttpDnsLog.LOGGERS.size() > 0) {
+ for (ILogger logger : HttpDnsLog.LOGGERS) {
+ logger.log("[I]" + infoLog);
+ }
+ }
+ }
+
+ public static void d(String debugLog) {
+ if (HttpDnsLog.printToLogcat) {
+ Log.d(TAG, debugLog);
+ }
+ if (HttpDnsLog.LOGGERS.size() > 0) {
+ for (ILogger logger : HttpDnsLog.LOGGERS) {
+ logger.log("[D]" + debugLog);
+ }
+ }
+ }
+
+ public static void w(String warnLog) {
+ if (HttpDnsLog.printToLogcat) {
+ Log.w(TAG, warnLog);
+ }
+ if (HttpDnsLog.LOGGERS.size() > 0) {
+ for (ILogger logger : HttpDnsLog.LOGGERS) {
+ logger.log("[W]" + warnLog);
+ }
+ }
+ }
+
+ public static void e(String errLog, Throwable throwable) {
+ if (HttpDnsLog.printToLogcat) {
+ Log.e(TAG, errLog, throwable);
+ }
+ if (HttpDnsLog.LOGGERS.size() > 0) {
+ for (ILogger logger : HttpDnsLog.LOGGERS) {
+ logger.log("[E]" + errLog);
+ }
+ printStackTrace(throwable);
+ }
+ }
+
+ public static void w(String warnLog, Throwable throwable) {
+ if (HttpDnsLog.printToLogcat) {
+ Log.e(TAG, warnLog, throwable);
+ }
+ if (HttpDnsLog.LOGGERS.size() > 0) {
+ for (ILogger logger : HttpDnsLog.LOGGERS) {
+ logger.log("[W]" + warnLog);
+ }
+ printStackTrace(throwable);
+ }
+ }
+
+ private static void printStackTrace(Throwable throwable) {
+ if (HttpDnsLog.LOGGERS.size() > 0) {
+ for (ILogger logger : HttpDnsLog.LOGGERS) {
+ logger.log(Log.getStackTraceString(throwable));
+ }
+ }
+ }
+
+ /**
+ * ip鏁扮粍杞垚瀛楃涓叉柟渚胯緭鍑?
+ *
+ * @param ips
+ * @return
+ */
+ public static String wrap(String[] ips) {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append("[");
+ for (int i = 0; i < ips.length; i++) {
+ if (i != 0) {
+ stringBuilder.append(",");
+ }
+ stringBuilder.append(ips[i]);
+ }
+ stringBuilder.append("]");
+ return stringBuilder.toString();
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/net/HttpDnsNetworkDetector.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/net/HttpDnsNetworkDetector.java
new file mode 100644
index 0000000..5f68794
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/net/HttpDnsNetworkDetector.java
@@ -0,0 +1,132 @@
+package com.newsdk.sdk.android.httpdns.net;
+
+import java.util.concurrent.ExecutorService;
+
+import com.newsdk.sdk.android.httpdns.HttpDnsSettings;
+import com.newsdk.sdk.android.httpdns.NetType;
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog;
+import com.newsdk.sdk.android.httpdns.utils.ThreadUtil;
+
+import android.content.Context;
+import com.aliyun.ams.ipdetector.Inet64Util;
+
+public class HttpDnsNetworkDetector implements HttpDnsSettings.NetworkDetector {
+
+ private static class Holder {
+ private static final HttpDnsNetworkDetector INSTANCE = new HttpDnsNetworkDetector();
+ }
+
+ public static HttpDnsNetworkDetector getInstance() {
+ return Holder.INSTANCE;
+ }
+
+ private HttpDnsNetworkDetector() {
+ }
+
+ private final ExecutorService mWorker = ThreadUtil.createSingleThreadService("NetType");
+ private boolean mCheckInterface = true;
+ private String mHostToCheckNetType = "www.taobao.com";
+ private NetType mCache = NetType.none;
+ private boolean mDisableCache = false;
+ private Context mContext;
+
+ /**
+ * 缃戠粶鍙樺寲鏃讹紝娓呴櫎缂撳瓨
+ */
+ public void cleanCache(final boolean connected) {
+ if (mDisableCache) {
+ return;
+ }
+ mCache = NetType.none;
+ if (connected && this.mContext != null) {
+ mWorker.execute(new Runnable() {
+ @Override
+ public void run() {
+ // 寮傛鎺㈡祴涓€涓?
+ if (mContext != null) {
+ mCache = detectNetType(mContext);
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * 鏄惁绂佺敤缂撳瓨锛岄粯璁や笉绂佺敤
+ * 涓嶇‘瀹氭槸鍚﹀瓨鍦ㄧ綉缁滈摼鎺ヤ笉鍙樼殑鎯呭喌涓嬶紝缃戠粶鎯呭喌浼氬彂鐢熷彉鍖栫殑鎯呭喌锛屾墍浠ユ彁渚涗簡姝ゅ紑鍏?
+ */
+ public void disableCache(boolean disable) {
+ this.mDisableCache = disable;
+ }
+
+ /**
+ * 濡傛灉涓嶈兘妫€鏌ユ湰鍦扮綉鍏砳p,鍙互璋冪敤姝ゆ帴鍙e叧闂?
+ */
+ public void setCheckInterface(boolean checkInterface) {
+ this.mCheckInterface = checkInterface;
+ }
+
+ /**
+ * 鏈変簺鍦烘櫙闇€瑕侀€氳繃鏈湴瑙f瀽鏉ョ‘璁ょ綉缁滅被鍨嬶紝榛樿浣跨敤 www.taobao.com
+ */
+ public void setHostToCheckNetType(String hostToCheckNetType) {
+ this.mHostToCheckNetType = hostToCheckNetType;
+ }
+
+ @Override
+ public NetType getNetType(Context context) {
+ if (mDisableCache) {
+ NetType tmp = detectNetType(context);
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("ipdetector type is " + tmp.name());
+ }
+ return tmp;
+ }
+ if (mCache != NetType.none) {
+ return mCache;
+ }
+ mCache = detectNetType(context);
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("ipdetector type is " + mCache.name());
+ }
+ return mCache;
+ }
+
+ private NetType detectNetType(Context context) {
+ this.mContext = context.getApplicationContext();
+ try {
+ int type;// 涓嶆鏌ユ湰鍦癐P鐨勬儏鍐典笅锛屾棤娉曡繃婊pv6鍙湁鏈湴ip鐨勬儏鍐碉紝闇€瑕侀€氳繃鍏跺畠鏂瑰紡妫€娴嬩笅銆?
+ // 娌℃湁缃戠粶锛?
+ if (mCheckInterface) {
+ type = Inet64Util.getIpStack(context);
+ } else {
+ type = Inet64Util.getIpStackCheckLocal(context);
+ }
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("ip detector type is " + type);
+ }
+ if (type == IP_DUAL_STACK) {
+ return NetType.both;
+ } else if (type == IPV4_ONLY) {
+ return NetType.v4;
+ } else if (type == IPV6_ONLY) {
+ return NetType.v6;
+ } else {
+ // 娌℃湁缃戠粶锛?
+ return NetType.none;
+ }
+
+ } catch (Throwable e) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.i("ip detector not exist.");
+ }
+ return NetType.none;
+ }
+ }
+
+ private final static int IPV4_ONLY = 1;
+ private final static int IPV6_ONLY = 2;
+ private final static int IP_DUAL_STACK = 3;
+
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/net/NetworkStateManager.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/net/NetworkStateManager.java
new file mode 100644
index 0000000..54b5ee7
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/net/NetworkStateManager.java
@@ -0,0 +1,238 @@
+package com.newsdk.sdk.android.httpdns.net;
+
+import java.util.ArrayList;
+import java.util.concurrent.ExecutorService;
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+
+import com.newsdk.sdk.android.httpdns.log.HttpDnsLog;
+import com.newsdk.sdk.android.httpdns.utils.ThreadUtil;
+
+import android.Manifest;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.Network;
+import android.net.LinkProperties;
+import android.net.LinkAddress;
+import android.os.Build;
+import android.os.Process;
+
+public class NetworkStateManager {
+ public static final String NONE_NETWORK = "None_Network";
+ private static final String NETWORK_KEY_PREFIX = "emasInner_";
+ private Context mContext;
+ private String mLastConnectedNetwork = NONE_NETWORK;
+ private volatile String mCurrentNetworkKey = NONE_NETWORK;
+ private final ArrayList mListeners = new ArrayList<>();
+
+ private final ExecutorService mWorker = ThreadUtil.createSingleThreadService("network");
+
+ private static class Holder {
+ private static final NetworkStateManager instance = new NetworkStateManager();
+ }
+
+ public static NetworkStateManager getInstance() {
+ return Holder.instance;
+ }
+
+ private NetworkStateManager() {
+ }
+
+ public void init(Context ctx) {
+ if (ctx == null) {
+ throw new IllegalStateException("Context can't be null");
+ }
+ if (this.mContext != null) {
+ // inited
+ return;
+ }
+ this.mContext = ctx.getApplicationContext();
+
+ // 绔嬪嵆妫€娴嬪綋鍓嶇綉缁滅姸鎬?
+ mWorker.execute(() -> {
+ try {
+ String currentNetwork = detectCurrentNetwork();
+ if (!currentNetwork.equals(NONE_NETWORK)) {
+ mLastConnectedNetwork = currentNetwork;
+ }
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("[NetworkStateManager.init] - Initial network detected: " + currentNetwork);
+ }
+ } catch (Exception e) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.e("[NetworkStateManager.init] - Failed to detect initial network", e);
+ }
+ }
+ });
+
+ BroadcastReceiver bcReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(final Context context, final Intent intent) {
+ try {
+ mWorker.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (isInitialStickyBroadcast()) { // no need to handle initial
+ // sticky broadcast
+ return;
+ }
+ String action = intent.getAction();
+ if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)
+ && hasNetInfoPermission(context)) {
+ String currentNetwork = detectCurrentNetwork();
+ HttpDnsNetworkDetector.getInstance().cleanCache(
+ !currentNetwork.equals(NONE_NETWORK));
+ if (!currentNetwork.equals(NONE_NETWORK)
+ && !currentNetwork.equalsIgnoreCase(mLastConnectedNetwork)) {
+ for (OnNetworkChange onNetworkChange : mListeners) {
+ onNetworkChange.onNetworkChange(currentNetwork);
+ }
+ }
+ if (!currentNetwork.equals(NONE_NETWORK)) {
+ mLastConnectedNetwork = currentNetwork;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ } catch (Exception ignored) {
+ }
+ }
+ };
+
+ try {
+ if (hasNetInfoPermission(mContext)) {
+ IntentFilter mFilter = new IntentFilter();
+ mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ mContext.registerReceiver(bcReceiver, mFilter);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String detectCurrentNetwork() {
+ try {
+ ConnectivityManager connectivityManager = (ConnectivityManager)mContext
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo info = connectivityManager.getActiveNetworkInfo();
+ if (info != null && info.isAvailable() && info.isConnected()) {
+ String name = info.getTypeName();
+
+ String ipPrefix = getLocalIpPrefix();
+ if (ipPrefix != null) {
+ name = name + "_" + ipPrefix;
+ }
+ // 澧炲姞鍓嶇紑锛岄槻姝笌鐢ㄦ埛cacheKey鍐茬獊
+ mCurrentNetworkKey = (name == null) ? NONE_NETWORK : (NETWORK_KEY_PREFIX + name);
+
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("[detectCurrentNetwork] - Network key:" + mCurrentNetworkKey + " subType "
+ + "name: "
+ + info.getSubtypeName());
+ }
+ return mCurrentNetworkKey;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ mCurrentNetworkKey = NONE_NETWORK;
+ return NONE_NETWORK;
+ }
+
+ private String getLocalIpPrefix() {
+ try {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ return null;
+ }
+
+ ConnectivityManager connectivityManager = (ConnectivityManager) mContext
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ Network activeNetwork = connectivityManager.getActiveNetwork();
+
+ if (activeNetwork == null) {
+ return null;
+ }
+
+ LinkProperties linkProperties = connectivityManager.getLinkProperties(activeNetwork);
+ if (linkProperties == null) {
+ return null;
+ }
+
+ String ipv6Backup = null;
+ for (LinkAddress linkAddress : linkProperties.getLinkAddresses()) {
+ InetAddress address = linkAddress.getAddress();
+ if (address.isLoopbackAddress() || address.isLinkLocalAddress()) {
+ continue;
+ }
+
+ if (address instanceof Inet4Address) {
+ String ip = address.getHostAddress();
+ String[] parts = ip.split("\\.");
+ if (parts.length >= 3) {
+ return parts[0] + "." + parts[1] + "." + parts[2];
+ }
+ } else if (address instanceof Inet6Address && ipv6Backup == null) {
+ String ipv6 = address.getHostAddress();
+ if (ipv6.contains("%")) {
+ ipv6 = ipv6.substring(0, ipv6.indexOf("%"));
+ }
+ String[] parts = ipv6.split(":");
+ if (parts.length >= 4) {
+ ipv6Backup = parts[0] + ":" + parts[1] + ":" + parts[2] + ":" + parts[3];
+ }
+ }
+ }
+ return ipv6Backup;
+ } catch (Exception e) {
+ if (HttpDnsLog.isPrint()) {
+ HttpDnsLog.d("[getLocalIpPrefix] - Failed to get IP prefix: " + e.getMessage());
+ }
+ }
+ return null;
+ }
+
+ public String getCurrentNetworkKey() {
+ return mCurrentNetworkKey;
+ }
+
+ public void addListener(OnNetworkChange change) {
+ this.mListeners.add(change);
+ }
+
+ public interface OnNetworkChange {
+ void onNetworkChange(String networkType);
+ }
+
+ public void reset() {
+ mContext = null;
+ mLastConnectedNetwork = NONE_NETWORK;
+ mCurrentNetworkKey = NONE_NETWORK;
+ mListeners.clear();
+ }
+
+ private static boolean hasNetInfoPermission(Context context) {
+ try {
+ return checkSelfPermission(context, Manifest.permission.ACCESS_NETWORK_STATE)
+ == PackageManager.PERMISSION_GRANTED;
+ } catch (Throwable e) {
+ HttpDnsLog.w("check network info permission fail", e);
+ }
+ return false;
+ }
+
+ private static int checkSelfPermission(Context context, String permission) {
+ return context.checkPermission(permission, Process.myPid(), Process.myUid());
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsAdapterException.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsAdapterException.java
new file mode 100644
index 0000000..ab775d9
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsAdapterException.java
@@ -0,0 +1,22 @@
+package com.newsdk.sdk.android.httpdns.network;
+
+import java.io.IOException;
+
+public class HttpDnsAdapterException extends IOException {
+ private final String errorCode;
+
+ public HttpDnsAdapterException(String errorCode, String message) {
+ super(message);
+ this.errorCode = errorCode;
+ }
+
+ public HttpDnsAdapterException(String errorCode, String message, Throwable cause) {
+ super(message, cause);
+ this.errorCode = errorCode;
+ }
+
+ public String getErrorCode() {
+ return errorCode;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsAdapterOptions.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsAdapterOptions.java
new file mode 100644
index 0000000..a800876
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsAdapterOptions.java
@@ -0,0 +1,71 @@
+package com.newsdk.sdk.android.httpdns.network;
+
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+
+public class HttpDnsAdapterOptions {
+ private final int connectTimeoutMillis;
+ private final int readTimeoutMillis;
+ private final boolean allowInsecureCertificatesForDebugOnly;
+ private final RequestIpType requestIpType;
+
+ private HttpDnsAdapterOptions(Builder builder) {
+ connectTimeoutMillis = builder.connectTimeoutMillis;
+ readTimeoutMillis = builder.readTimeoutMillis;
+ allowInsecureCertificatesForDebugOnly = builder.allowInsecureCertificatesForDebugOnly;
+ requestIpType = builder.requestIpType;
+ }
+
+ public int getConnectTimeoutMillis() {
+ return connectTimeoutMillis;
+ }
+
+ public int getReadTimeoutMillis() {
+ return readTimeoutMillis;
+ }
+
+ public boolean isAllowInsecureCertificatesForDebugOnly() {
+ return allowInsecureCertificatesForDebugOnly;
+ }
+
+ public RequestIpType getRequestIpType() {
+ return requestIpType;
+ }
+
+ public static class Builder {
+ private int connectTimeoutMillis = 3000;
+ private int readTimeoutMillis = 5000;
+ private boolean allowInsecureCertificatesForDebugOnly = false;
+ private RequestIpType requestIpType = RequestIpType.auto;
+
+ public Builder setConnectTimeoutMillis(int value) {
+ if (value > 0) {
+ connectTimeoutMillis = value;
+ }
+ return this;
+ }
+
+ public Builder setReadTimeoutMillis(int value) {
+ if (value > 0) {
+ readTimeoutMillis = value;
+ }
+ return this;
+ }
+
+ public Builder setAllowInsecureCertificatesForDebugOnly(boolean value) {
+ allowInsecureCertificatesForDebugOnly = value;
+ return this;
+ }
+
+ public Builder setRequestIpType(RequestIpType type) {
+ if (type != null) {
+ requestIpType = type;
+ }
+ return this;
+ }
+
+ public HttpDnsAdapterOptions build() {
+ return new HttpDnsAdapterOptions(this);
+ }
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsAdapterRequest.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsAdapterRequest.java
new file mode 100644
index 0000000..9c49241
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsAdapterRequest.java
@@ -0,0 +1,44 @@
+package com.newsdk.sdk.android.httpdns.network;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class HttpDnsAdapterRequest {
+ private final String method;
+ private final String url;
+ private final Map headers;
+ private final byte[] body;
+
+ public HttpDnsAdapterRequest(String method, String url) {
+ this(method, url, null, null);
+ }
+
+ public HttpDnsAdapterRequest(String method, String url, Map headers, byte[] body) {
+ this.method = method == null || method.trim().isEmpty() ? "GET" : method.trim().toUpperCase();
+ this.url = url;
+ if (headers == null || headers.isEmpty()) {
+ this.headers = Collections.emptyMap();
+ } else {
+ this.headers = Collections.unmodifiableMap(new LinkedHashMap<>(headers));
+ }
+ this.body = body;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public Map getHeaders() {
+ return headers;
+ }
+
+ public byte[] getBody() {
+ return body;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsAdapterResponse.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsAdapterResponse.java
new file mode 100644
index 0000000..3bf22a2
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsAdapterResponse.java
@@ -0,0 +1,35 @@
+package com.newsdk.sdk.android.httpdns.network;
+
+import java.util.List;
+import java.util.Map;
+
+public class HttpDnsAdapterResponse {
+ private final int statusCode;
+ private final Map> headers;
+ private final byte[] body;
+ private final String usedIp;
+
+ public HttpDnsAdapterResponse(int statusCode, Map> headers, byte[] body, String usedIp) {
+ this.statusCode = statusCode;
+ this.headers = headers;
+ this.body = body;
+ this.usedIp = usedIp;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public Map> getHeaders() {
+ return headers;
+ }
+
+ public byte[] getBody() {
+ return body;
+ }
+
+ public String getUsedIp() {
+ return usedIp;
+ }
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsErrorCode.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsErrorCode.java
new file mode 100644
index 0000000..356445a
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsErrorCode.java
@@ -0,0 +1,12 @@
+package com.newsdk.sdk.android.httpdns.network;
+
+public final class HttpDnsErrorCode {
+ private HttpDnsErrorCode() {
+ }
+
+ public static final String NO_IP_AVAILABLE = "NO_IP_AVAILABLE";
+ public static final String TLS_EMPTY_SNI_FAILED = "TLS_EMPTY_SNI_FAILED";
+ public static final String HOST_ROUTE_REJECTED = "HOST_ROUTE_REJECTED";
+ public static final String RESOLVE_SIGN_INVALID = "RESOLVE_SIGN_INVALID";
+}
+
diff --git a/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsHttpAdapter.java b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsHttpAdapter.java
new file mode 100644
index 0000000..739b5ea
--- /dev/null
+++ b/HttpDNSSDK/sdk/android/httpdns-sdk/src/main/java/com/newsdk/sdk/android/httpdns/network/HttpDnsHttpAdapter.java
@@ -0,0 +1,330 @@
+package com.newsdk.sdk.android.httpdns.network;
+
+import com.newsdk.sdk.android.httpdns.HTTPDNSResult;
+import com.newsdk.sdk.android.httpdns.HttpDnsService;
+import com.newsdk.sdk.android.httpdns.RequestIpType;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+public class HttpDnsHttpAdapter {
+ private static final int BUFFER_SIZE = 4096;
+
+ private final HttpDnsService httpDnsService;
+ private final HttpDnsAdapterOptions options;
+
+ public HttpDnsHttpAdapter(HttpDnsService httpDnsService) {
+ this(httpDnsService, new HttpDnsAdapterOptions.Builder().build());
+ }
+
+ public HttpDnsHttpAdapter(HttpDnsService httpDnsService, HttpDnsAdapterOptions options) {
+ if (httpDnsService == null) {
+ throw new IllegalArgumentException("httpDnsService should not be null");
+ }
+ this.httpDnsService = httpDnsService;
+ this.options = options == null ? new HttpDnsAdapterOptions.Builder().build() : options;
+ }
+
+ public HttpDnsAdapterResponse execute(HttpDnsAdapterRequest request) throws IOException {
+ if (request == null || request.getUrl() == null || request.getUrl().trim().isEmpty()) {
+ throw new HttpDnsAdapterException(HttpDnsErrorCode.HOST_ROUTE_REJECTED,
+ "request or url is empty");
+ }
+
+ URL originalURL = new URL(request.getUrl());
+ String originalHost = originalURL.getHost();
+ if (originalHost == null || originalHost.trim().isEmpty()) {
+ throw new HttpDnsAdapterException(HttpDnsErrorCode.HOST_ROUTE_REJECTED,
+ "invalid original host");
+ }
+ String scheme = originalURL.getProtocol();
+ boolean isHttps = "https".equalsIgnoreCase(scheme);
+ int defaultPort = isHttps ? 443 : 80;
+
+ List candidateIps = resolveIps(originalHost);
+ if (candidateIps.isEmpty()) {
+ throw new HttpDnsAdapterException(HttpDnsErrorCode.NO_IP_AVAILABLE,
+ "HTTPDNS returned no ip for host: " + originalHost);
+ }
+
+ IOException lastException = null;
+ for (String ip : candidateIps) {
+ if (ip == null || ip.trim().isEmpty()) {
+ continue;
+ }
+ String usedIp = ip.trim();
+ HttpURLConnection connection = null;
+ try {
+ int port = originalURL.getPort() > 0 ? originalURL.getPort() : defaultPort;
+ URL targetURL = new URL(scheme, usedIp, port, originalURL.getFile());
+ connection = (HttpURLConnection) targetURL.openConnection();
+ connection.setConnectTimeout(options.getConnectTimeoutMillis());
+ connection.setReadTimeout(options.getReadTimeoutMillis());
+ connection.setInstanceFollowRedirects(false);
+ connection.setRequestMethod(request.getMethod());
+
+ if (isHttps && connection instanceof HttpsURLConnection) {
+ HttpsURLConnection httpsConn = (HttpsURLConnection) connection;
+ httpsConn.setSSLSocketFactory(createSocketFactory());
+ httpsConn.setHostnameVerifier(createHostnameVerifier(originalHost));
+ }
+
+ connection.setRequestProperty("Host", originalHost);
+ for (Map.Entry entry : request.getHeaders().entrySet()) {
+ if (entry.getKey() == null || entry.getValue() == null) {
+ continue;
+ }
+ if ("host".equalsIgnoreCase(entry.getKey())) {
+ continue;
+ }
+ connection.setRequestProperty(entry.getKey(), entry.getValue());
+ }
+
+ byte[] body = request.getBody();
+ if (body != null && body.length > 0 && allowsRequestBody(request.getMethod())) {
+ connection.setDoOutput(true);
+ connection.getOutputStream().write(body);
+ }
+
+ int code = connection.getResponseCode();
+ byte[] payload = readResponseBytes(connection, code);
+ Map> headers = sanitizeHeaders(connection.getHeaderFields());
+ return new HttpDnsAdapterResponse(code, headers, payload, usedIp);
+ } catch (IOException e) {
+ lastException = e;
+ } finally {
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+ }
+
+ String errorCode = isHttps ? HttpDnsErrorCode.TLS_EMPTY_SNI_FAILED
+ : HttpDnsErrorCode.HOST_ROUTE_REJECTED;
+ if (lastException == null) {
+ throw new HttpDnsAdapterException(errorCode,
+ "all ip attempts failed with no explicit exception");
+ }
+
+ throw new HttpDnsAdapterException(errorCode,
+ "all ip attempts failed", lastException);
+ }
+
+ private List resolveIps(String host) {
+ RequestIpType type = options.getRequestIpType();
+ HTTPDNSResult result = httpDnsService.getHttpDnsResultForHostSyncNonBlocking(host, type, null, null);
+ List ips = collectIps(result);
+ if (!ips.isEmpty()) {
+ return ips;
+ }
+
+ // Non-blocking read may miss cache in startup/race windows; fallback to sync resolve once.
+ result = httpDnsService.getHttpDnsResultForHostSync(host, type, null, null);
+ return collectIps(result);
+ }
+
+ private List collectIps(HTTPDNSResult result) {
+ if (result == null) {
+ return Collections.emptyList();
+ }
+ List ips = new ArrayList<>();
+ appendIps(ips, result.getIps());
+ appendIps(ips, result.getIpv6s());
+ return ips;
+ }
+
+ private void appendIps(List target, String[] source) {
+ if (source == null || source.length == 0) {
+ return;
+ }
+ for (String item : source) {
+ if (item == null) {
+ continue;
+ }
+ String ip = item.trim();
+ if (ip.isEmpty()) {
+ continue;
+ }
+ if (!target.contains(ip)) {
+ target.add(ip);
+ }
+ }
+ }
+
+ private byte[] readResponseBytes(HttpURLConnection connection, int code) throws IOException {
+ InputStream stream = code >= 400 ? connection.getErrorStream() : connection.getInputStream();
+ if (stream == null) {
+ return new byte[0];
+ }
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte[] buffer = new byte[BUFFER_SIZE];
+ int count;
+ while ((count = stream.read(buffer)) > 0) {
+ out.write(buffer, 0, count);
+ }
+ stream.close();
+ return out.toByteArray();
+ }
+
+ private Map> sanitizeHeaders(Map> source) {
+ if (source == null || source.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ Map> result = new LinkedHashMap<>();
+ for (Map.Entry