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;
17 * COPS Handle Object (RFC 2748 pag. 9)
19 * The Handle Object encapsulates a unique value that identifies an
20 * installed state. This identification is used by most COPS operations.
24 * C-Type = 1, Client Handle.
26 * Variable-length field, no implied format other than it is unique from
27 * other client handles from the same PEP (a.k.a. COPS TCP connection)
28 * for a particular client-type. It is always initially chosen by the
29 * PEP and then deleted by the PEP when no longer applicable. The client
30 * handle is used to refer to a request state initiated by a particular
31 * PEP and installed at the PDP for a client-type. A PEP will specify a
32 * client handle in its Request messages, Report messages and Delete
33 * messages sent to the PDP. In all cases, <b>the client handle is used to
34 * uniquely identify a particular PEP's request for a client-type</b>.
36 * The client handle value is set by the PEP and is opaque to the PDP.
37 * The PDP simply performs a byte-wise comparison on the value in this
38 * object with respect to the handle object values of other currently
42 public class COPSHandle extends COPSObjBase {
47 private final COPSData _data;
50 * Bytes to add to outbound payload to ensure the length is divisible by 4 bytes
52 private final COPSData _padding;
55 * Constructor generally used for sending messages
56 * @param id - the identifier (must not be null)
57 * @throws java.lang.IllegalArgumentException when the id parameter is null
59 public COPSHandle(final COPSData id) {
60 this(new COPSObjHeader(CNum.HANDLE, CType.DEF), id);
64 * Constructor generally used when parsing the bytes of an inbound COPS message but can also be used when the
65 * COPSObjHeader information is known
66 * @param objHdr - the object header
67 * @param data - the ID
68 * @throws java.lang.IllegalArgumentException
70 protected COPSHandle(final COPSObjHeader objHdr, final COPSData data) {
72 if (!objHdr.getCNum().equals(CNum.HANDLE))
73 throw new IllegalArgumentException("CNum on header must be of type HANDLE");
74 if (!objHdr.getCType().equals(CType.DEF))
75 throw new IllegalArgumentException("Invalid CType value. Must be " + CType.DEF);
76 if (data == null) throw new IllegalArgumentException("COPSData must not be null");
80 if ((_data.length() % 4) != 0) {
81 final int padLen = 4 - (_data.length() % 4);
82 _padding = COPSObjectParser.getPadding(padLen);
84 _padding = new COPSData();
89 public int getDataLength() {
90 return _data.length() + _padding.length();
97 public COPSData getId() {
102 protected void writeBody(final Socket socket) throws IOException {
103 COPSUtil.writeData(socket, _data.getData(), _data.length());
104 if (_padding.length() != 0) COPSUtil.writeData(socket, _padding.getData(), _padding.length());
108 public void dumpBody(final OutputStream os) throws IOException {
109 os.write(("client-handle: " + _data.str() + "\n").getBytes());
113 public boolean equals(final Object o) {
117 if (!(o instanceof COPSHandle)) {
120 if (!super.equals(o)) {
124 final COPSHandle that = (COPSHandle) o;
126 return _data.equals(that._data) && _padding.equals(that._padding) ||
127 COPSUtil.copsDataPaddingEquals(this._data, this._padding, that._data, that._padding);
131 public int hashCode() {
132 int result = super.hashCode();
133 result = 31 * result + _data.hashCode();
134 result = 31 * result + _padding.hashCode();
139 * Parses bytes to return a COPSHandle object
140 * @param objHdrData - the associated header
141 * @param dataPtr - the data to parse
142 * @return - the object
143 * @throws java.lang.IllegalArgumentException
145 public static COPSHandle parse(final COPSObjHeaderData objHdrData, final byte[] dataPtr) {
146 if (dataPtr == null || dataPtr.length < 5)
147 throw new IllegalArgumentException("Data cannot be null or fewer than 5 bytes");
149 //Get the length of data following the obj header
150 final COPSData id = new COPSData(dataPtr, 4, objHdrData.msgByteCount - objHdrData.header.getHdrLength());
151 return new COPSHandle(objHdrData.header, id);