From aecc8c597352ddcf38c5cafb047f080210752c1b Mon Sep 17 00:00:00 2001 From: xis Date: Thu, 12 Oct 2023 19:40:38 +0200 Subject: [PATCH] cleanups --- .../controller/UpnpController.kt | 41 ++++++------------- .../nextcloud/{MediaDB.kt => NextcloudDB.kt} | 2 +- .../nextcloud/content/ContentTreeProvider.kt | 27 +++++++----- .../nextclouddlna/upnp/StreamRequestMapper.kt | 24 ++--------- 4 files changed, 32 insertions(+), 62 deletions(-) rename src/main/kotlin/net/schowek/nextclouddlna/nextcloud/{MediaDB.kt => NextcloudDB.kt} (99%) diff --git a/src/main/kotlin/net/schowek/nextclouddlna/controller/UpnpController.kt b/src/main/kotlin/net/schowek/nextclouddlna/controller/UpnpController.kt index 73ee314..e9d301d 100644 --- a/src/main/kotlin/net/schowek/nextclouddlna/controller/UpnpController.kt +++ b/src/main/kotlin/net/schowek/nextclouddlna/controller/UpnpController.kt @@ -32,48 +32,31 @@ class UpnpController( @PathVariable("uid") uid: String, request: HttpServletRequest ): 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()); } @RequestMapping( - method = [GET, HEAD], value = [ + method = [GET, HEAD, POST], value = [ "/dev/{uid}/desc", "/dev/{uid}/svc/upnp-org/ContentDirectory/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 { - 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/ConnectionManager/desc", "/dev/{uid}/svc/upnp-org/ContentDirectory/action" ], produces = ["application/xml;charset=utf8", "text/xml;charset=utf8"] ) - fun handlePost( + fun handleUpnp( @PathVariable("uid") uid: String, request: HttpServletRequest ): ResponseEntity { - logger.info { "POST 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) - ) + logger.info { "Upnp ${request.method} request from ${request.remoteAddr}: ${request.requestURI}" } + return with(upnpStreamProcessor.processMessage(streamRequestMapper.map(request))) { + ResponseEntity( + body, + HttpHeaders().also { h -> headers.entries.forEach { e -> h.add(e.key, e.value.joinToString { it }) } }, + HttpStatusCode.valueOf(operation.statusCode) + ) + } } companion object : KLogging() diff --git a/src/main/kotlin/net/schowek/nextclouddlna/nextcloud/MediaDB.kt b/src/main/kotlin/net/schowek/nextclouddlna/nextcloud/NextcloudDB.kt similarity index 99% rename from src/main/kotlin/net/schowek/nextclouddlna/nextcloud/MediaDB.kt rename to src/main/kotlin/net/schowek/nextclouddlna/nextcloud/NextcloudDB.kt index 8f602c4..b118fc8 100644 --- a/src/main/kotlin/net/schowek/nextclouddlna/nextcloud/MediaDB.kt +++ b/src/main/kotlin/net/schowek/nextclouddlna/nextcloud/NextcloudDB.kt @@ -14,7 +14,7 @@ import java.util.function.Consumer @Component -class MediaDB( +class NextcloudDB( private val nextcloudConfig: NextcloudConfigDiscovery, private val mimetypeRepository: MimetypeRepository, private val filecacheRepository: FilecacheRepository, diff --git a/src/main/kotlin/net/schowek/nextclouddlna/nextcloud/content/ContentTreeProvider.kt b/src/main/kotlin/net/schowek/nextclouddlna/nextcloud/content/ContentTreeProvider.kt index 17b2094..da10c1a 100644 --- a/src/main/kotlin/net/schowek/nextclouddlna/nextcloud/content/ContentTreeProvider.kt +++ b/src/main/kotlin/net/schowek/nextclouddlna/nextcloud/content/ContentTreeProvider.kt @@ -1,25 +1,26 @@ package net.schowek.nextclouddlna.nextcloud.content -import jakarta.annotation.PostConstruct import mu.KLogging -import net.schowek.nextclouddlna.nextcloud.MediaDB +import net.schowek.nextclouddlna.nextcloud.NextcloudDB import org.springframework.scheduling.annotation.Scheduled import org.springframework.stereotype.Component +import java.time.Instant import java.util.concurrent.atomic.AtomicInteger import java.util.regex.Pattern @Component class ContentTreeProvider( - private val mediaDB: MediaDB + private val nextcloudDB: NextcloudDB ) { private var tree = buildContentTree() 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() { - val maxMtime: Long = mediaDB.maxMtime() - if (lastMTime < maxMtime) { + val maxMtime: Long = nextcloudDB.maxMtime() + val now = Instant.now().epochSecond + if (lastMTime < maxMtime || lastMTime + MAX_REBUILD_OFFSET_IN_S > now) { logger.info("ContentTree seems to be outdated - Loading...") this.tree = buildContentTree() lastMTime = maxMtime @@ -30,12 +31,12 @@ class ContentTreeProvider( val tree = ContentTree() val root = ContentNode(0, -1, "ROOT") tree.addNode(root) - mediaDB.mainNodes().forEach { n -> + nextcloudDB.mainNodes().forEach { n -> root.addNode(n) fillNode(n, tree) } logger.info("Getting content from group folders...") - mediaDB.groupFolders().forEach { n -> + nextcloudDB.groupFolders().forEach { n -> logger.info(" Group folder found: {}", n.name) root.addNode(n) fillNode(n, tree) @@ -48,7 +49,7 @@ class ContentTreeProvider( private fun loadThumbnails(tree: ContentTree) { logger.info("Loading thumbnails...") val thumbsCount = AtomicInteger() - mediaDB.processThumbnails { thumb -> + nextcloudDB.processThumbnails { thumb -> val id = getItemIdForThumbnail(thumb) if (id != null) { val item = tree.getItem(id) @@ -72,7 +73,7 @@ class ContentTreeProvider( } private fun fillNode(node: ContentNode, tree: ContentTree) { - mediaDB.appendChildren(node) + nextcloudDB.appendChildren(node) tree.addNode(node) node.getItems().forEach { item -> logger.debug("Adding item[{}]: " + item.path, item.id) @@ -87,7 +88,11 @@ class ContentTreeProvider( fun getItem(id: String): ContentItem? = tree.getItem(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 + } } diff --git a/src/main/kotlin/net/schowek/nextclouddlna/upnp/StreamRequestMapper.kt b/src/main/kotlin/net/schowek/nextclouddlna/upnp/StreamRequestMapper.kt index c64d3be..1749418 100644 --- a/src/main/kotlin/net/schowek/nextclouddlna/upnp/StreamRequestMapper.kt +++ b/src/main/kotlin/net/schowek/nextclouddlna/upnp/StreamRequestMapper.kt @@ -12,8 +12,9 @@ class StreamRequestMapper { fun map(request: HttpServletRequest): StreamRequestMessage { val requestMessage = StreamRequestMessage( UpnpRequest.Method.getByHttpName(request.method), - URI(request.requestURI) - // TODO put request.inputStream.readBytes() here + URI(request.requestURI), + // TODO check if request is binary and create body as unwrapped byteArray + String(request.inputStream.readBytes()) ) if (requestMessage.operation.method == UpnpRequest.Method.UNKNOWN) { logger.warn("Method not supported by UPnP stack: {}", request.method) @@ -22,28 +23,9 @@ class StreamRequestMapper { requestMessage.connection = MyHttpServerConnection(request) requestMessage.headers = createHeaders(request) - setBody(request, 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 { val headers = mutableMapOf>() with(request.headerNames) {