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