github.com/godevsig/adaptiveservice@v0.9.23/registry.go (about) 1 package adaptiveservice 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "net" 8 "os" 9 "reflect" 10 "strings" 11 "sync" 12 "time" 13 14 "github.com/niubaoshu/gotiny" 15 ) 16 17 var ( 18 udsRegistry = "@adaptiveservice/" 19 chanRegistry = struct { 20 sync.RWMutex 21 table map[string]*chanTransport 22 }{table: make(map[string]*chanTransport)} 23 ) 24 25 func regServiceChan(publisherName, serviceName string, ct *chanTransport) { 26 name := publisherName + "_" + serviceName 27 chanRegistry.Lock() 28 defer chanRegistry.Unlock() 29 if _, has := chanRegistry.table[name]; has { 30 panic("registering duplicated channel for " + name) 31 } 32 chanRegistry.table[name] = ct 33 } 34 35 func delServiceChan(publisherName, serviceName string) { 36 name := publisherName + "_" + serviceName 37 chanRegistry.Lock() 38 delete(chanRegistry.table, name) 39 chanRegistry.Unlock() 40 } 41 42 func serviceNamesInProcess(publisherName, serviceName string) (names []string) { 43 name := publisherName + "_" + serviceName 44 if strings.Contains(name, "*") { 45 chanRegistry.RLock() 46 for ctname := range chanRegistry.table { 47 chanRegistry.RUnlock() 48 if wildcardMatch(name, ctname) { 49 names = append(names, ctname) 50 } 51 chanRegistry.RLock() 52 } 53 chanRegistry.RUnlock() 54 } else { 55 chanRegistry.RLock() 56 ct := chanRegistry.table[name] 57 chanRegistry.RUnlock() 58 if ct != nil { 59 names = append(names, name) 60 } 61 } 62 return 63 } 64 65 // support wildcard 66 func queryServiceProcess(publisherName, serviceName string) (serviceInfos []*ServiceInfo) { 67 names := serviceNamesInProcess(publisherName, serviceName) 68 for _, name := range names { 69 strs := strings.Split(name, "_") 70 sInfo := &ServiceInfo{strs[0], strs[1], "self", "internal"} 71 serviceInfos = append(serviceInfos, sInfo) 72 } 73 return 74 } 75 76 // support wildcard 77 func (c *Client) lookupServiceChan(publisherName, serviceName string) (ccts []*clientChanTransport) { 78 names := serviceNamesInProcess(publisherName, serviceName) 79 for _, name := range names { 80 chanRegistry.RLock() 81 ct := chanRegistry.table[name] 82 chanRegistry.RUnlock() 83 if ct != nil { 84 ccts = append(ccts, &clientChanTransport{c, ct}) 85 } 86 } 87 return 88 } 89 90 func toUDSAddr(publisherName, serviceName string) (addr string) { 91 return udsRegistry + publisherName + "_" + serviceName + ".sock" 92 } 93 94 func serviceNamesInOS(publisherName, serviceName string) (names []string) { 95 f, err := os.Open("/proc/net/unix") 96 if err != nil { 97 return nil 98 } 99 defer f.Close() 100 101 var b bytes.Buffer 102 _, err = b.ReadFrom(f) 103 if err != nil { 104 return nil 105 } 106 107 distinctEntires := make(map[string]struct{}) 108 tName := publisherName + "_" + serviceName 109 //skip first line 110 b.ReadString('\n') 111 for { 112 line, err := b.ReadString('\n') 113 if err != nil { 114 break 115 } 116 //0000000000000000: 00000002 00000000 00010000 0001 01 10156659 @adaptiveservice/publisherName_serviceName.sock 117 fs := strings.Fields(line) 118 if len(fs) == 8 { 119 addr := fs[7] 120 if strings.Contains(addr, udsRegistry) { 121 name := strings.TrimSuffix(strings.TrimPrefix(addr, udsRegistry), ".sock") 122 // there can be multiple entires with the same name 123 if _, has := distinctEntires[name]; has { 124 continue 125 } 126 distinctEntires[name] = struct{}{} 127 if wildcardMatch(tName, name) { 128 names = append(names, name) 129 } 130 } 131 } 132 } 133 134 return 135 } 136 137 // support wildcard 138 func queryServiceOS(publisherName, serviceName string) (serviceInfos []*ServiceInfo) { 139 names := serviceNamesInOS(publisherName, serviceName) 140 for _, name := range names { 141 strs := strings.Split(name, "_") 142 sInfo := &ServiceInfo{strs[0], strs[1], "self", udsRegistry + name + ".sock"} 143 serviceInfos = append(serviceInfos, sInfo) 144 } 145 return 146 } 147 148 // support wildcard 149 func lookupServiceUDS(publisherName, serviceName string) (addrs []string) { 150 names := serviceNamesInOS(publisherName, serviceName) 151 for _, name := range names { 152 addrs = append(addrs, udsRegistry+name+".sock") 153 } 154 return 155 } 156 157 func (svc *service) regServiceLAN(port string) error { 158 c := NewClient(WithScope(ScopeProcess|ScopeOS), WithLogger(svc.s.lg)).SetDiscoverTimeout(0) 159 conn := <-c.Discover(BuiltinPublisher, SrvLANRegistry) 160 if conn == nil { 161 return errors.New("LANRegistry not found") 162 } 163 defer conn.Close() 164 return conn.SendRecv(®ServiceInLAN{svc.publisherName, svc.serviceName, port}, nil) 165 } 166 167 func (svc *service) delServiceLAN() error { 168 c := NewClient(WithScope(ScopeProcess|ScopeOS), WithLogger(svc.s.lg)).SetDiscoverTimeout(0) 169 conn := <-c.Discover(BuiltinPublisher, SrvLANRegistry) 170 if conn == nil { 171 return errors.New("LANRegistry not found") 172 } 173 defer conn.Close() 174 return conn.Send(&delServiceInLAN{svc.publisherName, svc.serviceName}) 175 } 176 177 // support wildcard 178 func queryServiceLAN(publisherName, serviceName string, lg Logger) (serviceInfos []*ServiceInfo) { 179 c := NewClient(WithScope(ScopeProcess|ScopeOS), WithLogger(lg)).SetDiscoverTimeout(0) 180 conn := <-c.Discover(BuiltinPublisher, SrvLANRegistry) 181 if conn == nil { 182 return 183 } 184 defer conn.Close() 185 conn.SendRecv(&queryServiceInLAN{publisherName, serviceName}, &serviceInfos) 186 return 187 } 188 189 func (c *Client) lookupServiceLAN(publisherName, serviceName string, providerIDs ...string) (addrs []string) { 190 serviceInfos := queryServiceLAN(publisherName, serviceName, c.lg) 191 has := func(target string) bool { 192 if len(providerIDs) == 0 { // match all 193 return true 194 } 195 for _, str := range providerIDs { 196 if str == target { 197 return true 198 } 199 } 200 return false 201 } 202 for _, provider := range serviceInfos { 203 if has(provider.ProviderID) { 204 addrs = append(addrs, provider.Addr) 205 } 206 } 207 return 208 } 209 210 // taken from https://github.com/IBM/netaddr/blob/master/net_utils.go 211 // NewIP returns a new IP with the given size. The size must be 4 for IPv4 and 212 // 16 for IPv6. 213 func newIP(size int) net.IP { 214 if size == 4 { 215 return net.ParseIP("0.0.0.0").To4() 216 } 217 if size == 16 { 218 return net.ParseIP("::") 219 } 220 panic("Bad value for size") 221 } 222 223 // BroadcastAddr returns the last address in the given network, or the broadcast address. 224 func broadcastAddr(n *net.IPNet) net.IP { 225 // The golang net package doesn't make it easy to calculate the broadcast address. :( 226 broadcast := newIP(len(n.IP)) 227 for i := 0; i < len(n.IP); i++ { 228 broadcast[i] = n.IP[i] | ^n.Mask[i] 229 } 230 return broadcast 231 } 232 233 type infoLAN struct { 234 ip net.IP // self ip 235 ipnet *net.IPNet 236 bcastAddr *net.UDPAddr 237 } 238 239 type packetMsg struct { 240 msg interface{} 241 raddr net.Addr 242 } 243 244 type providerInfo struct { 245 timeStamp time.Time 246 addr string 247 proxied bool 248 } 249 250 type providers struct { 251 table map[string]*providerInfo // {"providerID1":{time, "192.168.0.11:12345"}, {time, "providerID2":"192.168.0.26:33556"}} 252 } 253 254 type serviceInfoTime struct { 255 timeStamp time.Time // last update time 256 si []*ServiceInfo 257 } 258 259 type registryLAN struct { 260 s *Server 261 packetConn net.PacketConn 262 infoLANs []*infoLAN 263 sync.RWMutex 264 serviceInfoCache map[string]*serviceInfoTime 265 done chan struct{} 266 cmdChan chan interface{} 267 } 268 269 func (s *Server) newLANRegistry() (*registryLAN, error) { 270 packetConn, err := net.ListenPacket("udp4", ":"+s.broadcastPort) 271 if err != nil { 272 s.lg.Errorf("listen lan broadcast error: %v", err) 273 return nil, err 274 } 275 s.addCloser(ioCloser(packetConn.Close)) 276 277 var infoLANs []*infoLAN 278 addrs, _ := net.InterfaceAddrs() 279 for _, addr := range addrs { 280 ip, ipnet, _ := net.ParseCIDR(addr.String()) 281 if ip.To4() != nil && !ip.IsLoopback() { 282 bcast := broadcastAddr(ipnet) 283 bcastAddr, _ := net.ResolveUDPAddr("udp4", bcast.String()+":"+s.broadcastPort) 284 il := &infoLAN{ 285 ip: ip, 286 ipnet: ipnet, 287 bcastAddr: bcastAddr, 288 } 289 infoLANs = append(infoLANs, il) 290 } 291 } 292 293 r := ®istryLAN{ 294 s: s, 295 packetConn: packetConn, 296 infoLANs: infoLANs, 297 serviceInfoCache: make(map[string]*serviceInfoTime), 298 done: make(chan struct{}), 299 cmdChan: make(chan interface{}), 300 } 301 302 go r.run() 303 return r, nil 304 } 305 306 // msg must be pointer 307 func (r *registryLAN) broadcast(msg interface{}) error { 308 bufMsg := gotiny.Marshal(&msg) 309 r.s.lg.Debugf("broadcast LAN msg %#v: %s", msg, bufMsg) 310 for _, lan := range r.infoLANs { 311 if _, err := r.packetConn.WriteTo(bufMsg, lan.bcastAddr); err != nil { 312 return err 313 } 314 } 315 return nil 316 } 317 318 // ServiceInfo is service information. 319 type ServiceInfo struct { 320 Publisher string 321 Service string 322 ProviderID string 323 Addr string // "192.168.0.11:12345", "192.168.0.11:12345P" if proxied 324 } 325 326 type queryInLAN struct { 327 name string // "publisher_service" 328 } 329 330 type foundInLAN struct { 331 name string // "publisher_service" 332 providerID string 333 port string 334 } 335 336 func init() { 337 RegisterType(([]*ServiceInfo)(nil)) 338 RegisterType((*queryInLAN)(nil)) 339 RegisterType((*foundInLAN)(nil)) 340 } 341 342 type cmdLANRegister struct { 343 name string // "publisher_service" 344 port string 345 } 346 347 type cmdLANDelete struct { 348 name string // "publisher_service" 349 } 350 351 type cmdLANQuery struct { 352 name string // "publisher_service" 353 chanServiceInfo chan []*ServiceInfo 354 } 355 356 func (r *registryLAN) registerServiceInLAN(publisher, service, port string) { 357 name := publisher + "_" + service 358 r.cmdChan <- &cmdLANRegister{name, port} 359 } 360 361 func (r *registryLAN) deleteServiceInLAN(publisher, service string) { 362 name := publisher + "_" + service 363 r.cmdChan <- &cmdLANDelete{name} 364 } 365 366 // support wildcard 367 func (r *registryLAN) queryServiceInLAN(publisher, service string) []*ServiceInfo { 368 name := publisher + "_" + service 369 r.Lock() 370 if len(r.serviceInfoCache) > 1000 { 371 r.serviceInfoCache = make(map[string]*serviceInfoTime) 372 } 373 sit := r.serviceInfoCache[name] 374 r.Unlock() 375 376 if sit != nil && time.Since(sit.timeStamp) < 15*time.Second { 377 return sit.si 378 } 379 380 cmd := &cmdLANQuery{name, make(chan []*ServiceInfo, 1)} 381 r.cmdChan <- cmd 382 si := <-cmd.chanServiceInfo 383 384 r.Lock() 385 r.serviceInfoCache[name] = &serviceInfoTime{time.Now(), si} 386 r.Unlock() 387 388 return si 389 } 390 391 func (r *registryLAN) run() { 392 pconn := r.packetConn 393 lg := r.s.lg 394 packetChan := make(chan *packetMsg) 395 // "publisher_service": "12345" 396 localServiceTable := make(map[string]string) 397 // "publisher_service": {time.Time, {"providerID1":"192.168.0.11:12345", "providerID2":"192.168.0.26:33556"}} 398 serviceCache := make(map[string]*providers) 399 400 f, err := os.Open("local_services.record") 401 if err == nil { 402 for { 403 var name, port string 404 _, err := fmt.Fscanln(f, &name, &port) 405 if err != nil { 406 break 407 } 408 localServiceTable[name] = port 409 } 410 f.Close() 411 os.Remove("local_services.record") 412 } 413 414 readConn := func() { 415 buf := make([]byte, 512) 416 for { 417 if r.done == nil { 418 break 419 } 420 pconn.SetReadDeadline(time.Now().Add(3 * time.Second)) 421 n, raddr, err := pconn.ReadFrom(buf) 422 if err != nil { 423 if !os.IsTimeout(err) { 424 lg.Warnf("lan registry receive error: %v", err) 425 } 426 continue 427 } 428 var msg interface{} 429 gotiny.Unmarshal(buf[:n], &msg) 430 lg.Debugf("received LAN msg from %v: %#v", raddr, msg) 431 packetChan <- &packetMsg{msg, raddr} 432 } 433 } 434 go readConn() 435 436 replyTo := func(msg interface{}, raddr net.Addr) { 437 bufMsg := gotiny.Marshal(&msg) 438 lg.Debugf("sending LAN msg to %v: %#v", raddr, msg) 439 if _, err := pconn.WriteTo(bufMsg, raddr); err != nil { 440 lg.Warnf("lan registry send error: %v", err) 441 } 442 } 443 444 getServiceInfos := func(cmd *cmdLANQuery) { 445 var serviceInfos []*ServiceInfo 446 walkProviders := func(prvds *providers, name string) { 447 ss := strings.Split(name, "_") 448 for pID, pInfo := range prvds.table { 449 svcInfo := &ServiceInfo{Publisher: ss[0], Service: ss[1], ProviderID: pID, Addr: pInfo.addr} 450 serviceInfos = append(serviceInfos, svcInfo) 451 if time.Since(pInfo.timeStamp) > 15*time.Minute { 452 delete(prvds.table, pID) 453 } 454 } 455 } 456 457 if strings.Contains(cmd.name, "*") { 458 for name, prvds := range serviceCache { 459 if wildcardMatch(cmd.name, name) { 460 walkProviders(prvds, name) 461 } 462 } 463 } else { 464 if prvds, has := serviceCache[cmd.name]; has { 465 walkProviders(prvds, cmd.name) 466 } 467 } 468 cmd.chanServiceInfo <- serviceInfos 469 } 470 471 delService := func(name string) { 472 delete(localServiceTable, name) 473 prvds, has := serviceCache[name] 474 if has { 475 delete(prvds.table, r.s.providerID) 476 } 477 } 478 479 tLocalServiceUpdate := time.Now() 480 chanDelay := make(chan *cmdLANQuery, 8) 481 for { 482 select { 483 case <-r.done: 484 f, err := os.Create("local_services.record") 485 if err == nil { 486 for name, port := range localServiceTable { 487 fmt.Fprintln(f, name, port) 488 } 489 f.Close() 490 } 491 return 492 case cmd := <-r.cmdChan: 493 switch cmd := cmd.(type) { 494 case *cmdLANRegister: 495 localServiceTable[cmd.name] = cmd.port 496 case *cmdLANDelete: 497 delService(cmd.name) 498 case *cmdLANQuery: 499 if err := r.broadcast(&queryInLAN{cmd.name}); err != nil { 500 lg.Warnf("lan registry send broadcast error: %v", err) 501 break 502 } 503 time.AfterFunc(100*time.Millisecond, func() { chanDelay <- cmd }) 504 default: 505 lg.Warnf("LAN receiver: unknown cmd: %v", cmd) 506 } 507 case cmd := <-chanDelay: 508 getServiceInfos(cmd) 509 case packetMsg := <-packetChan: 510 t := time.Now() 511 if t.After(tLocalServiceUpdate.Add(15 * time.Minute)) { 512 tLocalServiceUpdate = t 513 for name, port := range localServiceTable { 514 if err := pingService("127.0.0.1:" + port); err != nil { 515 delService(name) 516 } 517 } 518 } 519 msg := packetMsg.msg 520 raddr := packetMsg.raddr 521 switch msg := msg.(type) { 522 case *queryInLAN: 523 if strings.Contains(msg.name, "*") { 524 for name, port := range localServiceTable { 525 if wildcardMatch(msg.name, name) { 526 replyTo(&foundInLAN{name, r.s.providerID, port}, raddr) 527 } 528 } 529 } else { 530 port, has := localServiceTable[msg.name] 531 if has { 532 replyTo(&foundInLAN{msg.name, r.s.providerID, port}, raddr) 533 } 534 } 535 case *foundInLAN: 536 rhost, _, _ := net.SplitHostPort(raddr.String()) 537 prvds, has := serviceCache[msg.name] 538 if !has { 539 prvds = &providers{table: make(map[string]*providerInfo)} 540 serviceCache[msg.name] = prvds 541 } 542 prvds.table[msg.providerID] = &providerInfo{time.Now(), rhost + ":" + msg.port, false} 543 default: 544 lg.Warnf("LAN receiver: unknown msg: %v", msg) 545 } 546 } 547 } 548 } 549 550 func (r *registryLAN) close() { 551 close(r.done) 552 r.done = nil 553 } 554 555 func (svc *service) regServiceWAN(port string) error { 556 c := NewClient(WithScope(ScopeWAN), WithLogger(svc.s.lg)) 557 conn, err := c.newTCPConnection(svc.s.registryAddr) 558 if err != nil { 559 return err 560 } 561 defer conn.Close() 562 proxied := false 563 if svc.providerID != svc.s.providerID { 564 proxied = true 565 } 566 return conn.SendRecv(®ServiceInWAN{svc.publisherName, svc.serviceName, svc.providerID, port, proxied}, nil) 567 } 568 569 func (svc *service) delServiceWAN() error { 570 c := NewClient(WithScope(ScopeWAN), WithLogger(svc.s.lg)) 571 conn, err := c.newTCPConnection(svc.s.registryAddr) 572 if err != nil { 573 return err 574 } 575 defer conn.Close() 576 return conn.Send(&delServiceInWAN{svc.publisherName, svc.serviceName, svc.providerID}) 577 } 578 579 // support wildcard 580 func queryServiceWAN(registryAddr, publisherName, serviceName string, lg Logger) (serviceInfos []*ServiceInfo) { 581 c := NewClient(WithScope(ScopeWAN), WithLogger(lg)) 582 conn, err := c.newTCPConnection(registryAddr) 583 if err != nil { 584 lg.Errorf("connect to registry failed: %v", err) 585 return 586 } 587 defer conn.Close() 588 589 conn.SendRecv(&queryServiceInWAN{publisherName, serviceName}, &serviceInfos) 590 return 591 } 592 593 func (c *Client) lookupServiceWAN(publisherName, serviceName string, providerIDs ...string) (addrs []string) { 594 has := func(target string) bool { 595 if len(providerIDs) == 0 { // match all 596 return true 597 } 598 for _, str := range providerIDs { 599 if str == target { 600 return true 601 } 602 } 603 return false 604 } 605 606 serviceInfos := queryServiceWAN(c.registryAddr, publisherName, serviceName, c.lg) 607 for _, provider := range serviceInfos { 608 if has(provider.ProviderID) { 609 addrs = append(addrs, provider.Addr) 610 } 611 } 612 return 613 } 614 615 type providerMap struct { 616 sync.RWMutex 617 providers map[string]*providerInfo 618 } 619 620 type rootRegistry struct { 621 sync.RWMutex 622 // "publisher_service": {"providerID1":{timeStamp, "192.168.0.11:12345"}, "providerID2":{timeStamp, "192.168.0.26:33556"}} 623 serviceMap map[string]*providerMap 624 } 625 626 func pingService(addr string) error { 627 conn, err := net.DialTimeout("tcp", addr, time.Second) 628 if err != nil { 629 return ErrServiceNotReachable 630 } 631 conn.Close() 632 return nil 633 } 634 635 // reply OK or error 636 type testReverseProxy struct { 637 port string 638 } 639 640 func (msg *testReverseProxy) Handle(stream ContextStream) (reply interface{}) { 641 ss := stream.(*streamServerStream) 642 rhost, _, _ := net.SplitHostPort(ss.netconn.RemoteAddr().String()) 643 644 raddr := rhost + ":" + msg.port 645 if err := pingService(raddr); err != nil { 646 return err 647 } 648 return OK 649 } 650 651 // reply OK or error 652 type regServiceInWAN struct { 653 publisher string 654 service string 655 providerID string 656 port string 657 proxied bool 658 } 659 660 func (msg *regServiceInWAN) Handle(stream ContextStream) (reply interface{}) { 661 rr := stream.GetContext().(*rootRegistry) 662 ss := stream.(*streamServerStream) 663 rhost, _, _ := net.SplitHostPort(ss.netconn.RemoteAddr().String()) 664 665 raddr := rhost + ":" + msg.port 666 if err := pingService(raddr); err != nil { 667 return err 668 } 669 670 name := msg.publisher + "_" + msg.service 671 rr.Lock() 672 pmap, has := rr.serviceMap[name] 673 if !has { 674 pmap = &providerMap{ 675 providers: make(map[string]*providerInfo), 676 } 677 rr.serviceMap[name] = pmap 678 } 679 rr.Unlock() 680 681 pinfo := &providerInfo{time.Now(), raddr, msg.proxied} 682 pmap.Lock() 683 pmap.providers[msg.providerID] = pinfo 684 pmap.Unlock() 685 686 return OK 687 } 688 689 // no reply 690 type delServiceInWAN struct { 691 publisher string 692 service string 693 providerID string 694 } 695 696 func (msg *delServiceInWAN) Handle(stream ContextStream) (reply interface{}) { 697 rr := stream.GetContext().(*rootRegistry) 698 name := msg.publisher + "_" + msg.service 699 rr.RLock() 700 pmap, has := rr.serviceMap[name] 701 rr.RUnlock() 702 if !has { 703 return nil 704 } 705 706 pmap.Lock() 707 delete(pmap.providers, msg.providerID) 708 pmap.Unlock() 709 710 return nil 711 } 712 713 // reply []*ServiceInfo 714 // support wildcard(*) matching 715 type queryServiceInWAN struct { 716 publisher string 717 service string 718 } 719 720 func (msg *queryServiceInWAN) Handle(stream ContextStream) (reply interface{}) { 721 rr := stream.GetContext().(*rootRegistry) 722 name := msg.publisher + "_" + msg.service 723 var serviceInfos []*ServiceInfo 724 725 walkProviderMap := func(service string, pmap *providerMap) { 726 pmap.RLock() 727 for pID, pInfo := range pmap.providers { 728 func() { 729 pmap.RUnlock() 730 defer pmap.RLock() 731 t := time.Now() 732 if t.After(pInfo.timeStamp.Add(15 * time.Minute)) { 733 if err := pingService(pInfo.addr); err != nil { 734 pmap.Lock() 735 delete(pmap.providers, pID) 736 pmap.Unlock() 737 return 738 } 739 pInfo.timeStamp = t 740 } 741 addr := pInfo.addr 742 if pInfo.proxied { 743 addr += "P" 744 } 745 svcInfo := &ServiceInfo{ProviderID: pID, Addr: addr} 746 if len(service) != 0 { 747 ss := strings.Split(service, "_") 748 svcInfo.Publisher = ss[0] 749 svcInfo.Service = ss[1] 750 } 751 serviceInfos = append(serviceInfos, svcInfo) 752 }() 753 } 754 pmap.RUnlock() 755 } 756 757 if strings.Contains(name, "*") { 758 rr.RLock() 759 for service, pmap := range rr.serviceMap { 760 rr.RUnlock() 761 if wildcardMatch(name, service) { 762 walkProviderMap(service, pmap) 763 } 764 rr.RLock() 765 } 766 rr.RUnlock() 767 } else { 768 rr.RLock() 769 pmap, has := rr.serviceMap[name] 770 rr.RUnlock() 771 if has { 772 walkProviderMap("", pmap) 773 } 774 } 775 776 return serviceInfos 777 } 778 779 func init() { 780 RegisterType((*regServiceInWAN)(nil)) 781 RegisterType((*delServiceInWAN)(nil)) 782 RegisterType((*queryServiceInWAN)(nil)) 783 RegisterType((*testReverseProxy)(nil)) 784 } 785 786 func (s *Server) registryCheckSaver() { 787 for { 788 time.Sleep(time.Minute) 789 svcs := queryServiceWAN(s.registryAddr, "*", "*", s.lg) 790 f, err := os.Create("services.record.updating") 791 if err != nil { 792 s.lg.Errorf("root registry: record file not created: %v", err) 793 return 794 } 795 for _, si := range svcs { 796 fmt.Fprintf(f, "%s %s %s %s\n", si.Publisher, si.Service, si.ProviderID, si.Addr) 797 } 798 f.Close() 799 os.Rename("services.record.updating", "services.record") 800 } 801 } 802 803 func (s *Server) startRootRegistry(port string) error { 804 svc := &service{ 805 publisherName: BuiltinPublisher, 806 serviceName: "rootRegistry", 807 providerID: s.providerID, 808 knownMsgTypes: make(map[reflect.Type]struct{}), 809 s: s, 810 } 811 svc.knownMsgTypes[reflect.TypeOf((*regServiceInWAN)(nil))] = struct{}{} 812 svc.knownMsgTypes[reflect.TypeOf((*delServiceInWAN)(nil))] = struct{}{} 813 svc.knownMsgTypes[reflect.TypeOf((*queryServiceInWAN)(nil))] = struct{}{} 814 svc.knownMsgTypes[reflect.TypeOf((*testReverseProxy)(nil))] = struct{}{} 815 816 rr := &rootRegistry{ 817 serviceMap: make(map[string]*providerMap), 818 } 819 f, err := os.Open("services.record") 820 if err == nil { 821 for { 822 var publisher, service, providerID, addr string 823 _, err := fmt.Fscanln(f, &publisher, &service, &providerID, &addr) 824 if err != nil { 825 break 826 } 827 name := publisher + "_" + service 828 pmap := rr.serviceMap[name] 829 if pmap == nil { 830 pmap = &providerMap{providers: make(map[string]*providerInfo)} 831 rr.serviceMap[name] = pmap 832 } 833 pinfo := &providerInfo{time.Now(), addr, false} 834 if addr[len(addr)-1] == 'P' { 835 pinfo.addr = addr[:len(addr)-1] 836 pinfo.proxied = true 837 } 838 pmap.providers[providerID] = pinfo 839 } 840 f.Close() 841 } 842 svc.fnOnNewStream = func(ctx Context) { 843 ctx.SetContext(rr) 844 } 845 tran, err := svc.newTCPTransport(port) 846 if err != nil { 847 return err 848 } 849 s.addCloser(tran) 850 return nil 851 }