herlanS_ 4 anni fa
parent
commit
73c4007c73
2 ha cambiato i file con 137 aggiunte e 65 eliminazioni
  1. 2 2
      pom.xml
  2. 135 63
      src/main/kotlin/co/id/datacomsolusindo/ipphonebridge/BridgeFIlter.kt

+ 2 - 2
pom.xml

@@ -5,7 +5,7 @@
 	<parent>
 		<groupId>org.springframework.boot</groupId>
 		<artifactId>spring-boot-starter-parent</artifactId>
-		<version>2.3.3.RELEASE</version>
+		<version>2.4.1</version>
 		<relativePath/> <!-- lookup parent from repository -->
 	</parent>
 	<groupId>co.id.datacomsolusindo</groupId>
@@ -16,7 +16,7 @@
 
 	<properties>
 		<java.version>1.8</java.version>
-		<kotlin.version>1.3.72</kotlin.version>
+		<kotlin.version>1.4.21</kotlin.version>
 	</properties>
 
 	<dependencies>

+ 135 - 63
src/main/kotlin/co/id/datacomsolusindo/ipphonebridge/BridgeFIlter.kt

@@ -2,6 +2,7 @@ package co.id.datacomsolusindo.ipphonebridge
 
 import com.fasterxml.jackson.core.type.TypeReference
 import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.databind.ObjectWriter
 import org.apache.commons.io.IOUtils
 import org.apache.logging.log4j.LogManager
 import org.springframework.context.annotation.Configuration
