Add packetcable-driver as a bundle and fix karafe depends. Merge hop-along model...
[packetcable.git] / packetcable-driver / src / main / java / org / umu / cops / prpdp / COPSPdpConnection.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.Socket;\r
11 import java.util.Date;\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.COPSClientCloseMsg;\r
17 import org.umu.cops.stack.COPSContext;\r
18 import org.umu.cops.stack.COPSDeleteMsg;\r
19 import org.umu.cops.stack.COPSError;\r
20 import org.umu.cops.stack.COPSException;\r
21 import org.umu.cops.stack.COPSHeader;\r
22 import org.umu.cops.stack.COPSKAMsg;\r
23 import org.umu.cops.stack.COPSMsg;\r
24 import org.umu.cops.stack.COPSPepId;\r
25 import org.umu.cops.stack.COPSReportMsg;\r
26 import org.umu.cops.stack.COPSReqMsg;\r
27 import org.umu.cops.stack.COPSSyncStateMsg;\r
28 import org.umu.cops.stack.COPSTransceiver;\r
29 \r
30 /**\r
31  * Class for managing an provisioning connection at the PDP side.\r
32  */\r
33 public class COPSPdpConnection implements Runnable {\r
34 \r
35     /**\r
36         Socket connected to PEP\r
37      */\r
38     private Socket _sock;\r
39 \r
40     /**\r
41         PEP identifier\r
42     */\r
43     private COPSPepId _pepId;\r
44 \r
45     /**\r
46         Time of the latest keep-alive sent\r
47      */\r
48     private Date _lastKa;\r
49 \r
50     /**\r
51         Opcode of the latest message sent\r
52     */\r
53     private byte _lastmessage;\r
54 \r
55     /**\r
56      *  Time of the latest keep-alive received\r
57      */\r
58     protected Date _lastRecKa;\r
59 \r
60     /**\r
61         Maps a Client Handle to a Handler\r
62      */\r
63     protected Hashtable _managerMap;\r
64     // map < String(COPSHandle), COPSPdpHandler> HandlerMap;\r
65 \r
66     /**\r
67      *  PDP policy data processor class\r
68      */\r
69     protected COPSPdpDataProcess _process;\r
70 \r
71     /**\r
72         Accounting timer value (secs)\r
73      */\r
74     protected short _acctTimer;\r
75 \r
76     /**\r
77         Keep-alive timer value (secs)\r
78      */\r
79     protected short _kaTimer;\r
80 \r
81     /**\r
82         COPS error returned by PEP\r
83      */\r
84     protected COPSError _error;\r
85 \r
86     /**\r
87      * Creates a new PDP connection\r
88      *\r
89      * @param pepId PEP-ID of the connected PEP\r
90      * @param sock  Socket connected to PEP\r
91      * @param process   Object for processing policy data\r
92      */\r
93     public COPSPdpConnection(COPSPepId pepId, Socket sock, COPSPdpDataProcess process) {\r
94         _sock = sock;\r
95         _pepId = pepId;\r
96 \r
97         _lastKa = new Date();\r
98         _lastmessage = COPSHeader.COPS_OP_OPN;\r
99         _managerMap = new Hashtable(20);\r
100 \r
101         _kaTimer = 0;\r
102         _process = process;\r
103     }\r
104 \r
105     /**\r
106      * Gets the time of that latest keep-alive sent\r
107      * @return Time of that latest keep-alive sent\r
108      */\r
109     public Date getLastKAlive() {\r
110         return _lastKa;\r
111     }\r
112 \r
113     /**\r
114      * Sets the keep-alive timer value\r
115      * @param kaTimer Keep-alive timer value (secs)\r
116      */\r
117     public void setKaTimer(short kaTimer) {\r
118         _kaTimer = kaTimer;\r
119     }\r
120 \r
121     /**\r
122      * Gets the keep-alive timer value\r
123      * @return Keep-alive timer value (secs)\r
124      */\r
125     public short getKaTimer() {\r
126         return _kaTimer;\r
127     }\r
128 \r
129     /**\r
130      * Sets the accounting timer value\r
131      * @param acctTimer Accounting timer value (secs)\r
132      */\r
133     public void setAccTimer(short acctTimer) {\r
134         _acctTimer = acctTimer;\r
135     }\r
136 \r
137     /**\r
138      * Gets the accounting timer value\r
139      * @return Accounting timer value (secs)\r
140      */\r
141     public short getAcctTimer() {\r
142         return _acctTimer;\r
143     }\r
144 \r
145     /**\r
146      * Gets the latest COPS message\r
147      * @return   Code of the latest message sent\r
148      */\r
149     public byte getLastMessage() {\r
150         return _lastmessage;\r
151     }\r
152 \r
153     /**\r
154      * Gets active handles\r
155      * @return   An <tt>Enumeration</tt> holding all active handles\r
156      */\r
157     public Enumeration getHandles() {\r
158         return _managerMap.keys();\r
159     }\r
160 \r
161     /**\r
162      * Gets the handle map\r
163      * @return   A <tt>Hashtable</tt> holding the handle map\r
164      */\r
165     public Hashtable getReqStateMans() {\r
166         return _managerMap;\r
167     }\r
168 \r
169     /**\r
170      * Gets the PEP-ID\r
171      * @return   The ID of the PEP, as a <tt>String</tt>\r
172      */\r
173     public String getPepId() {\r
174         return _pepId.getData().str();\r
175     }\r
176 \r
177     /**\r
178      * Checks whether the socket to the PEP is closed or not\r
179      * @return   <tt>true</tt> if closed, <tt>false</tt> otherwise\r
180      */\r
181     public boolean isClosed() {\r
182         return _sock.isClosed();\r
183     }\r
184 \r
185     /**\r
186      * Closes the socket to the PEP\r
187      * @throws IOException\r
188      */\r
189     protected void close()\r
190     throws IOException {\r
191         _sock.close();\r
192     }\r
193 \r
194     /**\r
195      * Gets the socket to the PEP\r
196      * @return   Socket connected to the PEP\r
197      */\r
198     public Socket getSocket() {\r
199         return _sock;\r
200     }\r
201 \r
202     /**\r
203      * Main loop\r
204      */\r
205     public void run () {\r
206         Date _lastSendKa = new Date();\r
207         _lastRecKa = new Date();\r
208         try {\r
209             while (!_sock.isClosed()) {\r
210                 if (_sock.getInputStream().available() != 0) {\r
211                     _lastmessage = processMessage(_sock);\r
212                     _lastRecKa = new Date();\r
213                 }\r
214 \r
215                 // Keep Alive\r
216                 if (_kaTimer > 0) {\r
217                     // Timeout at PDP\r
218                     int _startTime = (int) (_lastRecKa.getTime());\r
219                     int cTime = (int) (new Date().getTime());\r
220 \r
221                     if ((int)(cTime - _startTime) > _kaTimer*1000) {\r
222                         _sock.close();\r
223                         // Notify all Request State Managers\r
224                         notifyNoKAAllReqStateMan();\r
225                     }\r
226 \r
227                     // Send to PEP\r
228                     _startTime = (int) (_lastSendKa.getTime());\r
229                     cTime = (int) (new Date().getTime());\r
230 \r
231                     if ((int)(cTime - _startTime) > ((_kaTimer*3/4)*1000)) {\r
232                         COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);\r
233                         COPSKAMsg msg = new COPSKAMsg();\r
234 \r
235                         msg.add(hdr);\r
236 \r
237                         COPSTransceiver.sendMsg(msg, _sock);\r
238                         _lastSendKa = new Date();\r
239                     }\r
240                 }\r
241 \r
242                 try {\r
243                     Thread.sleep(500);\r
244                 } catch (Exception e) {};\r
245 \r
246             }\r
247         } catch (Exception e) {\r
248             COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);\r
249         }\r
250 \r
251         // connection closed by server\r
252         // COPSDebug.out(getClass().getName(),"Connection closed by client");\r
253         try {\r
254             _sock.close();\r
255         } catch (IOException e) {};\r
256 \r
257         // Notify all Request State Managers\r
258         try {\r
259             notifyCloseAllReqStateMan();\r
260         } catch (COPSPdpException e) {};\r
261     }\r
262 \r
263     /**\r
264      * Gets a COPS message from the socket and processes it\r
265      * @param    conn Socket connected to the PEP\r
266      * @return Type of COPS message\r
267      */\r
268     private byte processMessage(Socket conn)\r
269     throws COPSPdpException, COPSException, IOException {\r
270         COPSMsg msg = COPSTransceiver.receiveMsg(conn);\r
271 \r
272         if (msg.getHeader().isAClientClose()) {\r
273             handleClientCloseMsg(conn, msg);\r
274             return COPSHeader.COPS_OP_CC;\r
275         } else if (msg.getHeader().isAKeepAlive()) {\r
276             handleKeepAliveMsg(conn, msg);\r
277             return COPSHeader.COPS_OP_KA;\r
278         } else if (msg.getHeader().isARequest()) {\r
279             handleRequestMsg(conn, msg);\r
280             return COPSHeader.COPS_OP_REQ;\r
281         } else if (msg.getHeader().isAReport()) {\r
282             handleReportMsg(conn, msg);\r
283             return COPSHeader.COPS_OP_RPT;\r
284         } else if (msg.getHeader().isADeleteReq()) {\r
285             handleDeleteRequestMsg(conn, msg);\r
286             return COPSHeader.COPS_OP_DRQ;\r
287         } else if (msg.getHeader().isASyncComplete()) {\r
288             handleSyncComplete(conn, msg);\r
289             return COPSHeader.COPS_OP_SSC;\r
290         } else {\r
291             throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");\r
292         }\r
293     }\r
294 \r
295     /**\r
296      * Handle Client Close Message, close the passed connection\r
297      *\r
298      * @param    conn                a  Socket\r
299      * @param    msg                 a  COPSMsg\r
300      *\r
301      *\r
302      * <Client-Close> ::= <Common Header>\r
303      *                      <Error>\r
304      *                      [<Integrity>]\r
305      *\r
306      * Not support [<Integrity>]\r
307      *\r
308      */\r
309     private void handleClientCloseMsg(Socket conn, COPSMsg msg) {\r
310         COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;\r
311         _error = cMsg.getError();\r
312 \r
313         // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +\r
314         //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");\r
315 \r
316         try {\r
317             // Support\r
318             if (cMsg.getIntegrity() != null) {\r
319                 COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
320                               "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
321             }\r
322 \r
323             conn.close();\r
324         } catch (Exception unae) { };\r
325     }\r
326 \r
327     /**\r
328      * Gets the occurred COPS Error\r
329      * @return   <tt>COPSError</tt> object\r
330      */\r
331     protected COPSError getError()  {\r
332         return _error;\r
333     }\r
334 \r
335     /**\r
336      * Handle Keep Alive Message\r
337      *\r
338      * <Keep-Alive> ::= <Common Header>\r
339      *                  [<Integrity>]\r
340      *\r
341      * Not support [<Integrity>]\r
342      *\r
343      * @param    conn                a  Socket\r
344      * @param    msg                 a  COPSMsg\r
345      *\r
346      */\r
347     private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {\r
348         COPSKAMsg cMsg = (COPSKAMsg) msg;\r
349 \r
350         COPSKAMsg kaMsg = (COPSKAMsg) msg;\r
351         try {\r
352             // Support\r
353             if (cMsg.getIntegrity() != null) {\r
354                 COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
355                               "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
356             }\r
357 \r
358             kaMsg.writeData(conn);\r
359         } catch (Exception unae) { };\r
360     }\r
361 \r
362     /**\r
363      * Handle Delete Request Message\r
364      *\r
365      * <Delete Request> ::= <Common Header>\r
366      *                      <Client Handle>\r
367      *                      <Reason>\r
368      *                      [<Integrity>]\r
369      *\r
370      * Not support [<Integrity>]\r
371      *\r
372      * @param    conn                a  Socket\r
373      * @param    msg                 a  COPSMsg\r
374      *\r
375      */\r
376     private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)\r
377     throws COPSPdpException {\r
378         COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;\r
379         // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +\r
380         //  conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");\r
381 \r
382         // Support\r
383         if (cMsg.getIntegrity() != null) {\r
384             COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
385                           "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
386         }\r
387 \r
388         // Delete clientHandler\r
389         if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {\r
390             // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +\r
391             //  cMsg.getClientHandle().getId().getData());\r
392         }\r
393 \r
394         COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
395         if (man == null) {\r
396             COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
397         } else {\r
398             man.processDeleteRequestState(cMsg);\r
399         }\r
400 \r
401     }\r
402 \r
403     /**\r
404      * Handle Request Message\r
405      *\r
406      * <Request> ::= <Common Header>\r
407      *                  <Client Handle>\r
408      *                  <Context>\r
409      *                  *(<Named ClientSI>)\r
410      *                  [<Integrity>]\r
411      * <Named ClientSI> ::= <*(<PRID> <EPD>)>\r
412      *\r
413      * Not support [<Integrity>]\r
414      *\r
415      * @param    conn                a  Socket\r
416      * @param    msg                 a  COPSMsg\r
417      *\r
418      */\r
419     private void handleRequestMsg(Socket conn, COPSMsg msg)\r
420     throws COPSPdpException {\r
421 \r
422         COPSReqMsg reqMsg = (COPSReqMsg) msg;\r
423         COPSContext cntxt = reqMsg.getContext();\r
424         COPSHeader header = reqMsg.getHeader();\r
425         //short reqType = cntxt.getRequestType();\r
426         short cType   = header.getClientType();\r
427 \r
428         // Support\r
429         if (reqMsg.getIntegrity() != null) {\r
430             COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
431                           "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
432         }\r
433 \r
434         COPSPdpReqStateMan man;\r
435         man = (COPSPdpReqStateMan) _managerMap.get(reqMsg.getClientHandle().getId().str());\r
436         if (man == null) {\r
437 \r
438             man = new COPSPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());\r
439             _managerMap.put(reqMsg.getClientHandle().getId().str(),man);\r
440             man.setDataProcess(_process);\r
441             man.initRequestState(_sock);\r
442 \r
443             // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +\r
444             //    header.getClientType() + " msgType=" +\r
445             //    cntxt.getMessageType() + ", connId=" + conn.toString());\r
446         }\r
447 \r
448         man.processRequest(reqMsg);\r
449     }\r
450 \r
451     /**\r
452      * Handle Report Message\r
453      *\r
454      * <Report State> ::= <Common Header>\r
455      *                      <Client Handle>\r
456      *                      <Report Type>\r
457      *                      *(<Named ClientSI>)\r
458      *                      [<Integrity>]\r
459      *\r
460      * Not support [<Integrity>]\r
461      *\r
462      * @param    conn                a  Socket\r
463      * @param    msg                 a  COPSMsg\r
464      *\r
465      */\r
466     private void handleReportMsg(Socket conn, COPSMsg msg)\r
467     throws COPSPdpException {\r
468         COPSReportMsg repMsg = (COPSReportMsg) msg;\r
469         // COPSHandle handle = repMsg.getClientHandle();\r
470         // COPSHeader header = repMsg.getHeader();\r
471 \r
472         // Support\r
473         if (repMsg.getIntegrity() != null) {\r
474             COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
475                           "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
476         }\r
477 \r
478         COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(repMsg.getClientHandle().getId().str());\r
479         if (man == null) {\r
480             COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
481         } else {\r
482             man.processReport(repMsg);\r
483         }\r
484     }\r
485 \r
486     /**\r
487      * Method handleSyncComplete\r
488      *\r
489      * @param    conn                a  Socket\r
490      * @param    msg                 a  COPSMsg\r
491      *\r
492      */\r
493     private void handleSyncComplete(Socket conn, COPSMsg msg)\r
494     throws COPSPdpException {\r
495         COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;\r
496         // COPSHandle handle = cMsg.getClientHandle();\r
497         // COPSHeader header = cMsg.getHeader();\r
498 \r
499         // Support\r
500         if (cMsg.getIntegrity() != null) {\r
501             COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
502                           "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
503         }\r
504 \r
505         COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
506         if (man == null) {\r
507             COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
508         } else {\r
509             man.processSyncComplete(cMsg);\r
510         }\r
511     }\r
512 \r
513     /**\r
514      * Requests a COPS sync from the PEP\r
515      * @throws COPSException\r
516      * @throws COPSPdpException\r
517      */\r
518     protected void syncAllRequestState()\r
519     throws COPSException, COPSPdpException {\r
520         if (_managerMap.size() > 0) {\r
521             for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
522                 String handle = (String) e.nextElement();\r
523                 COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(handle);\r
524 \r
525                 man.syncRequestState();\r
526             }\r
527         }\r
528     }\r
529 \r
530     private void notifyCloseAllReqStateMan()\r
531     throws COPSPdpException {\r
532         if (_managerMap.size() > 0) {\r
533             for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
534                 String handle = (String) e.nextElement();\r
535                 COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(handle);\r
536 \r
537                 man.processClosedConnection(_error);\r
538             }\r
539         }\r
540     }\r
541 \r
542     private void notifyNoKAAllReqStateMan()\r
543     throws COPSPdpException {\r
544         if (_managerMap.size() > 0) {\r
545             for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
546                 String handle = (String) e.nextElement();\r
547                 COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(handle);\r
548 \r
549                 man.processNoKAConnection();\r
550             }\r
551         }\r
552     }\r
553 \r
554 }\r
555 \r