cleanups
This commit is contained in:
parent
70ed4185fd
commit
aecc8c5973
4 changed files with 32 additions and 62 deletions
|
@ -32,48 +32,31 @@ class UpnpController(
|
||||||
@PathVariable("uid") uid: String,
|
@PathVariable("uid") uid: String,
|
||||||
request: HttpServletRequest
|
request: HttpServletRequest
|
||||||
): Resource {
|
): Resource {
|
||||||
logger.info { "GET ICON request from ${request.remoteAddr}: ${request.requestURI}" }
|
logger.info { "GET icon request from ${request.remoteAddr}: ${request.requestURI}" }
|
||||||
return InputStreamResource(MediaServer.iconResource());
|
return InputStreamResource(MediaServer.iconResource());
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(
|
@RequestMapping(
|
||||||
method = [GET, HEAD], value = [
|
method = [GET, HEAD, POST], value = [
|
||||||
"/dev/{uid}/desc",
|
"/dev/{uid}/desc",
|
||||||
"/dev/{uid}/svc/upnp-org/ContentDirectory/desc",
|
"/dev/{uid}/svc/upnp-org/ContentDirectory/desc",
|
||||||
"/dev/{uid}/svc/upnp-org/ConnectionManager/desc"
|
"/dev/{uid}/svc/upnp-org/ConnectionManager/desc",
|
||||||
],
|
|
||||||
produces = ["application/xml;charset=utf8", "text/xml;charset=utf8"]
|
|
||||||
)
|
|
||||||
fun handleGet(
|
|
||||||
@PathVariable("uid") uid: String,
|
|
||||||
request: HttpServletRequest
|
|
||||||
): ResponseEntity<Any> {
|
|
||||||
logger.info { "GET request from ${request.remoteAddr}: ${request.requestURI}" }
|
|
||||||
val r = upnpStreamProcessor.processMessage(streamRequestMapper.map(request))
|
|
||||||
return ResponseEntity(
|
|
||||||
r.body,
|
|
||||||
HttpHeaders().also { h -> r.headers.entries.forEach { h.add(it.key, it.value.joinToString { it }) } },
|
|
||||||
HttpStatusCode.valueOf(r.operation.statusCode)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(
|
|
||||||
method = [POST], value = [
|
|
||||||
"/dev/{uid}/svc/upnp-org/ContentDirectory/action"
|
"/dev/{uid}/svc/upnp-org/ContentDirectory/action"
|
||||||
],
|
],
|
||||||
produces = ["application/xml;charset=utf8", "text/xml;charset=utf8"]
|
produces = ["application/xml;charset=utf8", "text/xml;charset=utf8"]
|
||||||
)
|
)
|
||||||
fun handlePost(
|
fun handleUpnp(
|
||||||
@PathVariable("uid") uid: String,
|
@PathVariable("uid") uid: String,
|
||||||
request: HttpServletRequest
|
request: HttpServletRequest
|
||||||
): ResponseEntity<Any> {
|
): ResponseEntity<Any> {
|
||||||
logger.info { "POST request from ${request.remoteAddr}: ${request.requestURI}" }
|
logger.info { "Upnp ${request.method} request from ${request.remoteAddr}: ${request.requestURI}" }
|
||||||
val r = upnpStreamProcessor.processMessage(streamRequestMapper.map(request))
|
return with(upnpStreamProcessor.processMessage(streamRequestMapper.map(request))) {
|
||||||
return ResponseEntity(
|
ResponseEntity(
|
||||||
r.body,
|
body,
|
||||||
HttpHeaders().also { h -> r.headers.entries.forEach { h.add(it.key, it.value.joinToString { it }) } },
|
HttpHeaders().also { h -> headers.entries.forEach { e -> h.add(e.key, e.value.joinToString { it }) } },
|
||||||
HttpStatusCode.valueOf(r.operation.statusCode)
|
HttpStatusCode.valueOf(operation.statusCode)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : KLogging()
|
companion object : KLogging()
|
||||||
|
|
|
@ -14,7 +14,7 @@ import java.util.function.Consumer
|
||||||
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
class MediaDB(
|
class NextcloudDB(
|
||||||
private val nextcloudConfig: NextcloudConfigDiscovery,
|
private val nextcloudConfig: NextcloudConfigDiscovery,
|
||||||
private val mimetypeRepository: MimetypeRepository,
|
private val mimetypeRepository: MimetypeRepository,
|
||||||
private val filecacheRepository: FilecacheRepository,
|
private val filecacheRepository: FilecacheRepository,
|
|
@ -1,25 +1,26 @@
|
||||||
package net.schowek.nextclouddlna.nextcloud.content
|
package net.schowek.nextclouddlna.nextcloud.content
|
||||||
|
|
||||||
import jakarta.annotation.PostConstruct
|
|
||||||
import mu.KLogging
|
import mu.KLogging
|
||||||
import net.schowek.nextclouddlna.nextcloud.MediaDB
|
import net.schowek.nextclouddlna.nextcloud.NextcloudDB
|
||||||
import org.springframework.scheduling.annotation.Scheduled
|
import org.springframework.scheduling.annotation.Scheduled
|
||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
|
import java.time.Instant
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
class ContentTreeProvider(
|
class ContentTreeProvider(
|
||||||
private val mediaDB: MediaDB
|
private val nextcloudDB: NextcloudDB
|
||||||
) {
|
) {
|
||||||
private var tree = buildContentTree()
|
private var tree = buildContentTree()
|
||||||
private var lastMTime = 0L
|
private var lastMTime = 0L
|
||||||
|
|
||||||
@Scheduled(fixedDelay = 1000 * 60, initialDelay = 1000 * 60)
|
@Scheduled(fixedDelay = REBUILD_TREE_DELAY_IN_MS, initialDelay = REBUILD_TREE_INIT_DELAY_IN_MS)
|
||||||
final fun rebuildTree() {
|
final fun rebuildTree() {
|
||||||
val maxMtime: Long = mediaDB.maxMtime()
|
val maxMtime: Long = nextcloudDB.maxMtime()
|
||||||
if (lastMTime < maxMtime) {
|
val now = Instant.now().epochSecond
|
||||||
|
if (lastMTime < maxMtime || lastMTime + MAX_REBUILD_OFFSET_IN_S > now) {
|
||||||
logger.info("ContentTree seems to be outdated - Loading...")
|
logger.info("ContentTree seems to be outdated - Loading...")
|
||||||
this.tree = buildContentTree()
|
this.tree = buildContentTree()
|
||||||
lastMTime = maxMtime
|
lastMTime = maxMtime
|
||||||
|
@ -30,12 +31,12 @@ class ContentTreeProvider(
|
||||||
val tree = ContentTree()
|
val tree = ContentTree()
|
||||||
val root = ContentNode(0, -1, "ROOT")
|
val root = ContentNode(0, -1, "ROOT")
|
||||||
tree.addNode(root)
|
tree.addNode(root)
|
||||||
mediaDB.mainNodes().forEach { n ->
|
nextcloudDB.mainNodes().forEach { n ->
|
||||||
root.addNode(n)
|
root.addNode(n)
|
||||||
fillNode(n, tree)
|
fillNode(n, tree)
|
||||||
}
|
}
|
||||||
logger.info("Getting content from group folders...")
|
logger.info("Getting content from group folders...")
|
||||||
mediaDB.groupFolders().forEach { n ->
|
nextcloudDB.groupFolders().forEach { n ->
|
||||||
logger.info(" Group folder found: {}", n.name)
|
logger.info(" Group folder found: {}", n.name)
|
||||||
root.addNode(n)
|
root.addNode(n)
|
||||||
fillNode(n, tree)
|
fillNode(n, tree)
|
||||||
|
@ -48,7 +49,7 @@ class ContentTreeProvider(
|
||||||
private fun loadThumbnails(tree: ContentTree) {
|
private fun loadThumbnails(tree: ContentTree) {
|
||||||
logger.info("Loading thumbnails...")
|
logger.info("Loading thumbnails...")
|
||||||
val thumbsCount = AtomicInteger()
|
val thumbsCount = AtomicInteger()
|
||||||
mediaDB.processThumbnails { thumb ->
|
nextcloudDB.processThumbnails { thumb ->
|
||||||
val id = getItemIdForThumbnail(thumb)
|
val id = getItemIdForThumbnail(thumb)
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
val item = tree.getItem(id)
|
val item = tree.getItem(id)
|
||||||
|
@ -72,7 +73,7 @@ class ContentTreeProvider(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fillNode(node: ContentNode, tree: ContentTree) {
|
private fun fillNode(node: ContentNode, tree: ContentTree) {
|
||||||
mediaDB.appendChildren(node)
|
nextcloudDB.appendChildren(node)
|
||||||
tree.addNode(node)
|
tree.addNode(node)
|
||||||
node.getItems().forEach { item ->
|
node.getItems().forEach { item ->
|
||||||
logger.debug("Adding item[{}]: " + item.path, item.id)
|
logger.debug("Adding item[{}]: " + item.path, item.id)
|
||||||
|
@ -87,7 +88,11 @@ class ContentTreeProvider(
|
||||||
fun getItem(id: String): ContentItem? = tree.getItem(id)
|
fun getItem(id: String): ContentItem? = tree.getItem(id)
|
||||||
fun getNode(id: String): ContentNode? = tree.getNode(id)
|
fun getNode(id: String): ContentNode? = tree.getNode(id)
|
||||||
|
|
||||||
companion object : KLogging()
|
companion object : KLogging() {
|
||||||
|
const val REBUILD_TREE_DELAY_IN_MS = 1000 * 60L // 1m
|
||||||
|
const val REBUILD_TREE_INIT_DELAY_IN_MS = 1000 * 60L // 1m
|
||||||
|
const val MAX_REBUILD_OFFSET_IN_S = 60 * 60 * 12L // 12h
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,9 @@ class StreamRequestMapper {
|
||||||
fun map(request: HttpServletRequest): StreamRequestMessage {
|
fun map(request: HttpServletRequest): StreamRequestMessage {
|
||||||
val requestMessage = StreamRequestMessage(
|
val requestMessage = StreamRequestMessage(
|
||||||
UpnpRequest.Method.getByHttpName(request.method),
|
UpnpRequest.Method.getByHttpName(request.method),
|
||||||
URI(request.requestURI)
|
URI(request.requestURI),
|
||||||
// TODO put request.inputStream.readBytes() here
|
// TODO check if request is binary and create body as unwrapped byteArray
|
||||||
|
String(request.inputStream.readBytes())
|
||||||
)
|
)
|
||||||
if (requestMessage.operation.method == UpnpRequest.Method.UNKNOWN) {
|
if (requestMessage.operation.method == UpnpRequest.Method.UNKNOWN) {
|
||||||
logger.warn("Method not supported by UPnP stack: {}", request.method)
|
logger.warn("Method not supported by UPnP stack: {}", request.method)
|
||||||
|
@ -22,28 +23,9 @@ class StreamRequestMapper {
|
||||||
|
|
||||||
requestMessage.connection = MyHttpServerConnection(request)
|
requestMessage.connection = MyHttpServerConnection(request)
|
||||||
requestMessage.headers = createHeaders(request)
|
requestMessage.headers = createHeaders(request)
|
||||||
setBody(request, requestMessage)
|
|
||||||
return requestMessage
|
return requestMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setBody(
|
|
||||||
request: HttpServletRequest,
|
|
||||||
requestMessage: StreamRequestMessage
|
|
||||||
) {
|
|
||||||
val bodyBytes = request.inputStream.readBytes()
|
|
||||||
|
|
||||||
logger.debug(" Reading request body bytes: " + bodyBytes.size)
|
|
||||||
if (bodyBytes.isNotEmpty() && requestMessage.isContentTypeMissingOrText) {
|
|
||||||
logger.debug("Request contains textual entity body, converting then setting string on message")
|
|
||||||
requestMessage.setBodyCharacters(bodyBytes)
|
|
||||||
} else if (bodyBytes.isNotEmpty()) {
|
|
||||||
logger.debug("Request contains binary entity body, setting bytes on message")
|
|
||||||
requestMessage.setBody(UpnpMessage.BodyType.BYTES, bodyBytes)
|
|
||||||
} else {
|
|
||||||
logger.debug("Request did not contain entity body")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createHeaders(request: HttpServletRequest): UpnpHeaders {
|
private fun createHeaders(request: HttpServletRequest): UpnpHeaders {
|
||||||
val headers = mutableMapOf<String, List<String>>()
|
val headers = mutableMapOf<String, List<String>>()
|
||||||
with(request.headerNames) {
|
with(request.headerNames) {
|
||||||
|
|
Loading…
Reference in a new issue