2 * Copyright (c) 2003 University of Murcia. All rights reserved.
3 * --------------------------------------------------------------
4 * For more information, please see <http://www.umu.euro6ix.org/>.
7 package org.umu.cops.stack;
9 import org.umu.cops.stack.COPSObjHeader.CNum;
11 import java.io.IOException;
12 import java.io.OutputStream;
13 import java.net.Socket;
15 import java.util.concurrent.ConcurrentHashMap;
18 * COPS Client Specific Information Object (RFC 2748)
20 * The various types of this object are required for requests, and used
21 * in reports and opens when required. It contains client-type specific
26 * C-Type = 1, Signaled ClientSI.
28 * Variable-length field. All objects/attributes specific to a client's
29 * signaling protocol or internal state are encapsulated within one or
30 * more signaled Client Specific Information Objects. The format of the
31 * data encapsulated in the ClientSI object is determined by the
34 * C-Type = 2, Named ClientSI.
36 * Variable-length field. Contains named configuration information
37 * useful for relaying specific information about the PEP, a request, or
38 * configured state to the PDP server.
40 public class COPSClientSI extends COPSObjBase {
42 private final static Map<Integer, CSIType> VAL_TO_CSI = new ConcurrentHashMap<>();
44 VAL_TO_CSI.put(CSIType.NA.ordinal(), CSIType.NA);
45 VAL_TO_CSI.put(CSIType.SIGNALED.ordinal(), CSIType.SIGNALED);
46 VAL_TO_CSI.put(CSIType.NAMED.ordinal(), CSIType.NAMED);
50 * This value is not being used here but stored only for clarity as it is being mapped directly to the
51 * ordinal value of the CType
53 private final CSIType _csiType;
58 private final COPSData _data;
61 * Bytes to add to outbound payload to ensure the length is divisible by 4 bytes
63 private final COPSData _padding;
66 * Constructor generally used for sending messages
67 * @param csitype - the CSIType
68 * @param data - the data
69 * @throws java.lang.IllegalArgumentException
71 public COPSClientSI(final CSIType csitype, final COPSData data) {
72 /* The CSIType does not map directly to the CType, therefore the hook to map to a CType below is
73 required to ensure the header value outputs the correct value when streamed
75 this(new COPSObjHeader(CNum.CSI, COPSObjHeader.VAL_TO_CTYPE.get(csitype.ordinal())), data);
79 * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
80 * COPSObjHeader information is known
81 * @param hdr - the object header
82 * @param data - the data
83 * @throws java.lang.IllegalArgumentException
85 protected COPSClientSI(final COPSObjHeader hdr, final COPSData data) {
87 _csiType = VAL_TO_CSI.get(hdr.getCType().ordinal());
89 if (!hdr.getCNum().equals(CNum.CSI))
90 throw new IllegalArgumentException("CNum must be equal to " + CNum.CSI);
91 if (_csiType == null || _csiType.equals(CSIType.NA))
92 throw new IllegalArgumentException("Invalid CSIType");
93 if (_csiType.ordinal() != hdr.getCType().ordinal())
94 throw new IllegalArgumentException("Error mapping CSIType " + _csiType + " to CType" + hdr.getCType());
95 if (data == null) throw new IllegalArgumentException("Data must not be null");
98 if ((_data.length() % 4) != 0) {
99 final int padLen = 4 - (_data.length() % 4);
100 _padding = COPSObjectParser.getPadding(padLen);
102 _padding = new COPSData();
107 * Returns the CSIType
110 public CSIType getCsiType() { return _csiType; }
116 public COPSData getData() { return _data; }
119 /* The super says protected but this needs to be public due to usage in COPSDecisionMsgEX.java which is currently
120 calling this method. */
121 public int getDataLength() {
122 return _data.length() + _padding.length();
126 public void writeBody(final Socket socket) throws IOException {
127 COPSUtil.writeData(socket, _data.getData(), _data.length());
128 COPSUtil.writeData(socket, _padding.getData(), _padding.length());
132 public void dumpBody(final OutputStream os) throws IOException {
133 os.write(("CSI-type: " + _csiType + "\n").getBytes());
134 os.write(("client-SI: " + _data.str() + "\n").getBytes());
138 public boolean equals(Object o) {
142 if (!(o instanceof COPSClientSI)) {
145 if (!super.equals(o)) {
149 final COPSClientSI that = (COPSClientSI) o;
150 return _data.equals(that._data) && _padding.equals(that._padding) ||
151 COPSUtil.copsDataPaddingEquals(this._data, this._padding, that._data, that._padding);
155 public int hashCode() {
156 int result = super.hashCode();
157 result = 31 * result + (_data != null ? _data.hashCode() : 0);
158 result = 31 * result + (_padding != null ? _padding.hashCode() : 0);
163 * Parses bytes to return a COPSClientSI object
164 * @param objHdrData - the associated header
165 * @param dataPtr - the data to parse
166 * @return - the object
167 * @throws java.lang.IllegalArgumentException
169 public static COPSClientSI parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
170 short dLen = (short) (objHdrData.msgByteCount - 4);
171 return new COPSClientSI(objHdrData.header, new COPSData(dataPtr, 4, dLen));
175 * The different CSI types. NA does not exist but is a placeholder for 0 as the ordinal values will be used
176 * to determine which type for marshalling
178 public enum CSIType {