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

io.rsocket.frame.SetupFrameFlyweight Maven / Gradle / Ivy

There is a newer version: 1.1.4
Show newest version
package io.rsocket.frame;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import java.nio.charset.StandardCharsets;

public class SetupFrameFlyweight {
  /**
   * A flag used to indicate that the client requires connection resumption, if possible (the frame
   * contains a Resume Identification Token)
   */
  public static final int FLAGS_RESUME_ENABLE = 0b00_1000_0000;

  /** A flag used to indicate that the client will honor LEASE sent by the server */
  public static final int FLAGS_WILL_HONOR_LEASE = 0b00_0100_0000;

  public static final int CURRENT_VERSION = VersionFlyweight.encode(1, 0);

  private static final int VERSION_FIELD_OFFSET = FrameHeaderFlyweight.size();
  private static final int KEEPALIVE_INTERVAL_FIELD_OFFSET = VERSION_FIELD_OFFSET + Integer.BYTES;
  private static final int KEEPALIVE_MAX_LIFETIME_FIELD_OFFSET =
      KEEPALIVE_INTERVAL_FIELD_OFFSET + Integer.BYTES;
  private static final int VARIABLE_DATA_OFFSET =
      KEEPALIVE_MAX_LIFETIME_FIELD_OFFSET + Integer.BYTES;

  public static ByteBuf encode(
      final ByteBufAllocator allocator,
      boolean lease,
      boolean resume,
      final int keepaliveInterval,
      final int maxLifetime,
      final String metadataMimeType,
      final String dataMimeType,
      final ByteBuf metadata,
      final ByteBuf data) {
    return encode(
        allocator,
        lease,
        resume,
        keepaliveInterval,
        maxLifetime,
        Unpooled.EMPTY_BUFFER,
        metadataMimeType,
        dataMimeType,
        metadata,
        data);
  }

  public static ByteBuf encode(
      final ByteBufAllocator allocator,
      boolean lease,
      boolean resume,
      final int keepaliveInterval,
      final int maxLifetime,
      final ByteBuf resumeToken,
      final String metadataMimeType,
      final String dataMimeType,
      final ByteBuf metadata,
      final ByteBuf data) {

    int flags = 0;
    if (resume) {
      throw new IllegalArgumentException("RESUME_ENABLE not supported");
    }

    /*
    if (resume) {
      flags |= FLAGS_RESUME_ENABLE;
    }*/

    if (lease) {
      flags |= FLAGS_WILL_HONOR_LEASE;
    }

    if (metadata != null) {
      flags |= FrameHeaderFlyweight.FLAGS_M;
    }

    ByteBuf header = FrameHeaderFlyweight.encodeStreamZero(allocator, FrameType.SETUP, flags);

    header.writeInt(CURRENT_VERSION).writeInt(keepaliveInterval).writeInt(maxLifetime);

    if ((flags & FLAGS_RESUME_ENABLE) != 0) {
      header.writeShort(resumeToken.readableBytes()).writeBytes(resumeToken);
    }

    // Write metadata mime-type
    int length = ByteBufUtil.utf8Bytes(metadataMimeType);
    header.writeByte(length);
    ByteBufUtil.writeUtf8(header, metadataMimeType);

    // Write data mime-type
    length = ByteBufUtil.utf8Bytes(dataMimeType);
    header.writeByte(length);
    ByteBufUtil.writeUtf8(header, dataMimeType);
    if (metadata != null) {
      return DataAndMetadataFlyweight.encode(allocator, header, metadata, data);
    } else {
      return DataAndMetadataFlyweight.encodeOnlyData(allocator, header, data);
    }
  }

  public static int version(ByteBuf byteBuf) {
    FrameHeaderFlyweight.ensureFrameType(FrameType.SETUP, byteBuf);
    byteBuf.markReaderIndex();
    int version = byteBuf.skipBytes(VERSION_FIELD_OFFSET).readInt();
    byteBuf.resetReaderIndex();
    return version;
  }

  public static int resumeTokenLength(ByteBuf byteBuf) {
    byteBuf.markReaderIndex();
    int tokenLength = byteBuf.skipBytes(VARIABLE_DATA_OFFSET).readShort() & 0xFFFF;
    byteBuf.resetReaderIndex();
    return tokenLength;
  }

  public static int keepAliveInterval(ByteBuf byteBuf) {
    byteBuf.markReaderIndex();
    int keepAliveInterval = byteBuf.skipBytes(KEEPALIVE_INTERVAL_FIELD_OFFSET).readInt();
    byteBuf.resetReaderIndex();
    return keepAliveInterval;
  }

  public static int keepAliveMaxLifetime(ByteBuf byteBuf) {
    byteBuf.markReaderIndex();
    int keepAliveMaxLifetime = byteBuf.skipBytes(KEEPALIVE_MAX_LIFETIME_FIELD_OFFSET).readInt();
    byteBuf.resetReaderIndex();
    return keepAliveMaxLifetime;
  }

  public static boolean honorLease(ByteBuf byteBuf) {
    return (FLAGS_WILL_HONOR_LEASE & FrameHeaderFlyweight.flags(byteBuf)) == FLAGS_WILL_HONOR_LEASE;
  }

  public static boolean resumeEnabled(ByteBuf byteBuf) {
    return (FLAGS_RESUME_ENABLE & FrameHeaderFlyweight.flags(byteBuf)) == FLAGS_RESUME_ENABLE;
  }

  public static String metadataMimeType(ByteBuf byteBuf) {
    int skip = bytesToSkipToMimeType(byteBuf);
    byteBuf.markReaderIndex();
    int length = byteBuf.skipBytes(skip).readByte();
    String mimeType = byteBuf.readSlice(length).toString(StandardCharsets.UTF_8);
    byteBuf.resetReaderIndex();
    return mimeType;
  }

  public static String dataMimeType(ByteBuf byteBuf) {
    int skip = bytesToSkipToMimeType(byteBuf);
    byteBuf.markReaderIndex();
    int metadataLength = byteBuf.skipBytes(skip).readByte();
    int dataLength = byteBuf.skipBytes(metadataLength).readByte();
    String mimeType = byteBuf.readSlice(dataLength).toString(StandardCharsets.UTF_8);
    byteBuf.resetReaderIndex();
    return mimeType;
  }

  public static ByteBuf metadata(ByteBuf byteBuf) {
    boolean hasMetadata = FrameHeaderFlyweight.hasMetadata(byteBuf);
    byteBuf.markReaderIndex();
    skipToPayload(byteBuf);
    ByteBuf metadata = DataAndMetadataFlyweight.metadataWithoutMarking(byteBuf, hasMetadata);
    byteBuf.resetReaderIndex();
    return metadata;
  }

  public static ByteBuf data(ByteBuf byteBuf) {
    boolean hasMetadata = FrameHeaderFlyweight.hasMetadata(byteBuf);
    byteBuf.markReaderIndex();
    skipToPayload(byteBuf);
    ByteBuf data = DataAndMetadataFlyweight.dataWithoutMarking(byteBuf, hasMetadata);
    byteBuf.resetReaderIndex();
    return data;
  }

  private static int bytesToSkipToMimeType(ByteBuf byteBuf) {
    int bytesToSkip = VARIABLE_DATA_OFFSET;
    if ((FLAGS_RESUME_ENABLE & FrameHeaderFlyweight.flags(byteBuf)) == FLAGS_RESUME_ENABLE) {
      bytesToSkip = resumeTokenLength(byteBuf) + Short.BYTES;
    }
    return bytesToSkip;
  }

  private static void skipToPayload(ByteBuf byteBuf) {
    int skip = bytesToSkipToMimeType(byteBuf);
    byte length = byteBuf.skipBytes(skip).readByte();
    length = byteBuf.skipBytes(length).readByte();
    byteBuf.skipBytes(length);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy