com.mastfrog.scamper.MessageType.java Source code

Java tutorial

Introduction

Here is the source code for com.mastfrog.scamper.MessageType.java

Source

/*
 * Copyright (c) 2014 Tim Boudreau
 *
 * This file is part of Scamper.
 *
 * Scamper is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.mastfrog.scamper;

import io.netty.buffer.ByteBuf;

/**
 * Message types. Our SCTP messages begin with a 3-byte signature, consisting of
 * a magic number and two bytes identifying the type of message, which is used
 * to look up the handler the message will be dispatched to.
 * <p>
 * When creating a server, create some MessageType instances, and then use
 * ProtocolModule.bind() to map those to handlers.
 *
 * @author Tim Boudreau
 */
public final class MessageType {

    private final String name;
    private final byte byteOne;
    private final byte byteTwo;
    private boolean unknown;
    public static final int HEADER_SIZE = 2;

    public MessageType(String name, int byteOne, int byteTwo) {
        this(name, byteOne, byteTwo, false);
    }

    public MessageType(String name, byte byteOne, byte byteTwo) {
        this(name, byteOne, byteTwo, false);
    }

    private MessageType(String name, int byteOne, int byteTwo, boolean unknown) {
        this(name, (byte) byteOne, (byte) byteTwo, unknown);
        if (byteOne > Byte.MAX_VALUE || byteOne < Byte.MIN_VALUE) {
            throw new IllegalArgumentException("byteOne not expressible as a byte (" + Byte.MIN_VALUE + "-"
                    + Byte.MAX_VALUE + "): " + byteOne);
        }
        if (byteTwo > Byte.MAX_VALUE || byteTwo < Byte.MIN_VALUE) {
            throw new IllegalArgumentException("byteTwo not expressible as a byte (" + Byte.MIN_VALUE + "-"
                    + Byte.MAX_VALUE + "): " + byteTwo);
        }
    }

    private MessageType(String name, byte byteOne, byte byteTwo, boolean unknown) {
        if (!unknown && byteOne == 0 && byteTwo == 0) {
            throw new IllegalArgumentException("Zero/zero is reserved " + "for unknown messages");
        }
        this.name = name;
        this.byteOne = byteOne;
        this.byteTwo = byteTwo;
        this.unknown = unknown;
    }

    public <T> Message<T> newMessage(T obj) {
        return new Message<>(this, obj);
    }

    public int headerLength() {
        return HEADER_SIZE;
    }

    boolean match(byte one, byte two) {
        return byteOne == one && byteTwo == two;
    }

    /**
     * Returns true if this MessageType is not a registered one - it contains a
     * byte sequence the application doesn't recognize.
     *
     * @return true if this message is unknown
     */
    public boolean isUnknown() {
        return unknown;
    }

    public String toString() {
        return name + " (" + byteOne + "," + byteTwo + ")";
    }

    /**
     * Write this mesage type into a ByteBuf
     *
     * @param buf The buffeer
     * @return the buffer
     */
    public ByteBuf writeHeader(ByteBuf buf) {
        return buf.writeByte(byteOne).writeByte(byteTwo);
    }

    public static MessageType createUnknown(int one, int two) {
        if (one > Byte.MAX_VALUE || one < Byte.MIN_VALUE) {
            throw new IllegalArgumentException("Illegal byte value " + one);
        }
        if (two > Byte.MAX_VALUE || two < Byte.MIN_VALUE) {
            throw new IllegalArgumentException("Illegal byte value " + two);
        }
        return createUnknown((byte) one, (byte) two);
    }

    public static MessageType createUnknown(byte one, byte two) {
        return new MessageType("UNKNOWN", one, two, true);
    }

    @Override
    public int hashCode() {
        return ((byteOne & 0xFF) << 8) | (byteTwo & 0xFF);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof MessageType) {
            MessageType other = (MessageType) obj;
            return other.byteOne == byteOne && other.byteTwo == byteTwo;
        }
        return false;
    }
}