Merge "Add linkstate information to RIB"
[bgpcep.git] / bgp / parser-spi / src / main / java / org / opendaylight / protocol / bgp / parser / spi / pojo / AbstractMessageRegistry.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.bgp.parser.spi.pojo;
9
10 import java.util.Arrays;
11
12 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
13 import org.opendaylight.protocol.bgp.parser.BGPError;
14 import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
15 import org.opendaylight.protocol.bgp.parser.spi.MessageUtil;
16 import org.opendaylight.protocol.framework.DeserializerException;
17 import org.opendaylight.protocol.util.ByteArray;
18 import org.opendaylight.yangtools.yang.binding.Notification;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 import com.google.common.primitives.UnsignedBytes;
23
24 abstract class AbstractMessageRegistry implements MessageRegistry {
25         private final static Logger logger = LoggerFactory.getLogger(AbstractMessageRegistry.class);
26
27         protected abstract Notification parseBody(final int type, final byte[] body, final int messageLength) throws BGPDocumentedException;
28
29         protected abstract byte[] serializeMessageImpl(final Notification message);
30
31         @Override
32         public final Notification parseMessage(final byte[] bytes) throws BGPDocumentedException, DeserializerException {
33                 if (bytes == null) {
34                         throw new IllegalArgumentException("Array of bytes is mandatory.");
35                 }
36                 if (bytes.length < MessageUtil.COMMON_HEADER_LENGTH) {
37                         throw new IllegalArgumentException("Too few bytes in passed array. Passed: " + bytes.length + ". Expected: >= "
38                                         + MessageUtil.COMMON_HEADER_LENGTH + ".");
39                 }
40                 final byte[] marker = ByteArray.subByte(bytes, 0, MessageUtil.MARKER_LENGTH);
41                 final byte[] ones = new byte[MessageUtil.MARKER_LENGTH];
42                 Arrays.fill(ones, (byte) 0xff);
43                 // TODO: possible refactor
44                 // if (Arrays.equals(marker, ones)) {
45                 // throw new BGPDocumentedException("Marker not set to ones.", BGPError.CONNECTION_NOT_SYNC);
46                 // }
47                 final byte[] bs = ByteArray.cutBytes(bytes, MessageUtil.MARKER_LENGTH);
48                 final int messageLength = ByteArray.bytesToInt(ByteArray.subByte(bs, 0, MessageUtil.LENGTH_FIELD_LENGTH));
49                 final int messageType = UnsignedBytes.toInt(bs[MessageUtil.LENGTH_FIELD_LENGTH]);
50
51                 final byte[] msgBody = ByteArray.cutBytes(bs, MessageUtil.LENGTH_FIELD_LENGTH + MessageUtil.TYPE_FIELD_LENGTH);
52
53                 if (messageLength < MessageUtil.COMMON_HEADER_LENGTH) {
54                         throw BGPDocumentedException.badMessageLength("Message length field not within valid range.", messageLength);
55                 }
56                 if (msgBody.length != messageLength - MessageUtil.COMMON_HEADER_LENGTH) {
57                         throw new DeserializerException("Size doesn't match size specified in header. Passed: " + msgBody.length + "; Expected: "
58                                         + (messageLength - MessageUtil.COMMON_HEADER_LENGTH) + ". ");
59                 }
60
61                 logger.debug("Attempt to parse message from bytes: {}", ByteArray.bytesToHexString(msgBody));
62
63                 final Notification msg = parseBody(messageType, msgBody, messageLength);
64                 if (msg == null) {
65                         throw new BGPDocumentedException("Unhandled message type " + messageType, BGPError.BAD_MSG_TYPE, new byte[] { bs[MessageUtil.LENGTH_FIELD_LENGTH] });
66                 }
67
68                 return msg;
69         }
70
71         @Override
72         public final byte[] serializeMessage(final Notification message) {
73                 if (message == null) {
74                         throw new IllegalArgumentException("BGPMessage is mandatory.");
75                 }
76
77                 logger.trace("Serializing {}", message);
78
79                 final byte[] ret = serializeMessageImpl(message);
80                 if (ret == null) {
81                         throw new IllegalArgumentException("Unknown instance of BGPMessage. Passed " + message.getClass());
82                 }
83
84                 logger.trace("Serialized BGP message {}.", Arrays.toString(ret));
85                 return ret;
86         }
87 }