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