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 io.netty.buffer.ByteBuf;
11 import io.netty.buffer.UnpooledByteBufAllocator;
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.spi.MessageHandlerRegistry;
19 import org.opendaylight.protocol.pcep.spi.MessageSerializer;
20 import org.opendaylight.protocol.util.ByteArray;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
25 import com.google.common.base.Preconditions;
26 import com.google.common.primitives.UnsignedBytes;
29 * A PCEP message parser which also does validation.
31 public final class PCEPMessageFactory implements ProtocolMessageFactory<Message> {
33 private final static Logger logger = LoggerFactory.getLogger(PCEPMessageFactory.class);
35 private final static int TYPE_SIZE = 1; // bytes
37 private final static int LENGTH_SIZE = 2; // bytes
39 public final static int COMMON_HEADER_LENGTH = 4; // bytes
42 * Current supported version of PCEP.
44 public static final int PCEP_VERSION = 1;
46 private static final int VERSION_SF_LENGTH = 3;
48 private static final int VER_FLAGS_MF_LENGTH = 1;
49 private static final int TYPE_F_LENGTH = 1;
50 private static final int LENGTH_F_LENGTH = 2;
52 private static final int VER_FLAGS_MF_OFFSET = 0;
53 private static final int TYPE_F_OFFSET = VER_FLAGS_MF_LENGTH + VER_FLAGS_MF_OFFSET;
54 private static final int LENGTH_F_OFFSET = TYPE_F_LENGTH + TYPE_F_OFFSET;
56 private final MessageHandlerRegistry registry;
58 public PCEPMessageFactory(final MessageHandlerRegistry registry) {
59 this.registry = Preconditions.checkNotNull(registry);
63 public Message parse(final byte[] bytes) throws DeserializerException, DocumentedException {
64 Preconditions.checkArgument(bytes != null, "Bytes may not be null");
65 Preconditions.checkArgument(bytes.length != 0, "Bytes may not be empty");
67 logger.trace("Attempt to parse message from bytes: {}", ByteArray.bytesToHexString(bytes));
69 final int type = UnsignedBytes.toInt(bytes[1]);
71 final int msgLength = ByteArray.bytesToInt(ByteArray.subByte(bytes, TYPE_SIZE + 1, LENGTH_SIZE));
73 final byte[] msgBody = ByteArray.cutBytes(bytes, TYPE_SIZE + 1 + LENGTH_SIZE);
75 if (msgBody.length != msgLength - COMMON_HEADER_LENGTH) {
76 throw new DeserializerException("Body size " + msgBody.length + " does not match header size "
77 + (msgLength - COMMON_HEADER_LENGTH));
83 msg = this.registry.getMessageParser(type).parseMessage(msgBody);
84 } catch (final PCEPDeserializerException e) {
85 logger.debug("Unexpected deserializer problem", e);
86 throw new DeserializerException(e.getMessage(), e);
87 } catch (final PCEPDocumentedException e) {
88 logger.debug("Documented deserializer problem", e);
89 throw new DocumentedException(e.getMessage(), e);
91 logger.debug("Message was parsed. {}", msg);
96 public byte[] put(final Message msg) {
98 throw new IllegalArgumentException("PCEPMessage is mandatory.");
101 final ByteBuf buf = new UnpooledByteBufAllocator(false).buffer();
103 final MessageSerializer serializer = this.registry.getMessageSerializer(msg);
105 serializer.serializeMessage(msg, buf);
107 final byte[] msgBody = new byte[buf.readableBytes()];
109 buf.getBytes(0, msgBody);
111 final byte[] headerBytes = new byte[COMMON_HEADER_LENGTH];
114 headerBytes[VER_FLAGS_MF_OFFSET] = (byte) (PCEP_VERSION << (Byte.SIZE - VERSION_SF_LENGTH));
117 headerBytes[TYPE_F_OFFSET] = (byte) serializer.getMessageType();
120 System.arraycopy(ByteArray.intToBytes(msgBody.length + COMMON_HEADER_LENGTH), Integer.SIZE / Byte.SIZE - LENGTH_F_LENGTH,
121 headerBytes, LENGTH_F_OFFSET, LENGTH_F_LENGTH);
123 final byte[] retBytes = new byte[headerBytes.length + msgBody.length];
125 ByteArray.copyWhole(headerBytes, retBytes, 0);
126 ByteArray.copyWhole(msgBody, retBytes, COMMON_HEADER_LENGTH);