Added new constructor. May need to tighten down interfaces in the future.
[packetcable.git] / packetcable-driver / src / main / java / org / umu / cops / stack / COPSClientAcceptMsg.java
1 /*
2  * Copyright (c) 2003 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.stack;
8
9 import org.umu.cops.stack.COPSHeader.Flag;
10 import org.umu.cops.stack.COPSHeader.OPCode;
11
12 import java.io.IOException;
13 import java.io.OutputStream;
14 import java.net.Socket;
15
16 /**
17  * Client-Accept (CAT)  PDP -> PEP (RFC 2748 pag. 26)
18  *
19  * The Client-Accept message is used to positively respond to the
20  * Client-Open message. This message will return to the PEP a timer
21  * object indicating the maximum time interval between keep-alive
22  * messages. Optionally, a timer specifying the minimum allowed interval
23  * between accounting report messages may be included when applicable.
24  *
25  * <Client-Accept>  ::= <Common Header>
26  * <KA Timer>
27  * [<ACCT Timer>]
28  * [<Integrity>]
29  *
30  * If the PDP refuses the client, it will instead issue a Client-Close
31  * message.
32  *
33  * The KA Timer corresponds to maximum acceptable intermediate time
34  * between the generation of messages by the PDP and PEP. The timer
35  * value is determined by the PDP and is specified in seconds. A timer
36  * value of 0 implies no secondary connection verification is necessary.
37  *
38  * The optional ACCT Timer allows the PDP to indicate to the PEP that
39  * periodic accounting reports SHOULD NOT exceed the specified timer
40  * interval per client handle. This allows the PDP to control the rate
41  * at which accounting reports are sent by the PEP (when applicable).
42  *
43  * In general, accounting type Report messages are sent to the PDP when
44  * determined appropriate by the PEP. The accounting timer merely is
45  * used by the PDP to keep the rate of such updates in check (i.e.
46  * Preventing the PEP from blasting the PDP with accounting reports).
47  * Not including this object implies there are no PDP restrictions on
48  * the rate at which accounting updates are generated.
49  *
50  * If the PEP receives a malformed Client-Accept message it MUST
51  * generate a Client-Close message specifying the appropriate error
52  * code.
53  */
54 public class COPSClientAcceptMsg extends COPSMsg {
55
56     // Required
57     private final COPSKATimer _kaTimer;
58
59     // Optional
60     private final COPSAcctTimer _acctTimer;
61     private final COPSIntegrity _integrity;
62
63     /**
64      * Constructor (generally used for sending messages) which probably should not be used as the PCMM version and
65      * Flag values on the header are being hardcoded to 1 and UNSOLICITED respectively. Use the next one below instead
66      * @param clientType - the type of client that created the message (required)
67      * @param kaTimer - the Keep alive timer (required)
68      * @param acctTimer - the account timer (optional)
69      * @param integrity - the integrity (optional)
70      * @throws java.lang.IllegalArgumentException
71      */
72     @Deprecated
73     public COPSClientAcceptMsg(final short clientType, final COPSKATimer kaTimer, final COPSAcctTimer acctTimer,
74                                final COPSIntegrity integrity) {
75         this(new COPSHeader(OPCode.CAT, clientType), kaTimer, acctTimer, integrity);
76     }
77
78     /**
79      * Constructor (generally used for sending messages).
80      * @param version - the supported PCMM Version
81      * @param flag - the flag...
82      * @param clientType - the type of client that created the message (required)
83      * @param kaTimer - the Keep alive timer (required)
84      * @param acctTimer - the account timer (optional)
85      * @param integrity - the integrity (optional)
86      * @throws java.lang.IllegalArgumentException
87      */
88     public COPSClientAcceptMsg(final int version, final Flag flag, final short clientType,
89                                final COPSKATimer kaTimer, final COPSAcctTimer acctTimer, final COPSIntegrity integrity) {
90         this(new COPSHeader(version, flag, OPCode.CAT, clientType), kaTimer, acctTimer, integrity);
91     }
92
93     /**
94      * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
95      * COPSHeader information is known.
96      * @param hdr - COPS Header
97      * @param kaTimer - the Keep alive timer (required)
98      * @param acctTimer - the account timer (optional)
99      * @param integrity - the integrity (optional)
100      * @throws java.lang.IllegalArgumentException
101      */
102     protected COPSClientAcceptMsg(final COPSHeader hdr, final COPSKATimer kaTimer, final COPSAcctTimer acctTimer,
103                                final COPSIntegrity integrity) {
104         super(hdr);
105         if (!hdr.getOpCode().equals(OPCode.CAT))
106             throw new IllegalArgumentException("OPCode must be of type - " + OPCode.CAT);
107         if (kaTimer == null) throw new IllegalArgumentException("Keep alive timer must not be null");
108         _kaTimer = kaTimer;
109         _acctTimer = acctTimer;
110         _integrity = integrity;
111     }
112
113     // Getters
114     public COPSKATimer getKATimer() {
115         return _kaTimer;
116     }
117     public COPSAcctTimer getAcctTimer() {
118         return (_acctTimer);
119     }
120     public COPSIntegrity getIntegrity() {
121         return (_integrity);
122     }
123
124     @Override
125     protected void writeBody(final Socket socket) throws IOException {
126         _kaTimer.writeData(socket);
127         if (_acctTimer != null) _acctTimer.writeData(socket);
128         if (_integrity != null) _integrity.writeData(socket);
129     }
130
131     @Override
132     protected int getDataLength() {
133         int out = _kaTimer.getDataLength() + _kaTimer.getHeader().getHdrLength();
134         if (_acctTimer != null) out += _acctTimer.getDataLength() + _acctTimer.getHeader().getHdrLength();
135         if (_integrity != null) out += _integrity.getDataLength() + _integrity.getHeader().getHdrLength();
136         return out;
137     }
138     @Override
139     protected void dumpBody(final OutputStream os) throws IOException {
140         _kaTimer.dump(os);
141         if (_acctTimer != null) _acctTimer.dump(os);
142         if (_integrity != null)  _integrity.dump(os);
143     }
144
145     @Override
146     public boolean equals(final Object o) {
147         if (this == o) {
148             return true;
149         }
150         if (!(o instanceof COPSClientAcceptMsg)) {
151             return false;
152         }
153         if (!super.equals(o)) {
154             return false;
155         }
156
157         final COPSClientAcceptMsg acceptMsg = (COPSClientAcceptMsg) o;
158
159         return !(_acctTimer != null ? !_acctTimer.equals(acceptMsg._acctTimer) : acceptMsg._acctTimer != null) &&
160                 !(_integrity != null ? !_integrity.equals(acceptMsg._integrity) : acceptMsg._integrity != null) &&
161                 _kaTimer.equals(acceptMsg._kaTimer);
162
163     }
164
165     @Override
166     public int hashCode() {
167         int result = super.hashCode();
168         result = 31 * result + _kaTimer.hashCode();
169         result = 31 * result + (_acctTimer != null ? _acctTimer.hashCode() : 0);
170         result = 31 * result + (_integrity != null ? _integrity.hashCode() : 0);
171         return result;
172     }
173
174     /**
175      * Responsible for parsing a byte array to create a COPSDecisionMsg object
176      * @param hdrData - the object's header data
177      * @param data - the byte array to parse
178      * @return - the message object
179      * @throws COPSException
180      */
181     public static COPSClientAcceptMsg parse(final COPSHeaderData hdrData, final byte[] data) throws COPSException {
182         // Variables for constructor
183         COPSKATimer kaTimer = null;
184         COPSAcctTimer acctTimer = null;
185         COPSIntegrity integrity = null;
186
187         int dataStart = 0;
188         while (dataStart < data.length) {
189             final byte[] buf = new byte[data.length - dataStart];
190             System.arraycopy(data, dataStart, buf, 0, data.length - dataStart);
191
192             final COPSObjHeaderData objHdrData = COPSObjectParser.parseObjHeader(buf);
193             switch (objHdrData.header.getCNum()) {
194                 case KA:
195                     kaTimer = COPSKATimer.parse(objHdrData, buf);
196                     break;
197                 case ACCT_TIMER:
198                     acctTimer = COPSAcctTimer.parse(objHdrData, buf);
199                     break;
200                 case MSG_INTEGRITY:
201                     integrity = COPSIntegrity.parse(objHdrData, buf);
202                     break;
203                 default:
204                     throw new COPSException("Bad Message format, unknown object type");
205             }
206             dataStart += objHdrData.msgByteCount;
207         }
208
209         return new COPSClientAcceptMsg(hdrData.header, kaTimer, acctTimer, integrity);
210     }
211
212 }
213