1 package org.umu.cops.ospep;
\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
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
23 * COPSPepConnection represents a PEP-PDP Connection Manager.
\r
24 * Responsible for processing messages received from PDP.
\r
26 public class COPSPepOSConnection implements Runnable {
\r
27 /** Socket connected to PDP */
\r
28 protected Socket _sock;
\r
30 /** Time to wait responses (milliseconds), default is 10 seconds */
\r
31 protected int _responseTime;
\r
33 /** COPS Client-type */
\r
34 protected short _clientType;
\r
37 Accounting timer value (secs)
\r
39 protected short _acctTimer;
\r
42 Keep-alive timer value (secs)
\r
44 protected short _kaTimer;
\r
47 * Time of the latest keep-alive received
\r
49 protected Date _lastRecKa;
\r
52 Opcode of the latest message sent
\r
54 protected byte _lastmessage;
\r
57 Maps a COPS Client Handle to a Request State Manager
\r
59 protected Hashtable _managerMap;
\r
60 // map < String(COPSHandle), COPSPepOSReqStateMan>;
\r
63 COPS error returned by PDP
\r
65 protected COPSError _error;
\r
68 * Creates a new PEP connection
\r
69 * @param clientType PEP's client-type
\r
70 * @param sock Socket connected to PDP
\r
72 public COPSPepOSConnection(short clientType, Socket sock) {
\r
73 _clientType = clientType;
\r
79 _responseTime = 10000;
\r
80 _lastmessage = COPSHeader.COPS_OP_CAT;
\r
82 _managerMap = new Hashtable(20);
\r
86 * Gets the response time
\r
87 * @return Response time value (msecs)
\r
89 public int getResponseTime() {
\r
90 return _responseTime;
\r
94 * Gets the socket connected to the PDP
\r
95 * @return Socket connected to PDP
\r
97 public Socket getSocket() {
\r
102 * Gets keep-alive timer
\r
103 * @return Keep-alive timer value (secs)
\r
105 public short getKaTimer () {
\r
110 * Gets accounting timer
\r
111 * @return Accounting timer value (secs)
\r
113 public short getAcctTimer () {
\r
118 * Gets active COPS handles
\r
119 * @return An <tt>Enumeration</tt> holding all active handles
\r
121 protected Enumeration getHandles() {
\r
122 return _managerMap.keys();
\r
126 * Gets all request state managers
\r
127 * @return A <tt>Hashatable</tt> holding all request state managers
\r
129 protected Hashtable getReqStateMans() {
\r
130 return _managerMap;
\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
137 public boolean isClosed() {
\r
138 return _sock.isClosed();
\r
142 * Closes the socket
\r
144 * @throws java.io.IOException
\r
146 protected void close() throws IOException {
\r
151 * Gets the opcode of the lastest message sent
\r
152 * @return Message opcode
\r
154 public byte getLastmessage() {
\r
155 return _lastmessage;
\r
159 * Sets response time
\r
160 * @param respTime Response time value (msecs)
\r
162 public void setResponseTime(int respTime) {
\r
163 _responseTime = respTime;
\r
167 * Sets keep-alive timer
\r
168 * @param kaTimer Keep-alive timer value (secs)
\r
170 public void setKaTimer(short kaTimer) {
\r
171 _kaTimer = kaTimer;
\r
175 * Sets accounting timer
\r
176 * @param acctTimer Accounting timer value (secs)
\r
178 public void setAcctTimer(short acctTimer) {
\r
179 _acctTimer = acctTimer;
\r
183 * Message-processing loop
\r
185 public void run () {
\r
186 Date _lastSendKa = new Date();
\r
187 Date _lastSendAcc = new Date();
\r
188 _lastRecKa = new Date();
\r
191 while (!_sock.isClosed()) {
\r
192 if (_sock.getInputStream().available() != 0) {
\r
193 _lastmessage = processMessage(_sock);
\r
194 _lastRecKa = new Date();
\r
198 if (_kaTimer > 0) {
\r
200 int _startTime = (int) (_lastRecKa.getTime());
\r
201 int cTime = (int) (new Date().getTime());
\r
203 if ((int)(cTime - _startTime) > _kaTimer*1000) {
\r
205 // Notify all Request State Managers
\r
206 notifyNoKAAllReqStateMan();
\r
210 _startTime = (int) (_lastSendKa.getTime());
\r
211 cTime = (int) (new Date().getTime());
\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
219 COPSTransceiver.sendMsg(msg, _sock);
\r
220 _lastSendKa = new Date();
\r
225 if (_acctTimer > 0) {
\r
226 int _startTime = (int) (_lastSendAcc.getTime());
\r
227 int cTime = (int) (new Date().getTime());
\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
238 } catch (Exception e) {};
\r
240 } catch (Exception e) {
\r
241 e.printStackTrace();
\r
242 COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);
\r
245 // connection closed by server
\r
246 // COPSDebug.out(getClass().getName(),"Connection closed by server");
\r
249 } catch (IOException e) {};
\r
251 // Notify all Request State Managers
\r
253 notifyCloseAllReqStateMan();
\r
254 } catch (COPSPepException e) {};
\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
265 protected byte processMessage(Socket conn) throws COPSPepException, COPSException, IOException {
\r
266 COPSMsg msg = COPSTransceiver.receiveMsg(conn);
\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
281 throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");
\r
286 * Handle Client Close Message, close the passed connection
\r
288 * @param conn a Socket
\r
289 * @param msg a COPSMsg
\r
292 * <Client-Close> ::= <Common Header>
\r
296 * Not support [<Integrity>]
\r
299 private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
\r
300 COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
\r
301 _error = cMsg.getError();
\r
303 // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
\r
304 // conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
\r
308 if (cMsg.getIntegrity() != null)
\r
309 COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED, "Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
312 } catch (Exception unae) { };
\r
316 * Gets the COPS error
\r
317 * @return <tt>COPSError</tt> returned by PDP
\r
319 protected COPSError getError() {
\r
324 * Handle Keep Alive Message
\r
326 * <Keep-Alive> ::= <Common Header>
\r
329 * Not support [<Integrity>]
\r
331 * @param conn a Socket
\r
332 * @param msg a COPSMsg
\r
335 private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
\r
336 COPSKAMsg cMsg = (COPSKAMsg) msg;
\r
338 // COPSDebug.out(getClass().getName(),"Get KAlive Msg");
\r
342 if (cMsg.getIntegrity() != null)
\r
343 COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED, "Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
345 // must we do anything else?
\r
347 } catch (Exception unae) { };
\r
351 * Method handleDecisionMsg
\r
353 * <Decision Message> ::= <Common Header: Flag SOLICITED>
\r
355 * *(<Decision>) | <Error>
\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
366 * @param msg a COPSMsg
\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
377 * Method handleSyncStateReqMsg
\r
379 * <Synchronize State> ::= <Common Header>
\r
380 * [<Client Handle>]
\r
383 * @param conn a Socket
\r
384 * @param msg a COPSMsg
\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
393 if (cMsg.getIntegrity() != null)
\r
394 COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,
\r
395 "Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
397 COPSPepOSReqStateMan manager = (COPSPepOSReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
\r
399 if (manager == null)
\r
400 COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);
\r
402 manager.processSyncStateRequest(cMsg);
\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
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
419 manager.setDataProcess(process);
\r
420 manager.setClientSI(clientSIs);
\r
421 _managerMap.put(clientHandle, manager);
\r
422 manager.initRequestState(_sock);
\r
427 * Deletes a request state
\r
428 * @param manager Request state manager
\r
429 * @throws COPSException
\r
430 * @throws COPSPepException
\r
432 protected void deleteRequestState(COPSPepOSReqStateMan manager) throws COPSException, COPSPepException {
\r
433 manager.finalizeRequestState();
\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
442 man.processClosedConnection(_error);
\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
453 man.processNoKAConnection();
\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
464 man.processAcctReport();
\r