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

androidMain.com.yazantarifi.websocketmanager.manager.SocketInstance.kt Maven / Gradle / Ivy

There is a newer version: 0.13-alpha
Show newest version
package com.yazantarifi.websocketmanager.manager

import com.yazantarifi.websocketmanager.configuration.SocketClientConfiguration
import com.yazantarifi.websocketmanager.configuration.SocketHooksCallback
import com.yazantarifi.websocketmanager.configuration.SocketManagerTransport
import com.yazantarifi.websocketmanager.errors.SocketManagerException
import com.yazantarifi.websocketmanager.errors.childs.SocketClientTransportNotSupportedException
import com.yazantarifi.websocketmanager.errors.childs.SocketManagerInvalidUrlException
import com.yazantarifi.websocketmanager.errors.childs.SocketUnknownException
import com.yazantarifi.websocketmanager.models.SocketManagerPullEvents
import com.yazantarifi.websocketmanager.utils.SocketManagerUtils
import io.socket.client.Socket
import java.lang.Exception
import io.socket.client.IO
import io.socket.engineio.client.transports.Polling
import io.socket.engineio.client.transports.WebSocket
import okhttp3.OkHttpClient
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

class SocketInstance: BaseSocketInstance() {

    private var socketInstance: Socket? = null
    private var configuration: SocketClientConfiguration? = null
    private var errorListenerCallback: ((SocketManagerException) -> Unit?)? = null
    private var listener: SocketHooksCallback? = null

    override fun getInstance(): Socket? {
        return socketInstance
    }

    override fun isInstanceConnected(): Boolean {
        return ((socketInstance?.connected() ?: false) && (socketInstance?.isActive ?: false))
    }

    override fun registerSocketConnectionHooks(listener: SocketHooksCallback) {
        this.listener = listener
    }

    override fun buildSocketInstance() {
        try {
            if (!SocketManagerUtils.isUrlValid(configuration?.serverUrl ?: "")) {
                errorListenerCallback?.invoke(SocketManagerInvalidUrlException())
                return
            }

            val socketConfiguration = configuration ?: return
            val transports = arrayOfNulls(socketConfiguration.supportedTransports.size)
            for ((index, value) in socketConfiguration.supportedTransports.withIndex()) {
                if (value == SocketManagerTransport.WEB_SOCKET) {
                    transports[index] = WebSocket.NAME
                } else if (value == SocketManagerTransport.POLLING) {
                    transports[index] = Polling.NAME
                } else {
                    errorListenerCallback?.invoke(SocketClientTransportNotSupportedException())
                }
            }

            val options = IO.Options.builder()
                .setForceNew(socketConfiguration.isForceNewSession)
                .setPort(socketConfiguration.port)
                .setReconnection(socketConfiguration.isForceReconnectionEnabled)
                .setReconnectionAttempts(socketConfiguration.numberOfReconnectionRetries)
                .setReconnectionDelay(socketConfiguration.reconnectionDelay)
                .setTimeout(socketConfiguration.connectionTimeout)
                .setUpgrade(socketConfiguration.isUpgrade)
                .setAuth(null)
                .setTransports(transports)
                .setRememberUpgrade(socketConfiguration.isRememberUpgradeEnabled)
                .build()

            if (!socketConfiguration.isConnectionSecured) {
                options.webSocketFactory = getSecurityClient()
                options.callFactory = getSecurityClient()
            }

            this.socketInstance = IO.socket(socketConfiguration.serverUrl ?: "", options)
        } catch (ex: Exception) {
            errorListenerCallback?.invoke(SocketUnknownException(ex.message ?: ""))
        }
    }

    private fun getSecurityClient(): OkHttpClient {
        val hostnameVerifier = HostnameVerifier { hostname, sslSession -> true }

        val trustManager: X509TrustManager = object : X509TrustManager {
            override fun checkClientTrusted(arg0: Array?, arg1: String?) = Unit
            override fun checkServerTrusted(arg0: Array?, arg1: String?) = Unit
            override fun getAcceptedIssuers(): Array {
                return arrayOf()
            }
        }

        val sslContext = SSLContext.getInstance("TLS")
        sslContext.init(null, arrayOf(trustManager), null)

        return OkHttpClient.Builder()
            .hostnameVerifier(hostnameVerifier)
            .sslSocketFactory(sslContext.socketFactory, trustManager)
            .readTimeout(1, TimeUnit.MINUTES) // important for HTTP long-polling
            .build()
    }

    override fun registerDefaultSocketInstanceCallbacks() {
        socketInstance?.let {
            it.on(SocketManagerPullEvents.CONNECT.pullKey) {
                listener?.onSocketConnected()
            }

            it.on(SocketManagerPullEvents.DISCONNECT.pullKey) {
                listener?.onSocketDisconnected()
            }

            it.on(SocketManagerPullEvents.ERROR.pullKey) {
                if (it[0] is java.lang.Exception) {
                    errorListenerCallback?.invoke(SocketUnknownException((it[0] as java.lang.Exception).message ?: ""))
                }
            }
        }
    }

    override fun initInstanceConfiguration(configuration: SocketClientConfiguration) {
        this.configuration = configuration
    }

    override fun registerErrorListener(errorListener: (SocketManagerException) -> Unit) {
        errorListenerCallback = errorListener
    }

    override fun connectSocketInstance() {
        socketInstance?.connect()
    }

    override fun disconnectSocketInstance() {
        socketInstance?.disconnect()
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy