3ef912b51df8aba6e156259eb198e43837c15197
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / message / PCEPReplyMessageParser.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, 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 package org.opendaylight.protocol.pcep.impl.message;
9
10 import io.netty.buffer.ByteBuf;
11
12 import java.util.Arrays;
13 import java.util.List;
14
15 import org.opendaylight.protocol.pcep.PCEPDeserializerException;
16 import org.opendaylight.protocol.pcep.PCEPDocumentedException;
17 import org.opendaylight.protocol.pcep.PCEPErrorMapping;
18 import org.opendaylight.protocol.pcep.PCEPErrors;
19 import org.opendaylight.protocol.pcep.UnknownObject;
20 import org.opendaylight.protocol.pcep.spi.ObjectHandlerRegistry;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcerrBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcrep;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcrepBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Object;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.PcrepMessage;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.bandwidth.object.Bandwidth;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.Ero;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.include.route.object.Iro;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.Metrics;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.MetricsBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lspa.object.Lspa;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.metric.object.Metric;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.of.object.Of;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcep.error.object.ErrorObjectBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.PcerrMessageBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.ErrorsBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.PcrepMessageBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.Replies;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.RepliesBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.Result;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.Failure;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.FailureBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.Success;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.SuccessBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.failure.NoPath;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success.Paths;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success.PathsBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rp.object.Rp;
50
51 import com.google.common.collect.Lists;
52
53 /**
54  * Parser for {@link PcrepMessage}
55  */
56 public class PCEPReplyMessageParser extends AbstractMessageParser {
57
58         public static final int TYPE = 4;
59
60         public PCEPReplyMessageParser(final ObjectHandlerRegistry registry) {
61                 super(registry);
62         }
63
64         @Override
65         public void serializeMessage(final Message message, final ByteBuf buffer) {
66                 if (!(message instanceof Pcrep)) {
67                         throw new IllegalArgumentException("Wrong instance of Message. Passed instance of " + message.getClass()
68                                         + ". Nedded PcrepMessage.");
69                 }
70                 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.PcrepMessage repMsg = ((Pcrep) message).getPcrepMessage();
71                 if (repMsg.getReplies() == null || repMsg.getReplies().isEmpty()) {
72                         throw new IllegalArgumentException("Replies cannot be null or empty.");
73                 }
74                 for (final Replies reply : repMsg.getReplies()) {
75                         if (reply.getRp() == null) {
76                                 throw new IllegalArgumentException("Reply must contain RP object.");
77                         }
78                         buffer.writeBytes(serializeObject(reply.getRp()));
79                         if (reply.getResult() != null) {
80                                 if (reply.getResult() instanceof Failure) {
81                                         final Failure f = (Failure) reply.getResult();
82                                         buffer.writeBytes(serializeObject(f.getNoPath()));
83                                         if (f.getLspa() != null) {
84                                                 buffer.writeBytes(serializeObject(f.getLspa()));
85                                         }
86                                         if (f.getBandwidth() != null) {
87                                                 buffer.writeBytes(serializeObject(f.getBandwidth()));
88                                         }
89                                         if (f.getMetrics() != null && !f.getMetrics().isEmpty()) {
90                                                 for (final Metrics m : f.getMetrics()) {
91                                                         buffer.writeBytes(serializeObject(m.getMetric()));
92                                                 }
93                                         }
94                                         if (f.getIro() != null) {
95                                                 buffer.writeBytes(serializeObject(f.getIro()));
96                                         }
97                                 } else {
98                                         final Success s = (Success) reply.getResult();
99                                         for (final Paths p : s.getPaths()) {
100                                                 buffer.writeBytes(serializeObject(p.getEro()));
101                                                 if (p.getLspa() != null) {
102                                                         buffer.writeBytes(serializeObject(p.getLspa()));
103                                                 }
104                                                 if (p.getOf() != null) {
105                                                         buffer.writeBytes(serializeObject(p.getOf()));
106                                                 }
107                                                 if (p.getBandwidth() != null) {
108                                                         buffer.writeBytes(serializeObject(p.getBandwidth()));
109                                                 }
110                                                 if (p.getMetrics() != null && !p.getMetrics().isEmpty()) {
111                                                         for (final Metrics m : p.getMetrics()) {
112                                                                 buffer.writeBytes(serializeObject(m.getMetric()));
113                                                         }
114                                                 }
115                                                 if (p.getIro() != null) {
116                                                         buffer.writeBytes(serializeObject(p.getIro()));
117                                                 }
118                                         }
119                                 }
120                         }
121                 }
122         }
123
124         @Override
125         public Message parseMessage(final byte[] buffer) throws PCEPDeserializerException, PCEPDocumentedException {
126                 if (buffer == null || buffer.length == 0) {
127                         throw new PCEPDeserializerException("Error message is empty.");
128                 }
129                 final List<Object> objs = parseObjects(buffer);
130                 PcrepMessage m = null;
131                 try {
132                         m = validate(objs);
133                 } catch (final PCEPDocumentedException e) {
134                         final PCEPErrorMapping maping = PCEPErrorMapping.getInstance();
135                         return new PcerrBuilder().setPcerrMessage(
136                                         new PcerrMessageBuilder().setErrors(
137                                                         Arrays.asList(new ErrorsBuilder().setErrorObject(
138                                                                         new ErrorObjectBuilder().setType(maping.getFromErrorsEnum(e.getError()).type).setValue(
139                                                                                         maping.getFromErrorsEnum(e.getError()).value).build()).build())).build()).build();
140                 }
141                 return m;
142         }
143
144         private Pcrep validate(final List<Object> objects) throws PCEPDocumentedException {
145                 final List<Replies> replies = Lists.newArrayList();
146                 while (!objects.isEmpty()) {
147                         replies.add(this.getValidReply(objects));
148                 }
149                 return new PcrepBuilder().setPcrepMessage(new PcrepMessageBuilder().setReplies(replies).build()).build();
150         }
151
152         private Replies getValidReply(final List<Object> objects) throws PCEPDocumentedException {
153                 if (!(objects.get(0) instanceof Rp)) {
154                         throw new PCEPDocumentedException("Pcrep message must contain at least one RP object.", PCEPErrors.RP_MISSING);
155                 }
156                 final Rp rp = (Rp) objects.get(0);
157                 objects.remove(0);
158                 Result res = null;
159                 if (!objects.isEmpty()) {
160                         if (objects.get(0) instanceof NoPath) {
161                                 final NoPath noPath = (NoPath) objects.get(0);
162                                 objects.remove(0);
163                                 final FailureBuilder builder = new FailureBuilder();
164                                 builder.setNoPath(noPath);
165                                 while (!objects.isEmpty()) {
166                                         this.parseAttributes(builder, objects);
167                                 }
168                                 res = builder.build();
169                         } else if (objects.get(0) instanceof Ero) {
170                                 final Ero ero = (Ero) objects.get(0);
171                                 objects.remove(0);
172                                 final SuccessBuilder builder = new SuccessBuilder();
173                                 final List<Paths> paths = Lists.newArrayList();
174                                 final PathsBuilder pBuilder = new PathsBuilder();
175                                 pBuilder.setEro(ero);
176                                 while (!objects.isEmpty()) {
177                                         this.parsePath(pBuilder, objects);
178                                         paths.add(pBuilder.build());
179                                 }
180                                 builder.setPaths(paths);
181                                 res = builder.build();
182                         }
183                 }
184                 return new RepliesBuilder().setRp(rp).setResult(res).build();
185         }
186
187         private void parseAttributes(final FailureBuilder builder, final List<Object> objects) throws PCEPDocumentedException {
188                 final List<Metrics> pathMetrics = Lists.newArrayList();
189
190                 Object obj;
191                 State state = State.Init;
192                 while (!objects.isEmpty() && !state.equals(State.End)) {
193                         obj = objects.get(0);
194
195                         switch (state) {
196                         case Init:
197                                 state = State.LspaIn;
198                                 if (obj instanceof Lspa) {
199                                         builder.setLspa((Lspa) obj);
200                                         break;
201                                 }
202                         case LspaIn:
203                                 state = State.BandwidthIn;
204                                 if (obj instanceof Bandwidth) {
205                                         builder.setBandwidth((Bandwidth) obj);
206                                         break;
207                                 }
208                         case BandwidthIn:
209                                 state = State.MetricIn;
210                                 if (obj instanceof Metric) {
211                                         pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
212                                         state = State.MetricIn;
213                                         break;
214                                 }
215                         case MetricIn:
216                                 state = State.IroIn;
217                                 if (obj instanceof Iro) {
218                                         builder.setIro((Iro) obj);
219                                         break;
220                                 }
221                         case IroIn:
222                                 state = State.End;
223                                 break;
224                         case End:
225                                 break;
226                         default:
227                                 throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
228                         }
229                         if (!state.equals(State.End)) {
230                                 objects.remove(0);
231                         }
232                 }
233                 builder.setMetrics(pathMetrics);
234         }
235
236         private void parsePath(final PathsBuilder builder, final List<Object> objects) throws PCEPDocumentedException {
237                 final List<Metrics> pathMetrics = Lists.newArrayList();
238
239                 Object obj;
240                 State state = State.Init;
241                 while (!objects.isEmpty() && !state.equals(State.End)) {
242                         obj = objects.get(0);
243
244                         switch (state) {
245                         case Init:
246                                 state = State.LspaIn;
247                                 if (obj instanceof Lspa) {
248                                         builder.setLspa((Lspa) obj);
249                                         break;
250                                 }
251                         case LspaIn:
252                                 state = State.OfIn;
253                                 if (obj instanceof Of) {
254                                         builder.setOf((Of) obj);
255                                         break;
256                                 }
257                         case OfIn:
258                                 state = State.BandwidthIn;
259                                 if (obj instanceof Bandwidth) {
260                                         builder.setBandwidth((Bandwidth) obj);
261                                         break;
262                                 }
263                         case BandwidthIn:
264                                 state = State.MetricIn;
265                                 if (obj instanceof Metric) {
266                                         pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
267                                         state = State.BandwidthIn;
268                                         break;
269                                 }
270                         case MetricIn:
271                                 state = State.IroIn;
272                                 if (obj instanceof Iro) {
273                                         builder.setIro((Iro) obj);
274                                         break;
275                                 }
276                         case IroIn:
277                                 state = State.End;
278                                 break;
279                         case End:
280                                 break;
281                         default:
282                                 throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
283                         }
284                         if (!state.equals(State.End)) {
285                                 objects.remove(0);
286                         }
287                 }
288                 builder.setMetrics(pathMetrics);
289         }
290
291         private enum State {
292                 Init, LspaIn, OfIn, BandwidthIn, MetricIn, IroIn, End
293         }
294
295         @Override
296         public int getMessageType() {
297                 return TYPE;
298         }
299 }