Add packetcable-driver as a bundle and fix karafe depends. Merge hop-along model...
[packetcable.git] / packetcable-driver / src / main / java / org / umu / cops / ospep / COPSPepOSConnection.java
1 package org.umu.cops.ospep;\r
2 \r
3 import java.io.IOException;\r
4 import java.net.Socket;\r
5 import java.util.Date;\r
6 import java.util.Enumeration;\r
7 import java.util.Hashtable;\r
8 import java.util.Vector;\r
9 \r
10 import org.umu.cops.common.COPSDebug;\r
11 import org.umu.cops.stack.COPSClientCloseMsg;\r
12 import org.umu.cops.stack.COPSDecisionMsg;\r
13 import org.umu.cops.stack.COPSError;\r
14 import org.umu.cops.stack.COPSException;\r
15 import org.umu.cops.stack.COPSHandle;\r
16 import org.umu.cops.stack.COPSHeader;\r
17 import org.umu.cops.stack.COPSKAMsg;\r
18 import org.umu.cops.stack.COPSMsg;\r
19 import org.umu.cops.stack.COPSSyncStateMsg;\r
20 import org.umu.cops.stack.COPSTransceiver;\r
21 \r
22 /**\r
23  * COPSPepConnection represents a PEP-PDP Connection Manager.\r
24  * Responsible for processing messages received from PDP.\r
25  */\r
26 public class COPSPepOSConnection implements Runnable {\r
27     /** Socket connected to PDP */\r
28     protected Socket _sock;\r
29 \r
30     /** Time to wait responses (milliseconds), default is 10 seconds */\r
31     protected int _responseTime;\r
32 \r
33     /** COPS Client-type */\r
34     protected short _clientType;\r
35 \r
36     /**\r
37         Accounting timer value (secs)\r
38      */\r
39     protected short _acctTimer;\r
40 \r
41     /**\r
42         Keep-alive timer value (secs)\r
43      */\r
44     protected short _kaTimer;\r
45 \r
46     /**\r
47      *  Time of the latest keep-alive received\r
48      */\r
49     protected Date _lastRecKa;\r
50 \r
51     /**\r
52         Opcode of the latest message sent\r
53     */\r
54     protected byte _lastmessage;\r
55 \r
56     /**\r
57         Maps a COPS Client Handle to a Request State Manager\r
58      */\r
59     protected Hashtable _managerMap;\r
60     // map < String(COPSHandle), COPSPepOSReqStateMan>;\r
61 \r
62     /**\r
63         COPS error returned by PDP\r
64      */\r
65     protected COPSError _error;\r
66 \r
67     /**\r
68      * Creates a new PEP connection\r
69      * @param clientType    PEP's client-type\r
70      * @param sock          Socket connected to PDP\r
71      */\r
72     public COPSPepOSConnection(short clientType, Socket sock) {\r
73         _clientType = clientType;\r
74         _sock = sock;\r
75 \r
76         // Timers\r
77         _acctTimer = 0;\r
78         _kaTimer = 0;\r
79         _responseTime = 10000;\r
80         _lastmessage = COPSHeader.COPS_OP_CAT;\r
81 \r
82         _managerMap = new Hashtable(20);\r
83     }\r
84 \r
85     /**\r
86      * Gets the response time\r
87      * @return  Response time value (msecs)\r
88      */\r
89     public int getResponseTime() {\r
90         return _responseTime;\r
91     }\r
92 \r
93     /**\r
94      * Gets the socket connected to the PDP\r
95      * @return  Socket connected to PDP\r
96      */\r
97     public Socket getSocket() {\r
98         return _sock;\r
99     }\r
100 \r
101     /**\r
102      * Gets keep-alive timer\r
103      * @return  Keep-alive timer value (secs)\r
104      */\r
105     public short getKaTimer () {\r
106         return _kaTimer;\r
107     }\r
108 \r
109     /**\r
110      * Gets accounting timer\r
111      * @return  Accounting timer value (secs)\r
112      */\r
113     public short getAcctTimer () {\r
114         return _acctTimer;\r
115     }\r
116 \r
117     /**\r
118      * Gets active COPS handles\r
119      * @return  An <tt>Enumeration</tt> holding all active handles\r
120      */\r
121     protected Enumeration getHandles() {\r
122         return _managerMap.keys();\r
123     }\r
124 \r
125     /**\r
126      * Gets all request state managers\r
127      * @return  A <tt>Hashatable</tt> holding all request state managers\r
128      */\r
129     protected Hashtable getReqStateMans() {\r
130         return _managerMap;\r
131     }\r
132 \r
133     /**\r
134      * Checks whether the socket to the PDP is closed or not\r
135      * @return  <tt>true</tt> if the socket is closed, <tt>false</tt> otherwise\r
136      */\r
137     public boolean isClosed() {\r
138         return _sock.isClosed();\r
139     }\r
140 \r
141     /**\r
142      * Closes the socket\r
143      *\r
144      * @throws java.io.IOException\r
145      */\r
146     protected void close() throws IOException {\r
147         _sock.close();\r
148     }\r
149 \r
150     /**\r
151      * Gets the opcode of the lastest message sent\r
152      * @return  Message opcode\r
153      */\r
154     public byte getLastmessage() {\r
155         return _lastmessage;\r
156     }\r
157 \r
158     /**\r
159      * Sets response time\r
160      * @param respTime  Response time value (msecs)\r
161      */\r
162     public void setResponseTime(int respTime) {\r
163         _responseTime = respTime;\r
164     };\r
165 \r
166     /**\r
167      * Sets keep-alive timer\r
168      * @param kaTimer   Keep-alive timer value (secs)\r
169      */\r
170     public void setKaTimer(short kaTimer) {\r
171         _kaTimer = kaTimer;\r
172     }\r
173 \r
174     /**\r
175      * Sets accounting timer\r
176      * @param acctTimer Accounting timer value (secs)\r
177      */\r
178     public void setAcctTimer(short acctTimer) {\r
179         _acctTimer = acctTimer;\r
180     }\r
181 \r
182     /**\r
183      * Message-processing loop\r
184      */\r
185     public void run () {\r
186         Date _lastSendKa = new Date();\r
187         Date _lastSendAcc = new Date();\r
188         _lastRecKa = new Date();\r
189 \r
190         try {\r
191             while (!_sock.isClosed()) {\r
192                 if (_sock.getInputStream().available() != 0) {\r
193                     _lastmessage = processMessage(_sock);\r
194                     _lastRecKa = new Date();\r
195                 }\r
196 \r
197                 // Keep Alive\r
198                 if (_kaTimer > 0) {\r
199                     // Timeout del PDP\r
200                     int _startTime = (int) (_lastRecKa.getTime());\r
201                     int cTime = (int) (new Date().getTime());\r
202 \r
203                     if ((int)(cTime - _startTime) > _kaTimer*1000) {\r
204                         _sock.close();\r
205                         // Notify all Request State Managers\r
206                         notifyNoKAAllReqStateMan();\r
207                     }\r
208 \r
209                     // Send to PEP\r
210                     _startTime = (int) (_lastSendKa.getTime());\r
211                     cTime = (int) (new Date().getTime());\r
212 \r
213                     if ((int)(cTime - _startTime) > ((_kaTimer*3/4) * 1000)) {\r
214                         COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);\r
215                         COPSKAMsg msg = new COPSKAMsg();\r
216 \r
217                         msg.add(hdr);\r
218 \r
219                         COPSTransceiver.sendMsg(msg, _sock);\r
220                         _lastSendKa = new Date();\r
221                     }\r
222                 }\r
223 \r
224                 // Accounting\r
225                 if (_acctTimer > 0) {\r
226                     int _startTime = (int) (_lastSendAcc.getTime());\r
227                     int cTime = (int) (new Date().getTime());\r
228 \r
229                     if ((int)(cTime - _startTime) > ((_acctTimer*3/4)*1000)) {\r
230                         // Notify all Request State Managers\r
231                         notifyAcctAllReqStateMan();\r
232                         _lastSendAcc = new Date();\r
233                     }\r
234                 }\r
235 \r
236                 try {\r
237                     Thread.sleep(500);\r
238                 } catch (Exception e) {};\r
239             }\r
240         } catch (Exception e) {\r
241             e.printStackTrace();\r
242             COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);\r
243         }\r
244 \r
245         // connection closed by server\r
246         // COPSDebug.out(getClass().getName(),"Connection closed by server");\r
247         try {\r
248             _sock.close();\r
249         } catch (IOException e) {};\r
250 \r
251         // Notify all Request State Managers\r
252         try {\r
253             notifyCloseAllReqStateMan();\r
254         } catch (COPSPepException e) {};\r
255     }\r
256 \r
257     /**\r
258      * Gets a COPS message from the socket and processes it\r
259      * @param conn  Socket connected to the PDP\r
260      * @return COPS message type\r
261      * @throws COPSPepException\r
262      * @throws COPSException\r
263      * @throws IOException\r
264      */\r
265     protected byte processMessage(Socket conn) throws COPSPepException, COPSException, IOException {\r
266         COPSMsg msg = COPSTransceiver.receiveMsg(conn);\r
267 \r
268         if (msg.getHeader().isAClientClose()) {\r
269             handleClientCloseMsg(conn, msg);\r
270             return COPSHeader.COPS_OP_CC;\r
271         } else if (msg.getHeader().isADecision()) {\r
272             handleDecisionMsg(/*OJO conn, */msg);\r
273             return COPSHeader.COPS_OP_DEC;\r
274         } else if (msg.getHeader().isASyncStateReq()) {\r
275             handleSyncStateReqMsg(conn, msg);\r
276             return COPSHeader.COPS_OP_SSQ;\r
277         } else if (msg.getHeader().isAKeepAlive()) {\r
278             handleKeepAliveMsg(conn, msg);\r
279             return COPSHeader.COPS_OP_KA;\r
280         } else {\r
281             throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");\r
282         }\r
283     }\r
284 \r
285     /**\r
286      * Handle Client Close Message, close the passed connection\r
287      *\r
288      * @param    conn                a  Socket\r
289      * @param    msg                 a  COPSMsg\r
290      *\r
291      *\r
292      * <Client-Close> ::= <Common Header>\r
293      *                      <Error>\r
294      *                      [<Integrity>]\r
295      *\r
296      * Not support [<Integrity>]\r
297      *\r
298      */\r
299     private void handleClientCloseMsg(Socket conn, COPSMsg msg) {\r
300         COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;\r
301         _error = cMsg.getError();\r
302 \r
303         // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +\r
304         //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");\r
305 \r
306         try {\r
307             // Support\r
308             if (cMsg.getIntegrity() != null)\r
309                 COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED, "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
310 \r
311             conn.close();\r
312         } catch (Exception unae) { };\r
313     }\r
314 \r
315     /**\r
316      * Gets the COPS error\r
317      * @return  <tt>COPSError</tt> returned by PDP\r
318      */\r
319     protected COPSError getError() {\r
320         return _error;\r
321     }\r
322 \r
323     /**\r
324      * Handle Keep Alive Message\r
325      *\r
326      * <Keep-Alive> ::= <Common Header>\r
327      *                  [<Integrity>]\r
328      *\r
329      * Not support [<Integrity>]\r
330      *\r
331      * @param    conn                a  Socket\r
332      * @param    msg                 a  COPSMsg\r
333      *\r
334      */\r
335     private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {\r
336         COPSKAMsg cMsg = (COPSKAMsg) msg;\r
337 \r
338         // COPSDebug.out(getClass().getName(),"Get KAlive Msg");\r
339 \r
340         try {\r
341             // Support\r
342             if (cMsg.getIntegrity() != null)\r
343                 COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED, "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
344 \r
345             // must we do anything else?\r
346 \r
347         } catch (Exception unae) { };\r
348     }\r
349 \r
350     /**\r
351      * Method handleDecisionMsg\r
352      *\r
353      * <Decision Message> ::= <Common Header: Flag SOLICITED>\r
354      *                          <Client Handle>\r
355      *                          *(<Decision>) | <Error>\r
356      *                          [<Integrity>]\r
357      * <Decision> ::= <Context>\r
358      *                  <Decision: Flags>\r
359      *                  [<ClientSI Decision Data: Outsourcing>]\r
360      * <Decision: Flags> ::= <Command-Code> NULLFlag\r
361      * <Command-Code> ::= NULLDecision | Install | Remove\r
362      * <ClientSI Decision Data> ::= <<Install Decision> | <Remove Decision>>\r
363      * <Install Decision> ::= *(<PRID> <EPD>)\r
364      * <Remove Decision> ::= *(<PRID> | <PPRID>)\r
365      *\r
366      * @param    msg                 a  COPSMsg\r
367      *\r
368      */\r
369     private void handleDecisionMsg(/*OJO Socket conn, */COPSMsg msg) throws COPSPepException {\r
370         COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;\r
371         COPSHandle handle = dMsg.getClientHandle();\r
372         COPSPepOSReqStateMan manager = (COPSPepOSReqStateMan) _managerMap.get(handle.getId().str());\r
373         manager.processDecision(dMsg);\r
374     }\r
375 \r
376     /**\r
377      * Method handleSyncStateReqMsg\r
378      *\r
379      *              <Synchronize State> ::= <Common Header>\r
380      *                                      [<Client Handle>]\r
381      *                                      [<Integrity>]\r
382      *\r
383      * @param    conn                a  Socket\r
384      * @param    msg                 a  COPSMsg\r
385      *\r
386      */\r
387     private void handleSyncStateReqMsg(Socket conn, COPSMsg msg) throws COPSPepException {\r
388         COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;\r
389         // COPSHandle handle = cMsg.getClientHandle();\r
390         // COPSHeader header = cMsg.getHeader();\r
391 \r
392         // Support\r
393         if (cMsg.getIntegrity() != null)\r
394             COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
395                           "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
396 \r
397         COPSPepOSReqStateMan manager = (COPSPepOSReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
398 \r
399         if (manager == null)\r
400             COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
401         else\r
402             manager.processSyncStateRequest(cMsg);\r
403     }\r
404 \r
405     /**\r
406      * Adds a new request state\r
407      * @param clientHandle  Client's handle\r
408      * @param process       Policy data processing object\r
409      * @param clientSIs     Client data from the outsourcing event\r
410      * @return              The newly created request state manager\r
411      * @throws COPSException\r
412      * @throws COPSPepException\r
413      */\r
414     protected COPSPepOSReqStateMan addRequestState(String clientHandle, COPSPepOSDataProcess process, Vector clientSIs) throws COPSException, COPSPepException {\r
415         COPSPepOSReqStateMan manager = new COPSPepOSReqStateMan(_clientType, clientHandle);\r
416         if (_managerMap.get(clientHandle) != null)\r
417             throw new COPSPepException("Duplicate Handle, rejecting " + clientHandle);\r
418 \r
419         manager.setDataProcess(process);\r
420         manager.setClientSI(clientSIs);\r
421         _managerMap.put(clientHandle, manager);\r
422         manager.initRequestState(_sock);\r
423         return manager;\r
424     }\r
425 \r
426     /**\r
427      * Deletes a request state\r
428      * @param manager   Request state manager\r
429      * @throws COPSException\r
430      * @throws COPSPepException\r
431      */\r
432     protected void deleteRequestState(COPSPepOSReqStateMan manager) throws COPSException, COPSPepException {\r
433         manager.finalizeRequestState();\r
434     }\r
435 \r
436     private void notifyCloseAllReqStateMan() throws COPSPepException {\r
437         if (_managerMap.size() > 0) {\r
438             for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
439                 String handle = (String) e.nextElement();\r
440                 COPSPepOSReqStateMan man = (COPSPepOSReqStateMan) _managerMap.get(handle);\r
441 \r
442                 man.processClosedConnection(_error);\r
443             }\r
444         }\r
445     }\r
446 \r
447     private void notifyNoKAAllReqStateMan() throws COPSPepException {\r
448         if (_managerMap.size() > 0) {\r
449             for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
450                 String handle = (String) e.nextElement();\r
451                 COPSPepOSReqStateMan man = (COPSPepOSReqStateMan) _managerMap.get(handle);\r
452 \r
453                 man.processNoKAConnection();\r
454             }\r
455         }\r
456     }\r
457 \r
458     private void notifyAcctAllReqStateMan() throws COPSPepException {\r
459         if (_managerMap.size() > 0) {\r
460             for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
461                 String handle = (String) e.nextElement();\r
462                 COPSPepOSReqStateMan man = (COPSPepOSReqStateMan) _managerMap.get(handle);\r
463 \r
464                 man.processAcctReport();\r
465             }\r
466         }\r
467     }\r
468 \r
469 }\r