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

commonMain.io.rsocket.kotlin.frame.Frame.kt Maven / Gradle / Ivy

/*
 * Copyright 2015-2020 the original author or authors.
 *
 * 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.
 */

package io.rsocket.kotlin.frame

import io.ktor.utils.io.core.*
import io.ktor.utils.io.core.internal.*
import io.ktor.utils.io.pool.*
import io.rsocket.kotlin.frame.io.*

private const val FlagsMask: Int = 1023
private const val FrameTypeShift: Int = 10

sealed class Frame(open val type: FrameType) : Closeable {
    abstract val streamId: Int
    abstract val flags: Int

    abstract fun release()

    protected abstract fun BytePacketBuilder.writeSelf()
    protected abstract fun StringBuilder.appendFlags()
    protected abstract fun StringBuilder.appendSelf()

    @DangerousInternalIoApi
    fun toPacket(pool: ObjectPool): ByteReadPacket {
        check(type.canHaveMetadata || !(flags check Flags.Metadata)) { "bad value for metadata flag" }
        return buildPacket(pool) {
            writeInt(streamId)
            writeShort((type.encodedType shl FrameTypeShift or flags).toShort())
            writeSelf()
        }
    }

    internal fun dump(length: Long): String = buildString {
        append("\n").append(type).append(" frame -> Stream Id: ").append(streamId).append(" Length: ").append(length)
        append("\nFlags: 0b").append(flags.toBinaryString()).append(" (").apply { appendFlags() }.append(")")
        appendSelf()
    }

    protected fun StringBuilder.appendFlag(flag: Char, value: Boolean) {
        append(flag)
        if (value) append(1) else append(0)
    }

    override fun close() {
        release()
    }
}

@DangerousInternalIoApi
fun ByteReadPacket.readFrame(pool: ObjectPool): Frame = use {
    val streamId = readInt()
    val typeAndFlags = readShort().toInt() and 0xFFFF
    val flags = typeAndFlags and FlagsMask
    when (val type = FrameType(typeAndFlags shr FrameTypeShift)) {
        //stream id = 0
        FrameType.Setup        -> readSetup(pool, flags)
        FrameType.Resume       -> readResume(pool)
        FrameType.ResumeOk     -> readResumeOk()
        FrameType.MetadataPush -> readMetadataPush(pool)
        FrameType.Lease        -> readLease(pool, flags)
        FrameType.KeepAlive    -> readKeepAlive(pool, flags)
        //stream id != 0
        FrameType.Cancel       -> CancelFrame(streamId)
        FrameType.Error        -> readError(streamId)
        FrameType.RequestN     -> readRequestN(streamId)
        FrameType.Extension    -> readExtension(pool, streamId, flags)
        FrameType.Payload,
        FrameType.RequestFnF,
        FrameType.RequestResponse,
                               -> readRequest(pool, type, streamId, flags, withInitial = false)
        FrameType.RequestStream,
        FrameType.RequestChannel,
                               -> readRequest(pool, type, streamId, flags, withInitial = true)
        FrameType.Reserved     -> error("Reserved")
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy