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; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class DataPushingReplyPacket { private static final Logger LOGGER = LoggerFactory.getLogger(DataPushingReplyPacket.class); /** Magic */ public static final long MAGIC = 0x67446698L; /** Static size */ private static final int HEADER_SIZE = 32 / 8 + 32 / 8 + 64 / 8; /** Magic Number */ private final long magic; /** Error */ private final DataPushingError error; /** Handle to identify the request */ private final long handle; public DataPushingReplyPacket(final long magic, final DataPushingError error, final long handle) { super(); this.magic = magic; this.error = error; this.handle = handle; } /** * Get the magic number. * * @return the magic number */ public final long getMagic() { return magic; } /** * Get the error code. * * @return the error code */ public final DataPushingError getError() { return error; } /** * Get the handle. * * @return the handle */ public final long getHandle() { return handle; } /** * Allocate header for {@link DataPushingReplyPacket}. * * @return the allocated {@link ByteBuffer} */ public static final ByteBuffer allocateHeader() { return (ByteBuffer) NbdByteBufferCache.allocate(Utils.MAX_HEADER_SIZE).limit(HEADER_SIZE); } /** * Release an {@link ByteBuffer}. * * @param buffer * the buffer to release */ public static final void release(final ByteBuffer buffer) { NbdByteBufferCache.release(buffer); } /** * Serialize the {@link DataPushingReplyPacket}. * * @param packet * the {@link DataPushingReplyPacket} to serialize * * @return the serialized {@link ByteBuffer} */ public static final ByteBuffer serialize(final DataPushingReplyPacket packet) { final ByteBuffer buffer = allocateHeader(); Utils.putUnsignedInt(buffer, packet.magic); Utils.putUnsignedInt(buffer, packet.error.value()); buffer.putLong(packet.handle); buffer.flip(); return buffer; } /** * Deserialize a {@link ByteBuffer} in a {@link DataPushingReplyPacket} * * @param buffer * the buffer to decode * @return the {@link DataPushingReplyPacket} * * @throws NbdException * */ public static final DataPushingReplyPacket deserialize(final ByteBuffer buffer) throws NbdException { final long magic = Utils.getUnsignedInt(buffer); if (LOGGER.isDebugEnabled()) { LOGGER.debug("magic=0x" + Long.toHexString(magic)); } if (magic != MAGIC) { throw new NbdException("Illegal magic number for data pushing reply"); } final long error = Utils.getUnsignedInt(buffer); if (LOGGER.isDebugEnabled()) { LOGGER.debug("error=0x" + Long.toHexString(error)); } if (DataPushingError.valueOf(error) != DataPushingError.NBD_NO_ERROR) { throw new NbdException("Received error=" + error); } final long handle = Utils.getUnsignedLong(buffer); if (LOGGER.isDebugEnabled()) { LOGGER.debug("handle=0x" + Long.toHexString(handle)); } return new DataPushingReplyPacket(magic, DataPushingError.valueOf(error), handle); } }