Skip to content
Snippets Groups Projects
server.go 3 KiB
Newer Older
Oliver Herms's avatar
Oliver Herms committed
package server

import (
	"fmt"
	"io"
	"net"

Oliver Herms's avatar
Oliver Herms committed
	"github.com/bio-routing/bio-rd/config"
	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
	"github.com/bio-routing/bio-rd/routingtable"
Oliver Herms's avatar
Oliver Herms committed
	log "github.com/sirupsen/logrus"
)

const (
	uint16max  = 65535
	BGPVersion = 4
)

type BGPServer struct {
	listeners []*TCPListener
	acceptCh  chan *net.TCPConn
	peers     map[string]*Peer
	routerID  uint32
}

func NewBgpServer() *BGPServer {
	return &BGPServer{
		peers: make(map[string]*Peer),
	}
}

func (b *BGPServer) RouterID() uint32 {
	return b.routerID
}

func (b *BGPServer) Start(c *config.Global) error {
	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

	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() {
	for {
Oliver Herms's avatar
Oliver Herms committed
		// Disabled. We're active only for now.
Oliver Herms's avatar
Oliver Herms committed
		/*c := <-b.acceptCh
		fmt.Printf("Incoming connection!\n")
		fmt.Printf("Connection from: %v\n", c.RemoteAddr())
Oliver Herms's avatar
Oliver Herms committed

		peerAddr := strings.Split(c.RemoteAddr().String(), ":")[0]
		if _, ok := b.peers[peerAddr]; !ok {
			c.Close()
			log.WithFields(log.Fields{
				"source": c.RemoteAddr(),
			}).Warning("TCP connection from unknown source")
			continue
		}

		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")
Oliver Herms's avatar
Oliver Herms committed
		fmt.Printf("Initiating new ActiveFSM due to incoming connection from peer %s\n", peerAddr)
		fsm := NewActiveFSM2(b.peers[peerAddr])
		fsm.state = newActiveState(fsm)
		fsm.startConnectRetryTimer()

		fmt.Printf("Getting lock...\n")
		b.peers[peerAddr].fsmsMu.Lock()
		b.peers[peerAddr].fsms = append(b.peers[peerAddr].fsms, fsm)
		fmt.Printf("Releasing lock...\n")
		b.peers[peerAddr].fsmsMu.Unlock()

		go fsm.run()
		fsm.conCh <- c*/
Oliver Herms's avatar
Oliver Herms committed
	}
}

func (b *BGPServer) AddPeer(c config.Peer, rib routingtable.RouteTableClient) error {
Oliver Herms's avatar
Oliver Herms committed
	if c.LocalAS > uint16max || c.PeerAS > uint16max {
		return fmt.Errorf("32bit ASNs are not supported yet")
	}

Oliver Herms's avatar
Oliver Herms committed
	peer, err := NewPeer(c, rib, b)
Oliver Herms's avatar
Oliver Herms committed
	if err != nil {
		return err
	}

	peer.routerID = c.RouterID
	peerAddr := peer.GetAddr().String()
	b.peers[peerAddr] = peer
	b.peers[peerAddr].Start()

	return nil
}

Oliver Herms's avatar
Oliver Herms committed
func recvMsg(c net.Conn) (msg []byte, err error) {
Oliver Herms's avatar
Oliver Herms committed
	buffer := make([]byte, packet.MaxLen)
	_, err = io.ReadFull(c, buffer[0:packet.MinLen])
	if err != nil {
		return nil, fmt.Errorf("Read failed: %v", err)
	}

	l := int(buffer[16])*256 + int(buffer[17])
	toRead := l
	_, err = io.ReadFull(c, buffer[packet.MinLen:toRead])
	if err != nil {
		return nil, fmt.Errorf("Read failed: %v", err)
	}

	return buffer, nil
}