2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.protocol.pcep.impl;
10 import java.util.HashMap;
11 import java.util.List;
13 import org.opendaylight.protocol.framework.DeserializerException;
14 import org.opendaylight.protocol.framework.DocumentedException;
15 import org.opendaylight.protocol.framework.ProtocolMessageFactory;
16 import org.opendaylight.protocol.pcep.PCEPDeserializerException;
17 import org.opendaylight.protocol.pcep.PCEPDocumentedException;
18 import org.opendaylight.protocol.pcep.PCEPErrors;
19 import org.opendaylight.protocol.pcep.PCEPMessage;
20 import org.opendaylight.protocol.pcep.impl.message.PCCreateMessageParser;
21 import org.opendaylight.protocol.pcep.impl.message.PCEPCloseMessageParser;
22 import org.opendaylight.protocol.pcep.impl.message.PCEPErrorMessageParser;
23 import org.opendaylight.protocol.pcep.impl.message.PCEPKeepAliveMessageParser;
24 import org.opendaylight.protocol.pcep.impl.message.PCEPNotificationMessageParser;
25 import org.opendaylight.protocol.pcep.impl.message.PCEPOpenMessageParser;
26 import org.opendaylight.protocol.pcep.impl.message.PCEPReplyMessageParser;
27 import org.opendaylight.protocol.pcep.impl.message.PCEPReportMessageParser;
28 import org.opendaylight.protocol.pcep.impl.message.PCEPRequestMessageParser;
29 import org.opendaylight.protocol.pcep.impl.message.PCEPUpdateRequestMessageParser;
30 import org.opendaylight.protocol.pcep.message.PCCreateMessage;
31 import org.opendaylight.protocol.pcep.message.PCEPCloseMessage;
32 import org.opendaylight.protocol.pcep.message.PCEPErrorMessage;
33 import org.opendaylight.protocol.pcep.message.PCEPKeepAliveMessage;
34 import org.opendaylight.protocol.pcep.message.PCEPNotificationMessage;
35 import org.opendaylight.protocol.pcep.message.PCEPOpenMessage;
36 import org.opendaylight.protocol.pcep.message.PCEPReplyMessage;
37 import org.opendaylight.protocol.pcep.message.PCEPReportMessage;
38 import org.opendaylight.protocol.pcep.message.PCEPRequestMessage;
39 import org.opendaylight.protocol.pcep.message.PCEPUpdateRequestMessage;
40 import org.opendaylight.protocol.pcep.spi.PCEPMessageType;
41 import org.opendaylight.protocol.pcep.spi.RawMessage;
42 import org.opendaylight.protocol.util.ByteArray;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 import com.google.common.base.Preconditions;
47 import com.google.common.collect.Lists;
48 import com.google.common.primitives.UnsignedBytes;
51 * Factory for subclasses of {@link org.opendaylight.protocol.pcep.PCEPMessage PCEPMessage}
53 class RawPCEPMessageFactory implements ProtocolMessageFactory<PCEPMessage> {
55 private final static Logger logger = LoggerFactory.getLogger(PCEPMessageFactory.class);
57 private final static int TYPE_SIZE = 1; // bytes
59 private final static int LENGTH_SIZE = 2; // bytes
61 public final static int COMMON_HEADER_LENGTH = 4; // bytes
63 private static class MapOfParsers extends HashMap<PCEPMessageType, PCEPMessageParser> {
65 private static final long serialVersionUID = -5715193806554448822L;
67 private final static MapOfParsers instance = new MapOfParsers();
69 private MapOfParsers() {
73 private void fillInMap() {
74 this.put(PCEPMessageType.OPEN, new PCEPOpenMessageParser());
75 this.put(PCEPMessageType.KEEPALIVE, new PCEPKeepAliveMessageParser());
76 this.put(PCEPMessageType.NOTIFICATION, new PCEPNotificationMessageParser());
77 this.put(PCEPMessageType.ERROR, new PCEPErrorMessageParser());
78 this.put(PCEPMessageType.RESPONSE, new PCEPReplyMessageParser());
79 this.put(PCEPMessageType.REQUEST, new PCEPRequestMessageParser());
80 this.put(PCEPMessageType.UPDATE_REQUEST, new PCEPUpdateRequestMessageParser());
81 this.put(PCEPMessageType.STATUS_REPORT, new PCEPReportMessageParser());
82 this.put(PCEPMessageType.CLOSE, new PCEPCloseMessageParser());
83 this.put(PCEPMessageType.PCCREATE, new PCCreateMessageParser());
86 public static MapOfParsers getInstance() {
93 * @param bytes assume array of bytes without common header
94 * @return Parsed specific PCEPMessage
95 * @throws PCEPDeserializerException
96 * @throws PCEPDocumentedException
100 public List<PCEPMessage> parse(final byte[] bytes) throws DeserializerException, DocumentedException {
101 Preconditions.checkArgument(bytes != null, "Bytes may not be null");
102 Preconditions.checkArgument(bytes.length != 0, "Bytes may not be empty");
104 logger.trace("Attempt to parse message from bytes: {}", ByteArray.bytesToHexString(bytes));
106 final int type = UnsignedBytes.toInt(bytes[1]);
108 final int msgLength = ByteArray.bytesToInt(ByteArray.subByte(bytes, TYPE_SIZE + 1, LENGTH_SIZE));
110 final byte[] msgBody = ByteArray.cutBytes(bytes, TYPE_SIZE + 1 + LENGTH_SIZE);
112 if (msgBody.length != msgLength - COMMON_HEADER_LENGTH) {
113 throw new DeserializerException("Body size " + msgBody.length + " does not match header size " + (msgLength - COMMON_HEADER_LENGTH));
117 * if PCEPObjectIdentifier.getObjectClassFromInt() dont't throws
118 * exception and if returned null we know the error type
120 PCEPMessageType msgType = PCEPMessageType.getFromInt(type);
121 if (msgType == null) {
122 logger.debug("Unknown message type {}", type);
123 throw new DocumentedException("Unhandled message type " + type, new PCEPDocumentedException("Unhandled message type " + type, PCEPErrors.CAPABILITY_NOT_SUPPORTED));
128 msg = new RawMessage(PCEPObjectFactory.parseObjects(msgBody), msgType);
129 } catch (final PCEPDeserializerException e) {
130 logger.debug("Unexpected deserializer problem", e);
131 throw new DeserializerException(e.getMessage(), e);
132 } catch (final PCEPDocumentedException e) {
133 logger.debug("Documented deserializer problem", e);
134 throw new DocumentedException(e.getMessage(), e);
136 logger.debug("Message was parsed. {}", msg);
137 return Lists.newArrayList(msg);
141 public byte[] put(final PCEPMessage msg) {
143 throw new IllegalArgumentException("PCEPMessage is mandatory.");
146 final PCEPMessageType msgType;
148 if (msg instanceof PCEPOpenMessage) {
149 msgType = PCEPMessageType.OPEN;
150 } else if (msg instanceof PCEPKeepAliveMessage) {
151 msgType = PCEPMessageType.KEEPALIVE;
152 } else if (msg instanceof PCEPCloseMessage) {
153 msgType = PCEPMessageType.CLOSE;
154 } else if (msg instanceof PCEPReplyMessage) {
155 msgType = PCEPMessageType.RESPONSE;
156 } else if (msg instanceof PCEPRequestMessage) {
157 msgType = PCEPMessageType.REQUEST;
158 } else if (msg instanceof PCEPNotificationMessage) {
159 msgType = PCEPMessageType.NOTIFICATION;
160 } else if (msg instanceof PCEPErrorMessage) {
161 msgType = PCEPMessageType.ERROR;
162 } else if (msg instanceof PCEPReportMessage) {
163 msgType = PCEPMessageType.STATUS_REPORT;
164 } else if (msg instanceof PCEPUpdateRequestMessage) {
165 msgType = PCEPMessageType.UPDATE_REQUEST;
166 } else if (msg instanceof PCCreateMessage) {
167 msgType = PCEPMessageType.PCCREATE;
169 logger.error("Unknown instance of PCEPMessage. Message class: {}", msg.getClass());
170 throw new IllegalArgumentException("Unknown instance of PCEPMessage. Passed " + msg.getClass());
173 logger.trace("Serializing {}", msgType);
175 final byte[] msgBody = MapOfParsers.getInstance().get(msgType).put(msg);
177 final PCEPMessageHeader msgHeader = new PCEPMessageHeader(msgType.getIdentifier(), msgBody.length
178 + PCEPMessageHeader.COMMON_HEADER_LENGTH, PCEPMessage.PCEP_VERSION);
180 final byte[] headerBytes = msgHeader.toBytes();
181 final byte[] retBytes = new byte[headerBytes.length + msgBody.length];
183 ByteArray.copyWhole(headerBytes, retBytes, 0);
184 ByteArray.copyWhole(msgBody, retBytes, PCEPMessageHeader.COMMON_HEADER_LENGTH);