Added new JS5 file server (launcher no longer has to handle cache downloading) - PLEASE SET YOUR CACHE LOCATION IN file-server.properties
Updated client to connect to the new file server
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
package js5server
|
||||
|
||||
import com.displee.cache.CacheLibrary
|
||||
import io.ktor.utils.io.*
|
||||
import js5server.ext.readUMedium
|
||||
import kotlin.math.min
|
||||
|
||||
class FileServer(
|
||||
private val provider: DataProvider,
|
||||
private val versionTable: ByteArray
|
||||
) {
|
||||
|
||||
/**
|
||||
* Fulfills a request by sending the requested files data to the requester
|
||||
*/
|
||||
suspend fun fulfill(read: ByteReadChannel, write: ByteWriteChannel, prefetch: Boolean) {
|
||||
val value = read.readUMedium()
|
||||
val index = value shr 16
|
||||
val archive = value and 0xffff
|
||||
val data = data(index, archive) ?: return println("Unable to fulfill request $index $archive $prefetch.")
|
||||
if (index == 255 && archive == 255) {
|
||||
serve255(write, data)
|
||||
} else {
|
||||
serve(write, index, archive, data, prefetch)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return data for an [index]'s [archive] file or [versionTable] when index and archive are both 255
|
||||
*/
|
||||
fun data(index: Int, archive: Int): ByteArray? {
|
||||
if (index == 255 && archive == 255) {
|
||||
return versionTable
|
||||
}
|
||||
return provider.data(index, archive)
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes [source] [offset] [size] to [write] and starting at [headerSize] inserting a [SEPARATOR] every [split] bytes
|
||||
*/
|
||||
private suspend fun serve255(write: ByteWriteChannel, source: ByteArray) {
|
||||
write.writeByte(255)
|
||||
write.writeShort(255)
|
||||
write.writeByte(0)
|
||||
write.writeInt(source.size)
|
||||
write.writeFully(source)
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes response header followed by the contents of [data] to [write]
|
||||
*/
|
||||
suspend fun serve(write: ByteWriteChannel, index: Int, archive: Int, data: ByteArray, prefetch: Boolean) {
|
||||
val compression = data[0].toInt()
|
||||
val size = getInt(data[1], data[2], data[3], data[4]) + if (compression != 0) 8 else 4
|
||||
write.writeByte(index)
|
||||
write.writeShort(archive)
|
||||
write.writeByte(if (prefetch) compression or 0x80 else compression)
|
||||
serve(write, HEADER, data, OFFSET, size, SPLIT)
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes [source] [offset] [size] to [write] and starting at [headerSize] inserting a [SEPARATOR] every [split] bytes
|
||||
*/
|
||||
suspend fun serve(write: ByteWriteChannel, headerSize: Int, source: ByteArray, offset: Int, size: Int, split: Int) {
|
||||
var length = min(size, split - headerSize)
|
||||
write.writeFully(source, offset, length)
|
||||
var written = length
|
||||
while (written < size) {
|
||||
write.writeByte(SEPARATOR)
|
||||
|
||||
length = if (size - written < split) size - written else split - 1
|
||||
write.writeFully(source, written + offset, length)
|
||||
written += length
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private fun getInt(b1: Byte, b2: Byte, b3: Byte, b4: Byte) = b1.toInt() shl 24 or (b2.toInt() and 0xff shl 16) or (b3.toInt() and 0xff shl 8) or (b4.toInt() and 0xff)
|
||||
|
||||
private const val SEPARATOR = 255
|
||||
private const val HEADER = 4
|
||||
private const val SPLIT = 512
|
||||
private const val OFFSET = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Length of archive with [name] in [index]
|
||||
*/
|
||||
fun file(cacheLibrary: CacheLibrary, index: Int, name: String): Int {
|
||||
val idx = cacheLibrary.index(index)
|
||||
val archive = idx.archiveId(name)
|
||||
if (archive == -1) {
|
||||
return 0
|
||||
}
|
||||
return (idx.readArchiveSector(archive)?.size ?: 2) - 2
|
||||
}
|
||||
|
||||
/**
|
||||
* Length of all archives in [index]
|
||||
*/
|
||||
fun archive(cache: CacheLibrary, index: Int): Int {
|
||||
var total = 0
|
||||
val idx = cache.index(index)
|
||||
idx.archiveIds().forEach { archive ->
|
||||
total += idx.readArchiveSector(archive)?.size ?: 0
|
||||
}
|
||||
total += cache.index255?.readArchiveSector(index)?.size ?: 0
|
||||
return total
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user