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;
10 import org.umu.cops.stack.COPSObjHeader.CType;
12 import java.io.IOException;
13 import java.io.OutputStream;
14 import java.net.Socket;
15 import java.util.ArrayList;
16 import java.util.List;
19 * COPS Handle Object (RFC 2748 pag. 9)
21 * The Handle Object encapsulates a unique value that identifies an
22 * installed state. This identification is used by most COPS operations.
26 * C-Type = 1, Client Handle.
28 * Variable-length field, no implied format other than it is unique from
29 * other client handles from the same PEP (a.k.a. COPS TCP connection)
30 * for a particular client-type. It is always initially chosen by the
31 * PEP and then deleted by the PEP when no longer applicable. The client
32 * handle is used to refer to a request state initiated by a particular
33 * PEP and installed at the PDP for a client-type. A PEP will specify a
34 * client handle in its Request messages, Report messages and Delete
35 * messages sent to the PDP. In all cases, <b>the client handle is used to
36 * uniquely identify a particular PEP's request for a client-type</b>.
38 * The client handle value is set by the PEP and is opaque to the PDP.
39 * The PDP simply performs a byte-wise comparison on the value in this
40 * object with respect to the handle object values of other currently
44 public class COPSHandle extends COPSObjBase {
49 private final COPSData _data;
52 * Bytes to add to outbound payload to ensure the length is divisible by 4 bytes
54 private final COPSData _padding;
57 * Constructor generally used for sending messages
58 * @param id - the identifier (must not be null)
59 * @throws java.lang.IllegalArgumentException when the id parameter is null
61 public COPSHandle(final COPSData id) {
62 this(new COPSObjHeader(CNum.HANDLE, CType.DEF), id);
66 * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
67 * COPSObjHeader information is known
68 * @param objHdr - the object header
69 * @param data - the ID
70 * @throws java.lang.IllegalArgumentException
72 protected COPSHandle(final COPSObjHeader objHdr, final COPSData data) {
74 if (!objHdr.getCNum().equals(CNum.HANDLE))
75 throw new IllegalArgumentException("CNum on header must be of type HANDLE");
76 if (!objHdr.getCType().equals(CType.DEF))
77 throw new IllegalArgumentException("Invalid CType value. Must be " + CType.DEF);
78 if (data == null) throw new IllegalArgumentException("COPSData must not be null");
82 if ((_data.length() % 4) != 0) {
83 final int padLen = 4 - (_data.length() % 4);
84 _padding = COPSObjectParser.getPadding(padLen);
86 _padding = new COPSData();
91 public int getDataLength() {
92 return _data.length() + _padding.length();
99 public COPSData getId() {
104 protected void writeBody(final Socket socket) throws IOException {
105 COPSUtil.writeData(socket, _data.getData(), _data.length());
106 if (_padding.length() != 0) COPSUtil.writeData(socket, _padding.getData(), _padding.length());
110 public void dumpBody(final OutputStream os) throws IOException {
111 os.write(("client-handle: " + _data.str() + "\n").getBytes());
115 public boolean equals(final Object o) {
119 if (!(o instanceof COPSHandle)) {
122 if (!super.equals(o)) {
126 final COPSHandle that = (COPSHandle) o;
128 return _data.equals(that._data) && _padding.equals(that._padding) ||
129 COPSUtil.copsDataPaddingEquals(this._data, this._padding, that._data, that._padding);
133 public int hashCode() {
134 int result = super.hashCode();
135 List<Byte> allBytes = new ArrayList<>();
136 for (final byte val : _data.getData()) {
139 for (final byte val : _padding.getData()) {
142 result = 31 * allBytes.hashCode();
147 * Parses bytes to return a COPSHandle object
148 * @param objHdrData - the associated header
149 * @param dataPtr - the data to parse
150 * @return - the object
151 * @throws java.lang.IllegalArgumentException
153 public static COPSHandle parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
154 if (dataPtr == null || dataPtr.length < 5)
155 throw new IllegalArgumentException("Data cannot be null or fewer than 5 bytes");
157 //Get the length of data following the obj header
158 final COPSData id = new COPSData(dataPtr, 4, objHdrData.msgByteCount - objHdrData.header.getHdrLength());
159 return new COPSHandle(objHdrData.header, id);