e7ab809d9260249aec2701409b8f13f2eb7d9117
[packetcable.git] / packetcable-driver / src / main / java / org / umu / cops / prpep / COPSPepAgent.java
1 /*
2  * Copyright (c) 2004 University of Murcia.  All rights reserved.
3  * --------------------------------------------------------------
4  * For more information, please see <http://www.umu.euro6ix.org/>.
5  */
6
7 package org.umu.cops.prpep;
8
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11 import org.umu.cops.stack.*;
12 import org.umu.cops.stack.COPSHeader.OPCode;
13
14 import java.io.IOException;
15 import java.net.InetAddress;
16 import java.net.Socket;
17 import java.net.UnknownHostException;
18
19 /**
20  * This is a provisioning COPS PEP. Responsible for making
21  * connection to the PDP and maintaining it
22  */
23 public class COPSPepAgent {
24
25     private final static Logger logger = LoggerFactory.getLogger(COPSPepAgent.class);
26
27     /**
28         PEP's Identifier
29      */
30     private String _pepID;
31
32     /**
33         PEP's client-type
34      */
35     private short _clientType;
36
37     /**
38         PDP host name
39      */
40     private String _psHost;
41
42     /**
43         PDP port
44      */
45     private int _psPort;
46
47     /**
48         PEP-PDP connection manager
49      */
50     private COPSPepConnection _conn;
51
52     /**
53         COPS error returned by PDP
54      */
55     private COPSError _error;
56
57     /**
58      * Creates a PEP agent
59      * @param    pepID              PEP-ID
60      * @param    clientType         Client-type
61      */
62     public COPSPepAgent(final String pepID, final short clientType) {
63         _pepID = pepID;
64         _clientType = clientType;
65     }
66
67     /**
68      * Creates a PEP agent with a PEP-ID equal to "noname"
69      * @param    clientType         Client-type
70      */
71     public COPSPepAgent(final short clientType) {
72
73         // PEPId
74         try {
75             _pepID = InetAddress.getLocalHost().getHostName();
76         } catch (Exception e) {
77             _pepID = "noname";
78         }
79
80         _clientType = clientType;
81     }
82
83     /**
84      * Gets the identifier of the PEP
85      * @return  PEP-ID
86      */
87     public String getPepID() {
88         return _pepID;
89     }
90
91     /**
92      * Gets the COPS client-type
93      * @return  PEP's client-type
94      */
95     public short getClientType() {
96         return _clientType;
97     }
98
99     /**
100      * Gets PDP host name
101      * @return  PDP host name
102      */
103     public String getPDPName() {
104         return _psHost;
105     }
106
107     /**
108      * Gets the port of the PDP
109      * @return  PDP port
110      */
111     public int getPDPPort() {
112         return _psPort;
113     }
114
115     /**
116      * Connects to a PDP
117      * @param    psHost              PDP host name
118      * @param    psPort              PDP port
119      * @return   <tt>true</tt> if PDP accepts the connection; <tt>false</tt> otherwise
120      * @throws   java.io.IOException
121      * @throws   COPSException
122      * @throws   COPSPepException
123      */
124     public boolean connect(String psHost, int psPort) throws IOException, COPSException {
125         logger.info("Thread ( " + _pepID + ") - Connecting to PDP");
126         _psHost = psHost;
127         _psPort = psPort;
128
129         // Check whether it already exists
130         if (_conn == null)
131             _conn = processConnection(psHost,psPort);
132         else {
133             // Check if it's closed
134             if (_conn.isClosed()) {
135                 _conn = processConnection(psHost,psPort);
136             } else {
137                 disconnect(null);
138                 _conn = processConnection(psHost,psPort);
139             }
140         }
141
142         return (_conn != null);
143     }
144
145     /**
146      * Gets the connection manager
147      * @return  PEP-PDP connection manager object
148      */
149     public COPSPepConnection getConnection () {
150         return (_conn);
151     }
152
153     /**
154      * Gets the COPS error returned by the PDP
155      * @return   <tt>COPSError</tt> returned by PDP
156      */
157     public COPSError getConnectionError()   {
158         return _error;
159     }
160
161     /**
162      * Disconnects from the PDP
163      * @param error Reason
164      * @throws COPSException
165      * @throws IOException
166      */
167     public void disconnect(final COPSError error) throws COPSException, IOException {
168         final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType, error, null, null);
169         closeMsg.writeData(_conn.getSocket());
170         _conn.close();
171     }
172
173     /**
174      * Adds a request state to the connection manager.
175      * @return  The newly created connection manager
176      * @throws COPSPepException
177      * @throws COPSException
178      */
179     public COPSPepReqStateMan addRequestState(final COPSHandle handle, final COPSPepDataProcess process)
180             throws COPSException {
181         if (_conn != null) {
182             return _conn.addRequestState(handle, process);
183         }
184         return null;
185     }
186
187
188     /**
189      * Queries the connection manager to delete a request state
190      * @param man   Request state manager
191      * @throws COPSPepException
192      * @throws COPSException
193      */
194     public void deleteRequestState(final COPSPepReqStateMan man) throws COPSException {
195         if (_conn != null)
196             _conn.deleteRequestState(man);
197     }
198
199     /**
200      * Establish connection to PDP's IP address
201      *
202      * <Client-Open> ::= <Common Header>
203      *                  <PEPID>
204      *                  [<ClientSI>]
205      *                  [<LastPDPAddr>]
206      *                  [<Integrity>]
207      *
208      * Not support [<ClientSI>], [<LastPDPAddr>], [<Integrity>]
209      *
210      * <Client-Accept> ::= <Common Header>
211      *                      <KA Timer>
212      *                      [<ACCT Timer>]
213      *                      [<Integrity>]
214      *
215      * Not send [<Integrity>]
216      *
217      * <Client-Close> ::= <Common Header>
218      *                      <Error>
219      *                      [<PDPRedirAddr>]
220      *                      [<Integrity>]
221      *
222      * Not send [<PDPRedirAddr>], [<Integrity>]
223      *
224      * @throws   UnknownHostException
225      * @throws   IOException
226      * @throws   COPSException
227      * @throws   COPSPepException
228      *
229      */
230     private COPSPepConnection processConnection(final String psHost, final int psPort)
231             throws IOException, COPSException {
232         // Build OPN
233         final COPSClientOpenMsg msg = new COPSClientOpenMsg(_clientType, new COPSPepId(new COPSData(_pepID)),
234                 null, null, null);
235
236         // Create Socket and send OPN
237         final InetAddress addr = InetAddress.getByName(psHost);
238         final Socket socket = new Socket(addr,psPort);
239         msg.writeData(socket);
240
241         // Receive the response
242         final COPSMsg recvmsg = COPSTransceiver.receiveMsg(socket);
243
244         if (recvmsg.getHeader().getOpCode().equals(OPCode.CAT)) {
245             final COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvmsg;
246
247             // Support
248             if (cMsg.getIntegrity() != null) {
249                 throw new COPSPepException("Unsupported object (Integrity)");
250             }
251
252             // Mandatory KATimer
253             final COPSKATimer kt = cMsg.getKATimer();
254             if (kt == null)
255                 throw new COPSPepException ("Mandatory COPS object missing (KA Timer)");
256             short _kaTimeVal = kt.getTimerVal();
257
258             // ACTimer
259             final COPSAcctTimer at = cMsg.getAcctTimer();
260             short _acctTimer = 0;
261             if (at != null)
262                 _acctTimer = at.getTimerVal();
263
264             // Create the connection manager
265             final COPSPepConnection conn = new COPSPepConnection(_clientType, socket);
266             conn.setKaTimer(_kaTimeVal);
267             conn.setAcctTimer(_acctTimer);
268             new Thread(conn).start();
269
270             return conn;
271         } else if (recvmsg.getHeader().getOpCode().equals(OPCode.CC)) {
272             final COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvmsg;
273             _error = cMsg.getError();
274             socket.close();
275             return null;
276         } else { // messages of other types are not expected
277             throw new COPSPepException("Message not expected. Closing connection for " + socket.toString());
278         }
279     }
280 }
281
282
283