All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.qpid.framing.ProtocolInitiation Maven / Gradle / Ivy

There is a newer version: 6.1.7
Show newest version
/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package org.apache.qpid.framing;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

import org.apache.qpid.QpidException;
import org.apache.qpid.bytebuffer.QpidByteBuffer;
import org.apache.qpid.transport.ByteBufferSender;

public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQDataBlock
{

    // TODO: generate these constants automatically from the xml protocol spec file
    private static final byte[] AMQP_HEADER = new byte[]{(byte)'A',(byte)'M',(byte)'Q',(byte)'P'};

    private static final byte CURRENT_PROTOCOL_CLASS = 1;
    private static final byte TCP_PROTOCOL_INSTANCE = 1;

    private final byte[] _protocolHeader;
    private final byte _protocolClass;
    private final byte _protocolInstance;
    private final byte _protocolMajor;
    private final byte _protocolMinor;

    public ProtocolInitiation(byte[] protocolHeader, byte protocolClass, byte protocolInstance, byte protocolMajor, byte protocolMinor)
    {
        _protocolHeader = protocolHeader;
        _protocolClass = protocolClass;
        _protocolInstance = protocolInstance;
        _protocolMajor = protocolMajor;
        _protocolMinor = protocolMinor;
    }
    
    public ProtocolInitiation(ProtocolVersion pv)
    {
        this(AMQP_HEADER,
             pv.equals(ProtocolVersion.v0_91) ? 0 : CURRENT_PROTOCOL_CLASS,
             pv.equals(ProtocolVersion.v0_91) ? 0 : TCP_PROTOCOL_INSTANCE,
             pv.equals(ProtocolVersion.v0_91) ? 9 : pv.getMajorVersion(),
             pv.equals(ProtocolVersion.v0_91) ? 1 : pv.getMinorVersion());
    }

    public ProtocolInitiation(QpidByteBuffer in)
    {
        _protocolHeader = new byte[4];
        in.get(_protocolHeader);

        _protocolClass = in.get();
        _protocolInstance = in.get();
        _protocolMajor = in.get();
        _protocolMinor = in.get();
    }


    public long getSize()
    {
        return 4 + 1 + 1 + 1 + 1;
    }

    @Override
    public long writePayload(final ByteBufferSender sender)
    {
        byte[] data = new byte[8];
        for(int i = 0; i < _protocolHeader.length; i++)
        {
            data[i] = _protocolHeader[i];
        }
        data[4] = _protocolClass;
        data[5] = _protocolInstance;
        data[6] = _protocolMajor;
        data[7] = _protocolMinor;
        sender.send(QpidByteBuffer.wrap(data));
        return 8l;
    }

    public boolean equals(Object o)
    {
        if (!(o instanceof ProtocolInitiation))
        {
            return false;
        }

        ProtocolInitiation pi = (ProtocolInitiation) o;
        if (pi._protocolHeader == null)
        {
            return false;
        }

        if (_protocolHeader.length != pi._protocolHeader.length)
        {
            return false;
        }

        for (int i = 0; i < _protocolHeader.length; i++)
        {
            if (_protocolHeader[i] != pi._protocolHeader[i])
            {
                return false;
            }
        }

        return (_protocolClass == pi._protocolClass &&
                _protocolInstance == pi._protocolInstance &&
                _protocolMajor == pi._protocolMajor &&
                _protocolMinor == pi._protocolMinor);
    }

    @Override
    public int hashCode()
    {
        int result = _protocolHeader != null ? Arrays.hashCode(_protocolHeader) : 0;
        result = 31 * result + (int) _protocolClass;
        result = 31 * result + (int) _protocolInstance;
        result = 31 * result + (int) _protocolMajor;
        result = 31 * result + (int) _protocolMinor;
        return result;
    }

    public static class Decoder //implements MessageDecoder
    {
        /**
         *
         * @param in input buffer
         * @return number of extra octets of data required data to decode the PI frame fully
         */
        public int decodable(QpidByteBuffer in)
        {
            return (in.remaining() >= 8) ? 0 : 8 - in.remaining();
        }

    }

    public ProtocolVersion checkVersion() throws QpidException
    {

        if(_protocolHeader.length != 4)
        {
            throw new AMQProtocolHeaderException("Protocol header should have exactly four octets", null);
        }
        for(int i = 0; i < 4; i++)
        {
            if(_protocolHeader[i] != AMQP_HEADER[i])
            {
                try
                {
                    throw new AMQProtocolHeaderException("Protocol header is not correct: Got " + new String(_protocolHeader,"ISO-8859-1") + " should be: " + new String(AMQP_HEADER, "ISO-8859-1"), null);
                }
                catch (UnsupportedEncodingException e)
                {
                    
                }
            }
        }

        ProtocolVersion pv;

        // Hack for 0-9-1 which changed how the header was defined
        if(_protocolInstance == 0 && _protocolMajor == 9 && _protocolMinor == 1)
        {
            pv = ProtocolVersion.v0_91;
            if (_protocolClass != 0)
            {
                throw new AMQProtocolClassException("Protocol class " + 0 + " was expected; received " +
                                                    _protocolClass, null);
            }
        }
        else if (_protocolClass != CURRENT_PROTOCOL_CLASS)
        {
            throw new AMQProtocolClassException("Protocol class " + CURRENT_PROTOCOL_CLASS + " was expected; received " +
                                                _protocolClass, null);
        }
        else if (_protocolInstance != TCP_PROTOCOL_INSTANCE)
        {
            throw new AMQProtocolInstanceException("Protocol instance " + TCP_PROTOCOL_INSTANCE + " was expected; received " +
                                                   _protocolInstance, null);
        }
        else
        {
            pv = ProtocolVersion.get(_protocolMajor, _protocolMinor);
        }
        

        if (!pv.isSupported())
        {
            // TODO: add list of available versions in list to msg...
            throw new AMQProtocolVersionException("Protocol version " + _protocolMajor + "."
                                                  + _protocolMinor
                                                  + " not supported.", null);
        }
        return pv;
    }

    public byte getProtocolClass()
    {
        return _protocolClass;
    }

    public byte getProtocolInstance()
    {
        return _protocolInstance;
    }

    public byte getProtocolMajor()
    {
        return _protocolMajor;
    }

    public byte getProtocolMinor()
    {
        return _protocolMinor;
    }

    public String toString()
    {
        StringBuffer buffer = new StringBuffer(new String(_protocolHeader, StandardCharsets.US_ASCII));
        buffer.append(Integer.toHexString(_protocolClass));
        buffer.append(Integer.toHexString(_protocolInstance));
        buffer.append(Integer.toHexString(_protocolMajor));
        buffer.append(Integer.toHexString(_protocolMinor));
        return buffer.toString();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy