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