Solved Bug 6302-
[packetcable.git] / packetcable-driver / src / main / java / org / pcmm / gates / impl / Classifier.java
1 /*
2  * Copyright (c) 2015 Cable Television Laboratories, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.pcmm.gates.impl;
10
11 import com.google.common.primitives.Bytes;
12 import org.pcmm.base.impl.PCMMBaseObject;
13 import org.pcmm.gates.IClassifier;
14 import org.umu.cops.stack.COPSMsgParser;
15
16 import java.net.Inet4Address;
17 import java.net.InetAddress;
18 import java.net.UnknownHostException;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 /**
23  * Implementation of the IClassifier interface
24  */
25 public class Classifier extends PCMMBaseObject implements IClassifier {
26
27     /**
28      * The classifier's protocol
29      */
30     protected final Protocol protocol;
31
32     /**
33      * When enabled, the CMTS must mark the packets traversing the CMTS DSCP/TOS value
34      */
35     protected final byte tosOverwrite;
36
37     /**
38      * The TOS mask value
39      */
40     protected final byte tosMask;
41
42     // Instances of this and ExtendedClassifier require Inet4Address objects
43
44     /**
45      * The source address
46      */
47     protected final InetAddress srcAddress;
48
49     /**
50      * The destination address
51      */
52     protected final InetAddress dstAddress;
53
54     /**
55      * The source port number
56      */
57     protected final short srcPort;
58
59     /**
60      * The destination port number
61      */
62     protected final short dstPort;
63
64     /**
65      * The priority value
66      */
67     protected final byte priority;
68
69     /**
70      * Constructor for sub-classes
71      * @param protocol - the protocol being sent through the gate (can be null for IPv6Classifier instances)
72      * @param tosOverwrite - ENABLE/DISABLE
73      * @param tosMask - the mask
74      * @param srcAddress - the source IP
75      * @param dstAddress - the destination IP
76      * @param srcPort - the source port
77      * @param dstPort - the destination port
78      * @param priority - the priority value
79      */
80     public Classifier(final Protocol protocol, final byte tosOverwrite, final byte tosMask,
81                          final Inet4Address srcAddress, final Inet4Address dstAddress, final short srcPort,
82                          final short dstPort, final byte priority) {
83         this(STYPE, protocol, tosOverwrite, tosMask, srcAddress, dstAddress, srcPort, dstPort, priority);
84     }
85
86     /**
87      * Constructor for sub-classes
88      * @param sType - the type of classifier
89      * @param protocol - the protocol being sent through the gate
90      * @param tosOverwrite - ENABLE/DISABLE
91      * @param tosMask - the mask
92      * @param srcAddress - the source IP
93      * @param dstAddress - the destination IP
94      * @param srcPort - the source port
95      * @param dstPort - the destination port
96      * @param priority - the priority value
97      */
98     protected Classifier(final byte sType, final Protocol protocol, final byte tosOverwrite, final byte tosMask,
99                       final InetAddress srcAddress, final InetAddress dstAddress, final short srcPort,
100                       final short dstPort, final byte priority) {
101         super(SNum.CLASSIFIERS, sType);
102
103         if (protocol == null && !(this instanceof IPv6Classifier))
104             throw new IllegalArgumentException("Protocol value must not be null");
105         if (srcAddress == null) throw new IllegalArgumentException("Source address value must not be null");
106         if (dstAddress == null) throw new IllegalArgumentException("Destination address value must not be null");
107
108         this.protocol = protocol;
109         this.tosOverwrite = tosOverwrite;
110         this.tosMask = tosMask;
111         this.srcAddress = srcAddress;
112         this.dstAddress = dstAddress;
113         this.srcPort = srcPort;
114         this.dstPort = dstPort;
115         this.priority = priority;
116     }
117
118     @Override
119     public InetAddress getDestinationIPAddress() {
120         return dstAddress;
121     }
122
123     @Override
124     public short getDestinationPort() {
125         return dstPort;
126     }
127
128     @Override
129     public InetAddress getSourceIPAddress() {
130         return srcAddress;
131     }
132
133     @Override
134     public short getSourcePort() {
135         return srcPort;
136     }
137
138     @Override
139     public Protocol getProtocol() {
140         return protocol;
141     }
142
143     @Override
144     public byte getPriority() {
145         return priority;
146     }
147
148     @Override
149     public byte getDSCPTOS() {
150         return tosOverwrite;
151     }
152
153     @Override
154     public byte getDSCPTOSMask() {
155         return tosMask;
156     }
157
158     @Override
159     protected byte[] getBytes() {
160         final List<Byte> byteList = new ArrayList<>(Bytes.asList(COPSMsgParser.shortToBytes(protocol.getValue())));
161         byteList.add(tosOverwrite);
162         byteList.add(tosMask);
163         byteList.addAll(Bytes.asList(srcAddress.getAddress()));
164         byteList.addAll(Bytes.asList(dstAddress.getAddress()));
165         byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(srcPort)));
166         byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(dstPort)));
167         byteList.add(priority);
168
169         // reserved padding
170         byteList.addAll(Bytes.asList((byte) 0, (byte) 0, (byte) 0));
171
172         return Bytes.toArray(byteList);
173     }
174
175     @Override
176     public boolean equals(final Object o) {
177         if (this == o) {
178             return true;
179         }
180         if (!(o instanceof Classifier)) {
181             return false;
182         }
183         if (!super.equals(o)) {
184             return false;
185         }
186         final Classifier that = (Classifier) o;
187         return tosMask == that.tosMask && srcPort == that.srcPort && dstPort == that.dstPort &&
188                 priority == that.priority && protocol == that.protocol && tosOverwrite == that.tosOverwrite &&
189                 srcAddress.equals(that.srcAddress) && dstAddress.equals(that.dstAddress);
190     }
191
192     @Override
193     public int hashCode() {
194         int result = super.hashCode();
195         result = 31 * result + (protocol != null ? protocol.hashCode() : 0);
196         result = 31 * result + (int) tosOverwrite;
197         result = 31 * result + (int) tosMask;
198         result = 31 * result + srcAddress.hashCode();
199         result = 31 * result + dstAddress.hashCode();
200         result = 31 * result + (int) srcPort;
201         result = 31 * result + (int) dstPort;
202         result = 31 * result + (int) priority;
203         return result;
204     }
205
206     /**
207      * Returns a Classifier object from a byte array
208      * @param data - the data to parse
209      * @return - the object or null if cannot be parsed
210      * TODO - make me more robust as exceptions can be swallowed here.
211      */
212     public static Classifier parse(final byte[] data) {
213         final List<Byte> bytes = Bytes.asList(data);
214
215         try {
216             final byte[] srcAddrBytes = Bytes.toArray(bytes.subList(4, 8));
217             final byte[] dstAddrBytes = Bytes.toArray(bytes.subList(8, 12));
218             return new Classifier(Protocol.valueOf(COPSMsgParser.bytesToShort(data[0], data[1])), data[2], data[3],
219                     (Inet4Address)InetAddress.getByAddress(srcAddrBytes),
220                     (Inet4Address)InetAddress.getByAddress(dstAddrBytes),
221                     COPSMsgParser.bytesToShort(data[12], data[13]), COPSMsgParser.bytesToShort(data[14], data[15]),
222                     data[16]);
223         } catch (UnknownHostException e) {
224             return null;
225         }
226     }
227 }