Skip to content
Snippets Groups Projects
server.go 2.42 KiB
Newer Older
  • Learn to ignore specific revisions
  • Oliver Herms's avatar
    Oliver Herms committed
    package server
    
    import (
    	"fmt"
    	"net"
    
    Oliver Herms's avatar
    Oliver Herms committed
    	"strings"
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    
    Oliver Herms's avatar
    Oliver Herms committed
    	"github.com/bio-routing/bio-rd/config"
    
    Oliver Herms's avatar
    Oliver Herms committed
    	log "github.com/sirupsen/logrus"
    )
    
    const (
    	BGPVersion = 4
    )
    
    
    Oliver Herms's avatar
    Oliver Herms committed
    	listeners []*TCPListener
    	acceptCh  chan *net.TCPConn
    
    Oliver Herms's avatar
    Oliver Herms committed
    	routerID  uint32
    
    Oliver Herms's avatar
    Oliver Herms committed
    }
    
    
    type BGPServer interface {
    	RouterID() uint32
    	Start(*config.Global) error
    
    	AddPeer(config.Peer) error
    
    	GetPeerInfoAll() map[string]PeerInfo
    }
    
    func NewBgpServer() BGPServer {
    	return &bgpServer{}
    }
    
    func (b *bgpServer) GetPeerInfoAll() map[string]PeerInfo {
    	res := make(map[string]PeerInfo)
    	b.peers.Range(func(key, value interface{}) bool {
    		name := key.(string)
    		peer := value.(*peer)
    
    		res[name] = peer.snapshot()
    
    		return true
    	})
    	return res
    
    Oliver Herms's avatar
    Oliver Herms committed
    }
    
    
    func (b *bgpServer) RouterID() uint32 {
    
    Oliver Herms's avatar
    Oliver Herms committed
    	return b.routerID
    }
    
    
    func (b *bgpServer) Start(c *config.Global) error {
    
    Oliver Herms's avatar
    Oliver Herms committed
    	if err := c.SetDefaultGlobalConfigValues(); err != nil {
    		return fmt.Errorf("Failed to load defaults: %v", err)
    	}
    
    
    Christoph Petrausch's avatar
    Christoph Petrausch committed
    	log.Infof("ROUTER ID: %d\n", c.RouterID)
    
    Oliver Herms's avatar
    Oliver Herms committed
    	b.routerID = c.RouterID
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    	if c.Listen {
    		acceptCh := make(chan *net.TCPConn, 4096)
    		for _, addr := range c.LocalAddressList {
    			l, err := NewTCPListener(addr, c.Port, acceptCh)
    			if err != nil {
    				return fmt.Errorf("Failed to start TCPListener for %s: %v", addr.String(), err)
    			}
    			b.listeners = append(b.listeners, l)
    		}
    		b.acceptCh = acceptCh
    
    		go b.incomingConnectionWorker()
    	}
    
    	return nil
    }
    
    
    func (b *bgpServer) incomingConnectionWorker() {
    
    Oliver Herms's avatar
    Oliver Herms committed
    	for {
    
    Oliver Herms's avatar
    Oliver Herms committed
    		c := <-b.acceptCh
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    		peerAddr := strings.Split(c.RemoteAddr().String(), ":")[0]
    
    		peerInterface, ok := b.peers.Load(peerAddr)
    		if !ok {
    
    Oliver Herms's avatar
    Oliver Herms committed
    			c.Close()
    			log.WithFields(log.Fields{
    				"source": c.RemoteAddr(),
    			}).Warning("TCP connection from unknown source")
    			continue
    		}
    
    		peer := peerInterface.(*peer)
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    		log.WithFields(log.Fields{
    			"source": c.RemoteAddr(),
    		}).Info("Incoming TCP connection")
    
    
    Christoph Petrausch's avatar
    Christoph Petrausch committed
    		log.WithField("Peer", peerAddr).Debug("Sending incoming TCP connection to fsm for peer")
    
    		fsm := NewActiveFSM(peer)
    
    Oliver Herms's avatar
    Oliver Herms committed
    		fsm.state = newActiveState(fsm)
    		fsm.startConnectRetryTimer()
    
    
    		peer.fsmsMu.Lock()
    		peer.fsms = append(peer.fsms, fsm)
    		peer.fsmsMu.Unlock()
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    		go fsm.run()
    
    Oliver Herms's avatar
    Oliver Herms committed
    		fsm.conCh <- c
    
    Oliver Herms's avatar
    Oliver Herms committed
    	}
    }
    
    
    func (b *bgpServer) AddPeer(c config.Peer) error {
    	peer, err := newPeer(c, b)
    
    Oliver Herms's avatar
    Oliver Herms committed
    	if err != nil {
    		return err
    	}
    
    	peer.routerID = c.RouterID
    	peerAddr := peer.GetAddr().String()
    
    	b.peers.Store(peerAddr, peer)
    	peer.Start()
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    	return nil
    }