|
@@ -2,6 +2,7 @@ package co.id.datacomsolusindo.ipphonebridge
|
|
|
|
|
|
import com.fasterxml.jackson.core.type.TypeReference
|
|
import com.fasterxml.jackson.core.type.TypeReference
|
|
import com.fasterxml.jackson.databind.ObjectMapper
|
|
import com.fasterxml.jackson.databind.ObjectMapper
|
|
|
|
+import com.fasterxml.jackson.databind.ObjectWriter
|
|
import org.apache.commons.io.IOUtils
|
|
import org.apache.commons.io.IOUtils
|
|
import org.apache.logging.log4j.LogManager
|
|
import org.apache.logging.log4j.LogManager
|
|
import org.springframework.context.annotation.Configuration
|
|
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")) {
|
|
if (search != null && !search.endsWith("assets/bootstrap.js")) {
|
|
res.sendRedirect("/resources/$search")
|
|
res.sendRedirect("/resources/$search")
|
|
} else {
|
|
} 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 body = req.reader.lines().toList().joinToString(System.lineSeparator())
|
|
-
|
|
|
|
- val rb = RequestBuilder(reqId, toPath, HttpMethod.valueOf(req.method), headerMap.toMutableMap())
|
|
|
|
rb.body = body
|
|
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 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 {
|
|
class RequestBuilder(val id: String, val path: String, val method: HttpMethod, var headers: MutableMap<String, String>) : Serializable {
|
|
var body: String? = null
|
|
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)
|
|
class Resp(val body: ByteArray?, val statusCode: Int, val headers: Map<String, Array<String>>? = null)
|
|
|
|
|
|
|
|
+
|
|
object Singletons {
|
|
object Singletons {
|
|
|
|
+ // val sendQueue: ConcurrentMap<String, MessageHandler> by lazy { ConcurrentHashMap<String, MessageHandler>() }
|
|
val responseQue: MutableMap<String, Resp> by lazy { mutableMapOf<String, Resp>() }
|
|
val responseQue: MutableMap<String, Resp> by lazy { mutableMapOf<String, Resp>() }
|
|
val requestInstance: MutableMap<String, RequestQue> by lazy { mutableMapOf<String, RequestQue>() }
|
|
val requestInstance: MutableMap<String, RequestQue> by lazy { mutableMapOf<String, RequestQue>() }
|
|
val buildSocketChunkData: MutableMap<String, ChunkCollector> by lazy { mutableMapOf<String, ChunkCollector>() }
|
|
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>()
|
|
private val listSocketChunk = mutableListOf<SocketChunkData>()
|
|
fun add(dt: SocketChunkData) {
|
|
fun add(dt: SocketChunkData) {
|
|
if (!listSocketChunk.any { it.part == dt.part }) {
|
|
if (!listSocketChunk.any { it.part == dt.part }) {
|
|
|
|
+// LogManager.getLogger(this.javaClass).info("add chunk")
|
|
listSocketChunk.add(dt)
|
|
listSocketChunk.add(dt)
|
|
}
|
|
}
|
|
|
|
|
|
if (dt.part == dt.totalPart - 1) {
|
|
if (dt.part == dt.totalPart - 1) {
|
|
|
|
+// LogManager.getLogger(this.javaClass).info("timer completion")
|
|
val tStart = LocalDateTime.now()
|
|
val tStart = LocalDateTime.now()
|
|
- fixedRateTimer("timer-$id", false, 0L, 100) {
|
|
|
|
|
|
+ fixedRateTimer("timer-$id", false, 20, 100) {
|
|
if (listSocketChunk.size == dt.totalPart) {
|
|
if (listSocketChunk.size == dt.totalPart) {
|
|
|
|
+// LogManager.getLogger(this.javaClass).info("chunk complete")
|
|
val bodyList = listSocketChunk.sortedBy { it.part }.mapNotNull { it.body }
|
|
val bodyList = listSocketChunk.sortedBy { it.part }.mapNotNull { it.body }
|
|
var bd = ByteArray(0)
|
|
var bd = ByteArray(0)
|
|
bodyList.forEach { bd += it }
|
|
bodyList.forEach { bd += it }
|
|
@@ -244,6 +314,8 @@ class SocketChecker {
|
|
@Throws(Exception::class)
|
|
@Throws(Exception::class)
|
|
fun responseMsg(message: SocketChunkData, @DestinationVariable("id") id: String): MutableMap<*, *> {
|
|
fun responseMsg(message: SocketChunkData, @DestinationVariable("id") id: String): MutableMap<*, *> {
|
|
try {
|
|
try {
|
|
|
|
+ LogManager.getLogger(this.javaClass).info("req sent ${message.part} of ${message.totalPart}")
|
|
|
|
+
|
|
if (message.totalPart == 1) {
|
|
if (message.totalPart == 1) {
|
|
Singletons.responseQue[id] = Resp(
|
|
Singletons.responseQue[id] = Resp(
|
|
message.body,
|
|
message.body,
|