package es.tid.bgp.bgp4Peer.peer;
import es.tid.bgp.bgp4Peer.bgp4session.BGP4SessionsInformation;
import es.tid.bgp.bgp4Peer.management.BGP4ManagementServer;
import es.tid.bgp.bgp4Peer.updateTEDB.UpdateDispatcher;
import es.tid.tedb.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* BGP-LS Speaker.
* This class is a BGP-LS peer which has two modes:
* - Listens to incoming connections
* - Launches new BGP session with a list of peers.
* It can send periodically its learnt topology to other peers.
* TEDB can be initialized from:
* - XML file with the topolgoy
* - Other BGP-LS Sessions
*
* @author pac ogondio
*
*/
public class BGPPeer {
/**
* Session server. It opens a socket to listen to new connections.
*/
private BGP4SessionServerManager bgp4SessionServer;
/**
* Session client. It connects to peers.
*/
private BGP4SessionClientManager bgp4SessionClientManager;
/**
* BGP4 parameters. Needed to configure the connections.
*/
private BGP4Parameters params;
/**
* List of opened BGP4 sessions.
*/
private BGP4SessionsInformation bgp4SessionsInformation;
/**
* Topology database only for interDomain Links.
*/
private MultiDomainTEDB multiDomainTEDB;
/**
* Table with domainID - TEDB.
* The BGP-LS Peer can have several domains
*/
private Hashtable<String,TEDB> intraTEDBs;
/**
* Full TEDB with all Links
*/
private SimpleTEDB fullTEDB;
/**
* Class to send periodically the topology
*/
//private DomainTEDB readDomainTEDB;
/**
* True: This peer sends the topology to other peers
* False: This peer does NOT send the topology to other peers
*/
private boolean sendTopology;
/**
*
*/
private SendTopology sendTopologyTask;
/**
*
*/
private boolean saveTopology;
private SaveTopologyinDB saveTopologyDB;
/**
*
*/
/**
* List of peers to establish connections.
*/
private LinkedList<BGP4LSPeerInfo> peersToConnect;
//Whitelist and blacklist not yet implemented
/**
* Loggers
*/
private Logger logParser;
private Logger logClient;
private Logger logServer;
/**
* Class to read and process the BGP4 update messages
*/
private UpdateDispatcher ud;
/**
* Executor. To execute the session server, to execute periodically the session client.
*/
private ScheduledThreadPoolExecutor executor;
/**
* Function to configure the BGP4 Peer without specifying the file. It will read a file with name: BGP4Parameters.xml
*/
public void configure (){
this.configure (null);
}
/**
* Function to configure the BGP4 peer.
* It created the loggers, the executor,
* @param nameParametersFile Name of the Parameters File
*/
public void configure(String nameParametersFile){
configure(nameParametersFile, null, null);
}
/**
* Function to configure the BGP4 peer.
* It created the loggers, the executor,
* @param nameParametersFile Name of the Parameters File
* @param multiTEDB multidomain database
* @param iTEDBs internal domains database
*/
public void configure(String nameParametersFile, MultiDomainTEDB multiTEDB, Hashtable<String,TEDB> iTEDBs){
//First of all, read the parameters
if (nameParametersFile != null){
params=new BGP4Parameters(nameParametersFile);
}else{
params=new BGP4Parameters();
}
params.initialize();
peersToConnect = params.getPeersToConnect();
sendTopology = params.isSendTopology();
saveTopology = params.isSaveTopologyDB();
//Initialize loggers
// FileHandler fh;
// FileHandler fh1;
// FileHandler fh2;
// try {
// fh=new FileHandler(params.getBGP4LogFile());
logParser=LoggerFactory.getLogger("BGP4Parser");
// logParser.addHandler(fh);
// logParser.setLevel(Level.ALL);
// fh1=new FileHandler(params.getBGP4LogFileClient());
logClient=LoggerFactory.getLogger("BGP4Client");
// logClient.addHandler(fh1);
// logClient.setLevel(Level.ALL);
// fh2=new FileHandler(params.getBGP4LogFileServer());
logServer=LoggerFactory.getLogger("BGP4Peer");
// logServer.addHandler(fh2);
// logServer.setLevel(Level.ALL);
//
// } catch (Exception e1) {
// e1.printStackTrace();
// System.exit(1);
// }
logServer.info("Inizializing BGP4 Peer");
if (iTEDBs!= null) intraTEDBs=iTEDBs;
else intraTEDBs=new Hashtable<String,TEDB>();
if (multiTEDB!= null) multiDomainTEDB = multiTEDB;
else multiDomainTEDB = new MDTEDB();
if (params.getLearnTopology().equals("fromXML")){
//intraTEDBs=new Hashtable<Inet4Address,DomainTEDB>();
//multiDomainTEDB = new MDTEDB();
//intraTEDBs = FileTEDBUpdater.readMultipleDomainSimpleNetworks(params.getTopologyFile(), null, false,0,Integer.MAX_VALUE, false);
logParser.info("BGPIdentifier: "+params.getBGPIdentifier());
intraTEDBs = FileTEDBUpdater.readMultipleDomainSimpleNetworks(params.getTopologyFile(), null, false,0,Integer.MAX_VALUE, false, params.getBGPIdentifier());
//multiDomainTEDB.initializeFromFile(params.getTopologyFile());
multiDomainTEDB.initializeFromFile(params.getTopologyFile(), params.getBGPIdentifier());
}
// Create Thread executor
//FIXME: Actualizar n�mero de threads que se crean
executor = new ScheduledThreadPoolExecutor(20);//1 para el servidor, 1 para el que lanza y vigila los clientes
// Information about all the sessions of the PCE
if (params.isTest()) {
bgp4SessionsInformation = new BGP4SessionsInformation(params.isTest());
}
else{
bgp4SessionsInformation = new BGP4SessionsInformation();
}
//Create the task to send the topology. It has to be created because you can start sending the topology in the management (wirting): send topology on.
sendTopologyTask = new SendTopology();
saveTopologyDB= new SaveTopologyinDB();
if (params.isSaveTopologyDB() == true){
saveTopologyDB.configure(intraTEDBs, multiDomainTEDB, params.isSaveTopologyDB(), params.getTopologyDBIP().getHostAddress(), params.getTopologyDBport());
}
}
public void setWriteMultiTEDB(MultiDomainTEDB multiTEDB) {
this.multiDomainTEDB = multiTEDB;
saveTopologyDB.setMultiDomainTEDB(multiTEDB);
}
/*
//new function from Andrea
public void setWriteMultiAndIntraTEDB(MultiDomainTEDB multiTEDB, Hashtable<Inet4Address,DomainTEDB> intraTEDBs) {
this.multiDomainTEDB = multiTEDB;
this.intraTEDBs = intraTEDBs;
saveTopologyDB.setMultiDomainTEDB(multiTEDB);
saveTopologyDB.setIntraTEDBs(intraTEDBs);
}
*/
public void setReadDomainTEDB(DomainTEDB readDomainTEDB) {
//this.readDomainTEDB = readDomainTEDB;
//System.out.println("setReadDomain: readFomainTEDB().getDomainID()="+readDomainTEDB.getDomainID());
//System.out.println("setReadDomain: readFomainTEDB="+readDomainTEDB.printTopology());
if(readDomainTEDB.getDomainID() == null)
this.intraTEDBs.put("default", readDomainTEDB);
else
this.intraTEDBs.put(readDomainTEDB.getDomainID().toString(), readDomainTEDB);
}
public void createUpdateDispatcher(){
//Updater dispatcher
ud = new UpdateDispatcher(multiDomainTEDB,intraTEDBs);
}
/**
* Function to create the TEDBs of the peer.
* @param nameParametersFile Name of the Parameters File
*/
/**
* Start the session for the management of the BGP4.
*/
public void startManagementServer(){
logServer.debug("Initializing Management Server");
BGP4ManagementServer bms=new BGP4ManagementServer(params.getBGP4ManagementPort(),multiDomainTEDB,intraTEDBs,bgp4SessionsInformation,sendTopologyTask);
bms.start();
}
/**
* Function which start the peer as a client which try to establish new sessions with peers.
* It starts a new process for each peer.
*/
public void startClient(){
logClient.debug("Initializing Session Manager to connect as client");
if (params.getBGPIdentifier() != null){
Inet4Address BGPIdentifier=null;
try {
BGPIdentifier = (Inet4Address) InetAddress.getByName(params.getBGPIdentifier());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
for (int i =0;i<peersToConnect.size();i++){
bgp4SessionClientManager=new BGP4SessionClientManager(bgp4SessionsInformation,ud, peersToConnect.get(i), params.getBGP4Port(),params.getLocalBGPAddress(),params.getLocalBGPPort(),params.getHoldTime(),BGPIdentifier,params.getVersion(),params.getMyAutonomousSystem(),params.getKeepAliveTimer());
//FIXME: Ver si dejamos delay fijo o variable
executor.scheduleWithFixedDelay(bgp4SessionClientManager, 0,params.getDelay(), TimeUnit.MILLISECONDS);
}
}
else{
logClient.error("ERROR: BGPIdentifier is not configured. To configure: XML file (BGP4Parameters.xml) <localBGPAddress>.");
System.exit(1);
}
}
/**
* Function which starts the peer (listening BGP4 protocol) as a server.
* It starts once the session server manager.
*/
public void startServer(){
logServer.debug("Initializing Session Manager to connect as server");
Inet4Address localAddress=null;
Inet4Address BGPIdentifier=null;
if (params.getBGPIdentifier() != null){
try {
localAddress = (Inet4Address) InetAddress.getByName(params.getLocalBGPAddress());
BGPIdentifier = (Inet4Address) InetAddress.getByName(params.getBGPIdentifier());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
if (params.isTest()) {
bgp4SessionServer = new BGP4SessionServerManager(bgp4SessionsInformation, multiDomainTEDB, ud, params.getBGP4Port(), params.getHoldTime(), BGPIdentifier, params.getVersion(), params.getMyAutonomousSystem(), params.isNodelay(), localAddress, params.getKeepAliveTimer(), peersToConnect, params.isTest());
executor.execute(bgp4SessionServer);
}
else {
bgp4SessionServer = new BGP4SessionServerManager(bgp4SessionsInformation, multiDomainTEDB, ud, params.getBGP4Port(), params.getHoldTime(), BGPIdentifier, params.getVersion(), params.getMyAutonomousSystem(), params.isNodelay(), localAddress, params.getKeepAliveTimer(), peersToConnect);
executor.execute(bgp4SessionServer);
}
}else{
logServer.error("ERROR: BGPIdentifier is not configured. To configure: XML file (BGP4Parameters.xml) <localBGPAddress>.");
System.exit(1);
}
}
public void startSendTopology(){
if (params.isTest()) {
sendTopologyTask.configure(intraTEDBs, bgp4SessionsInformation, sendTopology, params.getInstanceID(),params.isSendIntradomainLinks(),this.multiDomainTEDB, params.isTest());
}
else{
sendTopologyTask.configure(intraTEDBs, bgp4SessionsInformation, sendTopology, params.getInstanceID(),params.isSendIntradomainLinks(),this.multiDomainTEDB);
}
executor.scheduleWithFixedDelay(sendTopologyTask, 0,params.getSendTopoDelay(), TimeUnit.MILLISECONDS);
}
public void startSaveTopology(){
//FIXME: ADD param to configure the delay
executor.scheduleWithFixedDelay(saveTopologyDB, 0,5000, TimeUnit.MILLISECONDS);
}
public SaveTopologyinDB getSaveTopologyDB() {
return saveTopologyDB;
}
public void setSaveTopologyDB(SaveTopologyinDB saveTopologyDB) {
this.saveTopologyDB = saveTopologyDB;
}
public boolean isSaveTopology() {
return saveTopology;
}
public void setSaveTopology(boolean saveTopology) {
this.saveTopology = saveTopology;
}
public UpdateDispatcher getUd() {
return ud;
}
public void setUd(UpdateDispatcher ud) {
this.ud = ud;
}
public void addSimpleTEDB(SimpleTEDB simpleTEDB, String domainID) {
this.intraTEDBs.put(domainID, simpleTEDB);
}
public void setSimpleTEDB(SimpleTEDB simpleTEDB) {
if(simpleTEDB.getDomainID() == null)
this.intraTEDBs.put("default", simpleTEDB);
else
this.intraTEDBs.put(simpleTEDB.getDomainID().toString(), simpleTEDB);
}
public void stopPeer(){
executor.shutdown();
}
public MultiDomainTEDB getMultiDomainTEDB() {
return multiDomainTEDB;
}
public Hashtable<String, TEDB> getIntraTEDBs() {
return intraTEDBs;
}
public void setIntraTEDBs(Hashtable<String, TEDB> intraTEDBs) {
this.intraTEDBs = intraTEDBs;
}
public void setMultiDomainTEDB(MultiDomainTEDB multiDomainTEDB) {
this.multiDomainTEDB = multiDomainTEDB;
}
}