DiameterPeer.java

Go to the documentation of this file.
00001 /*
00002  * $Id: DiameterPeer.java 585 2008-10-02 19:11:46Z vingarzan $
00003  * 
00004  * Copyright (C) 2004-2006 FhG Fokus
00005  *
00006  * This file is part of Open IMS Core - an open source IMS CSCFs & HSS
00007  * implementation
00008  *
00009  * Open IMS Core is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * For a license to use the Open IMS Core software under conditions
00015  * other than those described here, or to purchase support for this
00016  * software, please contact Fraunhofer FOKUS by e-mail at the following
00017  * addresses:
00018  *     info@open-ims.org
00019  *
00020  * Open IMS Core is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License
00026  * along with this program; if not, write to the Free Software
00027  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  *
00029  */
00030 
00031 package de.fhg.fokus.diameter.DiameterPeer;
00032 
00033 
00034 import java.io.IOException;
00035 import java.io.StringReader;
00036 import java.net.InetAddress;
00037 import java.net.UnknownHostException;
00038 import java.util.Iterator;
00039 import java.util.Vector;
00040 import java.util.concurrent.ArrayBlockingQueue;
00041 
00042 
00043 import javax.xml.parsers.DocumentBuilder;
00044 import javax.xml.parsers.DocumentBuilderFactory;
00045 import javax.xml.parsers.ParserConfigurationException;
00046 
00047 import org.apache.log4j.Logger;
00048 import org.w3c.dom.Document;
00049 import org.w3c.dom.Node;
00050 import org.w3c.dom.NodeList;
00051 import org.xml.sax.InputSource;
00052 import org.xml.sax.SAXException;
00053 
00054 import de.fhg.fokus.diameter.DiameterPeer.data.AVP;
00055 import de.fhg.fokus.diameter.DiameterPeer.data.DiameterMessage;
00056 import de.fhg.fokus.diameter.DiameterPeer.data.DiameterTask;
00057 import de.fhg.fokus.diameter.DiameterPeer.peer.Application;
00058 import de.fhg.fokus.diameter.DiameterPeer.peer.Peer;
00059 import de.fhg.fokus.diameter.DiameterPeer.peer.PeerManager;
00060 import de.fhg.fokus.diameter.DiameterPeer.peer.StateMachine;
00061 import de.fhg.fokus.diameter.DiameterPeer.routing.RoutingEngine;
00062 import de.fhg.fokus.diameter.DiameterPeer.transaction.TransactionListener;
00063 import de.fhg.fokus.diameter.DiameterPeer.transaction.TransactionWorker;
00064 import de.fhg.fokus.diameter.DiameterPeer.transport.Acceptor;
00090 public class DiameterPeer {
00091     
00093     private static final Logger LOGGER = Logger.getLogger(DiameterPeer.class);
00094     
00096     public String FQDN;
00097     
00099     public String Realm;
00100     
00102     public int Vendor_Id;
00103     
00105     public String Product_Name;
00106     
00108     public int Tc;
00109     
00111     public Vector<Acceptor> acceptors;
00112     
00114     public boolean AcceptUnknownPeers;
00115 
00117     public boolean DropUnknownOnDisconnect;
00118 
00120     public Vector<Application> AuthApp,AcctApp;
00121     
00123     public RoutingEngine routingTable=null;
00124     
00126     public PeerManager peerManager;
00127         
00132     public Vector<EventListener> eventListeners;
00133     
00135     public int queueLength;
00136     
00138     public ArrayBlockingQueue<DiameterTask> queueTasks;
00139     
00141     private DiameterWorker workers[]; 
00142     
00144     public int workerCount=1;
00145 
00147     private TransactionWorker transactionWorker=null;
00148     
00150     Document config;    
00151     
00153     public int hopbyhop_id=0;
00154 
00156     public int endtoend_id=0;
00157     
00159     public synchronized int getNextHopByHopId()
00160     {
00161         return ++hopbyhop_id;
00162     }
00164     public synchronized int getNextEndToEndId()
00165     {
00166         return ++endtoend_id;
00167     }
00168     
00172     public DiameterPeer()
00173     {
00174         LOGGER.info("Bean style constructor called, don't forget to configure!");
00175     }
00176     
00182     public DiameterPeer(String xml)
00183     {
00184         configure(xml,false);
00185     }
00186     
00194     public void configure(String xml, boolean isFile)
00195     {
00196         Acceptor acc;
00197         NodeList nl;
00198         Node n,nv;
00199         int port,app_id,vendor_id;
00200         InetAddress addr;
00201         String fqdn,realm;
00202         Application app;
00203         
00204         eventListeners = new Vector<EventListener>();
00205         
00206         java.util.Random rand = new java.util.Random();
00207         hopbyhop_id = rand.nextInt();
00208         endtoend_id = ((int) (System.currentTimeMillis()&0xFFF))<<20;
00209         endtoend_id |= rand.nextInt() & 0xFFFFF;
00210     
00211         if (isFile){
00212             /* parse the config */
00213             if (!readConfigFile(xml)) {
00214                 LOGGER.error("DiameterPeer: Error parsing config file");
00215                 return;
00216             }
00217         }
00218         else {
00219             /* parse the config */
00220             if (!readConfigString(xml)) {
00221                 LOGGER.error("DiameterPeer: Error parsing config String");
00222                 return;
00223             }
00224         }
00225         
00226         FQDN = config.getDocumentElement().getAttribute("FQDN");
00227         LOGGER.info("FQDN: " + config.getDocumentElement().getAttribute("FQDN"));
00228         Realm = config.getDocumentElement().getAttribute("Realm");
00229         LOGGER.info("Realm: " + config.getDocumentElement().getAttribute("Realm"));
00230         Vendor_Id = Integer.parseInt(config.getDocumentElement().getAttribute("Vendor_Id"));
00231         LOGGER.info("Vendor_ID : " + Integer.parseInt(config.getDocumentElement().getAttribute("Vendor_Id")));
00232         Product_Name = config.getDocumentElement().getAttribute("Product_Name");
00233         LOGGER.info("Product Name: " + config.getDocumentElement().getAttribute("Product_Name"));
00234         AcceptUnknownPeers = Integer.parseInt(config.getDocumentElement().getAttribute("AcceptUnknownPeers"))!=0;
00235         LOGGER.info("AcceptUnknwonPeers: " + AcceptUnknownPeers);
00236         DropUnknownOnDisconnect = Integer.parseInt(config.getDocumentElement().getAttribute("DropUnknownOnDisconnect"))!=0;
00237         LOGGER.info("DropUnknownOnDisconnect: " + DropUnknownOnDisconnect);
00238         
00239         Tc = Integer.parseInt(config.getDocumentElement().getAttribute("Tc"));
00240         workerCount = Integer.parseInt(config.getDocumentElement().getAttribute("Workers"));
00241         queueLength = Integer.parseInt(config.getDocumentElement().getAttribute("QueueLength"));
00242         
00243         queueTasks = new ArrayBlockingQueue<DiameterTask>(queueLength,true);
00244         
00245         startWorkers();
00246         
00247         /* Read Supported Application ids */
00248         this.AuthApp = new Vector<Application>();
00249         this.AcctApp = new Vector<Application>();
00250         nl = config.getDocumentElement().getElementsByTagName("Auth");
00251         for(int i=0;i<nl.getLength();i++){
00252             n = nl.item(i);
00253             app_id = 0;
00254             app_id = Integer.parseInt(n.getAttributes().getNamedItem("id").getNodeValue());
00255             vendor_id=0;
00256             if (n.getAttributes().getNamedItem("vendor")!=null)
00257                 vendor_id = Integer.parseInt(n.getAttributes().getNamedItem("vendor").getNodeValue());
00258             
00259             app = new Application(app_id,vendor_id,Application.Auth);
00260             this.AuthApp.add(app);
00261         }
00262         nl = config.getDocumentElement().getElementsByTagName("Acct");
00263         for(int i=0;i<nl.getLength();i++){
00264             n = nl.item(i);
00265             app_id = 0;
00266             app_id = Integer.parseInt(n.getAttributes().getNamedItem("id").getNodeValue());
00267             vendor_id=0;
00268             if (n.getAttributes().getNamedItem("vendor")!=null)
00269                 vendor_id = Integer.parseInt(n.getAttributes().getNamedItem("vendor").getNodeValue());
00270             
00271             app = new Application(app_id,vendor_id,Application.Acct);
00272             this.AcctApp.add(app);
00273         }
00274         /* Initialize the Peer Manager */
00275         peerManager = new PeerManager(this);
00276         
00277         /* Read the peers from the configuration file */
00278         nl = config.getDocumentElement().getElementsByTagName("Peer");
00279         for(int i=0;i<nl.getLength();i++){
00280             n = nl.item(i);
00281  
00282             fqdn = n.getAttributes().getNamedItem("FQDN").getNodeValue();
00283             
00284             realm = n.getAttributes().getNamedItem("Realm").getNodeValue(); 
00285             
00286             port = 3868;
00287             nv = n.getAttributes().getNamedItem("port");
00288             if (nv==null) port = 3868;
00289             else port = Integer.parseInt(nv.getNodeValue());
00290                 
00291             peerManager.configurePeer(fqdn,realm,port);
00292         }
00293         
00294         /* Create & start connection acceptors */
00295         acceptors = new Vector<Acceptor>();
00296         nl = config.getDocumentElement().getElementsByTagName("Acceptor");
00297         for(int i=0;i<nl.getLength();i++){
00298             n = nl.item(i);
00299             
00300             port = 3868;
00301             nv = n.getAttributes().getNamedItem("port");
00302             if (nv==null) port = 3868;
00303             else port = Integer.parseInt(nv.getNodeValue());
00304             
00305             addr = null;
00306             nv = n.getAttributes().getNamedItem("bind");
00307             if (nv !=null && nv.getNodeValue().length()!=0  )               
00308                 try {
00309                     addr = InetAddress.getByName(nv.getNodeValue());
00310                 } catch (UnknownHostException e) {
00311                     LOGGER.error("DiameterPeer: Can not resolve "+nv.getNodeValue());
00312                     e.printStackTrace();
00313                     continue;
00314                 } 
00315             acc = new Acceptor(port,addr,this);
00316             acc.startAccepting();
00317             acceptors.add(acc);
00318         }
00319         
00320         initRoutingTable(config);
00321 
00322         peerManager.start();
00323         
00324     }
00325     
00326     private boolean readConfigFile(String cfgFile)
00327     {
00328         DocumentBuilderFactory factory =
00329             DocumentBuilderFactory.newInstance();
00330         //factory.setValidating(true);   
00331         //factory.setNamespaceAware(true);
00332         try {
00333            DocumentBuilder builder = factory.newDocumentBuilder();
00334            config = builder.parse( cfgFile );
00335         } catch (SAXException sxe) {
00336            // Error generated during parsing)
00337            Exception  x = sxe;
00338            if (sxe.getException() != null)
00339                x = sxe.getException();
00340            x.printStackTrace();
00341            return false;
00342         } catch (ParserConfigurationException pce) {
00343             // Parser with specified options can't be built
00344             pce.printStackTrace();
00345             return false;
00346         } catch (IOException ioe) {
00347            // I/O error
00348            ioe.printStackTrace();
00349            return false;
00350         }
00351         return true;
00352     }
00353     
00354     private boolean readConfigString(String cfgString)
00355     {
00356         DocumentBuilderFactory factory =
00357             DocumentBuilderFactory.newInstance();
00358         //factory.setValidating(true);   
00359         //factory.setNamespaceAware(true);
00360         try {
00361            DocumentBuilder builder = factory.newDocumentBuilder();
00362            config = builder.parse( new InputSource(new StringReader(cfgString)) );
00363         } catch (SAXException sxe) {
00364            // Error generated during parsing)
00365            Exception  x = sxe;
00366            if (sxe.getException() != null)
00367                x = sxe.getException();
00368            x.printStackTrace();
00369            return false;
00370         } catch (ParserConfigurationException pce) {
00371             // Parser with specified options can't be built
00372             pce.printStackTrace();
00373             return false;
00374         } catch (IOException ioe) {
00375            // I/O error
00376            ioe.printStackTrace();
00377            return false;
00378         }
00379         return true;
00380     }
00381     
00382     /* configure routing table */
00383     private void initRoutingTable(Document config) {        
00384         NodeList nl, nlc;
00385         String fqdn,realm;
00386         int metric;
00387         
00388         this.routingTable = new RoutingEngine();
00389         nl = config.getDocumentElement().getElementsByTagName("DefaultRoute");
00390         for(int i=0;i<nl.getLength();i++){
00391             fqdn = nl.item(i).getAttributes().getNamedItem("FQDN").getNodeValue();
00392             metric = Integer.valueOf(nl.item(i).getAttributes().getNamedItem("metric").getNodeValue());
00393             routingTable.addDefaultRoute(fqdn, metric);
00394         }
00395         nl = config.getDocumentElement().getElementsByTagName("Realm");
00396         for(int i=0;i<nl.getLength();i++){
00397             realm = nl.item(i).getAttributes().getNamedItem("name").getNodeValue();
00398             nlc = nl.item(i).getChildNodes();
00399             for(int j=0;j<nlc.getLength();j++)
00400                 if (nlc.item(j).getNodeName().equalsIgnoreCase("Route")){
00401                     fqdn = nlc.item(j).getAttributes().getNamedItem("FQDN").getNodeValue();
00402                     metric = Integer.valueOf(nlc.item(j).getAttributes().getNamedItem("metric").getNodeValue());
00403                     routingTable.addRealmRoute(realm, fqdn, metric);
00404                 }
00405         }
00406          
00407     }
00408         
00409     
00410     private void startWorkers()
00411     {
00412         workers = new DiameterWorker[workerCount];
00413         for(int i=0;i<workerCount;i++)
00414             workers[i] = new DiameterWorker(i,this.queueTasks);
00415     }
00416     
00423     public void enableTransactions(long timeout,long checkInterval)
00424     {
00425         if (this.transactionWorker == null)
00426             this.transactionWorker = new TransactionWorker(this,timeout,checkInterval);
00427     }
00428     
00429     
00430     
00438     public DiameterMessage newRequest(int command_code, int application_id)
00439     {
00440         return newRequest(command_code, true, application_id);
00441     }
00442     
00443     
00444     
00453     public DiameterMessage newRequest(int command_code, boolean Proxiable, 
00454             int application_id)
00455     {
00456         DiameterMessage msg = new DiameterMessage(command_code, 
00457                                                   true, 
00458                                                   Proxiable, 
00459                                                   application_id, 
00460                                                   this.getNextHopByHopId(), 
00461                                                   this.getNextEndToEndId());
00462         AVP avp;
00463         
00464         avp = new AVP(AVP.Origin_Host,true,0);
00465         avp.setData(this.FQDN);
00466         msg.addAVP(avp);
00467         
00468         avp = new AVP(AVP.Origin_Realm,true,0);
00469         avp.setData(this.Realm);
00470         msg.addAVP(avp);
00471 
00472         return msg;
00473     }
00474     
00475     
00476     
00483     public DiameterMessage newResponse(DiameterMessage request)
00484     {
00485         DiameterMessage msg = new DiameterMessage(request.commandCode,false,request.applicationID);
00486         AVP avp;
00487         
00488         msg.endToEndID = request.endToEndID;
00489         msg.hopByHopID = request.hopByHopID;
00490         
00491         if (request.getSessionId() != null) {
00492             avp = request.getSessionId();
00493             msg.addAVP(avp);
00494         }
00495         
00496         avp = new AVP(AVP.Origin_Host,true,0);
00497         avp.setData(this.FQDN);
00498         msg.addAVP(avp);
00499         
00500         avp = new AVP(AVP.Origin_Realm,true,0);
00501         avp.setData(this.Realm);
00502         msg.addAVP(avp);
00503         
00504         
00505         return msg;
00506     }
00507     
00515     public boolean sendMessage(String peerFQDN,DiameterMessage msg)
00516     {
00517         Peer p;
00518         p = peerManager.getPeerByFQDN(peerFQDN);
00519         if (p==null){
00520             LOGGER.error("DiameterPeer: Peer "+peerFQDN+" not found in peer list.");
00521             return false;
00522         }
00523         if (p.state!=StateMachine.I_Open &&
00524             p.state!=StateMachine.R_Open){
00525             LOGGER.error("DiameterPeer: Peer "+peerFQDN+" not connected.");
00526             return false;
00527         }
00528         return p.sendMessage(msg);
00529     }
00530 
00537     public boolean sendMessage(DiameterMessage msg)
00538     {
00539         Peer p;
00540         if (routingTable==null){
00541             LOGGER.error("DiameterPeer: RoutingTable not initialized!");
00542             return false;
00543         }
00544         p = routingTable.getRoute(msg,peerManager);
00545         if (p==null){
00546             LOGGER.error("DiameterPeer: No suitable peer to route to could be found.");
00547             return false;
00548         }
00549         return p.sendMessage(msg);
00550     }
00551 
00560     public boolean sendRequestTransactional(String peerFQDN,DiameterMessage req,TransactionListener tl)
00561     {
00562         if (this.transactionWorker!=null) return transactionWorker.sendRequestTransactional(peerFQDN,req,tl);
00563         else {
00564             LOGGER.error("DiameterPeer:sendRequestTransactional(): Transactions are not enabled on this peer!");
00565             return false;
00566         }
00567     }
00568 
00576     public boolean sendRequestTransactional(DiameterMessage req,TransactionListener tl)
00577     {
00578         if (this.transactionWorker!=null) return transactionWorker.sendRequestTransactional(req,tl);
00579         else {
00580             LOGGER.error("DiameterPeer:sendRequestTransactional(): Transactions are not enabled on this peer!");
00581             return false;
00582         }
00583     }
00584     
00593     public DiameterMessage sendRequestBlocking(String peerFQDN,DiameterMessage req)
00594     {
00595         if (this.transactionWorker!=null) return transactionWorker.sendRequestBlocking(peerFQDN,req);
00596         else {
00597             LOGGER.error("DiameterPeer:sendRequestBlocking(): Transactions are not enabled on this peer!");
00598             return null;
00599         }
00600     }
00601 
00609     public DiameterMessage sendRequestBlocking(DiameterMessage req)
00610     {
00611         if (this.transactionWorker!=null) return transactionWorker.sendRequestBlocking(req);
00612         else {
00613             LOGGER.error("DiameterPeer:sendRequestBlocking(): Transactions are not enabled on this peer!");
00614             return null;
00615         }
00616     }
00617     
00618 
00624     public void addEventListener(EventListener l)
00625     {
00626         eventListeners.add(l);
00627     }
00628     
00629     
00635     public void removeEventListener(EventListener l)
00636     {
00637         eventListeners.remove(l);
00638     }
00639     
00643     public void shutdown()
00644     {
00645         Acceptor acc;
00646         Iterator<Acceptor> i = acceptors.iterator();
00647         while(i.hasNext()){
00648             acc = i.next();
00649             acc.stopAccepting();
00650         }
00651         peerManager.shutdown();
00652         for(int j=0;j<workerCount;j++)
00653             workers[j].shutdown();
00654         if (transactionWorker!=null) transactionWorker.shutdown();
00655     }
00656 }

Generated on Thu Oct 23 04:07:36 2008 for Open IMS Core JavaDiameterPeer by  doxygen 1.5.2