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