| 
					
				 | 
			
			
				@@ -8,8 +8,10 @@ import org.springframework.context.annotation.Configuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.core.Ordered 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.core.annotation.Order 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.core.io.ResourceLoader 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.http.HttpHeaders 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.http.HttpMethod 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.http.HttpStatus 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.messaging.handler.annotation.DestinationVariable 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.messaging.handler.annotation.MessageMapping 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.messaging.handler.annotation.SendTo 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.messaging.simp.SimpMessagingTemplate 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -27,13 +29,14 @@ import java.io.File 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.io.IOException 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.io.Serializable 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.net.InetAddress 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.time.Duration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.time.LocalDateTime 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import java.time.format.DateTimeFormatter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.concurrent.TimeUnit 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import javax.servlet.* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import javax.servlet.http.HttpServletRequest 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import javax.servlet.http.HttpServletResponse 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import kotlin.concurrent.fixedRateTimer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import kotlin.streams.toList 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -96,7 +99,7 @@ class BridgeFilter(private val template: SimpMessagingTemplate, val resourceLoad 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         rb.queryString = req.parameterMap 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         Singletons.requestInstance[reqId] = RequestQue(reqId, rb, null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         template.convertAndSend("/topic/$client", RequestTrigger(reqId)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                        template.convertAndSend("/topic/str/$client", rb) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        template.convertAndSend("/topic/str/$client", rb) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         var i = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         while (Singletons.responseQue[reqId] == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             TimeUnit.MILLISECONDS.sleep(100) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -138,12 +141,13 @@ class BridgeFilter(private val template: SimpMessagingTemplate, val resourceLoad 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        ClientHolder.addSuccessRequest(client, duration) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } catch (e: Exception) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        e.printStackTrace() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         res.status = HttpStatus.REQUEST_TIMEOUT.value() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        res.writer.write("{\"message\":\"Request timeout. Client not responding\"}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        res.writer.write("{\"message\":\"Request timeout. Unknown error\"}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         res.flushBuffer() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         Singletons.requestInstance.remove(reqId) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         val endTime = System.nanoTime() 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -190,8 +194,40 @@ class Resp(val body: ByteArray?, val statusCode: Int, val headers: Map<String, A 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 object Singletons { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     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>() } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class SocketChunkData(val body: ByteArray?, val header: HttpHeaders?, val status: Int, val part: Int, val totalPart: Int) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class ChunkCollector(private val id: String) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private val listSocketChunk = mutableListOf<SocketChunkData>() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fun add(dt: SocketChunkData) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!listSocketChunk.any { it.part == dt.part }) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            listSocketChunk.add(dt) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (dt.part == dt.totalPart - 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            val tStart = LocalDateTime.now() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            fixedRateTimer("timer-$id", false, 0L, 100) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (listSocketChunk.size == dt.totalPart) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    val bodyList = listSocketChunk.sortedBy { it.part }.mapNotNull { it.body } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    var bd = ByteArray(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    bodyList.forEach { bd += it } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    Singletons.responseQue[id] = Resp( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            bd, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            dt.status, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            dt.header?.entries?.map { Pair(it.key, it.value.toTypedArray()) }?.toMap() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    this.cancel() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (Duration.between(tStart, LocalDateTime.now()).toMillis() > 6000) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    this.cancel() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 @Controller 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 class SocketChecker { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -201,6 +237,38 @@ class SocketChecker { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fun greeting(message: MutableMap<*, *>): MutableMap<*, *> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return mutableMapOf(Pair("Hi", "I'am Ok")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @MessageMapping("/response/{id}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @SendTo("/topic/healthCheck") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Throws(Exception::class) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fun responseMsg(message: SocketChunkData, @DestinationVariable("id") id: String): MutableMap<*, *> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            println(message.body) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            println(message.header) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            println(message.status) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            println(message.part) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            println(message.totalPart) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (message.totalPart == 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Singletons.responseQue[id] = Resp( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        message.body, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        message.status, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        message.header?.entries?.map { Pair(it.key, it.value.toTypedArray()) }?.toMap() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var sc = Singletons.buildSocketChunkData[id] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (sc == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    Singletons.buildSocketChunkData[id] = ChunkCollector(id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    sc = Singletons.buildSocketChunkData[id] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                sc?.add(message) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (e: Exception) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            e.printStackTrace() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return mutableMapOf(Pair("Hi", "I'am Ok")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 @RestController 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -235,6 +303,7 @@ class BridgeRestController { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fun getClientData(): Map<String, Client> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return ClientHolder.get() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @GetMapping("/clientStat/{id}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fun getClientDataOne(@PathVariable("id") id: String): Client? { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return ClientHolder.get()[id] 
			 |