From 25cacf0bca0ce27ea5c4aec7d086fa37d2b5e100 Mon Sep 17 00:00:00 2001 From: luorijun Date: Fri, 12 Jun 2026 16:43:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=8A=82=E7=82=B9=E7=AD=9B?= =?UTF-8?q?=E9=80=89=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- scripts/sql/init.sql | 2 +- web/handlers/channel.go | 34 ++++++++++++++--------------- web/models/edge.go | 3 ++- web/routes.go | 42 ------------------------------------ web/services/channel.go | 8 +++++-- web/services/channel_gost.go | 31 +++++++++++--------------- 7 files changed, 40 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index b161489..8eba393 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## TODO -- 日志记录 +- edge.area_id 可为空,代表节点无固定地区 - 后台展示 mac, ip:port,实际地区 上传文件平铺到 uploads,不分子文件夹 diff --git a/scripts/sql/init.sql b/scripts/sql/init.sql index caedae3..4403f5d 100644 --- a/scripts/sql/init.sql +++ b/scripts/sql/init.sql @@ -669,7 +669,7 @@ create table edge ( ip inet not null, port int, isp int not null, - area_id int not null, + area_id int, status int not null default 0, rtt int default 0, loss int default 0, diff --git a/web/handlers/channel.go b/web/handlers/channel.go index 250d859..6762de5 100644 --- a/web/handlers/channel.go +++ b/web/handlers/channel.go @@ -230,23 +230,6 @@ type CreateChannelReqV3 struct { Isp *int `json:"isp"` } -func buildCreateChannelResp(result []*m.Channel, protocol int, authType s.ChannelAuthType) []*CreateChannelRespItem { - resp := make([]*CreateChannelRespItem, len(result)) - for i, channel := range result { - resp[i] = &CreateChannelRespItem{ - Proto: protocol, - Host: channel.Host, - IP: channel.Proxy.IP.String(), - Port: channel.Port, - } - if authType == s.ChannelAuthTypePass { - resp[i].Username = channel.Username - resp[i].Password = channel.Password - } - } - return resp -} - type CreateChannelRespItem struct { Proto int `json:"-"` Host string `json:"host"` @@ -474,3 +457,20 @@ type SyncChannelClearExpiredByAdminReq struct { type SyncChannelClearExpiredByAdminResp struct { Count int `json:"count"` } + +func buildCreateChannelResp(result []*m.Channel, protocol int, authType s.ChannelAuthType) []*CreateChannelRespItem { + resp := make([]*CreateChannelRespItem, len(result)) + for i, channel := range result { + resp[i] = &CreateChannelRespItem{ + Proto: protocol, + Host: channel.Host, + IP: channel.Proxy.IP.String(), + Port: channel.Port, + } + if authType == s.ChannelAuthTypePass { + resp[i].Username = channel.Username + resp[i].Password = channel.Password + } + } + return resp +} diff --git a/web/models/edge.go b/web/models/edge.go index 39c59b7..9604cc9 100644 --- a/web/models/edge.go +++ b/web/models/edge.go @@ -14,7 +14,7 @@ type Edge struct { IP orm.Inet `json:"ip" gorm:"column:ip;not null"` // 节点地址或 GOST chain addr 的 IP Port *uint16 `json:"port,omitempty" gorm:"column:port"` // GOST chain addr 的端口 ISP EdgeISP `json:"isp" gorm:"column:isp"` // 运营商:0-未知,1-电信,2-联通,3-移动 - AreaID int32 `json:"area_id" gorm:"column:area_id"` // 城市地区ID + AreaID *int32 `json:"area_id,omitempty" gorm:"column:area_id"` // 城市地区ID Status EdgeStatus `json:"status" gorm:"column:status"` // 节点状态:0-离线,1-正常 RTT int32 `json:"rtt" gorm:"column:rtt"` // 最近平均延迟 Loss int32 `json:"loss" gorm:"column:loss"` // 最近丢包率 @@ -41,6 +41,7 @@ const ( type EdgeISP int const ( + EdgeISPUnknown EdgeISP = 0 // 未知/任意 EdgeISPTelecom EdgeISP = 1 // 电信 EdgeISPUnicom EdgeISP = 2 // 联通 EdgeISPMobile EdgeISP = 3 // 移动 diff --git a/web/routes.go b/web/routes.go index c709119..d37d22e 100644 --- a/web/routes.go +++ b/web/routes.go @@ -1,13 +1,11 @@ package web import ( - "fmt" "platform/pkg/env" auth2 "platform/web/auth" "platform/web/core" "platform/web/globals" "platform/web/handlers" - "strings" "time" q "platform/web/queries" @@ -51,46 +49,6 @@ func ApplyRouters(app *fiber.App) { } return ctx.JSON(resp) }) - debug.Get("/gen-edge", func(ctx *fiber.Ctx) error { - areas, err := q.Area.Where(q.Area.Level.Eq(2)).Find() - if err != nil { - return err - } - - sb := strings.Builder{} - sb.WriteString("INSERT INTO edge (type, version, mac, ip, port, isp, area_id, status) VALUES\n") - - for i, area := range areas { - // jh edges - for j := range 20 { - fmt.Fprintf(&sb, "(2, 1, 'jh-%d-%d-%d', '192.168.50.%d', %d, 0, %d, 1)", area.ID, j+1, i+44001, j+2, i+44001, area.ID) - sb.WriteString(",\n") - } - - // jg edges - for j := range 10 { - var ip string - var n int - if i < 100 { - ip = "192.168.0.232" - n = 1 - } else if i < 200 { - ip = "192.168.59.236" - n = 2 - } else { - ip = "192.168.59.237" - n = 3 - } - fmt.Fprintf(&sb, "(2, 1, 'jg-%d-%d-%d', '%s', %d, 0, %d, 1)", area.ID, n, i*10+j+20001, ip, i*10+j+20001, area.ID) - if i < len(areas)-1 || j < 9 { - sb.WriteString(",\n") - } - } - } - - sb.WriteString(";\n") - return ctx.SendString(sb.String()) - }) } } diff --git a/web/services/channel.go b/web/services/channel.go index 4a51e15..e04b9d9 100644 --- a/web/services/channel.go +++ b/web/services/channel.go @@ -40,6 +40,10 @@ type channelServer struct { } func (s *channelServer) CreateChannels(source netip.Addr, resourceNo string, authWhitelist bool, authPassword bool, count int, edgeFilter *EdgeFilter) ([]*m.Channel, error) { + if edgeFilter == nil { + edgeFilter = &EdgeFilter{} + } + var area *m.Area if edgeFilter.AreaID != nil { var err error @@ -265,8 +269,8 @@ func persistChannelCreate(ctx *channelCreateContext, channels []*m.Channel) erro BatchNo: ctx.BatchNo, Count: int32(ctx.Count), ISP: u.X(ctx.Filter.Isp.String()), - Prov: prov, - City: city, + Prov: u.Ternary(ctx.Filter.AreaID != nil, prov, nil), + City: u.Ternary(ctx.Filter.AreaID != nil, city, nil), IP: orm.Inet{Addr: ctx.Source}, Time: ctx.Now, }); err != nil { diff --git a/web/services/channel_gost.go b/web/services/channel_gost.go index 60cc5c8..10a1eac 100644 --- a/web/services/channel_gost.go +++ b/web/services/channel_gost.go @@ -10,7 +10,7 @@ import ( q "platform/web/queries" "strings" - "gorm.io/gen" + "gorm.io/gen/field" ) type channelGostProvider struct{} @@ -37,7 +37,7 @@ func (s *channelGostProvider) prepareCreate(ctx *channelCreateContext) (*channel serviceName := gostServiceName(ctx.BatchNo, port) channel := newBaseChannel(ctx, port) channel.EdgeID = u.P(edge.ID) - channel.EdgeRef = u.P(serviceName) + channel.EdgeRef = u.P(edge.Mac) channel.IP = u.P(edge.IP) service := &g.GostServiceConfig{ @@ -141,40 +141,34 @@ func (s *channelGostProvider) selectEdge(filter *EdgeFilter, area *m.Area, count filter = &EdgeFilter{} } - conds := []gen.Condition{ + do := q.Edge.Where( q.Edge.Type.Eq(int(m.EdgeTypeGostChain)), q.Edge.Status.Eq(int(m.EdgeStatusNormal)), + ) + if filter.Isp != nil { + do = do.Where(q.Edge.ISP.In(int(m.EdgeISPUnknown), int(*filter.Isp))) } - if isp := u.X(filter.Isp.String()); isp != nil { - conds = append(conds, q.Edge.ISP.Eq(int(*filter.Isp))) - } - - query := q.Edge.Where(conds...) if area != nil { switch area.Level { case m.AreaLevelProvince: edgeArea := q.Area.As("EdgeArea") - query = query. - Join(edgeArea, edgeArea.ID.EqCol(q.Edge.AreaID)). - Where(edgeArea.ParentID.Eq(area.ID)) + do = do. + Where(edgeArea.ParentID.Eq(area.ID)). + Join(edgeArea, edgeArea.ID.EqCol(q.Edge.AreaID)) case m.AreaLevelCity: - query = query.Where(q.Edge.AreaID.Eq(area.ID)) + do = do.Where(q.Edge.AreaID.Eq(area.ID)) default: return nil, core.NewBizErr("地区层级不支持") } } - edges, err := query. - Order(q.Edge.ID). + edges, err := do. + Order(field.NewUnsafeFieldRaw("random()")). Limit(count). Find() if err != nil { return nil, core.NewBizErr("查询可用节点失败", err) } - return expandGostEdges(edges, count) -} - -func expandGostEdges(edges []*m.Edge, count int) ([]*m.Edge, error) { if len(edges) == 0 { return nil, core.NewBizErr("地区可用节点数量不足") } @@ -183,6 +177,7 @@ func expandGostEdges(edges []*m.Edge, count int) ([]*m.Edge, error) { for i := range count { result[i] = edges[i%len(edges)] } + return result, nil }