github.com/TeaOSLab/EdgeNode@v1.3.8/internal/nodes/node_tasks.go (about) 1 // Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . 2 3 package nodes 4 5 import ( 6 "encoding/json" 7 "errors" 8 "fmt" 9 "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs" 10 "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" 11 "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" 12 "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs" 13 "github.com/TeaOSLab/EdgeNode/internal/configs" 14 "github.com/TeaOSLab/EdgeNode/internal/firewalls" 15 "github.com/TeaOSLab/EdgeNode/internal/goman" 16 "github.com/TeaOSLab/EdgeNode/internal/iplibrary" 17 "github.com/TeaOSLab/EdgeNode/internal/remotelogs" 18 "github.com/TeaOSLab/EdgeNode/internal/rpc" 19 "github.com/TeaOSLab/EdgeNode/internal/trackers" 20 "github.com/TeaOSLab/EdgeNode/internal/utils" 21 "github.com/TeaOSLab/EdgeNode/internal/waf" 22 "github.com/iwind/TeaGo/Tea" 23 "github.com/iwind/TeaGo/maps" 24 "github.com/iwind/TeaGo/types" 25 "os" 26 "strings" 27 "time" 28 ) 29 30 // 循环 31 func (this *Node) loopTasks() error { 32 var tr = trackers.Begin("CHECK_NODE_CONFIG_CHANGES") 33 defer tr.End() 34 35 // 检查api_node.yaml是否存在 36 var apiConfigFile = Tea.ConfigFile(configs.ConfigFileName) 37 _, err := os.Stat(apiConfigFile) 38 if err != nil { 39 return nil 40 } 41 42 rpcClient, err := rpc.SharedRPC() 43 if err != nil { 44 return fmt.Errorf("create rpc client failed: %w", err) 45 } 46 47 tasksResp, err := rpcClient.NodeTaskRPC.FindNodeTasks(rpcClient.Context(), &pb.FindNodeTasksRequest{ 48 Version: this.lastTaskVersion, 49 }) 50 if err != nil { 51 if rpc.IsConnError(err) && !Tea.IsTesting() { 52 return nil 53 } 54 return fmt.Errorf("read node tasks failed: %w", err) 55 } 56 for _, task := range tasksResp.NodeTasks { 57 err := this.execTask(rpcClient, task) 58 if !this.finishTask(task.Id, task.Version, err) { 59 // 防止失败的任务无法重试 60 break 61 } 62 } 63 64 return nil 65 } 66 67 // 执行任务 68 func (this *Node) execTask(rpcClient *rpc.RPCClient, task *pb.NodeTask) error { 69 var err error 70 switch task.Type { 71 case "ipItemChanged": 72 err = this.execIPItemChangedTask() 73 case "configChanged": 74 err = this.execConfigChangedTask(task) 75 case "nodeVersionChanged": 76 err = this.execNodeVersionChangedTask() 77 case "scriptsChanged": 78 err = this.execScriptsChangedTask() 79 case "nodeLevelChanged": 80 err = this.execNodeLevelChangedTask(rpcClient) 81 case "ddosProtectionChanged": 82 err = this.execDDoSProtectionChangedTask(rpcClient) 83 case "globalServerConfigChanged": 84 err = this.execGlobalServerConfigChangedTask(rpcClient) 85 case "userServersStateChanged": 86 err = this.execUserServersStateChangedTask(rpcClient, task) 87 case "uamPolicyChanged": 88 err = this.execUAMPolicyChangedTask(rpcClient) 89 case "httpCCPolicyChanged": 90 err = this.execHTTPCCPolicyChangedTask(rpcClient) 91 case "http3PolicyChanged": 92 err = this.execHTTP3PolicyChangedTask(rpcClient) 93 case "httpPagesPolicyChanged": 94 err = this.execHTTPPagesPolicyChangedTask(rpcClient) 95 case "updatingServers": 96 err = this.execUpdatingServersTask(rpcClient) 97 case "plusChanged": 98 err = this.notifyPlusChange() 99 case "toaChanged": 100 err = this.execTOAChangedTask() 101 case "networkSecurityPolicyChanged": 102 err = this.execNetworkSecurityPolicyChangedTask(rpcClient) 103 case "webPPolicyChanged": 104 err = this.execWebPPolicyChangedTask(rpcClient) 105 case "planChanged": 106 err = this.execPlanChangedTask(rpcClient) 107 default: 108 // 特殊任务 109 if strings.HasPrefix(task.Type, "ipListDeleted") { // 删除IP名单 110 err = this.execDeleteIPList(task.Type) 111 } else { // 未处理的任务 112 remotelogs.Error("NODE", "task '"+types.String(task.Id)+"', type '"+task.Type+"' has not been handled") 113 } 114 } 115 116 return err 117 } 118 119 // 更新IP条目变更 120 func (this *Node) execIPItemChangedTask() error { 121 // 防止阻塞 122 select { 123 case iplibrary.IPListUpdateNotify <- true: 124 default: 125 126 } 127 return nil 128 } 129 130 // 更新节点配置变更 131 func (this *Node) execConfigChangedTask(task *pb.NodeTask) error { 132 if task.ServerId > 0 { 133 return this.syncServerConfig(task.ServerId) 134 } 135 if !task.IsPrimary { 136 // 我们等等主节点配置准备完毕 137 time.Sleep(2 * time.Second) 138 } 139 return this.syncConfig(task.Version) 140 } 141 142 // 节点程序版本号变更 143 func (this *Node) execNodeVersionChangedTask() error { 144 if !sharedUpgradeManager.IsInstalling() { 145 goman.New(func() { 146 sharedUpgradeManager.Start() 147 }) 148 } 149 return nil 150 } 151 152 // 节点级别变更 153 func (this *Node) execNodeLevelChangedTask(rpcClient *rpc.RPCClient) error { 154 levelInfoResp, err := rpcClient.NodeRPC.FindNodeLevelInfo(rpcClient.Context(), &pb.FindNodeLevelInfoRequest{}) 155 if err != nil { 156 return err 157 } 158 159 if sharedNodeConfig != nil { 160 sharedNodeConfig.Level = levelInfoResp.Level 161 } 162 163 var parentNodes = map[int64][]*nodeconfigs.ParentNodeConfig{} 164 if len(levelInfoResp.ParentNodesMapJSON) > 0 { 165 err = json.Unmarshal(levelInfoResp.ParentNodesMapJSON, &parentNodes) 166 if err != nil { 167 return fmt.Errorf("decode level info failed: %w", err) 168 } 169 } 170 171 if sharedNodeConfig != nil { 172 sharedNodeConfig.ParentNodes = parentNodes 173 } 174 175 return nil 176 } 177 178 // DDoS配置变更 179 func (this *Node) execDDoSProtectionChangedTask(rpcClient *rpc.RPCClient) error { 180 resp, err := rpcClient.NodeRPC.FindNodeDDoSProtection(rpcClient.Context(), &pb.FindNodeDDoSProtectionRequest{}) 181 if err != nil { 182 return err 183 } 184 if len(resp.DdosProtectionJSON) == 0 { 185 if sharedNodeConfig != nil { 186 sharedNodeConfig.DDoSProtection = nil 187 } 188 return nil 189 } 190 191 var ddosProtectionConfig = &ddosconfigs.ProtectionConfig{} 192 err = json.Unmarshal(resp.DdosProtectionJSON, ddosProtectionConfig) 193 if err != nil { 194 return fmt.Errorf("decode DDoS protection config failed: %w", err) 195 } 196 197 if ddosProtectionConfig != nil && sharedNodeConfig != nil { 198 sharedNodeConfig.DDoSProtection = ddosProtectionConfig 199 } 200 201 go func() { 202 err = firewalls.SharedDDoSProtectionManager.Apply(ddosProtectionConfig) 203 if err != nil { 204 // 不阻塞 205 remotelogs.Warn("NODE", "apply DDoS protection failed: "+err.Error()) 206 } 207 }() 208 209 return nil 210 } 211 212 // 服务全局配置变更 213 func (this *Node) execGlobalServerConfigChangedTask(rpcClient *rpc.RPCClient) error { 214 resp, err := rpcClient.NodeRPC.FindNodeGlobalServerConfig(rpcClient.Context(), &pb.FindNodeGlobalServerConfigRequest{}) 215 if err != nil { 216 return err 217 } 218 if len(resp.GlobalServerConfigJSON) > 0 { 219 var globalServerConfig = serverconfigs.NewGlobalServerConfig() 220 err = json.Unmarshal(resp.GlobalServerConfigJSON, globalServerConfig) 221 if err != nil { 222 return fmt.Errorf("decode global server config failed: %w", err) 223 } 224 225 if globalServerConfig != nil { 226 err = globalServerConfig.Init() 227 if err != nil { 228 return fmt.Errorf("validate global server config failed: %w", err) 229 } 230 if sharedNodeConfig != nil { 231 sharedNodeConfig.GlobalServerConfig = globalServerConfig 232 } 233 } 234 } 235 return nil 236 } 237 238 // 单个用户服务状态变更 239 func (this *Node) execUserServersStateChangedTask(rpcClient *rpc.RPCClient, task *pb.NodeTask) error { 240 if task.UserId > 0 { 241 resp, err := rpcClient.UserRPC.CheckUserServersState(rpcClient.Context(), &pb.CheckUserServersStateRequest{UserId: task.UserId}) 242 if err != nil { 243 return err 244 } 245 246 SharedUserManager.UpdateUserServersIsEnabled(task.UserId, resp.IsEnabled) 247 248 if resp.IsEnabled { 249 err = this.syncUserServersConfig(task.UserId) 250 if err != nil { 251 return err 252 } 253 } 254 } 255 return nil 256 } 257 258 // 更新一组服务列表 259 func (this *Node) execUpdatingServersTask(rpcClient *rpc.RPCClient) error { 260 if this.lastUpdatingServerListId <= 0 { 261 this.lastUpdatingServerListId = sharedNodeConfig.UpdatingServerListId 262 } 263 264 resp, err := rpcClient.UpdatingServerListRPC.FindUpdatingServerLists(rpcClient.Context(), &pb.FindUpdatingServerListsRequest{LastId: this.lastUpdatingServerListId}) 265 if err != nil { 266 return err 267 } 268 269 if resp.MaxId <= 0 || len(resp.ServersJSON) == 0 { 270 return nil 271 } 272 273 var serverConfigs = []*serverconfigs.ServerConfig{} 274 err = json.Unmarshal(resp.ServersJSON, &serverConfigs) 275 if err != nil { 276 return fmt.Errorf("decode server configs failed: %w", err) 277 } 278 279 if resp.MaxId > this.lastUpdatingServerListId { 280 this.lastUpdatingServerListId = resp.MaxId 281 } 282 283 if len(serverConfigs) == 0 { 284 return nil 285 } 286 287 this.locker.Lock() 288 defer this.locker.Unlock() 289 for _, serverConfig := range serverConfigs { 290 if serverConfig == nil { 291 continue 292 } 293 294 if serverConfig.IsOn { 295 this.updatingServerMap[serverConfig.Id] = serverConfig 296 } else { 297 this.updatingServerMap[serverConfig.Id] = nil 298 } 299 } 300 301 return nil 302 } 303 304 // 删除IP名单 305 func (this *Node) execDeleteIPList(taskType string) error { 306 optionsString, ok := utils.CutPrefix(taskType, "ipListDeleted@") 307 if !ok { 308 return errors.New("invalid task type '" + taskType + "'") 309 } 310 var optionMap = maps.Map{} 311 err := json.Unmarshal([]byte(optionsString), &optionMap) 312 if err != nil { 313 return fmt.Errorf("decode options failed: %w, options: %s", err, optionsString) 314 } 315 var listId = optionMap.GetInt64("listId") 316 if listId <= 0 { 317 return nil 318 } 319 320 // 标记已被删除 321 waf.AddDeletedIPList(listId) 322 323 var list = iplibrary.SharedIPListManager.FindList(listId) 324 325 if list != nil { 326 list.SetDeleted() 327 } 328 329 return nil 330 } 331 332 // WebP策略变更 333 func (this *Node) execWebPPolicyChangedTask(rpcClient *rpc.RPCClient) error { 334 remotelogs.Println("NODE", "updating webp policies ...") 335 resp, err := rpcClient.NodeRPC.FindNodeWebPPolicies(rpcClient.Context(), &pb.FindNodeWebPPoliciesRequest{}) 336 if err != nil { 337 return err 338 } 339 var webPPolicyMap = map[int64]*nodeconfigs.WebPImagePolicy{} 340 for _, policy := range resp.WebPPolicies { 341 if len(policy.WebPPolicyJSON) > 0 { 342 var webPPolicy = nodeconfigs.NewWebPImagePolicy() 343 err = json.Unmarshal(policy.WebPPolicyJSON, webPPolicy) 344 if err != nil { 345 remotelogs.Error("NODE", "decode webp policy failed: "+err.Error()) 346 continue 347 } 348 err = webPPolicy.Init() 349 if err != nil { 350 remotelogs.Error("NODE", "initialize webp policy failed: "+err.Error()) 351 continue 352 } 353 webPPolicyMap[policy.NodeClusterId] = webPPolicy 354 } 355 } 356 sharedNodeConfig.UpdateWebPImagePolicies(webPPolicyMap) 357 return nil 358 } 359 360 // 标记任务完成 361 func (this *Node) finishTask(taskId int64, taskVersion int64, taskErr error) (success bool) { 362 if taskId <= 0 { 363 return true 364 } 365 366 rpcClient, err := rpc.SharedRPC() 367 if err != nil { 368 remotelogs.Debug("NODE", "create rpc client failed: "+err.Error()) 369 return false 370 } 371 372 var isOk = taskErr == nil 373 if isOk && taskVersion > this.lastTaskVersion { 374 this.lastTaskVersion = taskVersion 375 } 376 377 var errMsg = "" 378 if taskErr != nil { 379 errMsg = taskErr.Error() 380 } 381 382 _, err = rpcClient.NodeTaskRPC.ReportNodeTaskDone(rpcClient.Context(), &pb.ReportNodeTaskDoneRequest{ 383 NodeTaskId: taskId, 384 IsOk: isOk, 385 Error: errMsg, 386 }) 387 success = err == nil 388 389 if err != nil { 390 // 连接错误不需要上报到服务中心 391 if rpc.IsConnError(err) { 392 remotelogs.Debug("NODE", "report task done failed: "+err.Error()) 393 } else { 394 remotelogs.Error("NODE", "report task done failed: "+err.Error()) 395 } 396 } 397 398 return success 399 }