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