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

orbit.server.net.ClientConnection.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0a19
Show newest version
/*
 Copyright (C) 2015 - 2019 Electronic Arts Inc.  All rights reserved.
 This file is part of the Orbit Project .
 See license in LICENSE.
 */

package orbit.server.net

import io.micrometer.core.instrument.Metrics
import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.channels.SendChannel
import orbit.server.auth.AuthInfo
import orbit.server.pipeline.Pipeline
import orbit.server.service.Meters
import orbit.shared.exception.CapacityExceededException
import orbit.shared.exception.toErrorContent
import orbit.shared.mesh.NodeId
import orbit.shared.net.Message
import orbit.shared.net.MessageTarget
import orbit.shared.proto.Messages
import orbit.shared.proto.toMessage
import orbit.shared.proto.toMessageProto
import orbit.shared.router.Route

class ClientConnection(
    private val authInfo: AuthInfo,
    private val incomingChannel: ReceiveChannel,
    private val outgoingChannel: SendChannel,
    private val pipeline: Pipeline
) : MessageSender {

    val nodeId get() = authInfo.nodeId

    suspend fun consumeMessages() {
        val messageSizes = Metrics.summary(Meters.Names.MessageSizes)

        for (protoMessage in incomingChannel) {
            messageSizes.record(protoMessage.toByteArray().size.toDouble())

            val message = protoMessage.toMessage()
            val meta = MessageMetadata(
                authInfo = authInfo,
                messageDirection = MessageDirection.INBOUND
            )

            try {
                pipeline.pushMessage(message, meta)
            } catch (t: Throwable) {
                pipeline.pushMessage(
                    msg = Message(
                        target = message.source?.let(MessageTarget::Unicast),
                        messageId = message.messageId,
                        content = t.toErrorContent()
                    ),
                    meta = MessageMetadata(
                        authInfo = authInfo,
                        messageDirection = MessageDirection.OUTBOUND,
                        respondOnError = false
                    )
                )
            }
        }

        close()
    }

    override suspend fun sendMessage(message: Message, route: Route?) {
        outgoingChannel.send(message.toMessageProto())
    }

    fun offerMessage(message: Message) {
        val queued = outgoingChannel.offer(message.toMessageProto())
        if (!queued) throw CapacityExceededException("Could not offer message.")
    }

    fun close(cause: Throwable? = null, messageId: Long? = null) {
        if (cause !=null){
            offerMessage(
                Message(
                    messageId = messageId,
                    content = cause.toErrorContent()
                )
            )}
        outgoingChannel.close()
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy