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