-
-
Proxy Manager
-
-
-
-
-
Proxy Details
-
-
- Location: {location}
-
+
+
+
+ Proxy Manager
+
+ ProxyManager only supports SOCKS5 proxies.
+ This is a prototype design for testing purposes and is NOT the final design.
+
+
+
+
Proxies
+
+
+ Host |
+ Port |
+ Auth |
+ Actions |
+
+
+ None |
+ |
+
+ {#each proxies as proxy (proxy.id)}
+
+ {proxy.host} |
+ {proxy.port} |
+ {#if proxy.username.length > 0}
+ 🔒 |
+ {:else}
+ 🔓 |
+ {/if}
+
+
+
+
+ |
+
+ {/each}
+
-
-
-
-
+
+
+
Add New Proxy
+
+
+
+
+
Current Proxy
+
{currentProxy ? currentProxy : 'No active proxy'}
+
Location: {currentLocation}
+
+
+
+
diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/misc/ProxyManager.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/misc/ProxyManager.kt
index 49c6e3ecc90..0c0d79499be 100644
--- a/src/main/kotlin/net/ccbluex/liquidbounce/features/misc/ProxyManager.kt
+++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/misc/ProxyManager.kt
@@ -23,10 +23,12 @@ import io.netty.handler.proxy.Socks5ProxyHandler
import net.ccbluex.liquidbounce.api.IpInfoApi
import net.ccbluex.liquidbounce.config.ConfigSystem
import net.ccbluex.liquidbounce.config.Configurable
+import net.ccbluex.liquidbounce.config.ListValueType
import net.ccbluex.liquidbounce.event.Listenable
import net.ccbluex.liquidbounce.event.events.PipelineEvent
import net.ccbluex.liquidbounce.event.handler
-import net.ccbluex.liquidbounce.script.ScriptApi
+import net.ccbluex.liquidbounce.features.misc.ProxyManager.Proxy.Companion.NO_PROXY
+import net.ccbluex.liquidbounce.features.misc.ProxyManager.ProxyCredentials.Companion.credentialsFromUserInput
import java.net.InetSocketAddress
/**
@@ -36,15 +38,12 @@ import java.net.InetSocketAddress
*/
object ProxyManager : Configurable("proxy"), Listenable {
- private val noProxy = Proxy("", 0, null)
- var proxy by value("proxy", noProxy)
+ var proxy by value("proxy", NO_PROXY)
+ val proxies by value(name, mutableListOf
(), listType = ListValueType.Proxy)
/**
* The proxy that is set in the current session and used for all server connections
- *
- * !! DO NOT CHANGE IT TO PRIVATE AS IT IS USED BY THE ULTRALIGHT GUI. !!
*/
- @ScriptApi
val currentProxy
get() = proxy.takeIf { it.host.isNotBlank() }
@@ -52,24 +51,28 @@ object ProxyManager : Configurable("proxy"), Listenable {
ConfigSystem.root(this)
}
- fun setProxy(host: String, port: Int, username: String, password: String) {
- proxy = Proxy(host, port,
- if (username.isNotBlank())
- ProxyCredentials(username, password)
- else
- null
- )
+ fun addProxy(host: String, port: Int, username: String = "", password: String = "") {
+ proxies.add(Proxy(host, port, credentialsFromUserInput(username, password)))
ConfigSystem.storeConfigurable(this)
+ }
- // Refreshes local IP info when proxy is set
- IpInfoApi.refreshLocalIpInfo()
+ fun removeProxy(index: Int) {
+ proxies.removeAt(index)
+ ConfigSystem.storeConfigurable(this)
+ }
+
+ fun setProxy(index: Int) {
+ proxy = proxies[index]
+ sync()
}
fun unsetProxy() {
- proxy = noProxy
- ConfigSystem.storeConfigurable(this)
+ proxy = NO_PROXY
+ sync()
+ }
- // Refreshes local IP info when proxy is unset
+ private fun sync() {
+ ConfigSystem.storeConfigurable(this)
IpInfoApi.refreshLocalIpInfo()
}
@@ -103,11 +106,24 @@ object ProxyManager : Configurable("proxy"), Listenable {
data class Proxy(val host: String, val port: Int, val credentials: ProxyCredentials?) {
val address
get() = InetSocketAddress(host, port)
+
+ companion object {
+ val NO_PROXY = Proxy("", 0, null)
+ }
+
}
/**
* Contains serializable proxy credentials
*/
- data class ProxyCredentials(val username: String, val password: String)
+ data class ProxyCredentials(val username: String, val password: String) {
+ companion object {
+ fun credentialsFromUserInput(username: String, password: String) =
+ if (username.isNotBlank() && password.isNotBlank())
+ ProxyCredentials(username, password)
+ else
+ null
+ }
+ }
}
diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/web/socket/protocol/rest/client/ProxyRest.kt b/src/main/kotlin/net/ccbluex/liquidbounce/web/socket/protocol/rest/client/ProxyRest.kt
index a617d297809..d4e1e888b17 100644
--- a/src/main/kotlin/net/ccbluex/liquidbounce/web/socket/protocol/rest/client/ProxyRest.kt
+++ b/src/main/kotlin/net/ccbluex/liquidbounce/web/socket/protocol/rest/client/ProxyRest.kt
@@ -19,6 +19,7 @@
*/
package net.ccbluex.liquidbounce.web.socket.protocol.rest.client
+import com.google.gson.JsonArray
import com.google.gson.JsonObject
import net.ccbluex.liquidbounce.config.util.decode
import net.ccbluex.liquidbounce.features.misc.ProxyManager
@@ -28,15 +29,13 @@ import net.ccbluex.liquidbounce.web.socket.netty.rest.RestNode
/**
* Proxy endpoints
- *
- * TODO: These need to be reworked since we are going to use a proxy pool in the future
- * similar to the account pool
*/
internal fun RestNode.proxyRest() {
get("/proxy") {
val proxyObject = JsonObject()
ProxyManager.currentProxy?.let {
+ proxyObject.addProperty("id", ProxyManager.proxies.indexOf(it))
proxyObject.addProperty("host", it.host)
proxyObject.addProperty("port", it.port)
proxyObject.addProperty("username", it.credentials?.username)
@@ -46,24 +45,66 @@ internal fun RestNode.proxyRest() {
httpOk(proxyObject)
}
- post("/proxy") {
+ delete("/proxy") {
+ ProxyManager.unsetProxy()
+ httpOk(JsonObject())
+ }
+
+ get("/proxies") {
+ val proxiesArray = JsonArray()
+
+ ProxyManager.proxies.forEachIndexed { index, proxy ->
+ val proxyObject = JsonObject()
+ proxyObject.addProperty("id", index)
+ proxyObject.addProperty("host", proxy.host)
+ proxyObject.addProperty("port", proxy.port)
+ proxyObject.addProperty("username", proxy.credentials?.username)
+ proxyObject.addProperty("password", proxy.credentials?.password)
+ proxiesArray.add(proxyObject)
+ }
+
+ httpOk(proxiesArray)
+ }
+
+ post("/proxies") {
data class ProxyRequest(val host: String, val port: Int, val username: String, val password: String)
val body = decode(it.content)
- if (body.host.isBlank())
+ if (body.host.isBlank()) {
return@post httpForbidden("No host")
+ }
- if (body.port <= 0)
+ if (body.port <= 0) {
return@post httpForbidden("No port")
+ }
- ProxyManager.setProxy(body.host, body.port, body.username, body.password)
+ ProxyManager.addProxy(body.host, body.port, body.username, body.password)
+ httpOk(JsonObject())
+ }
+
+ delete("/proxies") {
+ data class ProxyRequest(val id: Int)
+ val body = decode(it.content)
+ if (body.id < 0 || body.id >= ProxyManager.proxies.size) {
+ return@delete httpForbidden("Invalid id")
+ }
+
+ ProxyManager.removeProxy(body.id)
httpOk(JsonObject())
}
- delete("/proxy") {
- ProxyManager.unsetProxy()
+ put("/proxies") {
+ data class ProxyRequest(val id: Int)
+ val body = decode(it.content)
+
+ if (body.id < 0 || body.id >= ProxyManager.proxies.size) {
+ return@put httpForbidden("Invalid id")
+ }
+
+ ProxyManager.setProxy(body.id)
httpOk(JsonObject())
}
+
}