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  }