Java tutorial
/* * $Id: StateMachine.java,v 1.3 2011/06/01 17:51:08 qiwenyuan Exp $ * * Copyright (C) 2004-2006 FhG Fokus * * This file is part of Open IMS Core - an open source IMS CSCFs & HSS implementation * * Open IMS Core is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. * * For a license to use the Open IMS Core software under conditions other than those described here, or to purchase support for this * software, please contact Fraunhofer FOKUS by e-mail at the following addresses: info@open-ims.org * * Open IMS Core is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package de.fhg.fokus.diameter.DiameterPeer.peer; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.Iterator; import java.util.concurrent.TimeUnit; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.sun.nio.sctp.SctpChannel; import de.fhg.fokus.diameter.DiameterPeer.data.AVP; import de.fhg.fokus.diameter.DiameterPeer.data.AVPDecodeException; import de.fhg.fokus.diameter.DiameterPeer.data.DiameterCEA; import de.fhg.fokus.diameter.DiameterPeer.data.DiameterCER; import de.fhg.fokus.diameter.DiameterPeer.data.DiameterDPA; import de.fhg.fokus.diameter.DiameterPeer.data.DiameterDPR; import de.fhg.fokus.diameter.DiameterPeer.data.DiameterDWA; import de.fhg.fokus.diameter.DiameterPeer.data.DiameterDWR; import de.fhg.fokus.diameter.DiameterPeer.data.DiameterMessage; import de.fhg.fokus.diameter.DiameterPeer.data.DiameterTask; import de.fhg.fokus.diameter.DiameterPeer.transport.Communicator; /** * This class defines the Diameter Peer State Machine. * * @author Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de * */ public class StateMachine { /** The logger */ private static Log log = LogFactory.getLog(StateMachine.class); /* State definitions */ /** Not connected. */ public static final int Closed = 0; /** Connecting - waiting for Ack. */ public static final int Wait_Conn_Ack = 1; /** Connecting - waiting for Capabilities-Exchange-Answer. */ public static final int Wait_I_CEA = 2; /** Connecting - Acknowledged and going for Election. */ public static final int Wait_Conn_Ack_Elect = 3; /** Connecting - done. */ public static final int Wait_Returns = 4; /** Connected as receiver. */ public static final int R_Open = 5; /** Connected as initiator. */ public static final int I_Open = 6; /** Closing the connection. */ public static final int Closing = 7; /* Event definitions */ /** Start connection attempt. */ public static final int Start = 101; /** Stop. */ public static final int Stop = 102; /** Time-out */ public static final int Timeout = 103; /** Winning the election */ public static final int Win_Election = 104; /** Receiver - Received connection Capabilities-Exchange-Request. */ public static final int R_Conn_CER = 105; /** Initiator - Received connection Ack. */ public static final int I_Rcv_Conn_Ack = 106; /** Initiator - Received connection NAck. */ public static final int I_Rcv_Conn_NAck = 107; /** Initiator - Received Capabilities-Exhange-Request. */ public static final int I_Rcv_CER = 108; /** Initiator - Recieved Capabilities-Exchange-Request. */ public static final int I_Rcv_CEA = 109; /** Receiver - Receiver Capabilities-Exchange-Request. */ public static final int R_Rcv_CER = 110; /** Receiver - Receiver Capabilities-Exchange-Answer. */ public static final int R_Rcv_CEA = 111; /** Initiator - Received non-Capabilities-Exchange-Answer. */ public static final int I_Rcv_Non_CEA = 112; /** Initiator - Received Disconnect-Peer-Request. */ public static final int I_Rcv_DPR = 113; /** Initiator - Received Disconnect-Peer-Answer. */ public static final int I_Rcv_DPA = 114; /** Receiver - Received Disconnect-Peer-Request. */ public static final int R_Rcv_DPR = 115; /** Receiver - Received Disconnect-Peer-Answer. */ public static final int R_Rcv_DPA = 116; /** Initiator - Received Diameter-Watchdog-Request. */ public static final int I_Rcv_DWR = 117; /** Initiator - Received Diameter-Watchdog-Answer. */ public static final int I_Rcv_DWA = 118; /** Receiver - Received Diameter-Watchdog-Request. */ public static final int R_Rcv_DWR = 119; /** Receiver - Received Diameter-Watchdog-Answer. */ public static final int R_Rcv_DWA = 120; /** Send a message. */ public static final int Send_Message = 121; /** Initiator - Received a message. */ public static final int I_Rcv_Message = 122; /** Receiver - Received a message. */ public static final int R_Rcv_Message = 123; /** Initiator - Peer disconnected. */ public static final int I_Peer_Disc = 124; /** Receiver - Peer disconnected. */ public static final int R_Peer_Disc = 125; /** * Process a transition in the state machine. * * @param p * The peer for which the event happened. * @param event * The event happened. * @return 1 one success, 0 on error. Also the peer states are updated. */ public static int process(Peer p, int event) { return process(p, event, null, null); } /** * Process a transition in the state machine. * * @param p * The peer for which the event happend. * @param event * The event happened. * @param msg * Received message. * @return 1 one success, 0 one error. Also the peer states are upated. */ public static int process(Peer p, int event, DiameterMessage msg) { return process(p, event, msg, null); } /** * Process a transition in the state machine. * * @param p * The peer for which the event happend. * @param event * The event happened. * @param msg * Received message. * @param comm * Communicator used to send a DiameterMessage * @return 1 one success, 0 one error. Also the peer states are upated. */ public static int process(Peer p, int event, DiameterMessage msg, Communicator comm) { int next_event, result_code; boolean msg_received = false; // log.debug("Peer Old State=" + p.state + " FQDN=" + p.FQDN); // log.debug("Now event=" + event + " FQDN=" + p.FQDN); synchronized (p) { switch (p.state) { case Closed: switch (event) { case Start: p.state = Wait_Conn_Ack; next_event = I_Snd_Conn_Req(p); StateMachine.process(p, next_event, null, p.I_comm); break; case R_Conn_CER: R_Accept(p, comm); result_code = Process_CER(p, msg); Snd_CEA(p, msg, result_code, p.R_comm); if (result_code >= 2000 && result_code < 3000) { p.state = R_Open; } else { R_Disc(p); p.state = Closed; } break; case Stop: /* just ignore this state */ p.state = Closed; break; default: log.error("StateMachine: Invalid event " + event + " for state " + p.state); return 0; } break; case Wait_Conn_Ack: switch (event) { case I_Rcv_Conn_Ack: log.debug("@@@Now sending CER!"); I_Snd_CER(p); p.state = Wait_I_CEA; break; case I_Rcv_Conn_NAck: Cleanup(p, comm); p.state = Closed; break; /* Commented as not reachable */ // case R_Conn_CER: // R_Accept(p,comm); // result_code = Process_CER(p,msg); // if (result_code>=2000 && result_code<3000) // p.state = Wait_Conn_Ack_Elect; // else { // p.state = Wait_Conn_Ack; // comm.shutdown(); // } // break; case Timeout: Error(p, p.I_comm); p.state = Closed; default: log.error("StateMachine: Invalid event " + event + " for state " + p.state); return 0; } break; case Wait_I_CEA: switch (event) { case I_Rcv_CEA: result_code = Process_CEA(p, msg); // if (result_code>=2000 && result_code<3000) p.state = I_Open; // else { // Cleanup(p,p.I_comm); // p.state = Closed; // } break; case R_Conn_CER: R_Accept(p, comm); result_code = Process_CER(p, msg); p.state = Wait_Returns; if (Elect(p, msg)) StateMachine.process(p, Win_Election, msg, comm); break; case I_Peer_Disc: I_Disc(p); p.state = Closed; break; case I_Rcv_Non_CEA: Error(p, p.I_comm); p.state = Closed; break; case Timeout: Error(p, p.I_comm); p.state = Closed; break; default: log.error("StateMachine: Invalid event " + event + " for state " + p.state); return 0; } break; /* commented as not reachable */ // case Wait_Conn_Ack_Elect: // switch(event){ // default: // LOGGER.error("StateMachine: Invalid event "+event+" for state "+p.state); // return 0; // } // break; case Wait_Returns: switch (event) { case Win_Election: I_Disc(p); result_code = Process_CER(p, msg); Snd_CEA(p, msg, result_code, p.R_comm); if (result_code >= 2000 && result_code < 3000) { p.state = R_Open; } else { R_Disc(p); p.state = Closed; } break; case I_Peer_Disc: I_Disc(p); result_code = Process_CER(p, msg); Snd_CEA(p, msg, result_code, p.R_comm); if (result_code >= 2000 && result_code < 3000) { p.state = R_Open; } else { R_Disc(p); p.state = Closed; } break; case I_Rcv_CEA: R_Disc(p); // result_code = Process_CEA(p,msg); // if (result_code>=2000 && result_code<3000) p.state = I_Open; // else { // Cleanup(p,p.I_comm); // p.state = Closed; // } break; case R_Peer_Disc: R_Disc(p); p.state = Wait_I_CEA; break; case R_Conn_CER: R_Reject(p, comm); p.state = Wait_Returns; break; case Timeout: Error(p, comm); p.state = Closed; default: log.error("StateMachine: Invalid event " + event + " for state " + p.state); return 0; } break; case R_Open: switch (event) { case Send_Message: Snd_Message(p, msg); p.state = R_Open; break; case R_Rcv_Message: // delayed processing until out of the critical zone // Rcv_Process(p,msg); msg_received = true; p.state = R_Open; break; case R_Rcv_DWR: result_code = Process_DWR(p, msg); Snd_DWA(p, msg, result_code, p.R_comm); p.isNormal = true; p.state = R_Open; break; case R_Rcv_DWA: Process_DWA(p, msg); p.isNormal = true; p.state = R_Open; break; case R_Conn_CER: R_Reject(p, comm); p.state = R_Open; break; case Stop: Snd_DPR(p); p.state = Closing; break; case R_Rcv_DPR: Snd_DPA(p, msg, DiameterMessage.DIAMETER_SUCCESS, p.R_comm); R_Disc(p); p.state = Closed; break; case R_Peer_Disc: R_Disc(p); p.state = Closed; break; case R_Rcv_CER: result_code = Process_CER(p, msg); Snd_CEA(p, msg, result_code, p.R_comm); if (result_code >= 2000 && result_code < 3000) { p.state = R_Open; } else { /* R_Disc(p);p.state = Closed; */ p.state = R_Open; /* Or maybe I should disconnect it? */ } break; case R_Rcv_CEA: result_code = Process_CEA(p, msg); if (result_code >= 2000 && result_code < 3000) p.state = R_Open; else { /* R_Disc(p);p.state = Closed; */ p.state = R_Open; /* Or maybe I should disconnect it? */ } break; default: log.error("StateMachine: Invalid event " + event + " for state " + p.state); return 0; } break; case I_Open: switch (event) { case Send_Message: Snd_Message(p, msg); p.state = I_Open; break; case I_Rcv_Message: // delayed processing until out of the critical zone // Rcv_Process(p,msg); msg_received = true; p.state = I_Open; break; case I_Rcv_DWR: result_code = Process_DWR(p, msg); Snd_DWA(p, msg, result_code, p.I_comm); p.state = I_Open; break; case I_Rcv_DWA: Process_DWA(p, msg); p.state = I_Open; break; case R_Conn_CER: R_Reject(p, comm); p.state = I_Open; break; case Stop: Snd_DPR(p); p.state = Closing; break; case I_Rcv_DPR: Snd_DPA(p, msg, 2001, p.I_comm); R_Disc(p); p.state = Closed; break; case I_Peer_Disc: I_Disc(p); p.state = Closed; break; case I_Rcv_CER: result_code = Process_CER(p, msg); Snd_CEA(p, msg, result_code, p.I_comm); if (result_code >= 2000 && result_code < 3000) p.state = I_Open; else { /* I_Disc(p);p.state = Closed; */ p.state = I_Open; /* Or maybe I should disconnect it? */ } break; case I_Rcv_CEA: result_code = Process_CEA(p, msg); if (result_code >= 2000 && result_code < 3000) p.state = I_Open; else { /* I_Disc(p);p.state = Closed; */ p.state = I_Open; /* Or maybe I should disconnect it? */ } break; default: log.error("StateMachine: Invalid event " + event + " for state " + p.state); return 0; } break; case Closing: switch (event) { case I_Rcv_DPA: I_Disc(p); p.state = Closed; break; case R_Rcv_DPA: R_Disc(p); p.state = Closed; break; case Timeout: if (p.I_comm != null) Error(p, p.I_comm); if (p.R_comm != null) Error(p, p.R_comm); p.state = Closed; break; case I_Peer_Disc: I_Disc(p); p.state = Closed; break; case R_Peer_Disc: R_Disc(p); p.state = Closed; break; default: log.error("StateMachine: Invalid event " + event + " for state " + p.state); return 0; } break; default: log.error("StateMachine: Invalid state " + p.state); return 0; } // LOGGER.debug("Peer New State: "+p.state+" FQDN:"+p.FQDN); } if (msg_received) { // delayed processing until out of the critical zone Rcv_Process(p, msg); } return 1; } private static int I_Snd_Conn_Req(Peer p) { SctpChannel sc = null; String bindLocalIp = p.localIp; int bindLocalPort = p.localPort; try { InetAddress bindLocalAdd = InetAddress.getByName(bindLocalIp); InetSocketAddress bindSocketAdd = new InetSocketAddress(bindLocalAdd, bindLocalPort); sc = SctpChannel.open(); sc.bind(bindSocketAdd); } catch (IOException e) { log.error("DiameterPeer: Can not resolve " + bindLocalIp); log.error(e, e); } if (p.I_comm != null) { p.I_comm.shutdown(); } p.I_comm = null; if (log.isInfoEnabled()) { StringBuilder sb = new StringBuilder(); sb.append("Start connect the peer:").append(p.FQDN).append(":").append(p.port); log.info(sb.toString()); } InetSocketAddress serverAddr = new InetSocketAddress(p.FQDN, p.port); try { if (sc.connect(serverAddr, 0, 0)) { Communicator r = new Communicator(sc, p, Communicator.Initiator); p.I_comm = r; log.info("Remote peer <" + p.FQDN + ":" + p.port + "> connectted !"); return StateMachine.I_Rcv_Conn_Ack; } else { log.error("Connect return false:Remote peer <" + p.FQDN + ":" + p.port + "> not responding to hss connection attempt !"); return StateMachine.I_Rcv_Conn_NAck; } } catch (IOException e1) { log.error("IOException:Remote peer <" + p.FQDN + ":" + p.port + "> not responding to hss connection attempt !"); return StateMachine.I_Rcv_Conn_NAck; } } private static void R_Accept(Peer p, Communicator comm) { p.R_comm = comm; p.refreshTimer(); } private static void R_Reject(Peer p, Communicator comm) { comm.shutdown(); } private static void I_Snd_CER(Peer p) { DiameterCER cer = new DiameterCER(); cer.hopByHopID = p.diameterPeer.getNextHopByHopId(); cer.endToEndID = p.diameterPeer.getNextEndToEndId(); cer.origin_host.setData(p.diameterPeer.FQDN); cer.origin_realm.setData(p.diameterPeer.Realm); Snd_CE_add_hostIpAddress(cer, p); cer.vendor_id.setData(p.diameterPeer.Vendor_Id); cer.product_name.setData(p.diameterPeer.Product_Name); Snd_CE_add_applications(cer, p); // log.debug(cer.toString()); p.I_comm.sendDirect(cer); } private static void Cleanup(Peer p, Communicator comm) { if (comm == null) return; comm.shutdown(); if (p.I_comm == comm) p.I_comm = null; if (p.R_comm == comm) p.R_comm = null; } private static void Error(Peer p, Communicator comm) { Cleanup(p, comm); } private static boolean Elect(Peer p, DiameterMessage cer) { /* returns if we win the election */ AVP avp; byte[] remote, local; int x, i; local = p.diameterPeer.FQDN.getBytes(); avp = cer.findAVP(AVP.Origin_Host, true, 0); if (avp == null) { return true; } else { remote = avp.data; for (i = 0; i < remote.length && i < local.length; i++) { x = ((int) local[i] & 0xFF) - ((int) remote[i] & 0xFF); if (x > 0) return true; if (x < 0) return false; } if (local.length > remote.length) return true; return false; } } private static int Process_CER(Peer p, DiameterMessage cer) { log.debug("Now processing CER msg for peer:" + p); int common_app = 0; Iterator<AVP> i = cer.avps.iterator(); Iterator<Application> i2; Application app; AVP avp, avp_vendor, avp2; p.AuthApp.clear(); p.AcctApp.clear(); while (i.hasNext() && common_app == 0) { avp = i.next(); switch (avp.code) { case AVP.Auth_Application_Id: p.AuthApp.add(new Application(avp.int_data, 0, Application.Auth)); i2 = p.diameterPeer.AuthApp.iterator(); while (i2.hasNext()) { app = i2.next(); if (avp.int_data == Application.Relay || (app.id == avp.int_data && app.vendor == 0)) { common_app++; break; } } break; case AVP.Acct_Application_Id: p.AcctApp.add(new Application(avp.int_data, 0, Application.Acct)); i2 = p.diameterPeer.AcctApp.iterator(); while (i2.hasNext()) { app = i2.next(); if (avp.int_data == Application.Relay || (app.id == avp.int_data && app.vendor == 0)) { common_app++; break; } } break; case AVP.Vendor_Specific_Application_Id: try { avp.ungroup(); } catch (AVPDecodeException e) { e.printStackTrace(); } avp_vendor = avp.findChildAVP(AVP.Vendor_Id, true, 0); if (avp_vendor == null) break; avp2 = avp.findChildAVP(AVP.Auth_Application_Id, true, 0); if (avp2 != null) { p.AuthApp.add(new Application(avp2.int_data, avp_vendor.int_data, Application.Auth)); i2 = p.diameterPeer.AuthApp.iterator(); while (i2.hasNext()) { app = i2.next(); if (avp2.int_data == Application.Relay || (app.id == avp2.int_data && app.vendor == avp_vendor.int_data)) { common_app++; break; } } } avp2 = avp.findChildAVP(AVP.Acct_Application_Id, true, 0); if (avp2 != null) { p.AcctApp.add(new Application(avp2.int_data, avp_vendor.int_data, Application.Acct)); i2 = p.diameterPeer.AcctApp.iterator(); while (i2.hasNext()) { app = i2.next(); if (avp2.int_data == Application.Relay || (app.id == avp2.int_data && app.vendor == avp_vendor.int_data)) { common_app++; break; } } } break; } } if (common_app != 0) { log.debug( "Finished processing CER msg for peer:" + p + " result is:" + DiameterMessage.DIAMETER_SUCCESS); return DiameterMessage.DIAMETER_SUCCESS; } else { log.debug("Finished processing CER msg for peer:" + p + " result is:" + DiameterMessage.DIAMETER_NO_COMMON_APPLICATION); return DiameterMessage.DIAMETER_NO_COMMON_APPLICATION; } } private static int Process_CEA(Peer p, DiameterMessage cea) { AVP avp; avp = cea.findAVP(AVP.Result_Code, true, 0); if (avp == null) { return DiameterMessage.DIAMETER_UNABLE_TO_COMPLY; } else { return avp.int_data; } } private static void Snd_CEA(Peer p, DiameterMessage cer, int result_code, Communicator comm) { DiameterCEA cea; cea = new DiameterCEA(result_code); cea.hopByHopID = cer.hopByHopID; cea.endToEndID = cer.endToEndID; cea.origin_host.setData(p.diameterPeer.FQDN); cea.origin_realm.setData(p.diameterPeer.Realm); byte addr[] = null; byte laddr[] = convertIpAddToByteArray(p.diameterPeer.bindIp); switch (laddr.length) { case 16: addr = new byte[18]; addr[0] = (byte) 0; addr[1] = (byte) 2; System.arraycopy(laddr, 0, addr, 2, laddr.length); break; default: case 4: addr = new byte[6]; addr[0] = (byte) 0; addr[1] = (byte) 1; System.arraycopy(laddr, 0, addr, 2, laddr.length); break; } cea.host_ip_address.setData(addr); cea.vendor_id.setData(p.diameterPeer.Vendor_Id); cea.product_name.setData(p.diameterPeer.Product_Name); Snd_CE_add_applications(cea, p); comm.sendDirect(cea); } private static void I_Disc(Peer p) { if (p.I_comm != null) { p.I_comm.peer = null; p.I_comm.shutdown(); } p.I_comm = null; } private static void R_Disc(Peer p) { log.debug("Now doing disconnect the peer:" + p); if (p.R_comm != null) { p.R_comm.peer = null; p.R_comm.shutdown(); } p.R_comm = null; log.debug("Finished disconnect the peer:" + p); } private static void Snd_CE_add_applications(DiameterMessage msg, Peer p) { AVP avp, avp2, avp3; Iterator<Application> i; Application app; i = p.diameterPeer.AuthApp.iterator(); while (i.hasNext()) { app = i.next(); if (app.vendor == 0) { avp = new AVP(AVP.Auth_Application_Id, true, 0); avp.setData(app.id); msg.addAVP(avp); } else { avp = new AVP(AVP.Vendor_Specific_Application_Id, true, 0); avp2 = new AVP(AVP.Vendor_Id, true, 0); avp2.setData(app.vendor); avp.addChildAVP(avp2); avp3 = new AVP(AVP.Auth_Application_Id, true, 0); avp3.setData(app.id); avp.addChildAVP(avp3); avp.group(); msg.addAVP(avp); } } i = p.diameterPeer.AcctApp.iterator(); while (i.hasNext()) { app = i.next(); if (app.vendor == 0) { avp = new AVP(AVP.Acct_Application_Id, true, 0); avp.setData(app.id); msg.addAVP(avp); } else { avp = new AVP(AVP.Vendor_Specific_Application_Id, true, 0); avp2 = new AVP(AVP.Vendor_Id, true, 0); avp2.setData(app.vendor); avp.addChildAVP(avp2); avp3 = new AVP(AVP.Acct_Application_Id, true, 0); avp3.setData(app.id); avp.addChildAVP(avp3); avp.group(); msg.addAVP(avp); } } } private static void Snd_CE_add_hostIpAddress(DiameterMessage msg, Peer p) { Iterator<String> i = p.diameterPeer.hostIpAdds.iterator(); String hostIpAddress = null; while (i.hasNext()) { hostIpAddress = i.next(); byte addr[] = null; byte laddr[] = convertIpAddToByteArray(hostIpAddress); if (null != laddr) { switch (laddr.length) { case 16: addr = new byte[18]; addr[0] = (byte) 0; addr[1] = (byte) 2; System.arraycopy(laddr, 0, addr, 2, laddr.length); break; default: case 4: addr = new byte[6]; addr[0] = (byte) 0; addr[1] = (byte) 1; System.arraycopy(laddr, 0, addr, 2, laddr.length); break; } AVP avp = new AVP(AVP.Host_IP_Address, true, 0); avp.setData(addr); msg.addAVP(avp); } } } private static int Process_DWR(Peer p, DiameterMessage dwr) { return DiameterMessage.DIAMETER_SUCCESS; } private static void Process_DWA(Peer p, DiameterMessage dwa) { p.waitingDWA = false; } /** * Send Device-Watchdog-Request. * * @param p * Peer sending the request. * @return true if sending successful, false otherwise. */ public static boolean Snd_DWR(Peer p) { DiameterDWR dwr; boolean r = false; dwr = new DiameterDWR(); dwr.hopByHopID = p.diameterPeer.getNextHopByHopId(); dwr.endToEndID = p.diameterPeer.getNextEndToEndId(); dwr.origin_host.setData(p.diameterPeer.FQDN); dwr.origin_realm.setData(p.diameterPeer.Realm); if (p.state == I_Open) r = p.I_comm.sendDirect(dwr); if (p.state == R_Open) r = p.R_comm.sendDirect(dwr); return r; } private static void Snd_DWA(Peer p, DiameterMessage dwr, int result_code, Communicator comm) { DiameterDWA dwa; dwa = new DiameterDWA(result_code); dwa.hopByHopID = dwr.hopByHopID; dwa.endToEndID = dwr.endToEndID; dwa.origin_host.setData(p.diameterPeer.FQDN); dwa.origin_realm.setData(p.diameterPeer.Realm); log.debug(dwa.toString()); comm.sendDirect(dwa); } /** * Send Disconnect-Peer-Request. * * @param p * Peer sending the message. */ public static void Snd_DPR(Peer p) { DiameterDPR dpr; dpr = new DiameterDPR(); dpr.hopByHopID = p.diameterPeer.getNextHopByHopId(); dpr.endToEndID = p.diameterPeer.getNextEndToEndId(); dpr.origin_host.setData(p.diameterPeer.FQDN); dpr.origin_realm.setData(p.diameterPeer.Realm); dpr.disconnect_cause.setData(0/* Busy */); log.debug(dpr.toString()); if (p.state == I_Open) p.I_comm.sendDirect(dpr); if (p.state == R_Open) p.R_comm.sendDirect(dpr); } private static void Snd_DPA(Peer p, DiameterMessage dpr, int result_code, Communicator comm) { DiameterDPA dpa; dpa = new DiameterDPA(result_code); dpa.hopByHopID = dpr.hopByHopID; dpa.endToEndID = dpr.endToEndID; dpa.origin_host.setData(p.diameterPeer.FQDN); dpa.origin_realm.setData(p.diameterPeer.Realm); log.debug(dpa.toString()); comm.sendDirect(dpa); } /** * Send a Diameter message. * * @param p * Peer sending the Diameter message. * @param msg * Diameter message being sent. */ public static void Snd_Message(Peer p, DiameterMessage msg) { p.refreshTimer(); } /** * Process the received Diameter message. * * @param p * Peer receiving the Diameter message. * @param msg * The received Diameter message. */ public static void Rcv_Process(Peer p, DiameterMessage msg) { boolean done = false; if (p.diameterPeer.eventListeners.size() != 0) { while (!done) { try { done = p.diameterPeer.queueTasks.offer(new DiameterTask(p, msg), 1000, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { e.printStackTrace(); break; } // if (!done) LOGGER.debug("ful "+p.diameterPeer.queueTasks.size()); // else LOGGER.debug("put "+p.diameterPeer.queueTasks.size()); // //LOGGER.debug("StateMachine: Processing queue is full. Overload..."); } } // LOGGER.debug("StateMachine: Received message "+msg.toString()+"---"); } private static byte[] convertIpAddToByteArray(String localIp) { byte[] address = null; try { InetAddress bindLocalAdd = InetAddress.getByName(localIp); address = bindLocalAdd.getAddress(); } catch (UnknownHostException e) { log.error(e, e); e.printStackTrace(); } return address; } }