func (ovl *Overlay) SendMessageSync(msg *protobuf.Message, routingType protobuf.RoutingType, replyTimeout time.Duration) (*protobuf.Message, bool, error) {
	if replyTimeout == 0 {
		replyTimeout = ovl.LocalNode.DefaultReplyTimeout
	}
	replyChan, success, err := ovl.SendMessage(msg, routingType, true, replyTimeout)
	if !success {
		return nil, false, err
	}
	select {
	case replyMsg := <-replyChan:
		return replyMsg.Msg, true, nil
	case <-time.After(replyTimeout):
		return nil, true, errors.New("Wait for reply timeout")
	}
}
SendMessageSync sends msg to the best next hop, returns reply message, if
send success (which is true if successfully send message to at least one next
hop), and aggregated error during message sending, will also returns error if
haven't receive reply within replyTimeout. Will use default reply timeout if
replyTimeout = 0.
package overlay
import (
	"errors"
	"fmt"
	"time"
	"github.com/nknorg/nnet/common"
	"github.com/nknorg/nnet/node"
	"github.com/nknorg/nnet/overlay/routing"
	"github.com/nknorg/nnet/protobuf"
)
type Overlay struct {
	LocalNode    *node.LocalNode
	LocalMsgChan chan *node.RemoteMessage
	routers      map[protobuf.RoutingType]routing.Router
	common.LifeCycle
}
func NewOverlay(localNode *node.LocalNode) (*Overlay, error) {
	if localNode == nil {
		return nil, errors.New("Local node is nil")
	}
	overlay := &Overlay{
		LocalNode:    localNode,
		LocalMsgChan: make(chan *node.RemoteMessage, localNode.OverlayLocalMsgChanLen),
		routers:      make(map[protobuf.RoutingType]routing.Router),
	}
	return overlay, nil
}
func (ovl *Overlay) GetLocalNode() *node.LocalNode {
	return ovl.LocalNode
}
func (ovl *Overlay) AddRouter(routingType protobuf.RoutingType, router routing.Router) error {
	_, ok := ovl.routers[routingType]
	if ok {
		return fmt.Errorf("Router for type %v is already added", routingType)
	}
	ovl.routers[routingType] = router
	return nil
}
func (ovl *Overlay) GetRouter(routingType protobuf.RoutingType) (routing.Router, error) {
	router, ok := ovl.routers[routingType]
	if !ok {
		return nil, fmt.Errorf("Router for type %v has not been added yet", routingType)
	}
	return router, nil
}
func (ovl *Overlay) GetRouters() []routing.Router {
	routers := make([]routing.Router, 0)
	for _, router := range ovl.routers {
		routers = append(routers, router)
	}
	return routers
}
func (ovl *Overlay) SetRouter(routingType protobuf.RoutingType, router routing.Router) {
	ovl.routers[routingType] = router
}
func (ovl *Overlay) StartRouters() error {
	for _, router := range ovl.routers {
		err := router.Start()
		if err != nil {
			return nil
		}
	}
	return nil
}
func (ovl *Overlay) StopRouters(err error) {
	for _, router := range ovl.routers {
		router.Stop(err)
	}
}
func (ovl *Overlay) SendMessage(msg *protobuf.Message, routingType protobuf.RoutingType, hasReply bool, replyTimeout time.Duration) (<-chan *node.RemoteMessage, bool, error) {
	router, err := ovl.GetRouter(routingType)
	if err != nil {
		return nil, false, err
	}
	return router.SendMessage(router, &node.RemoteMessage{Msg: msg}, hasReply, replyTimeout)
}
func (ovl *Overlay) SendMessageAsync(msg *protobuf.Message, routingType protobuf.RoutingType) (bool, error) {
	_, success, err := ovl.SendMessage(msg, routingType, false, 0)
	return success, err
}