gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/server/rpc_server.go (about)

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