github.com/godevsig/adaptiveservice@v0.9.23/server.go (about) 1 package adaptiveservice 2 3 import ( 4 "crypto/rand" 5 "encoding/hex" 6 "errors" 7 "net" 8 "os" 9 "reflect" 10 "strings" 11 "sync" 12 ) 13 14 // Server provides services. 15 type Server struct { 16 sync.Mutex 17 *conf 18 publisher string 19 broadcastPort string 20 rootRegistry bool 21 autoReverseProxy bool 22 serviceLister bool 23 ipObserver bool 24 errRecovers chan errorRecover 25 mq *msgQ 26 residentWorkers int 27 qSizePerCore int 28 msgTypeCheck bool 29 closers []closer 30 initialized bool 31 closed chan struct{} 32 } 33 34 // NewServer creates a server which publishes services. 35 func NewServer(options ...Option) *Server { 36 s := &Server{ 37 conf: newConf(), 38 publisher: "default.org", 39 errRecovers: make(chan errorRecover, 1), 40 residentWorkers: 1, 41 qSizePerCore: 32, 42 msgTypeCheck: true, 43 closed: make(chan struct{}), 44 } 45 46 for _, o := range options { 47 o(s.conf) 48 } 49 50 s.lg.Debugf("new server created") 51 return s 52 } 53 54 func genID() string { 55 var b []byte 56 57 itfs, _ := net.Interfaces() 58 for _, itf := range itfs { 59 dev, err := os.Readlink("/sys/class/net/" + itf.Name) 60 if err != nil || strings.Contains(dev, "virtual") { 61 continue 62 } 63 if len(itf.HardwareAddr) != 0 { 64 b = itf.HardwareAddr 65 break 66 } 67 } 68 69 if len(b) == 0 { 70 b = make([]byte, 6) 71 rand.Read(b) 72 } 73 74 id := hex.EncodeToString(b) 75 return id 76 } 77 78 func (s *Server) init() error { 79 if s.initialized { 80 return nil 81 } 82 s.initialized = true 83 initSigCleaner(s.lg) 84 addSigCloser(s) 85 s.mq = newMsgQ(s.residentWorkers, s.qSizePerCore, s.lg) 86 s.addCloser(s.mq) 87 88 if s.scope&ScopeLAN == ScopeLAN { 89 s.lg.Infof("configuring server in local network scope") 90 c := NewClient(WithScope(ScopeProcess|ScopeOS), WithLogger(s.lg)).SetDiscoverTimeout(0) 91 conn := <-c.Discover(BuiltinPublisher, SrvLANRegistry) 92 if conn != nil { 93 conn.Close() 94 s.lg.Infof("LAN registry running") 95 } else { 96 if len(s.broadcastPort) == 0 { 97 s.lg.Infof("LAN registry not found or configured") 98 s.scope &= ^ScopeLAN // not ScopeLAN 99 } else { 100 if err := s.publishLANRegistryService(); err != nil { 101 return err 102 } 103 s.lg.Infof("user specified broadcast port: %s, LAN registry service started", s.broadcastPort) 104 } 105 } 106 } 107 108 if s.scope&ScopeWAN == ScopeWAN { 109 s.lg.Infof("configuring server in public network scope") 110 if addr, err := discoverRegistryAddr(s.lg); err != nil { 111 if len(s.registryAddr) == 0 { 112 s.lg.Infof("root registry address not found or configured") 113 s.scope &= ^ScopeWAN // not ScopeWAN 114 } else { 115 if err := s.publishRegistryInfoService(); err != nil { 116 return err 117 } 118 s.lg.Infof("user specified root registry address: %s, registry info service started", s.registryAddr) 119 } 120 } else { 121 s.registryAddr = addr 122 s.lg.Infof("discovered root registry address: %s", addr) 123 } 124 } 125 126 if s.scope&ScopeLAN == ScopeLAN || s.scope&ScopeWAN == ScopeWAN { 127 if id, err := discoverProviderID(s.lg); err != nil { 128 if len(s.providerID) == 0 { 129 s.providerID = genID() 130 } 131 if err := s.publishProviderInfoService(); err != nil { 132 return err 133 } 134 s.lg.Infof("provider info service started with provider ID: %s", s.providerID) 135 } else { 136 s.providerID = id 137 s.lg.Infof("discovered provider ID: %s", s.providerID) 138 } 139 } 140 141 if s.rootRegistry { 142 if len(s.registryAddr) == 0 { 143 return errors.New("root registry address not configured") 144 } 145 if s.scope&ScopeWAN != ScopeWAN { 146 panic("scope error") 147 } 148 149 _, port, _ := net.SplitHostPort(s.registryAddr) 150 if err := s.startRootRegistry(port); err != nil { 151 return err 152 } 153 154 go s.registryCheckSaver() 155 s.lg.Infof("root registry started at %s", port) 156 } 157 158 if s.scope&ScopeWAN == ScopeWAN && s.autoReverseProxy { 159 canProxy := func() bool { 160 if s.rootRegistry { 161 return true 162 } 163 164 network := 0 165 addrs, _ := net.InterfaceAddrs() 166 for _, addr := range addrs { 167 ip, _, _ := net.ParseCIDR(addr.String()) 168 if ip.To4() != nil && !ip.IsLoopback() { 169 network++ 170 } 171 } 172 if network < 2 { 173 s.lg.Debugf("reverse proxy not needed in less than 2 networks") 174 return false 175 } 176 177 lnr, err := net.Listen("tcp", ":0") 178 if err != nil { 179 s.lg.Debugf("auto reverse proxy: listen error: %v", err) 180 return false 181 } 182 defer lnr.Close() 183 go func() { 184 for { 185 netconn, err := lnr.Accept() 186 if err != nil { 187 return 188 } 189 netconn.Close() 190 } 191 }() 192 addr := lnr.Addr().String() 193 _, port, _ := net.SplitHostPort(addr) // from [::]:43807 194 195 c := NewClient(WithScope(ScopeWAN), WithLogger(s.lg)) 196 conn, err := c.newTCPConnection(s.registryAddr) 197 if err != nil { 198 s.lg.Debugf("root registry not reachable: %v", err) 199 return false 200 } 201 defer conn.Close() 202 if err := conn.SendRecv(&testReverseProxy{port: port}, nil); err != nil { 203 s.lg.Debugf("reverse port not reachable: %v", err) 204 return false 205 } 206 return true 207 } 208 209 if canProxy() { 210 scope := ScopeLAN 211 if s.rootRegistry { 212 scope |= ScopeWAN 213 } 214 if err := s.publishReverseProxyService(scope); err != nil { 215 return err 216 } 217 s.lg.Infof("reverse proxy started") 218 } 219 } 220 221 if s.serviceLister { 222 if err := s.publishServiceListerService(ScopeProcess | ScopeOS); err != nil { 223 return err 224 } 225 s.lg.Infof("service lister started") 226 } 227 228 if s.ipObserver { 229 if err := s.publishIPObserverService(); err != nil { 230 return err 231 } 232 s.lg.Infof("IP observer started") 233 } 234 s.lg.Debugf("server initialized") 235 return nil 236 } 237 238 type service struct { 239 publisherName string 240 serviceName string 241 providerID string 242 knownMsgTypes map[reflect.Type]struct{} 243 s *Server 244 scope Scope 245 fnOnNewStream func(Context) // called on new stream accepted 246 fnOnConnect func(Netconn) (stop bool) // called on new connection established 247 fnOnDisconnect func(Netconn) // called on connection disconnected 248 } 249 250 func (svc *service) canHandle(msg interface{}) bool { 251 if _, ok := msg.(KnownMessage); !ok { 252 return false 253 } 254 if svc.s.msgTypeCheck { 255 _, has := svc.knownMsgTypes[reflect.TypeOf(msg)] 256 return has 257 } 258 return true 259 } 260 261 func (s *Server) publish(scope Scope, publisherName, serviceName string, knownMessages []KnownMessage, options ...ServiceOption) error { 262 s.lg.Debugf("publishing %s %s in scope %b", publisherName, serviceName, scope) 263 if !s.initialized { 264 if err := s.init(); err != nil { 265 return err 266 } 267 } 268 scope = s.scope & scope 269 s.lg.Debugf("adjusted %s %s in scope %b", publisherName, serviceName, scope) 270 271 newService := func() *service { 272 svc := &service{ 273 publisherName: publisherName, 274 serviceName: serviceName, 275 providerID: s.providerID, 276 knownMsgTypes: make(map[reflect.Type]struct{}), 277 s: s, 278 scope: scope, 279 } 280 281 for _, msg := range knownMessages { 282 tp := reflect.TypeOf(msg) 283 svc.knownMsgTypes[tp] = struct{}{} 284 } 285 return svc 286 } 287 288 svc := newService() 289 for _, opt := range options { 290 opt(svc) 291 } 292 293 if scope&ScopeProcess == ScopeProcess { 294 tran, err := svc.newChanTransport() 295 if err != nil { 296 return err 297 } 298 s.addCloser(tran) 299 } 300 if scope&ScopeOS == ScopeOS { 301 tran, err := svc.newUDSTransport() 302 if err != nil { 303 return err 304 } 305 s.addCloser(tran) 306 } 307 if scope&ScopeLAN == ScopeLAN || scope&ScopeWAN == ScopeWAN { 308 tran, err := svc.newTCPTransport("") 309 if err != nil { 310 return err 311 } 312 s.addCloser(tran) 313 } 314 315 return nil 316 } 317 318 // Publish publishes service to all available scope of Server s. 319 // knownMessages are messages that the service can handle, e.g. 320 // []KnownMessage{(*PublicStructA)(nil), (*PublicStructB)(nil), ...}, 321 // where (*PublicStructA) and (*PublicStructB) are the known messages that 322 // have `Handle(stream ContextStream) reply interface{}` method. 323 func (s *Server) Publish(serviceName string, knownMessages []KnownMessage, options ...ServiceOption) error { 324 if strings.ContainsAny(serviceName, "_/") { 325 panic("serviceName should not contain _ or /") 326 } 327 return s.publish(s.scope, s.publisher, serviceName, knownMessages, options...) 328 } 329 330 // PublishIn is like Publish, but with specified scope which should be 331 // a subset of the scope of Server s. 332 func (s *Server) PublishIn(scope Scope, serviceName string, knownMessages []KnownMessage, options ...ServiceOption) error { 333 if strings.ContainsAny(serviceName, "_/") { 334 panic("serviceName should not contain _ or /") 335 } 336 return s.publish(scope, s.publisher, serviceName, knownMessages, options...) 337 } 338 339 // Serve starts serving. 340 func (s *Server) Serve() error { 341 if !s.initialized { 342 if err := s.init(); err != nil { 343 return err 344 } 345 } 346 defer s.doClose() 347 s.lg.Infof("server in serve") 348 for e := range s.errRecovers { 349 if (e == noError{}) { 350 break 351 } 352 if e.Recover() { 353 s.lg.Infof("error recovered: %s : %v", e.String(), e.Error()) 354 } else { 355 s.lg.Errorf("error not recovered: %s : %v", e.String(), e.Error()) 356 return e.Error() 357 } 358 } 359 return nil 360 } 361 362 func (s *Server) addCloser(closer closer) { 363 s.closers = append(s.closers, closer) 364 } 365 366 // Close triggers the close procedure of the server. 367 func (s *Server) Close() { 368 if s.closers == nil { 369 return 370 } 371 s.errRecovers <- noError{} 372 } 373 374 // CloseWait triggers the close procedure and waits 375 // until the server is fully closed. 376 func (s *Server) CloseWait() { 377 s.Close() 378 <-s.closed 379 } 380 381 func (s *Server) close() { 382 if s.closers == nil { 383 return 384 } 385 s.errRecovers <- unrecoverableError{ErrServerClosed} 386 } 387 388 func (s *Server) doClose() { 389 s.Lock() 390 defer s.Unlock() 391 if s.closers == nil { 392 return 393 } 394 for _, closer := range s.closers { 395 closer.close() 396 } 397 s.lg.Infof("server closed") 398 s.closers = nil 399 close(s.closed) 400 }