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