github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/server/mucp/rpc_server.go (about)

     1  // Copyright 2020 Asim Aslam
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     https://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // Original source: github.com/micro/go-micro/v3/server/mucp/rpc_server.go
    16  
    17  package mucp
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"io"
    23  	"net"
    24  	"runtime/debug"
    25  	"sort"
    26  	"strconv"
    27  	"strings"
    28  	"sync"
    29  	"time"
    30  
    31  	"github.com/tickoalcantara12/micro/v3/service/broker"
    32  	"github.com/tickoalcantara12/micro/v3/service/context/metadata"
    33  	"github.com/tickoalcantara12/micro/v3/service/logger"
    34  	"github.com/tickoalcantara12/micro/v3/service/network/transport"
    35  	"github.com/tickoalcantara12/micro/v3/service/registry"
    36  	"github.com/tickoalcantara12/micro/v3/service/server"
    37  	"github.com/tickoalcantara12/micro/v3/util/addr"
    38  	"github.com/tickoalcantara12/micro/v3/util/backoff"
    39  	"github.com/tickoalcantara12/micro/v3/util/codec"
    40  	raw "github.com/tickoalcantara12/micro/v3/util/codec/bytes"
    41  	mnet "github.com/tickoalcantara12/micro/v3/util/net"
    42  	"github.com/tickoalcantara12/micro/v3/util/socket"
    43  )
    44  
    45  type rpcServer struct {
    46  	router *router
    47  	exit   chan chan error
    48  
    49  	sync.RWMutex
    50  	opts        server.Options
    51  	handlers    map[string]server.Handler
    52  	subscribers map[server.Subscriber][]broker.Subscriber
    53  	// marks the serve as started
    54  	started bool
    55  	// used for first registration
    56  	registered bool
    57  	// subscribe to service name
    58  	subscriber broker.Subscriber
    59  	// graceful exit
    60  	wg *sync.WaitGroup
    61  
    62  	rsvc *registry.Service
    63  }
    64  
    65  var (
    66  	log = logger.NewHelper(logger.DefaultLogger).WithFields(map[string]interface{}{"service": "server"})
    67  )
    68  
    69  func wait(ctx context.Context) *sync.WaitGroup {
    70  	if ctx == nil {
    71  		return nil
    72  	}
    73  	wg, ok := ctx.Value("wait").(*sync.WaitGroup)
    74  	if !ok {
    75  		return nil
    76  	}
    77  	return wg
    78  }
    79  
    80  func newServer(opts ...server.Option) server.Server {
    81  	options := newOptions(opts...)
    82  	router := newRpcRouter()
    83  	router.hdlrWrappers = options.HdlrWrappers
    84  	router.subWrappers = options.SubWrappers
    85  
    86  	return &rpcServer{
    87  		opts:        options,
    88  		router:      router,
    89  		handlers:    make(map[string]server.Handler),
    90  		subscribers: make(map[server.Subscriber][]broker.Subscriber),
    91  		exit:        make(chan chan error),
    92  		wg:          wait(options.Context),
    93  	}
    94  }
    95  
    96  // HandleEvent handles inbound messages to the service directly
    97  // TODO: handle requests from an event. We won't send a response.
    98  func (s *rpcServer) HandleEvent(msg *broker.Message) error {
    99  	if msg.Header == nil {
   100  		// create empty map in case of headers empty to avoid panic later
   101  		msg.Header = make(map[string]string)
   102  	}
   103  
   104  	// get codec
   105  	ct := msg.Header["Content-Type"]
   106  
   107  	// default content type
   108  	if len(ct) == 0 {
   109  		msg.Header["Content-Type"] = DefaultContentType
   110  		ct = DefaultContentType
   111  	}
   112  
   113  	// get codec
   114  	cf, err := s.newCodec(ct)
   115  	if err != nil {
   116  		return err
   117  	}
   118  
   119  	// copy headers
   120  	hdr := make(map[string]string, len(msg.Header))
   121  	for k, v := range msg.Header {
   122  		hdr[k] = v
   123  	}
   124  
   125  	// create context
   126  	ctx := metadata.NewContext(context.Background(), hdr)
   127  
   128  	// TODO: inspect message header
   129  	// Micro-Service means a request
   130  	// Micro-Topic means a message
   131  
   132  	rpcMsg := &rpcMessage{
   133  		topic:       msg.Header["Micro-Topic"],
   134  		contentType: ct,
   135  		payload:     &raw.Frame{Data: msg.Body},
   136  		codec:       cf,
   137  		header:      msg.Header,
   138  		body:        msg.Body,
   139  	}
   140  
   141  	// existing router
   142  	r := server.Router(s.router)
   143  
   144  	// if the router is present then execute it
   145  	if s.opts.Router != nil {
   146  		// create a wrapped function
   147  		handler := s.opts.Router.ProcessMessage
   148  
   149  		// execute the wrapper for it
   150  		for i := len(s.opts.SubWrappers); i > 0; i-- {
   151  			handler = s.opts.SubWrappers[i-1](handler)
   152  		}
   153  
   154  		// set the router
   155  		r = rpcRouter{m: handler}
   156  	}
   157  
   158  	return r.ProcessMessage(ctx, rpcMsg)
   159  }
   160  
   161  // ServeConn serves a single connection
   162  func (s *rpcServer) ServeConn(sock transport.Socket) {
   163  	// streams are multiplexed on Micro-Stream or Micro-Id header
   164  	pool := socket.NewPool()
   165  
   166  	// get global waitgroup
   167  	s.Lock()
   168  	gg := s.wg
   169  	s.Unlock()
   170  
   171  	// waitgroup to wait for processing to finish
   172  	wg := &waitGroup{
   173  		gg: gg,
   174  	}
   175  
   176  	defer func() {
   177  		// wait till done
   178  		wg.Wait()
   179  
   180  		// close all the sockets for this connection
   181  		pool.Close()
   182  
   183  		// close underlying socket
   184  		sock.Close()
   185  
   186  		// recover any panics
   187  		if r := recover(); r != nil {
   188  			if logger.V(logger.ErrorLevel, log) {
   189  				log.Error("panic recovered: ", r)
   190  				log.Error(string(debug.Stack()))
   191  			}
   192  		}
   193  	}()
   194  
   195  	for {
   196  		var msg transport.Message
   197  		// process inbound messages one at a time
   198  		if err := sock.Recv(&msg); err != nil {
   199  			return
   200  		}
   201  
   202  		// check the message header for
   203  		// Micro-Service is a request
   204  		// Micro-Topic is a message
   205  		if t := msg.Header["Micro-Topic"]; len(t) > 0 {
   206  			// TODO: handle the error event
   207  			if err := s.HandleEvent(newMessage(msg)); err != nil {
   208  				msg.Header["Micro-Error"] = err.Error()
   209  			}
   210  			// write back some 200
   211  			if err := sock.Send(&transport.Message{
   212  				Header: msg.Header,
   213  			}); err != nil {
   214  				break
   215  			}
   216  			// we're done
   217  			continue
   218  		}
   219  
   220  		// business as usual
   221  
   222  		// use Micro-Stream as the stream identifier
   223  		// in the event its blank we'll always process
   224  		// on the same socket
   225  		id := msg.Header["Micro-Stream"]
   226  
   227  		// if there's no stream id then its a standard request
   228  		// use the Micro-Id
   229  		if len(id) == 0 {
   230  			id = msg.Header["Micro-Id"]
   231  		}
   232  
   233  		// check stream id
   234  		var stream bool
   235  
   236  		if v := getHeader("Micro-Stream", msg.Header); len(v) > 0 {
   237  			stream = true
   238  		}
   239  
   240  		// check if we have an existing socket
   241  		psock, ok := pool.Get(id)
   242  
   243  		// if we don't have a socket and its a stream
   244  		if !ok && stream {
   245  			// check if its a last stream EOS error
   246  			err := msg.Header["Micro-Error"]
   247  			if err == lastStreamResponseError.Error() {
   248  				pool.Release(psock)
   249  				continue
   250  			}
   251  		}
   252  
   253  		// got an existing socket already
   254  		if ok {
   255  			// we're starting processing
   256  			wg.Add(1)
   257  
   258  			// pass the message to that existing socket
   259  			if err := psock.Accept(&msg); err != nil {
   260  				// release the socket if there's an error
   261  				pool.Release(psock)
   262  			}
   263  
   264  			// done waiting
   265  			wg.Done()
   266  
   267  			// continue to the next message
   268  			continue
   269  		}
   270  
   271  		// no socket was found so its new
   272  		// set the local and remote values
   273  		psock.SetLocal(sock.Local())
   274  		psock.SetRemote(sock.Remote())
   275  
   276  		// load the socket with the current message
   277  		psock.Accept(&msg)
   278  
   279  		// now walk the usual path
   280  
   281  		// we use this Timeout header to set a server deadline
   282  		to := msg.Header["Timeout"]
   283  		// we use this Content-Type header to identify the codec needed
   284  		ct := msg.Header["Content-Type"]
   285  
   286  		// copy the message headers
   287  		hdr := make(map[string]string, len(msg.Header))
   288  		for k, v := range msg.Header {
   289  			hdr[k] = v
   290  		}
   291  
   292  		// set local/remote ips
   293  		hdr["Local"] = sock.Local()
   294  		hdr["Remote"] = sock.Remote()
   295  
   296  		// create new context with the metadata
   297  		ctx := metadata.NewContext(context.Background(), hdr)
   298  
   299  		// set the timeout from the header if we have it
   300  		if len(to) > 0 {
   301  			if n, err := strconv.ParseUint(to, 10, 64); err == nil {
   302  				var cancel context.CancelFunc
   303  				ctx, cancel = context.WithTimeout(ctx, time.Duration(n))
   304  				defer cancel()
   305  			}
   306  		}
   307  
   308  		// if there's no content type default it
   309  		if len(ct) == 0 {
   310  			msg.Header["Content-Type"] = DefaultContentType
   311  			ct = DefaultContentType
   312  		}
   313  
   314  		// setup old protocol
   315  		cf := setupProtocol(&msg)
   316  
   317  		// no legacy codec needed
   318  		if cf == nil {
   319  			var err error
   320  			// try get a new codec
   321  			if cf, err = s.newCodec(ct); err != nil {
   322  				// no codec found so send back an error
   323  				sock.Send(&transport.Message{
   324  					Header: map[string]string{
   325  						"Content-Type": "text/plain",
   326  					},
   327  					Body: []byte(err.Error()),
   328  				})
   329  
   330  				// release the socket we just created
   331  				pool.Release(psock)
   332  				// now continue
   333  				continue
   334  			}
   335  		}
   336  
   337  		// create a new rpc codec based on the pseudo socket and codec
   338  		rcodec := newRpcCodec(&msg, psock, cf)
   339  		// check the protocol as well
   340  		protocol := rcodec.String()
   341  
   342  		// internal request
   343  		request := &rpcRequest{
   344  			service:     getHeader("Micro-Service", msg.Header),
   345  			method:      getHeader("Micro-Method", msg.Header),
   346  			endpoint:    getHeader("Micro-Endpoint", msg.Header),
   347  			contentType: ct,
   348  			codec:       rcodec,
   349  			header:      msg.Header,
   350  			body:        msg.Body,
   351  			socket:      psock,
   352  			stream:      stream,
   353  		}
   354  
   355  		// internal response
   356  		response := &rpcResponse{
   357  			header: make(map[string]string),
   358  			socket: psock,
   359  			codec:  rcodec,
   360  		}
   361  
   362  		// set router
   363  		r := server.Router(s.router)
   364  
   365  		// if not nil use the router specified
   366  		if s.opts.Router != nil {
   367  			// create a wrapped function
   368  			handler := func(ctx context.Context, req server.Request, rsp interface{}) error {
   369  				return s.opts.Router.ServeRequest(ctx, req, rsp.(server.Response))
   370  			}
   371  
   372  			// execute the wrapper for it
   373  			for i := len(s.opts.HdlrWrappers); i > 0; i-- {
   374  				handler = s.opts.HdlrWrappers[i-1](handler)
   375  			}
   376  
   377  			// set the router
   378  			r = rpcRouter{h: handler}
   379  		}
   380  
   381  		// wait for two coroutines to exit
   382  		// serve the request and process the outbound messages
   383  		wg.Add(2)
   384  
   385  		// process the outbound messages from the socket
   386  		go func(id string, psock *socket.Socket) {
   387  			defer func() {
   388  				// TODO: don't hack this but if its grpc just break out of the stream
   389  				// We do this because the underlying connection is h2 and its a stream
   390  				switch protocol {
   391  				case "grpc":
   392  					sock.Close()
   393  				}
   394  				// release the socket
   395  				pool.Release(psock)
   396  				// signal we're done
   397  				wg.Done()
   398  
   399  				// recover any panics for outbound process
   400  				if r := recover(); r != nil {
   401  					if logger.V(logger.ErrorLevel, log) {
   402  						log.Error("panic recovered: ", r)
   403  						log.Error(string(debug.Stack()))
   404  					}
   405  				}
   406  			}()
   407  
   408  			for {
   409  				// get the message from our internal handler/stream
   410  				m := new(transport.Message)
   411  				if err := psock.Process(m); err != nil {
   412  					return
   413  				}
   414  
   415  				// send the message back over the socket
   416  				if err := sock.Send(m); err != nil {
   417  					return
   418  				}
   419  			}
   420  		}(id, psock)
   421  
   422  		// serve the request in a go routine as this may be a stream
   423  		go func(id string, psock *socket.Socket) {
   424  			defer func() {
   425  				// release the socket
   426  				pool.Release(psock)
   427  				// signal we're done
   428  				wg.Done()
   429  
   430  				// recover any panics for call handler
   431  				if r := recover(); r != nil {
   432  					log.Error("panic recovered: ", r)
   433  					log.Error(string(debug.Stack()))
   434  				}
   435  			}()
   436  
   437  			// serve the actual request using the request router
   438  			if serveRequestError := r.ServeRequest(ctx, request, response); serveRequestError != nil {
   439  				// write an error response
   440  				writeError := rcodec.Write(&codec.Message{
   441  					Header: msg.Header,
   442  					Error:  serveRequestError.Error(),
   443  					Type:   codec.Error,
   444  				}, nil)
   445  
   446  				// if the server request is an EOS error we let the socket know
   447  				// sometimes the socket is already closed on the other side, so we can ignore that error
   448  				alreadyClosed := serveRequestError == lastStreamResponseError && writeError == io.EOF
   449  
   450  				// could not write error response
   451  				if writeError != nil && !alreadyClosed {
   452  					log.Debugf("rpc: unable to write error response: %v", writeError)
   453  				}
   454  			}
   455  		}(id, psock)
   456  	}
   457  }
   458  
   459  func (s *rpcServer) newCodec(contentType string) (codec.NewCodec, error) {
   460  	if cf, ok := s.opts.Codecs[contentType]; ok {
   461  		return cf, nil
   462  	}
   463  	if cf, ok := DefaultCodecs[contentType]; ok {
   464  		return cf, nil
   465  	}
   466  	return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType)
   467  }
   468  
   469  func (s *rpcServer) Options() server.Options {
   470  	s.RLock()
   471  	opts := s.opts
   472  	s.RUnlock()
   473  	return opts
   474  }
   475  
   476  func (s *rpcServer) Init(opts ...server.Option) error {
   477  	s.Lock()
   478  	defer s.Unlock()
   479  
   480  	for _, opt := range opts {
   481  		opt(&s.opts)
   482  	}
   483  	// update router if its the default
   484  	if s.opts.Router == nil {
   485  		r := newRpcRouter()
   486  		r.hdlrWrappers = s.opts.HdlrWrappers
   487  		r.serviceMap = s.router.serviceMap
   488  		r.subWrappers = s.opts.SubWrappers
   489  		s.router = r
   490  	}
   491  
   492  	s.rsvc = nil
   493  
   494  	return nil
   495  }
   496  
   497  func (s *rpcServer) NewHandler(h interface{}, opts ...server.HandlerOption) server.Handler {
   498  	return s.router.NewHandler(h, opts...)
   499  }
   500  
   501  func (s *rpcServer) Handle(h server.Handler) error {
   502  	s.Lock()
   503  	defer s.Unlock()
   504  
   505  	if err := s.router.Handle(h); err != nil {
   506  		return err
   507  	}
   508  
   509  	s.handlers[h.Name()] = h
   510  
   511  	return nil
   512  }
   513  
   514  func (s *rpcServer) NewSubscriber(topic string, sb interface{}, opts ...server.SubscriberOption) server.Subscriber {
   515  	return s.router.NewSubscriber(topic, sb, opts...)
   516  }
   517  
   518  func (s *rpcServer) Subscribe(sb server.Subscriber) error {
   519  	s.Lock()
   520  	defer s.Unlock()
   521  
   522  	if err := s.router.Subscribe(sb); err != nil {
   523  		return err
   524  	}
   525  
   526  	s.subscribers[sb] = nil
   527  	return nil
   528  }
   529  
   530  func (s *rpcServer) Register() error {
   531  	s.RLock()
   532  	rsvc := s.rsvc
   533  	config := s.Options()
   534  	s.RUnlock()
   535  
   536  	// only register if it exists or is not noop
   537  	if config.Registry == nil || config.Registry.String() == "noop" {
   538  		return nil
   539  	}
   540  
   541  	regFunc := func(service *registry.Service) error {
   542  		// create registry options
   543  		rOpts := []registry.RegisterOption{
   544  			registry.RegisterTTL(config.RegisterTTL),
   545  			registry.RegisterDomain(s.opts.Namespace),
   546  		}
   547  
   548  		var regErr error
   549  
   550  		for i := 0; i < 3; i++ {
   551  			// attempt to register
   552  			if err := config.Registry.Register(service, rOpts...); err != nil {
   553  				// set the error
   554  				regErr = err
   555  				// backoff then retry
   556  				time.Sleep(backoff.Do(i + 1))
   557  				continue
   558  			}
   559  			// success so nil error
   560  			regErr = nil
   561  			break
   562  		}
   563  
   564  		return regErr
   565  	}
   566  
   567  	// have we registered before?
   568  	if rsvc != nil {
   569  		if err := regFunc(rsvc); err != nil {
   570  			return err
   571  		}
   572  		return nil
   573  	}
   574  
   575  	var err error
   576  	var advt, host, port string
   577  	var cacheService bool
   578  
   579  	// check the advertise address first
   580  	// if it exists then use it, otherwise
   581  	// use the address
   582  	if len(config.Advertise) > 0 {
   583  		advt = config.Advertise
   584  	} else {
   585  		advt = config.Address
   586  	}
   587  
   588  	if cnt := strings.Count(advt, ":"); cnt >= 1 {
   589  		// ipv6 address in format [host]:port or ipv4 host:port
   590  		host, port, err = net.SplitHostPort(advt)
   591  		if err != nil {
   592  			return err
   593  		}
   594  	} else {
   595  		host = advt
   596  	}
   597  
   598  	if ip := net.ParseIP(host); ip != nil {
   599  		cacheService = true
   600  	}
   601  
   602  	addr, err := addr.Extract(host)
   603  	if err != nil {
   604  		return err
   605  	}
   606  
   607  	// make copy of metadata
   608  	md := metadata.Copy(config.Metadata)
   609  
   610  	// mq-rpc(eg. nats) doesn't need the port. its addr is queue name.
   611  	if port != "" {
   612  		addr = mnet.HostPort(addr, port)
   613  	}
   614  
   615  	// register service
   616  	node := &registry.Node{
   617  		Id:       config.Name + "-" + config.Id,
   618  		Address:  addr,
   619  		Metadata: md,
   620  	}
   621  
   622  	node.Metadata["transport"] = config.Transport.String()
   623  	node.Metadata["broker"] = config.Broker.String()
   624  	node.Metadata["server"] = s.String()
   625  	node.Metadata["registry"] = config.Registry.String()
   626  	node.Metadata["protocol"] = "mucp"
   627  
   628  	s.RLock()
   629  
   630  	// Maps are ordered randomly, sort the keys for consistency
   631  	var handlerList []string
   632  	for n, e := range s.handlers {
   633  		// Only advertise non internal handlers
   634  		if !e.Options().Internal {
   635  			handlerList = append(handlerList, n)
   636  		}
   637  	}
   638  
   639  	sort.Strings(handlerList)
   640  
   641  	var subscriberList []server.Subscriber
   642  	for e := range s.subscribers {
   643  		// Only advertise non internal subscribers
   644  		if !e.Options().Internal {
   645  			subscriberList = append(subscriberList, e)
   646  		}
   647  	}
   648  
   649  	sort.Slice(subscriberList, func(i, j int) bool {
   650  		return subscriberList[i].Topic() > subscriberList[j].Topic()
   651  	})
   652  
   653  	endpoints := make([]*registry.Endpoint, 0, len(handlerList)+len(subscriberList))
   654  
   655  	for _, n := range handlerList {
   656  		endpoints = append(endpoints, s.handlers[n].Endpoints()...)
   657  	}
   658  
   659  	for _, e := range subscriberList {
   660  		endpoints = append(endpoints, e.Endpoints()...)
   661  	}
   662  
   663  	service := &registry.Service{
   664  		Name:      config.Name,
   665  		Version:   config.Version,
   666  		Nodes:     []*registry.Node{node},
   667  		Endpoints: endpoints,
   668  	}
   669  
   670  	// get registered value
   671  	registered := s.registered
   672  
   673  	s.RUnlock()
   674  
   675  	if !registered {
   676  		if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   677  			log.Infof("Registry [%s] Registering node: %s", config.Registry.String(), node.Id)
   678  		}
   679  	}
   680  
   681  	// register the service
   682  	if err := regFunc(service); err != nil {
   683  		return err
   684  	}
   685  
   686  	// already registered? don't need to register subscribers
   687  	if registered {
   688  		return nil
   689  	}
   690  
   691  	s.Lock()
   692  	defer s.Unlock()
   693  
   694  	// set what we're advertising
   695  	s.opts.Advertise = addr
   696  
   697  	// router can exchange messages
   698  	if s.opts.Router != nil {
   699  		// subscribe to the topic with own name
   700  		sub, err := s.opts.Broker.Subscribe(config.Name, s.HandleEvent)
   701  		if err != nil {
   702  			return err
   703  		}
   704  
   705  		// save the subscriber
   706  		s.subscriber = sub
   707  	}
   708  
   709  	// subscribe for all of the subscribers
   710  	for sb := range s.subscribers {
   711  		var opts []broker.SubscribeOption
   712  		if queue := sb.Options().Queue; len(queue) > 0 {
   713  			opts = append(opts, broker.Queue(queue))
   714  		}
   715  
   716  		if cx := sb.Options().Context; cx != nil {
   717  			opts = append(opts, broker.SubscribeContext(cx))
   718  		}
   719  
   720  		sub, err := config.Broker.Subscribe(sb.Topic(), s.HandleEvent, opts...)
   721  		if err != nil {
   722  			return err
   723  		}
   724  		if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   725  			log.Infof("Subscribing to topic: %s", sub.Topic())
   726  		}
   727  		s.subscribers[sb] = []broker.Subscriber{sub}
   728  	}
   729  	if cacheService {
   730  		s.rsvc = service
   731  	}
   732  	s.registered = true
   733  
   734  	return nil
   735  }
   736  
   737  func (s *rpcServer) Deregister() error {
   738  	var err error
   739  	var advt, host, port string
   740  
   741  	s.RLock()
   742  	config := s.Options()
   743  	s.RUnlock()
   744  
   745  	// only register if it exists or is not noop
   746  	if config.Registry == nil || config.Registry.String() == "noop" {
   747  		return nil
   748  	}
   749  
   750  	// check the advertise address first
   751  	// if it exists then use it, otherwise
   752  	// use the address
   753  	if len(config.Advertise) > 0 {
   754  		advt = config.Advertise
   755  	} else {
   756  		advt = config.Address
   757  	}
   758  
   759  	if cnt := strings.Count(advt, ":"); cnt >= 1 {
   760  		// ipv6 address in format [host]:port or ipv4 host:port
   761  		host, port, err = net.SplitHostPort(advt)
   762  		if err != nil {
   763  			return err
   764  		}
   765  	} else {
   766  		host = advt
   767  	}
   768  
   769  	addr, err := addr.Extract(host)
   770  	if err != nil {
   771  		return err
   772  	}
   773  
   774  	// mq-rpc(eg. nats) doesn't need the port. its addr is queue name.
   775  	if port != "" {
   776  		addr = mnet.HostPort(addr, port)
   777  	}
   778  
   779  	node := &registry.Node{
   780  		Id:      config.Name + "-" + config.Id,
   781  		Address: addr,
   782  	}
   783  
   784  	service := &registry.Service{
   785  		Name:    config.Name,
   786  		Version: config.Version,
   787  		Nodes:   []*registry.Node{node},
   788  	}
   789  
   790  	if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   791  		log.Infof("Registry [%s] Deregistering node: %s", config.Registry.String(), node.Id)
   792  	}
   793  	if err := config.Registry.Deregister(service, registry.DeregisterDomain(s.opts.Namespace)); err != nil {
   794  		return err
   795  	}
   796  
   797  	s.Lock()
   798  	s.rsvc = nil
   799  
   800  	if !s.registered {
   801  		s.Unlock()
   802  		return nil
   803  	}
   804  
   805  	s.registered = false
   806  
   807  	// close the subscriber
   808  	if s.subscriber != nil {
   809  		s.subscriber.Unsubscribe()
   810  		s.subscriber = nil
   811  	}
   812  
   813  	for sb, subs := range s.subscribers {
   814  		for _, sub := range subs {
   815  			if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   816  				log.Infof("Unsubscribing %s from topic: %s", node.Id, sub.Topic())
   817  			}
   818  			sub.Unsubscribe()
   819  		}
   820  		s.subscribers[sb] = nil
   821  	}
   822  
   823  	s.Unlock()
   824  	return nil
   825  }
   826  
   827  func (s *rpcServer) Start() error {
   828  	s.RLock()
   829  	if s.started {
   830  		s.RUnlock()
   831  		return nil
   832  	}
   833  	s.RUnlock()
   834  
   835  	config := s.Options()
   836  
   837  	// start listening on the transport
   838  	ts, err := config.Transport.Listen(config.Address)
   839  	if err != nil {
   840  		return err
   841  	}
   842  
   843  	if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   844  		log.Infof("Transport [%s] Listening on %s", config.Transport.String(), ts.Addr())
   845  	}
   846  
   847  	// swap address
   848  	s.Lock()
   849  	addr := s.opts.Address
   850  	s.opts.Address = ts.Addr()
   851  	s.Unlock()
   852  
   853  	bname := config.Broker.String()
   854  
   855  	// connect to the broker
   856  	if err := config.Broker.Connect(); err != nil {
   857  		if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
   858  			log.Errorf("Broker [%s] connect error: %v", bname, err)
   859  		}
   860  		return err
   861  	}
   862  
   863  	if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   864  		log.Infof("Broker [%s] Connected to %s", bname, config.Broker.Address())
   865  	}
   866  
   867  	// use RegisterCheck func before register
   868  	if err = s.opts.RegisterCheck(s.opts.Context); err != nil {
   869  		if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
   870  			log.Errorf("Server %s-%s register check error: %s", config.Name, config.Id, err)
   871  		}
   872  	} else {
   873  		// announce self to the world
   874  		if err = s.Register(); err != nil {
   875  			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
   876  				log.Errorf("Server %s-%s register error: %s", config.Name, config.Id, err)
   877  			}
   878  		}
   879  	}
   880  
   881  	exit := make(chan bool)
   882  
   883  	go func() {
   884  		for {
   885  			// listen for connections
   886  			err := ts.Accept(s.ServeConn)
   887  
   888  			// TODO: listen for messages
   889  			// msg := broker.Exchange(service).Consume()
   890  
   891  			select {
   892  			// check if we're supposed to exit
   893  			case <-exit:
   894  				return
   895  			// check the error and backoff
   896  			default:
   897  				if err != nil {
   898  					if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
   899  						log.Errorf("Accept error: %v", err)
   900  					}
   901  					time.Sleep(time.Second)
   902  					continue
   903  				}
   904  			}
   905  
   906  			// no error just exit
   907  			return
   908  		}
   909  	}()
   910  
   911  	go func() {
   912  		t := new(time.Ticker)
   913  
   914  		// only process if it exists
   915  		if s.opts.RegisterInterval > time.Duration(0) {
   916  			// new ticker
   917  			t = time.NewTicker(s.opts.RegisterInterval)
   918  		}
   919  
   920  		// return error chan
   921  		var ch chan error
   922  
   923  	Loop:
   924  		for {
   925  			select {
   926  			// register self on interval
   927  			case <-t.C:
   928  				s.RLock()
   929  				registered := s.registered
   930  				s.RUnlock()
   931  				rerr := s.opts.RegisterCheck(s.opts.Context)
   932  				if rerr != nil && registered {
   933  					if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
   934  						log.Errorf("Server %s-%s register check error: %s, deregister it", config.Name, config.Id, rerr)
   935  					}
   936  					// deregister self in case of error
   937  					if err := s.Deregister(); err != nil {
   938  						if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
   939  							log.Errorf("Server %s-%s deregister error: %s", config.Name, config.Id, err)
   940  						}
   941  					}
   942  				} else if rerr != nil && !registered {
   943  					if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
   944  						log.Errorf("Server %s-%s register check error: %s", config.Name, config.Id, rerr)
   945  					}
   946  					continue
   947  				}
   948  				if err := s.Register(); err != nil {
   949  					if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
   950  						log.Errorf("Server %s-%s register error: %s", config.Name, config.Id, err)
   951  					}
   952  				}
   953  			// wait for exit
   954  			case ch = <-s.exit:
   955  				t.Stop()
   956  				close(exit)
   957  				break Loop
   958  			}
   959  		}
   960  
   961  		s.RLock()
   962  		registered := s.registered
   963  		s.RUnlock()
   964  		if registered {
   965  			// deregister self
   966  			if err := s.Deregister(); err != nil {
   967  				if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
   968  					log.Errorf("Server %s-%s deregister error: %s", config.Name, config.Id, err)
   969  				}
   970  			}
   971  		}
   972  
   973  		s.Lock()
   974  		swg := s.wg
   975  		s.Unlock()
   976  
   977  		// wait for requests to finish
   978  		if swg != nil {
   979  			swg.Wait()
   980  		}
   981  
   982  		// close transport listener
   983  		ch <- ts.Close()
   984  
   985  		if logger.V(logger.InfoLevel, logger.DefaultLogger) {
   986  			log.Infof("Broker [%s] Disconnected from %s", bname, config.Broker.Address())
   987  		}
   988  		// disconnect the broker
   989  		if err := config.Broker.Disconnect(); err != nil {
   990  			if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
   991  				log.Errorf("Broker [%s] Disconnect error: %v", bname, err)
   992  			}
   993  		}
   994  
   995  		// swap back address
   996  		s.Lock()
   997  		s.opts.Address = addr
   998  		s.Unlock()
   999  	}()
  1000  
  1001  	// mark the server as started
  1002  	s.Lock()
  1003  	s.started = true
  1004  	s.Unlock()
  1005  
  1006  	return nil
  1007  }
  1008  
  1009  func (s *rpcServer) Stop() error {
  1010  	s.RLock()
  1011  	if !s.started {
  1012  		s.RUnlock()
  1013  		return nil
  1014  	}
  1015  	s.RUnlock()
  1016  
  1017  	ch := make(chan error)
  1018  	s.exit <- ch
  1019  
  1020  	err := <-ch
  1021  	s.Lock()
  1022  	s.started = false
  1023  	s.Unlock()
  1024  
  1025  	return err
  1026  }
  1027  
  1028  func (s *rpcServer) String() string {
  1029  	return "mucp"
  1030  }