@@ -89,80 +90,114 @@ class BridgeFilter(private val template: SimpMessagingTemplate, val resourceLoad
             if (search != null && !search.endsWith("assets/bootstrap.js")) {
                 res.sendRedirect("/resources/$search")
             } else {
-                if (req.getHeader("User-Agent").contains("(dart:io)") || req.requestURL.toString().endsWith("api/license")) {
-                    val reqId = UUID.randomUUID().toString()
-                    try {
-                        val headerMap = req.headerNames.toList().associateBy({ it }, { req.getHeader(it) })
+//                if (req.getHeader("User-Agent").contains("(dart:io)") || req.requestURL.toString().endsWith("api/license")) {
+                val reqId = UUID.randomUUID().toString()
+                try {
+                    val headerMap = req.headerNames.toList().associateBy({ it }, { req.getHeader(it) })
+                    val rb = RequestBuilder(reqId, toPath, HttpMethod.valueOf(req.method), headerMap.toMutableMap())
+
+                    rb.queryString = req.queryString
+                    if (req.contentType != null && req.contentType.toLowerCase().indexOf("multipart/form-data") > -1) {
+                        rb.parts =
+                                req.parts.map {
+                                    val fb64 = Base64.getEncoder().encodeToString(it.inputStream.readBytes())
+                                    FilePart(it.name, it.submittedFileName, fb64)
+                                }.toMutableList()
+                    } else {
                         val body = req.reader.lines().toList().joinToString(System.lineSeparator())
-
-                        val rb = RequestBuilder(reqId, toPath, HttpMethod.valueOf(req.method), headerMap.toMutableMap())
                         rb.body = body
-                        rb.queryString = req.parameterMap
-                        Singletons.requestInstance[reqId] = RequestQue(reqId, rb, null)
-                        template.convertAndSend("/topic/$client", RequestTrigger(reqId))
-                        template.convertAndSend("/topic/str/$client", rb)
-                        var i = 0
-                        while (Singletons.responseQue[reqId] == null) {
-                            TimeUnit.MILLISECONDS.sleep(100)
-                            i++
-                            if (i >= 600) {
-                                res.status = HttpStatus.REQUEST_TIMEOUT.value()
-                                res.writer.write("{\"message\":\"Request timeout. Client not responding\"}")
-                                res.flushBuffer()
-                                Singletons.requestInstance.remove(reqId)
-                                val endTime = System.nanoTime()
-                                val duration = (endTime - startTime).toDouble() / 1000000 //divide by 1000000 to get milliseconds.
-                                LogManager.getLogger("client.$client").info("Request failed, No Response. Time: $duration  UA: " + req.getHeader("User-Agent") + " From: " + InetAddress.getLocalHost().hostAddress + " To: " + req.requestURL.toString() + "?" + req.queryString)
-
-                                ClientHolder.addFailedRequest(client)
-                                return
-                            }
-                        }
+                    }
 
-                        val resFromSocket = Singletons.responseQue[reqId]
+                    Singletons.requestInstance[reqId] = RequestQue(reqId, rb, null)
+                    val ow: ObjectWriter = ObjectMapper().writer().withDefaultPrettyPrinter()
+                    val partStr = ow.writeValueAsString(rb).chunked(1500)
+
+
+//                    val mid = UUID.randomUUID().toString()
+//                    partStr.forEachIndexed(
+//
+//                    )
+//                    val mList = mutableListOf<Message>()
+//                    partStr.forEachIndexed { i, s ->
+//                        mList.add(Message(mid, s, i + 1, partStr.size))
+//                    }
+//                    Singletons.sendQueue[mid] = mList.sortedBy { it.part }.toMutableList()
+                    //send first
+                    //template.convertAndSend("/topic/request/$client",Singletons.sendQueue[mid]!!.first())
+
+
+                    LogManager.getLogger(this.javaClass).info("part size ${partStr.size}")
+//                    if (partStr.size > 1) {
+                    val partialID = UUID.randomUUID().toString()
+                    val st2 = System.nanoTime()
+                    partStr.forEachIndexed { idx, it ->
+                        template.convertAndSend("/topic/partial/$client", PartialData(partialID, partStr.size, idx + 1, it, st2))
+                    }
 
-                        res.status = resFromSocket!!.statusCode
-                        resFromSocket.headers?.let {
-                            it.entries
-                                    .filter { f -> resFromSocket.statusCode < 400 || (resFromSocket.statusCode >= 400 && f.key == "Content-Type") }
-                                    .forEach { en ->
-                                        res.setHeader(en.key, en.value.joinToString(","))
-                                    }
-                        }
 
-                        resFromSocket.body?.let {
-                            res.outputStream.write(it)
+                    var i = 0
+                    while (Singletons.responseQue[reqId] == null) {
+                        TimeUnit.MILLISECONDS.sleep(100)
+                        i++
+                        if (i >= 600 * partStr.size) {
+                            res.status = HttpStatus.REQUEST_TIMEOUT.value()
+                            res.writer.write("{\"message\":\"Request timeout. Client not responding\"}")
+                            res.flushBuffer()
+                            Singletons.requestInstance.remove(reqId)
+                            val endTime = System.nanoTime()
+                            val duration = (endTime - startTime).toDouble() / 1000000 //divide by 1000000 to get milliseconds.
+                            LogManager.getLogger("client.$client").info("Request failed, No Response. Time: $duration  UA: " + req.getHeader("User-Agent") + " From: " + InetAddress.getLocalHost().hostAddress + " To: " + req.requestURL.toString() + "?" + req.queryString)
+
+                            ClientHolder.addFailedRequest(client)
+                            return
                         }
+                    }
 
-                        res.flushBuffer()
+                    val resFromSocket = Singletons.responseQue[reqId]
 
-                        Singletons.requestInstance.remove(reqId)
-                        val endTime = System.nanoTime()
+                    res.status = resFromSocket!!.statusCode
+                    resFromSocket.headers?.let {
+                        it.entries
+                                .filter { f -> resFromSocket.statusCode < 400 || (resFromSocket.statusCode >= 400 && f.key == "Content-Type") }
+                                .forEach { en ->
+                                    res.setHeader(en.key, en.value.joinToString(","))
+                                }
+                    }
 
-                        val duration = (endTime - startTime).toDouble() / 1000000 //divide by 1000000 to get milliseconds.
-                        LogManager.getLogger("client.$client").info("Request Success. Time: $duration  UA: " + req.getHeader("User-Agent") + " From: " + req.remoteAddr + " To: " + req.requestURL.toString() + "?" + req.queryString)
+                    resFromSocket.body?.let {
+                        res.outputStream.write(it)
+                    }
 
-                        ClientHolder.addSuccessRequest(client, duration)
-                        return
+                    res.flushBuffer()
 
-                    } catch (e: Exception) {
-                        e.printStackTrace()
-                        res.status = HttpStatus.REQUEST_TIMEOUT.value()
-                        res.writer.write("{\"message\":\"Request timeout. Unknown error\"}")
-                        res.flushBuffer()
-                        Singletons.requestInstance.remove(reqId)
-                        val endTime = System.nanoTime()
-                        val duration = (endTime - startTime).toDouble() / 1000000 //divide by 1000000 to get milliseconds.
-                        LogManager.getLogger("client.$client").info("Request failed, Unknown error. Time: $duration  UA: " + req.getHeader("User-Agent") + " From: " + InetAddress.getLocalHost().hostAddress + " To: " + req.requestURL.toString() + "?" + req.queryString)
-                        ClientHolder.addFailedRequest(client)
-                        return
-                    }
+                    Singletons.requestInstance.remove(reqId)
+                    val endTime = System.nanoTime()
 
-                } else {
+                    val duration = (endTime - startTime).toDouble() / 1000000 //divide by 1000000 to get milliseconds.
+                    LogManager.getLogger("client.$client").info("Request Success. Time: $duration  UA: " + req.getHeader("User-Agent") + " From: " + req.remoteAddr + " To: " + req.requestURL.toString() + "?" + req.queryString)
+
+                    ClientHolder.addSuccessRequest(client, duration)
+                    return
 
-                    response.status = HttpStatus.NOT_FOUND.value()
-                    response.getWriter().write("Resource not found")
+
+                } catch (e: Exception) {
+                    e.printStackTrace()
+                    res.status = HttpStatus.REQUEST_TIMEOUT.value()
+                    res.writer.write("{\"message\":\"Request timeout. Unknown error\"}")
+                    res.flushBuffer()
+                    Singletons.requestInstance.remove(reqId)
+                    val endTime = System.nanoTime()
+                    val duration = (endTime - startTime).toDouble() / 1000000 //divide by 1000000 to get milliseconds.
+                    LogManager.getLogger("client.$client").info("Request failed, Unknown error. Time: $duration  UA: " + req.getHeader("User-Agent") + " From: " + InetAddress.getLocalHost().hostAddress + " To: " + req.requestURL.toString() + "?" + req.queryString)
+                    ClientHolder.addFailedRequest(client)
+                    return
                 }
+
+//                } else {
+//
+//                    response.status = HttpStatus.NOT_FOUND.value()
+//                    response.getWriter().write("Resource not found")
+//                }
             }
         }
     }
@@ -182,17 +217,49 @@ class BridgeFilter(private val template: SimpMessagingTemplate, val resourceLoad
 }
 
 class RequestQue(val id: String, val requestBuilder: RequestBuilder, var responseObj: Resp?)
+class PartialData(val id: String, val total: Int, val idx: Int, val data: String, val startTime: Long)
 
-class RequestTrigger(val id: String)
+//class RequestTrigger(val id: String)
 
 class RequestBuilder(val id: String, val path: String, val method: HttpMethod, var headers: MutableMap<String, String>) : Serializable {
     var body: String? = null
-    var queryString: MutableMap<String, Array<String>>? = null
+    var queryString: String? = null
+    var parts: MutableList<FilePart>? = null
 }
 
+class FilePart(val name: String, val fileName: String, val data: String)
+
+//class Message(val id: String, val data: String, val part: Int, val total: Int) : Serializable
+
+//class MessageHandler(val message: Message, template: SimpMessagingTemplate, val onComplete: () -> Unit) {
+//    init {
+//        template.convertAndSend(message)
+//        Thread({
+//            while (!sent.get()) {
+//                Thread.sleep(300)
+//                if (sent.get()) {
+//                    break
+//                } else {
+//                    template.convertAndSend(message)
+//                }
+//            }
+//        }, "sendThread").start()
+//    }
+//
+//    fun complate() {
+//        sent.set(true)
+//        onComplete()
+//    }
+//
+//    private var sent: AtomicBoolean = AtomicBoolean(false)
+//}
+
+
 class Resp(val body: ByteArray?, val statusCode: Int, val headers: Map<String, Array<String>>? = null)
 
+
 object Singletons {
+    //    val sendQueue: ConcurrentMap<String, MessageHandler> by lazy { ConcurrentHashMap<String, MessageHandler>() }
     val responseQue: MutableMap<String, Resp> by lazy { mutableMapOf<String, Resp>() }
     val requestInstance: MutableMap<String, RequestQue> by lazy { mutableMapOf<String, RequestQue>() }
     val buildSocketChunkData: MutableMap<String, ChunkCollector> by lazy { mutableMapOf<String, ChunkCollector>() }
@@ -204,13 +271,16 @@ class ChunkCollector(private val id: String) {
     private val listSocketChunk = mutableListOf<SocketChunkData>()
     fun add(dt: SocketChunkData) {
         if (!listSocketChunk.any { it.part == dt.part }) {
+//            LogManager.getLogger(this.javaClass).info("add chunk")
             listSocketChunk.add(dt)
         }
 
         if (dt.part == dt.totalPart - 1) {
+//            LogManager.getLogger(this.javaClass).info("timer completion")
             val tStart = LocalDateTime.now()
-            fixedRateTimer("timer-$id", false, 0L, 100) {
+            fixedRateTimer("timer-$id", false, 20, 100) {
                 if (listSocketChunk.size == dt.totalPart) {
+//                    LogManager.getLogger(this.javaClass).info("chunk complete")
                     val bodyList = listSocketChunk.sortedBy { it.part }.mapNotNull { it.body }
                     var bd = ByteArray(0)
                     bodyList.forEach { bd += it }
@@ -244,6 +314,8 @@ class SocketChecker {
     @Throws(Exception::class)
     fun responseMsg(message: SocketChunkData, @DestinationVariable("id") id: String): MutableMap<*, *> {
         try {
+            LogManager.getLogger(this.javaClass).info("req sent ${message.part} of ${message.totalPart}")
+
             if (message.totalPart == 1) {
                 Singletons.responseQue[id] = Resp(
                         message.body,