Client Connection: [Auto]Retry Once
if Connection is lost or timed out
This commit is contained in:
parent
19eb6660e1
commit
f4db466b37
@ -19,7 +19,7 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun getStreams(): Pair<DataInputStream, DataOutputStream> {
|
private fun <R> withStreams(retry: Boolean = true, inner: (DataInputStream, DataOutputStream) -> R): R {
|
||||||
val i: DataInputStream
|
val i: DataInputStream
|
||||||
val o: DataOutputStream
|
val o: DataOutputStream
|
||||||
|
|
||||||
@ -40,31 +40,40 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
o = output!!
|
o = output!!
|
||||||
}
|
}
|
||||||
|
|
||||||
return Pair(i, o)
|
return try {
|
||||||
|
inner(i, o)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
if (retry) {
|
||||||
|
println("Got IOException; Retry ${e.message}")
|
||||||
|
close()
|
||||||
|
withStreams(false, inner)
|
||||||
|
} else {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, ConnectionException::class)
|
@Throws(IOException::class, ConnectionException::class)
|
||||||
@Synchronized
|
|
||||||
fun ping() {
|
fun ping() {
|
||||||
val io = getStreams()
|
return withStreams { i, o ->
|
||||||
|
|
||||||
val obj = JsonObject()
|
val obj = JsonObject()
|
||||||
obj.add("ping", JsonObject())
|
obj.add("ping", JsonObject())
|
||||||
|
|
||||||
JsonPackage(obj).write(io.second)
|
JsonPackage(obj).write(o)
|
||||||
|
|
||||||
when (val pkg = Package.read(io.first)) {
|
when (val pkg = Package.read(i)) {
|
||||||
is JsonPackage -> return
|
is JsonPackage -> return@withStreams
|
||||||
is BinaryPackage -> throw ConnectionUnexpectedPacketException()
|
is BinaryPackage -> throw ConnectionUnexpectedPacketException()
|
||||||
is ErrorPackage -> throw ConnectionErrorException(pkg)
|
is ErrorPackage -> throw ConnectionErrorException(pkg)
|
||||||
else -> throw RuntimeException("Unreachable")
|
else -> throw RuntimeException("Unreachable")
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, ConnectionException::class)
|
@Throws(IOException::class, ConnectionException::class)
|
||||||
@Synchronized
|
|
||||||
fun query(query: Array<String>): Array<Texture> {
|
fun query(query: Array<String>): Array<Texture> {
|
||||||
val io = getStreams()
|
return withStreams { i, o ->
|
||||||
|
|
||||||
val obj = JsonObject()
|
val obj = JsonObject()
|
||||||
obj.add("query", {
|
obj.add("query", {
|
||||||
@ -79,12 +88,15 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
inner
|
inner
|
||||||
}())
|
}())
|
||||||
|
|
||||||
JsonPackage(obj).write(io.second)
|
JsonPackage(obj).write(o)
|
||||||
|
|
||||||
when (val pkg = Package.read(io.first)) {
|
when (val pkg = Package.read(i)) {
|
||||||
is JsonPackage -> {
|
is JsonPackage -> {
|
||||||
try {
|
try {
|
||||||
return Gson().fromJson<Array<InternalTexture>>(pkg.content, Array<InternalTexture>::class.java)
|
return@withStreams Gson().fromJson<Array<InternalTexture>>(
|
||||||
|
pkg.content,
|
||||||
|
Array<InternalTexture>::class.java
|
||||||
|
)
|
||||||
.map { tex ->
|
.map { tex ->
|
||||||
tex.toTexture()
|
tex.toTexture()
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
@ -97,11 +109,12 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
else -> throw RuntimeException("Unreachable")
|
else -> throw RuntimeException("Unreachable")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, ConnectionException::class)
|
@Throws(IOException::class, ConnectionException::class)
|
||||||
@Synchronized
|
|
||||||
fun getTextureById(id: UUID): Texture? {
|
fun getTextureById(id: UUID): Texture? {
|
||||||
val io = getStreams()
|
return withStreams { i, o ->
|
||||||
|
|
||||||
|
|
||||||
val obj = JsonObject()
|
val obj = JsonObject()
|
||||||
obj.add("get_texture", {
|
obj.add("get_texture", {
|
||||||
@ -110,11 +123,11 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
inner
|
inner
|
||||||
}())
|
}())
|
||||||
|
|
||||||
JsonPackage(obj).write(io.second)
|
JsonPackage(obj).write(o)
|
||||||
|
|
||||||
when (val pkg = Package.read(io.first)) {
|
when (val pkg = Package.read(i)) {
|
||||||
is JsonPackage -> {
|
is JsonPackage -> {
|
||||||
return if (pkg.content.isJsonNull) {
|
return@withStreams if (pkg.content.isJsonNull) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@ -132,11 +145,11 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, ConnectionException::class)
|
@Throws(IOException::class, ConnectionException::class)
|
||||||
@Synchronized
|
|
||||||
fun getTextureByName(name: String): Texture? {
|
fun getTextureByName(name: String): Texture? {
|
||||||
val io = getStreams()
|
return withStreams { i, o ->
|
||||||
|
|
||||||
val obj = JsonObject()
|
val obj = JsonObject()
|
||||||
obj.add("get_texture", {
|
obj.add("get_texture", {
|
||||||
@ -145,11 +158,11 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
inner
|
inner
|
||||||
}())
|
}())
|
||||||
|
|
||||||
JsonPackage(obj).write(io.second)
|
JsonPackage(obj).write(o)
|
||||||
|
|
||||||
when (val pkg = Package.read(io.first)) {
|
when (val pkg = Package.read(i)) {
|
||||||
is JsonPackage -> {
|
is JsonPackage -> {
|
||||||
return if (pkg.content.isJsonNull) {
|
return@withStreams if (pkg.content.isJsonNull) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@ -165,13 +178,12 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
is ErrorPackage -> throw ConnectionErrorException(pkg)
|
is ErrorPackage -> throw ConnectionErrorException(pkg)
|
||||||
else -> throw RuntimeException("Unreachable")
|
else -> throw RuntimeException("Unreachable")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, ConnectionException::class)
|
@Throws(IOException::class, ConnectionException::class)
|
||||||
@Synchronized
|
|
||||||
fun getTextureFile(hash: Sha256): ByteArray {
|
fun getTextureFile(hash: Sha256): ByteArray {
|
||||||
val io = getStreams()
|
return withStreams { i, o ->
|
||||||
|
|
||||||
val obj = JsonObject()
|
val obj = JsonObject()
|
||||||
obj.add("get_texture_file", {
|
obj.add("get_texture_file", {
|
||||||
@ -180,22 +192,20 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
inner
|
inner
|
||||||
}())
|
}())
|
||||||
|
|
||||||
JsonPackage(obj).write(io.second)
|
JsonPackage(obj).write(o)
|
||||||
|
|
||||||
when (val pkg = Package.read(io.first)) {
|
when (val pkg = Package.read(i)) {
|
||||||
is JsonPackage -> throw ConnectionUnexpectedPacketException()
|
is JsonPackage -> throw ConnectionUnexpectedPacketException()
|
||||||
is BinaryPackage -> return pkg.content
|
is BinaryPackage -> return@withStreams pkg.content
|
||||||
is ErrorPackage -> throw ConnectionErrorException(pkg)
|
is ErrorPackage -> throw ConnectionErrorException(pkg)
|
||||||
else -> throw RuntimeException("Unreachable")
|
else -> throw RuntimeException("Unreachable")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, ConnectionException::class)
|
@Throws(IOException::class, ConnectionException::class)
|
||||||
@Synchronized
|
|
||||||
fun getTexturePreview(hash: Sha256): Image {
|
fun getTexturePreview(hash: Sha256): Image {
|
||||||
val io = getStreams()
|
return withStreams { i, o ->
|
||||||
|
|
||||||
val obj = JsonObject()
|
val obj = JsonObject()
|
||||||
obj.add("get_texture_preview", {
|
obj.add("get_texture_preview", {
|
||||||
val inner = JsonObject()
|
val inner = JsonObject()
|
||||||
@ -204,22 +214,23 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
inner
|
inner
|
||||||
}())
|
}())
|
||||||
|
|
||||||
JsonPackage(obj).write(io.second)
|
JsonPackage(obj).write(o)
|
||||||
|
|
||||||
when (val pkg = Package.read(io.first)) {
|
when (val pkg = Package.read(i)) {
|
||||||
is JsonPackage -> throw ConnectionUnexpectedPacketException()
|
is JsonPackage -> throw ConnectionUnexpectedPacketException()
|
||||||
is BinaryPackage -> {
|
is BinaryPackage -> {
|
||||||
return Image(ByteArrayInputStream(pkg.content))
|
return@withStreams Image(ByteArrayInputStream(pkg.content))
|
||||||
}
|
}
|
||||||
is ErrorPackage -> throw ConnectionErrorException(pkg)
|
is ErrorPackage -> throw ConnectionErrorException(pkg)
|
||||||
else -> throw RuntimeException("Unreachable")
|
else -> throw RuntimeException("Unreachable")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, ConnectionException::class, IllegalArgumentException::class)
|
@Throws(IOException::class, ConnectionException::class, IllegalArgumentException::class)
|
||||||
@Synchronized
|
|
||||||
private fun replaceTexture(old: Texture?, new: Texture?, image: ByteArray?) {
|
private fun replaceTexture(old: Texture?, new: Texture?, image: ByteArray?) {
|
||||||
val io = getStreams()
|
return withStreams { i, o ->
|
||||||
|
|
||||||
|
|
||||||
val obj = JsonObject()
|
val obj = JsonObject()
|
||||||
obj.add("replace_texture", {
|
obj.add("replace_texture", {
|
||||||
@ -237,19 +248,19 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
inner
|
inner
|
||||||
}())
|
}())
|
||||||
|
|
||||||
JsonPackage(obj).write(io.second)
|
JsonPackage(obj).write(o)
|
||||||
|
|
||||||
when (val pkg = Package.read(io.first)) {
|
when (val pkg = Package.read(i)) {
|
||||||
is JsonPackage -> {
|
is JsonPackage -> {
|
||||||
when {
|
when {
|
||||||
pkg.content == JsonPrimitive(true) -> // everthing is fine!
|
pkg.content == JsonPrimitive(true) -> // everthing is fine!
|
||||||
return
|
return@withStreams
|
||||||
image != null -> {
|
image != null -> {
|
||||||
// should be { "get_texture_file": { texture_hash : <Hash> }}
|
// should be { "get_texture_file": { texture_hash : <Hash> }}
|
||||||
// we don't check, since there is no good way to handle it.
|
// we don't check, since there is no good way to handle it.
|
||||||
|
|
||||||
BinaryPackage(image).write(io.second)
|
BinaryPackage(image).write(o)
|
||||||
when (val ipkg = Package.read(io.first)) {
|
when (val ipkg = Package.read(i)) {
|
||||||
is JsonPackage -> {
|
is JsonPackage -> {
|
||||||
if (ipkg.content != JsonPrimitive(true)) {
|
if (ipkg.content != JsonPrimitive(true)) {
|
||||||
// Protokoll Assertion failed
|
// Protokoll Assertion failed
|
||||||
@ -262,7 +273,7 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
ErrorPackage(404, "Texture not found!").write(io.second)
|
ErrorPackage(404, "Texture not found!").write(o)
|
||||||
close() // gets re-opened on next request.
|
close() // gets re-opened on next request.
|
||||||
throw IllegalArgumentException("Image Argument was needed.")
|
throw IllegalArgumentException("Image Argument was needed.")
|
||||||
}
|
}
|
||||||
@ -273,9 +284,9 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
else -> throw RuntimeException("Unreachable")
|
else -> throw RuntimeException("Unreachable")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, ConnectionException::class, IllegalArgumentException::class)
|
@Throws(IOException::class, ConnectionException::class, IllegalArgumentException::class)
|
||||||
@Synchronized
|
|
||||||
fun uploadTexture(texture: Texture, image: ByteArray) {
|
fun uploadTexture(texture: Texture, image: ByteArray) {
|
||||||
if (texture.textureHash != Sha256(image)) {
|
if (texture.textureHash != Sha256(image)) {
|
||||||
throw IllegalArgumentException("Sha256 of Image does not Match with Texture.")
|
throw IllegalArgumentException("Sha256 of Image does not Match with Texture.")
|
||||||
@ -285,7 +296,6 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, ConnectionException::class, IllegalArgumentException::class)
|
@Throws(IOException::class, ConnectionException::class, IllegalArgumentException::class)
|
||||||
@Synchronized
|
|
||||||
fun updateTexture(old: Texture, new: Texture, image: ByteArray) {
|
fun updateTexture(old: Texture, new: Texture, image: ByteArray) {
|
||||||
if (new.textureHash != Sha256(image)) {
|
if (new.textureHash != Sha256(image)) {
|
||||||
throw IllegalArgumentException("Sha256 of Image does not Match with Texture.")
|
throw IllegalArgumentException("Sha256 of Image does not Match with Texture.")
|
||||||
@ -295,14 +305,13 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, ConnectionException::class, IllegalArgumentException::class)
|
@Throws(IOException::class, ConnectionException::class, IllegalArgumentException::class)
|
||||||
@Synchronized
|
|
||||||
fun deleteTexture(texture: Texture) {
|
fun deleteTexture(texture: Texture) {
|
||||||
replaceTexture(texture, null, null)
|
replaceTexture(texture, null, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
@Synchronized
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
|
try {
|
||||||
if (output != null) {
|
if (output != null) {
|
||||||
output!!.close()
|
output!!.close()
|
||||||
output = null
|
output = null
|
||||||
@ -315,6 +324,9 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
|
|||||||
socket!!.close()
|
socket!!.close()
|
||||||
socket = null
|
socket = null
|
||||||
}
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user