Refactor shared attributes and methods to the PEP agent super COPSPepAgent.
[packetcable.git] / packetcable-driver / src / main / java / org / umu / cops / prpep / COPSPepAgent.java
1 /*
2  * Copyright (c) 2004 University of Murcia.  All rights reserved.
3  * --------------------------------------------------------------
4  * For more information, please see <http://www.umu.euro6ix.org/>.
5  */
6
7 package org.umu.cops.prpep;
8
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11 import org.umu.cops.stack.*;
12 import org.umu.cops.stack.COPSError.ErrorTypes;
13 import org.umu.cops.stack.COPSHeader.OPCode;
14
15 import java.io.IOException;
16 import java.net.InetAddress;
17 import java.net.Socket;
18
19 /**
20  * This is a provisioning COPS PEP. Responsible for making
21  * connection to the PDP and maintaining it
22  */
23 public class COPSPepAgent {
24
25     /** Well-known port for COPS */
26     public static final int WELL_KNOWN_CMTS_PORT = 3918;
27
28     private final static Logger logger = LoggerFactory.getLogger(COPSPepAgent.class);
29
30     /**
31      PEP's client-type
32      */
33     protected final short _clientType;
34
35     /**
36      * PEP's Identifier
37      */
38     protected final COPSPepId _pepID;
39
40     /**
41      * PDP port
42      */
43     private final int _psPort;
44
45     // The next two attributes are instantiated after the connect() method has successfully completed.
46     /**
47      * PEP-PDP connection manager
48      */
49     protected transient COPSPepConnection _conn;
50
51     /**
52      * The thread object to manage the connection thread.
53      */
54     private transient Thread thread;
55
56     /**
57      * Creates a PEP agent
58      * @param    clientType         Client-type
59      * @param    pepID              PEP-ID
60      * @param    port               the server socket port to open on this host
61      */
62     public COPSPepAgent(final short clientType, final COPSPepId pepID, final int port) {
63         _clientType = clientType;
64         _pepID = pepID;
65         this._psPort = port;
66     }
67
68     /**
69      * Connects to a PDP and is responsible for setting up the connection
70      * @throws   java.io.IOException
71      * @throws   COPSException
72      * @throws   COPSPepException
73      */
74     public void connect() throws IOException, COPSException {
75         logger.info("Thread ( " + _pepID + ") - Connecting to PDP");
76
77         // Check whether it already exists
78         if (_conn == null)
79             _conn = processConnection();
80         else {
81             // Check if it's closed
82             if (_conn.isClosed()) {
83                 _conn = processConnection();
84             } else {
85                 disconnect(new COPSError(ErrorTypes.SHUTTING_DOWN, ErrorTypes.NA));
86                 _conn = processConnection();
87             }
88         }
89
90         if (_conn == null) throw new COPSException("Unable to process PEP connection");
91     }
92
93     /**
94      * Disconnects from the PDP
95      * @param error Reason
96      * @throws COPSException
97      * @throws IOException
98      */
99     public void disconnect(final COPSError error) throws COPSException, IOException {
100         final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType, error, null, null);
101         thread.interrupt();
102         thread = null;
103         closeMsg.writeData(_conn.getSocket());
104         _conn.close();
105         _conn = null;
106     }
107
108     /**
109      * Adds a request state to the connection manager.
110      * @return  The newly created connection manager
111      * @throws COPSPepException
112      * @throws COPSException
113      */
114     public COPSPepReqStateMan addRequestState(final COPSHandle handle, final COPSPepDataProcess process)
115             throws COPSException {
116         if (_conn != null) {
117             return _conn.addRequestState(handle, process);
118         }
119         return null;
120     }
121
122
123     /**
124      * Queries the connection manager to delete a request state
125      * @param man   Request state manager
126      * @throws COPSPepException
127      * @throws COPSException
128      */
129     public void deleteRequestState(final COPSPepReqStateMan man) throws COPSException {
130         if (_conn != null)
131             _conn.deleteRequestState(man);
132     }
133
134     /**
135      * Establish connection to PDP's IP address
136      * @throws   COPSException
137      * @throws   COPSPepException
138      */
139     private COPSPepConnection processConnection() throws IOException, COPSException {
140         // Create Socket and send OPN
141         final InetAddress addr = InetAddress.getLocalHost();
142         return processConnection(new Socket(addr, _psPort));
143     }
144
145     /**
146      * Establish connection to PDP's IP address
147      * @throws   COPSException
148      * @throws   COPSPepException
149      */
150     private COPSPepConnection processConnection(final Socket socket) throws IOException, COPSException {
151         // Create Socket and send OPN
152         final COPSClientOpenMsg msg = new COPSClientOpenMsg(_clientType, _pepID, null, null, null);
153         msg.writeData(socket);
154
155         // Receive the response
156         final COPSMsg recvmsg = COPSTransceiver.receiveMsg(socket);
157
158         if (recvmsg.getHeader().getOpCode().equals(OPCode.CAT)) {
159             final COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvmsg;
160
161             // Support
162             if (cMsg.getIntegrity() != null) {
163                 throw new COPSPepException("Unsupported object (Integrity)");
164             }
165
166             // Mandatory KATimer
167             final COPSKATimer kt = cMsg.getKATimer();
168             if (kt == null)
169                 throw new COPSPepException ("Mandatory COPS object missing (KA Timer)");
170             short _kaTimeVal = kt.getTimerVal();
171
172             // ACTimer
173             final COPSAcctTimer at = cMsg.getAcctTimer();
174             short _acctTimer = 0;
175             if (at != null)
176                 _acctTimer = at.getTimerVal();
177
178             // Create the connection manager
179             final COPSPepConnection conn = createPepConnection(socket);
180             conn.setKaTimer(_kaTimeVal);
181             conn.setAcctTimer(_acctTimer);
182             thread = new Thread(conn);
183             thread.start();
184
185             return conn;
186         } else if (recvmsg.getHeader().getOpCode().equals(OPCode.CC)) {
187             final COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvmsg;
188             logger.error("Received client-close message with error description [" + cMsg.getError().getDescription()
189                     + "]. Closing socket.");
190             socket.close();
191             return null;
192         } else { // messages of other types are not expected
193             throw new COPSPepException("Message not expected. Closing connection for " + socket.toString());
194         }
195     }
196
197     /**
198      * Creates a COPSPepConnection object
199      * @param socket - the socket on which to create the connection
200      * @return - the connection object
201      */
202     protected COPSPepConnection createPepConnection(final Socket socket) {
203         return new COPSPepConnection(_clientType, socket);
204     }
205
206 }
207
208
209