b6043c60ab19c58f150751fca575ece68c36b142
[packetcable.git] / packetcable-driver / src / main / java / org / umu / cops / prpdp / COPSPdpAgent.java
1 /*\r
2  * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
3  * --------------------------------------------------------------\r
4  * For more information, please see <http://www.umu.euro6ix.org/>.\r
5  */\r
6 \r
7 package org.umu.cops.prpdp;\r
8 \r
9 import java.io.IOException;\r
10 import java.net.ServerSocket;\r
11 import java.net.Socket;\r
12 import java.util.Enumeration;\r
13 import java.util.Hashtable;\r
14 \r
15 import org.umu.cops.common.COPSDebug;\r
16 import org.umu.cops.stack.COPSAcctTimer;\r
17 import org.umu.cops.stack.COPSClientAcceptMsg;\r
18 import org.umu.cops.stack.COPSClientCloseMsg;\r
19 import org.umu.cops.stack.COPSClientOpenMsg;\r
20 import org.umu.cops.stack.COPSError;\r
21 import org.umu.cops.stack.COPSException;\r
22 import org.umu.cops.stack.COPSHeader;\r
23 import org.umu.cops.stack.COPSKATimer;\r
24 import org.umu.cops.stack.COPSMsg;\r
25 import org.umu.cops.stack.COPSPepId;\r
26 import org.umu.cops.stack.COPSTransceiver;\r
27 \r
28 /**\r
29  * Core PDP agent for provisioning\r
30  */\r
31 public class COPSPdpAgent extends Thread {\r
32     /** Well-known port for COPS */\r
33     public static final int WELL_KNOWN_PDP_PORT = 3288;\r
34     /** Default keep-alive timer value (secs) */\r
35     public static final short KA_TIMER_VALUE = 30;\r
36     /** Default accounting timer value (secs) */\r
37     public static final short ACCT_TIMER_VALUE = 0;\r
38 \r
39     /**\r
40         PDP host IP\r
41      */\r
42     private ServerSocket _serverSocket;\r
43 \r
44     /**\r
45         PDP host port\r
46      */\r
47     private int _serverPort;\r
48 \r
49     /**\r
50         Client-type of connecting PEP\r
51      */\r
52     private short _clientType;\r
53 \r
54     /**\r
55         Accounting timer (secs)\r
56      */\r
57     private short _acctTimer;\r
58 \r
59     /**\r
60         Keep-alive timer (secs)\r
61      */\r
62     private short _kaTimer;\r
63 \r
64     /**\r
65         Maps a PEP-ID to a connection\r
66      */\r
67     private Hashtable _connectionMap;\r
68     // map < String(PEPID), COPSPdpConnection > ConnectionMap;\r
69 \r
70     /**\r
71      *  Policy data processing object\r
72      */\r
73     private COPSPdpDataProcess _process;\r
74 \r
75     /**\r
76      * Creates a PDP Agent\r
77      *\r
78      * @param clientType    COPS Client-type\r
79      * @param process       Object to perform policy data processing\r
80      */\r
81     public COPSPdpAgent(short clientType, COPSPdpDataProcess process) {\r
82         _serverPort = WELL_KNOWN_PDP_PORT;\r
83         _kaTimer = KA_TIMER_VALUE;\r
84         _acctTimer = ACCT_TIMER_VALUE;\r
85 \r
86         _clientType = clientType;\r
87         _connectionMap = new Hashtable(40);\r
88         _process = process;\r
89     }\r
90 \r
91     /**\r
92      * Creates a PDP Agent\r
93      *\r
94      * @param port  Port to listen to\r
95      * @param clientType    COPS Client-type\r
96      * @param process   Object to perform policy data processing\r
97      */\r
98     public COPSPdpAgent(int port, short clientType, COPSPdpDataProcess process) {\r
99         _serverPort = port;\r
100 \r
101         _kaTimer = KA_TIMER_VALUE;\r
102         _acctTimer = ACCT_TIMER_VALUE;\r
103 \r
104         _clientType = clientType;\r
105         _connectionMap = new Hashtable(40);\r
106         _process = process;\r
107     }\r
108 \r
109     /**\r
110      * Sets the keep-alive timer value\r
111      * @param    kaTimer    Keep alive timer value (secs)\r
112      */\r
113     public void setKaTimer (short kaTimer) {\r
114         _kaTimer = kaTimer;\r
115     }\r
116 \r
117     /**\r
118      * Sets the accounting timer value\r
119      * @param    acctTimer  Accounting timer value (secs)\r
120      */\r
121     public void setAcctTimer (short acctTimer) {\r
122         _acctTimer = acctTimer;\r
123     }\r
124 \r
125     /**\r
126      * Gets the value of the keep-alive timer\r
127      * @return   Keep-alive timer value (secs)\r
128      */\r
129     public short getKaTimer () {\r
130         return _kaTimer;\r
131     }\r
132 \r
133     /**\r
134      * Gets the accounting timer value\r
135      * @return   Accounting timer value (secs)\r
136      */\r
137     public short getAcctTimer () {\r
138         return _acctTimer;\r
139     }\r
140 \r
141     /**\r
142      * Gets the PEPs connected to this PDP\r
143      * @return   An <tt>Enumeration</tt> of all connected PEPs\r
144      */\r
145     public Enumeration getConnectedPEPIds() {\r
146         return _connectionMap.keys();\r
147     }\r
148 \r
149     /**\r
150      * Gets the connection map\r
151      * @return   A <tt>Hashtable</tt> holding the connection map\r
152      */\r
153     public Hashtable getConnectionMap() {\r
154         return _connectionMap;\r
155     }\r
156 \r
157     /**\r
158      * Gets the client-type\r
159      * @return   The client-type\r
160      */\r
161     public short getClientType() {\r
162         return _clientType;\r
163     }\r
164 \r
165     /**\r
166      * Disconnects a PEP\r
167      * @param pepID PEP-ID of the PEP to be disconnected\r
168      * @param error COPS Error to be reported as a reason\r
169      * @throws COPSException\r
170      * @throws IOException\r
171      */\r
172     public void disconnect (String pepID, COPSError error)\r
173     throws COPSException, IOException {\r
174 \r
175         COPSPdpConnection pdpConn = (COPSPdpConnection) _connectionMap.get(pepID);\r
176 \r
177         COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, _clientType);\r
178         COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
179         closeMsg.add(cHdr);\r
180         if (error != null)\r
181             closeMsg.add(error);\r
182 \r
183         closeMsg.writeData(pdpConn.getSocket());\r
184         pdpConn.close();\r
185         pdpConn = null;\r
186     }\r
187 \r
188     /**\r
189      * Requests a COPS sync for a PEP\r
190      * @param pepID PEP-ID of the PEP to be synced\r
191      * @throws COPSException\r
192      * @throws COPSPdpException\r
193      */\r
194     public void sync (String pepID)\r
195     throws COPSException, COPSPdpException {\r
196 \r
197         COPSPdpConnection pdpConn = (COPSPdpConnection) _connectionMap.get(pepID);\r
198         pdpConn.syncAllRequestState();\r
199     }\r
200 \r
201     /**\r
202      * Removes a PEP from the connection map\r
203      * @param pepID PEP-ID of the PEP to be removed\r
204      */\r
205     public void delete (String pepID) {\r
206         _connectionMap.remove(pepID);\r
207     }\r
208 \r
209 \r
210     /**\r
211      * Runs the PDP process\r
212      */\r
213     public void run() {\r
214         try {\r
215             _serverSocket = new ServerSocket (_serverPort);\r
216 \r
217             //Loop through for Incoming messages\r
218 \r
219             // server infinite loop\r
220             while (true) {\r
221 \r
222                 // Wait for an incoming connection from a PEP\r
223                 Socket socket = _serverSocket.accept();\r
224 \r
225                 // COPSDebug.out(getClass().getName(),"New connection accepted " +\r
226                 //           socket.getInetAddress() +\r
227                 //           ":" + socket.getPort());\r
228 \r
229                 // We're waiting for an OPN message\r
230                 try {\r
231                     COPSMsg msg = COPSTransceiver.receiveMsg(socket);\r
232                     if (msg.getHeader().isAClientOpen()) {\r
233                         handleClientOpenMsg(socket, msg);\r
234                     } else {\r
235                         // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
236                         try {\r
237                             socket.close();\r
238                         } catch (Exception ex) {};\r
239                     }\r
240                 } catch (Exception e) { // COPSException, IOException\r
241                     // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_EXCEPTION,\r
242                     //    "(" + socket.getInetAddress() + ":" + socket.getPort() + ")", e);\r
243                     try {\r
244                         socket.close();\r
245                     } catch (Exception ex) {};\r
246                 }\r
247             }\r
248         } catch (IOException e) {\r
249             COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);\r
250             return;\r
251         }\r
252     }\r
253 \r
254     /**\r
255       * Handles a COPS client-open message\r
256       * @param    conn Socket to the PEP\r
257       * @param    msg <tt>COPSMsg</tt> holding the client-open message\r
258       * @throws COPSException\r
259       * @throws IOException\r
260       */\r
261     private void handleClientOpenMsg(Socket conn, COPSMsg msg)\r
262     throws COPSException, IOException {\r
263         COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;\r
264         COPSPepId pepId = cMsg.getPepId();\r
265 \r
266         // Validate Client Type\r
267         if (msg.getHeader().getClientType() != _clientType) {\r
268             // Unsupported client type\r
269             COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
270             COPSError err = new COPSError(COPSError.COPS_ERR_UNSUPPORTED_CLIENT_TYPE, (short) 0);\r
271             COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
272             closeMsg.add(cHdr);\r
273             closeMsg.add(err);\r
274             try {\r
275                 closeMsg.writeData(conn);\r
276             } catch (IOException unae) {}\r
277 \r
278             throw new COPSException("Unsupported client type");\r
279         }\r
280 \r
281         // PEPId is mandatory\r
282         if (pepId == null) {\r
283             // Mandatory COPS object missing\r
284             COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
285             COPSError err = new COPSError(COPSError.COPS_ERR_MANDATORY_OBJECT_MISSING, (short) 0);\r
286             COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
287             closeMsg.add(cHdr);\r
288             closeMsg.add(err);\r
289             try {\r
290                 closeMsg.writeData(conn);\r
291             } catch (IOException unae) {}\r
292 \r
293             throw new COPSException("Mandatory COPS object missing (PEPId)");\r
294         }\r
295 \r
296         // Support\r
297         if ( (cMsg.getClientSI() != null) ||\r
298                 (cMsg.getPdpAddress() != null) ||\r
299                 (cMsg.getIntegrity() != null)) {\r
300 \r
301             // Unsupported objects\r
302             COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
303             COPSError err = new COPSError(COPSError.COPS_ERR_UNKNOWN_OBJECT, (short) 0);\r
304             COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
305             closeMsg.add(cHdr);\r
306             closeMsg.add(err);\r
307             try {\r
308                 closeMsg.writeData(conn);\r
309             } catch (IOException unae) {}\r
310 \r
311             throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");\r
312         }\r
313 \r
314         // Connection accepted\r
315         COPSHeader ahdr = new COPSHeader(COPSHeader.COPS_OP_CAT, msg.getHeader().getClientType());\r
316         COPSKATimer katimer = new COPSKATimer(_kaTimer);\r
317         COPSAcctTimer acctTimer = new COPSAcctTimer(_acctTimer);\r
318         COPSClientAcceptMsg acceptMsg = new COPSClientAcceptMsg();\r
319         acceptMsg.add(ahdr);\r
320         acceptMsg.add(katimer) ;\r
321         if (_acctTimer != 0) acceptMsg.add(acctTimer);\r
322         acceptMsg.writeData(conn);\r
323 \r
324         COPSPdpConnection pdpConn = new COPSPdpConnection(pepId,conn,_process);\r
325         pdpConn.setKaTimer(_kaTimer);\r
326         if (_acctTimer != 0) pdpConn.setAccTimer(_acctTimer);\r
327         new Thread(pdpConn).start();\r
328         _connectionMap.put(pepId.getData().str(),pdpConn);\r
329     }\r
330 \r
331 }\r
332 \r
333 \r
334 \r