Fix communication issues devportal

This commit is contained in:
Kelvin 2023-11-16 17:13:23 +01:00
commit 7fa80ec048
5 changed files with 75 additions and 24 deletions

View file

@ -7,13 +7,15 @@ import com.futo.platformplayer.api.media.Serializer
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import java.io.BufferedInputStream
import java.io.BufferedReader import java.io.BufferedReader
import java.io.OutputStream import java.io.OutputStream
import java.io.StringWriter import java.io.StringWriter
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
import java.nio.ByteBuffer
class HttpContext : AutoCloseable { class HttpContext : AutoCloseable {
private val _stream: BufferedReader; private val _stream: BufferedInputStream;
private var _responseStream: OutputStream? = null; private var _responseStream: OutputStream? = null;
var id: String? = null; var id: String? = null;
@ -38,14 +40,40 @@ class HttpContext : AutoCloseable {
private val _responseHeaders: HttpHeaders = HttpHeaders(); private val _responseHeaders: HttpHeaders = HttpHeaders();
private val newLineByte = "\n"[0];
private fun readStreamLine(): String {
//TODO: This is not ideal..
var twoByteArray = ByteBuffer.allocate(2);
var lastChar: Char = Char.MIN_VALUE;
val builder = StringBuilder();
do {
val firstByte = _stream.read();
if(firstByte == -1)
break;
if(isCharacter2Bytes(firstByte)) {
twoByteArray.put(0, firstByte.toByte());
val secondByte = _stream.read();
if(secondByte == -1)
break;
twoByteArray.put(1, secondByte.toByte());
}
else
lastChar = firstByte.toChar();
builder.append(lastChar);
if(lastChar == newLineByte)
break;
}
while(lastChar != Char.MIN_VALUE);
return builder.toString();
}
constructor(stream: BufferedReader, responseStream: OutputStream? = null, requestId: String? = null, timeout: Int? = null) { constructor(stream: BufferedInputStream, responseStream: OutputStream? = null, requestId: String? = null, timeout: Int? = null) {
_stream = stream; _stream = stream;
_responseStream = responseStream; _responseStream = responseStream;
this.id = requestId; this.id = requestId;
try { try {
head = stream.readLine() ?: throw EmptyRequestException("No head found"); head = readStreamLine() ?: throw EmptyRequestException("No head found");
} }
catch(ex: SocketTimeoutException) { catch(ex: SocketTimeoutException) {
if((timeout ?: 0) > 0) if((timeout ?: 0) > 0)
@ -78,7 +106,7 @@ class HttpContext : AutoCloseable {
} }
while (true) { while (true) {
val line = stream.readLine(); val line = readStreamLine();
val headerEndIndex = line.indexOf(":"); val headerEndIndex = line.indexOf(":");
if (headerEndIndex == -1) if (headerEndIndex == -1)
break; break;
@ -172,27 +200,37 @@ class HttpContext : AutoCloseable {
statusCode = status; statusCode = status;
} }
fun readContentBytes(buffer: CharArray, length: Int) : Int { fun readContentBytes(buffer: ByteArray, length: Int) : Int {
val reading = Math.min(length, (contentLength - _totalRead).toInt()); val reading = if(contentLength - _totalRead < length)
(contentLength - _totalRead).toInt();
else
length;
val read = _stream.read(buffer, 0, reading); val read = _stream.read(buffer, 0, reading);
_totalRead += read; _totalRead += read;
//TODO: Fix this properly
if(contentLength - _totalRead < 400 && read < length) {
_totalRead = contentLength;
}
return read; return read;
} }
fun readContentString() : String{ fun readContentString() : String{
val writer = StringWriter(); val writer = StringWriter();
var read = 0; var read = 0;
val buffer = CharArray(4096); val buffer = ByteArray(8192);
val twoByteArray = ByteArray(2);
do { do {
read = readContentBytes(buffer, buffer.size); read = readContentBytes(buffer, buffer.size);
writer.write(buffer, 0, read);
} while(read > 0);// && _stream.ready()); if(read > 0) {
//if(!_stream.ready()) if (isCharacter2Bytes(buffer[read - 1].toInt())) {
// _totalRead = contentLength; //Fixes overlapping buffers
writer.write(String(buffer, 0, read - 1));
twoByteArray[0] = buffer[read - 1];
val secondByte = _stream.read();
if (secondByte < 0)
break;
twoByteArray[1] = secondByte.toByte();
writer.write(String(twoByteArray));
} else
writer.write(String(buffer, 0, read));
}
} while(read > 0);
return writer.toString(); return writer.toString();
} }
inline fun <reified T> readContentJson() : T { inline fun <reified T> readContentJson() : T {
@ -210,6 +248,10 @@ class HttpContext : AutoCloseable {
} }
} }
private fun isCharacter2Bytes(firstByte: Int): Boolean {
return firstByte and 0xE0 == 0xC0
}
companion object { companion object {
private val TAG = "HttpRequest"; private val TAG = "HttpRequest";
private val statusCodeMap = mapOf( private val statusCodeMap = mapOf(

View file

@ -5,8 +5,7 @@ import com.futo.platformplayer.api.http.ManagedHttpClient
import com.futo.platformplayer.api.http.server.exceptions.EmptyRequestException import com.futo.platformplayer.api.http.server.exceptions.EmptyRequestException
import com.futo.platformplayer.api.http.server.handlers.HttpFuntionHandler import com.futo.platformplayer.api.http.server.handlers.HttpFuntionHandler
import com.futo.platformplayer.api.http.server.handlers.HttpHandler import com.futo.platformplayer.api.http.server.handlers.HttpHandler
import java.io.BufferedReader import java.io.BufferedInputStream
import java.io.InputStreamReader
import java.io.OutputStream import java.io.OutputStream
import java.lang.reflect.Field import java.lang.reflect.Field
import java.lang.reflect.Method import java.lang.reflect.Method
@ -76,12 +75,12 @@ class ManagedHttpServer(private val _requestedPort: Int = 0) {
private fun handleClientRequest(socket: Socket) { private fun handleClientRequest(socket: Socket) {
_workerPool?.submit { _workerPool?.submit {
val requestReader = BufferedReader(InputStreamReader(socket.getInputStream())) val requestStream = BufferedInputStream(socket.getInputStream());
val responseStream = socket.getOutputStream(); val responseStream = socket.getOutputStream();
val requestId = UUID.randomUUID().toString().substring(0, 5); val requestId = UUID.randomUUID().toString().substring(0, 5);
try { try {
keepAliveLoop(requestReader, responseStream, requestId) { req -> keepAliveLoop(requestStream, responseStream, requestId) { req ->
req.use { httpContext -> req.use { httpContext ->
if(!httpContext.path.startsWith("/plugin/")) if(!httpContext.path.startsWith("/plugin/"))
Logger.i(TAG, "[${req.id}] ${httpContext.method}: ${httpContext.path}") Logger.i(TAG, "[${req.id}] ${httpContext.method}: ${httpContext.path}")
@ -107,7 +106,7 @@ class ManagedHttpServer(private val _requestedPort: Int = 0) {
Logger.e(TAG, "Failed to handle client request.", e); Logger.e(TAG, "Failed to handle client request.", e);
} }
finally { finally {
requestReader.close(); requestStream.close();
responseStream.close(); responseStream.close();
} }
}; };
@ -188,7 +187,7 @@ class ManagedHttpServer(private val _requestedPort: Int = 0) {
} }
} }
private fun keepAliveLoop(requestReader: BufferedReader, responseStream: OutputStream, requestId: String, handler: (HttpContext)->Unit) { private fun keepAliveLoop(requestReader: BufferedInputStream, responseStream: OutputStream, requestId: String, handler: (HttpContext)->Unit) {
val stopCount = _stopCount; val stopCount = _stopCount;
var keepAlive = false; var keepAlive = false;
var requestsMax = 0; var requestsMax = 0;
@ -200,7 +199,7 @@ class ManagedHttpServer(private val _requestedPort: Int = 0) {
handler(req); handler(req);
requestsTotal++; requestsTotal++;
if(req.keepAlive){// && requestReader.ready()) { if(req.keepAlive) {
keepAlive = true; keepAlive = true;
if(req.keepAliveMax > 0) if(req.keepAliveMax > 0)
requestsMax = req.keepAliveMax; requestsMax = req.keepAliveMax;

View file

@ -301,7 +301,7 @@ class DeveloperEndpoints(private val context: Context) {
if(method != "isLoggedIn") if(method != "isLoggedIn")
Logger.i(TAG, "Remote Call [${objId}].${method}(...)"); Logger.i(TAG, "Remote Call [${objId}].${method}(...)");
val parameters = context.readContentString(); //TODO: Temporary val parameters = context.readContentString();
val remoteObj = getRemoteObject(objId); val remoteObj = getRemoteObject(objId);
val paras = JsonParser.parseString(parameters); val paras = JsonParser.parseString(parameters);

View file

@ -0,0 +1,5 @@
package com.futo.platformplayer.stores.db
class ManagedDBIndex {
}

View file

@ -0,0 +1,5 @@
package com.futo.platformplayer.stores.db
class ManagedDBStore {
}