package io.eguan.nbdsrv.packet; /* * #%L * Project eguan * %% * Copyright (C) 2012 - 2017 Oodrive * %% * Licensed 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. * #L% */ import java.nio.ByteBuffer; public final class InitPacket { /** Magic */ public static final String MAGIC_STR = "NBDMAGIC"; public static final long MAGIC = 0x49484156454F5054L; /** Flags */ public static final short NBD_FLAG_FIXED_NEWSTYLE = 1 << 0; /** Header size */ private static final int HEADER_SIZE = 64 / 8 + 64 / 8 + 16 / 8; /** NBD magic string */ private final String magicStr; /** NBD magic number for init */ private final long magic; /** global flags for the server */ private final int globalFlags; public InitPacket(final String magicStr, final long magic, final int flags) { super(); this.magicStr = magicStr; this.magic = magic; this.globalFlags = flags; } /** * Get the magic string. * * @return the magic string */ public final String getMagicStr() { return magicStr; } /** * Get the magic number. * * @return the magic number */ public final long getMagic() { return magic; } /** * Gets the global flags. * * * @return the global flags */ public final int getGlobalFlags() { return globalFlags; } /** * Allocate a {@link ByteBuffer} for a {@link InitPacket}. * * @return the allocated {@link ByteBuffer} */ public static final ByteBuffer allocateHeader() { return (ByteBuffer) NbdByteBufferCache.allocate(Utils.MAX_HEADER_SIZE).limit(HEADER_SIZE); } /** * Release a {@link ByteBuffer}. * * @param buffer * the buffer to release */ public static final void release(final ByteBuffer buffer) { NbdByteBufferCache.release(buffer); } /** * Serialize a {@link InitPacket} in a {@link ByteBuffer}. * * @param packet * the {@link InitPacket} to serialize * * @return the {@link ByteBuffer} serialized */ public static final ByteBuffer serialize(final InitPacket packet) { final ByteBuffer buffer = allocateHeader(); buffer.put(packet.magicStr.getBytes()); Utils.putUnsignedLong(buffer, packet.magic); Utils.putUnsignedShort(buffer, packet.globalFlags); buffer.flip(); return buffer; } /** * Deserialize a {@link ByteBuffer} in a {@link InitPacket} * * @param buffer * the {@link ByteBuffer} to decode * * @return the {@link InitPacket} * @throws NbdException */ public static final InitPacket deserialize(final ByteBuffer buffer) throws NbdException { final byte[] magicBytes = new byte[MAGIC_STR.length()]; buffer.get(magicBytes); final String magicStr = new String(magicBytes); if (!magicStr.equals(MAGIC_STR)) { throw new NbdException("Bad magic String"); } final long magic = Utils.getUnsignedLong(buffer); if (magic != MAGIC) { throw new NbdException("Bad magic Number"); } final int flags = Utils.getUnsignedShort(buffer); return new InitPacket(magicStr, magic, flags); } }