Commit e9636e86 authored by Elek's avatar Elek
Browse files

Extend docs

parent ebeb31c3
Pipeline #185988 failed with stage
package de.kthesis.lib.application
import de.kthesis.lib.domain.verifiable_data_registry.repository.IDataRepository
import de.kthesis.lib.domain.verifiable_data_registry.NamedVerifiableDataRegistry
import net.named_data.jndn.Face
import net.named_data.jndn.Interest
import net.named_data.jndn.InterestFilter
......@@ -8,6 +9,10 @@ import net.named_data.jndn.Name
import net.named_data.jndn.OnInterestCallback
import java.util.logging.Logger
/**
* Simple class, which receives Interest, requesting [NamedVerifiableDataRegistry] stored data packets and
* return them
*/
class DataProvider(
private val dataRepository: IDataRepository
) : OnInterestCallback {
......
......@@ -17,6 +17,7 @@ import de.kthesis.lib.domain.verifiable_data_registry.command.ValidateCommand
import de.kthesis.lib.domain.verifiable_data_registry.repository.ICertificateRepository
import de.kthesis.lib.domain.verifiable_data_registry.repository.IPendingRegistrationRepository
import de.kthesis.lib.domain.verifiable_data_registry.service.IDataManagementService
import de.kthesis.lib.domain.verifiable_data_registry.NamedVerifiableDataRegistry
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
......@@ -26,13 +27,19 @@ import net.named_data.jndn.Interest
import net.named_data.jndn.security.v2.Validator
import java.util.logging.Logger
/**
* Communication "heart" of the [NamedVerifiableDataRegistry].
* Receive Interests and execute the corresponding actions.
*
*/
class InterestHandler(
private val repositoryConfig: RepositoryConfig,
private val registrationConfig: CommandVerificationConfig,
private val certificateRepository: ICertificateRepository,
private val pendingRegistrationRepository: IPendingRegistrationRepository,
private var validator: Validator,
private val dataManagementService: IDataManagementService
private val dataManagementService: IDataManagementService,
) {
private val logger = Logger.getLogger(this::class.java.simpleName)
......@@ -41,7 +48,7 @@ class InterestHandler(
Logger.getLogger(this::class.java.simpleName)
.info("Handle received Interest '${receivedInterest.name}'")
// reload config each time in case something changed
registrationConfig.loadConfig(certificateRepository.findAll())
registrationConfig.loadConfig(certificateRepository.findAll(),pendingRegistrationRepository.findAll())
// parse the command
val command = RegistryCommandInterest.decodeCommand(
......@@ -72,6 +79,11 @@ class InterestHandler(
}
}
/**
* Receive the command interest and execute the corresponding action
*
* @return The response data packet
*/
private suspend fun execute(registryCommandInterest: RegistryCommandInterest): Data =
when (registryCommandInterest.commandType) {
CommandType.INSERT -> InsertCommand(
......
package de.kthesis.lib.domain.verifiable_data_registry
import net.named_data.jndn.Interest
import net.named_data.jndn.security.v2.InterestValidationSuccessCallback
class CommandValidationSuccess : InterestValidationSuccessCallback {
override fun successCallback(p0: Interest?) {
TODO("Not yet implemented")
}
}
\ No newline at end of file
......@@ -9,14 +9,25 @@ import net.named_data.jndn.security.v2.ValidationPolicyConfig
import net.named_data.jndn.util.Common
import java.util.logging.Logger
/**
* Access policy to authorize the received command interests.
*
* Can be passed to a ndn Validator class to apply the policy
*/
class CommandVerificationConfig(
private val repoPrefix: Name,
rootCertificateList: List<CertificateV2>
) :
ValidationPolicyConfig() {
/**
* contains the entries for the trust anchors
*/
private val trustAnchorEntries = rootCertificateList.map(::createTrustAnchorEntry)
/**
* Create for each certificate a trust rule
*/
private fun createCommandTrustRule(registeredCertificates: List<CertificateV2>): String {
if (registeredCertificates.isEmpty()) return ""
val checkerEntries = registeredCertificates.map(::createCheckerEntryForRegistryCommands)
......@@ -79,7 +90,8 @@ class CommandVerificationConfig(
}"""
fun loadConfig(registeredCertificates: List<CertificateRepositoryEntry>) {
// TODO updates trust rules to contains the desired name space, too
fun loadConfig(registeredCertificates: List<CertificateRepositoryEntry>, pendingCertificateV2: List<CertificateV2>) {
val config = getFullValidatorConfig(registeredCertificates.map { certificateRepositoryEntry -> certificateRepositoryEntry.registeredCertificate })
Logger.getLogger(this::class.java.simpleName).info("ValidatorConfig $config")
load(config, "config")
......
......@@ -26,6 +26,11 @@ import org.koin.core.context.startKoin
import org.koin.dsl.module
import org.koin.mp.KoinPlatformTools
/**
* Main class to setup a named verifiable data registry.
*
* Can be simply passed to a [Face.registerPrefix] Method and handles all Interests for the registry.
*/
class NamedVerifiableDataRegistry(
internal val nvdrPrefix: Name,
// TODO remove later is unused if face from interest callback is used
......@@ -73,8 +78,6 @@ class NamedVerifiableDataRegistry(
if (receivedInterest == null) return
interestHandler.handleInterest(receivedInterest, face)
}
}
\ No newline at end of file
......@@ -24,4 +24,5 @@ interface IPendingRegistrationRepository {
fun update(requestId:String, entry : PendingRegistrationEntry) : Boolean
fun removeForNameSpace(nameSpace: Name)
fun findAll(): List<PendingRegistrationEntry>
}
\ No newline at end of file
package de.kthesis.lib.domain.verifiable_data_registry.service
/**
* information about the insert/deletion operations
*/
data class DataIOOperation(val processId: Int, val startBlockId: Int, val endBlockId: Int?)
\ No newline at end of file
......@@ -4,35 +4,71 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import net.named_data.jndn.Name
/**
* Holds and manage information about insert/deletion process.
*/
class DataIOOperationManager {
// simple hash map later replace with database
private val operationMap = HashMap<Name, DataIOOperation>()
private val mutex = Mutex()
/**
* Creates a new entry for an insert/deletion process for the given data name
*
* @param dataName The name of the data which is edited (inserted/deleted)
* @return A entry for the data operation.
*/
suspend fun createDataIOOperationIfNotExist(dataName: Name): DataIOOperation = mutex.withLock {
// find the process id
if (operationMap.contains(dataName)) return operationMap[dataName]!!
// find the correct process id
// create a new unused process id
for (processId in 0 until Int.MAX_VALUE) {
if (operationMap.values.any { commandOperation -> commandOperation.processId == processId }) continue
operationMap[dataName] = DataIOOperation(processId, 0, null)
// found a new one
break
}
// return the new entry
return operationMap[dataName]!!
}
/**
* Checks if the manager has a data operation entry for the given data name
*
* @param dataName The name of the data which is edited (inserted/deleted)
* @param startBlockId The start block id of the data name
* @param endBlockId The end block id of the data name
* @return true if a entry for the given name, start and end block id exist, false otherwise
*/
suspend fun hasDataIOOperation(dataName: Name,startBlockId: Int?, endBlockId: Int?) = mutex.withLock {
return@withLock operationMap[dataName]?.run {
this.startBlockId == startBlockId && this.endBlockId == endBlockId
}?:false
}
suspend fun getCommandOperation(dataName: Name) = mutex.withLock {
/**
* Search for an operation information entry.
*
* @param dataName The name of a data packet for which an io operation is searched
* @return The operation entry for the given name, null if none exist
*/
suspend fun getDataIOOperation(dataName: Name) = mutex.withLock {
operationMap[dataName]
}
suspend fun updateCommandOperation(
/**
* Updates an existing operation information with the given parameter.
* Nothing happens if no operation entry exist.
* Use [getDataIOOperation] to obtain the current operation information.
*
* @param dataName The name of the data which is edited (inserted/deleted)
* @param startBlockId The (new) start block id of the data name
* @param endBlockId The (new) end block id of the data name
*/
suspend fun updateDataIOOperation(
dataName: Name,
startBlockId: Int,
endBlockId: Int?
......@@ -41,7 +77,12 @@ class DataIOOperationManager {
operationMap[dataName] = state.copy(startBlockId = startBlockId, endBlockId = endBlockId)
}
suspend fun removeProcessId(dataName: Name) {
/**
* Deletes the stored information for the given data name
*
* @param dataName The name of the data which is edited (inserted/deleted)
*/
suspend fun removeDataIOOperation(dataName: Name) {
mutex.withLock {
operationMap.remove(dataName)
}
......
......@@ -14,6 +14,15 @@ import java.util.logging.Logger
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
/**
* Manage the insertion and deletion for the data according to the NDN Repo protocol.
*
* See https://redmine.named-data.net/projects/repo-ng/wiki/Repo_Protocol_Specification for more information.
*
* @param face NDN Interface to express Interests for data
* @param dataRepository Repository to store/delete data
* @param dataProvider Used to provide the stored data for each receiving Interest
*/
class DataManagementService(
private val face: Face,
private val dataRepository: IDataRepository,
......@@ -23,6 +32,7 @@ class DataManagementService(
private val logger = Logger.getLogger(this::class.java.simpleName)
private val registeredPrefixes = mutableMapOf<Name,Long>()
// separate manager for each operation type
private val insertionOperationManager = DataIOOperationManager()
private val deletionOperationManager = DataIOOperationManager()
......@@ -31,9 +41,9 @@ class DataManagementService(
startBlockId: Int?,
endBlockId: Int?
): DataIOOperation = withContext(Dispatchers.IO) {
logger.info("Before insert start")
val commandOperation = insertionOperationManager.createDataIOOperationIfNotExist(dataName)
logger.info("Before launch")
// do the data fetch asynchronous
CoroutineScope(Dispatchers.IO + SupervisorJob()).launch {
var start = startBlockId ?: 0
// no endBlock missing timer implemented yet
......@@ -44,17 +54,21 @@ class DataManagementService(
// fetch data packet
for (i in 0 until 3) {
// fetch data
logger.info("Try to fetch $interestedDataName")
val data = fetchData(interestedDataName) ?: continue
// store data or update data if already existing
if (!dataRepository.add(data)) dataRepository.update(data)
logger.info("Register Interest Prefix for $dataName")
// register prefix to provide the inserted data
val registeredPrefixId = face.registerPrefix(dataName, dataProvider) {
logger.warning("Could not register interest prefix for '${data.name}'")
}
registeredPrefixes[dataName] = registeredPrefixId
// update start and end block
if (data.metaInfo.finalBlockId != null && data.metaInfo.finalBlockId.value.toString()
.isNotEmpty()
) end =
......@@ -63,11 +77,13 @@ class DataManagementService(
break
}
val currentState = insertionOperationManager.getCommandOperation(dataName) ?: break
// update the insertion operation state information
val currentState = insertionOperationManager.getDataIOOperation(dataName) ?: break
if (currentState.startBlockId == start && currentState.endBlockId == end) break
insertionOperationManager.updateCommandOperation(dataName, start, end)
insertionOperationManager.updateDataIOOperation(dataName, start, end)
}
insertionOperationManager.removeProcessId(dataName)
// insertion is complete
insertionOperationManager.removeDataIOOperation(dataName)
}
logger.info("Insert operation $commandOperation")
return@withContext commandOperation
......@@ -85,7 +101,7 @@ class DataManagementService(
logger.info("Remove Interest Prefix for $dataName")
val start = startBlockId ?: 0
// endblock is missing, delete every segment
// end block is missing, delete every segment
if (endBlockId == null) {
val dataSegmentPrefix = Name(dataName).append(Name(start.toString()))
dataRepository.removeByPrefix(dataSegmentPrefix)
......@@ -95,9 +111,9 @@ class DataManagementService(
val dataSegmentName = Name(dataName).append(Name(start.toString()))
// delete the data packet
dataRepository.remove(dataSegmentName)
deletionOperationManager.updateCommandOperation(dataName, index, endBlockId)
deletionOperationManager.updateDataIOOperation(dataName, index, endBlockId)
}
deletionOperationManager.removeProcessId(dataName)
deletionOperationManager.removeDataIOOperation(dataName)
return commandOperation
}
......@@ -109,10 +125,13 @@ class DataManagementService(
) = deletionOperationManager.hasDataIOOperation(dataName, startBlockId, endBlockId)
/**
* Simple wrapper to express and Interest for the given data name and wait for the data packet (or a timeout)
*
* @param dataName The name of the data which should be fetched.
*/
private suspend fun fetchData(dataName: Name): Data? = suspendCoroutine { continuation ->
face.expressInterest(dataName, { _, data ->
// TODO validate that the data is signed with a registered public key
// TODO what if data is put into new packet and signed by registry?
continuation.resume(data)
}) {
// timeout occurs
......
......@@ -2,19 +2,44 @@ package de.kthesis.lib.domain.verifiable_data_registry.service
import net.named_data.jndn.Name
/**
* Basic service for the insertion and deletion of data according to the
* NDN Repo protocol.
*/
interface IDataManagementService {
/**
* Start the insertion process for the given data name.
* See https://redmine.named-data.net/projects/repo-ng/wiki/Basic_Repo_Insertion_Protocol for a more detailed description of the whole process.
*
* @param dataName The name of the data which should be inserted
* @param startBlockId (Optional) The start block for the data.
* Will be combined with the data name, e.g. "/prefix/data-name/0". Default 0.
* @param endBlockId (Optional) The end block for the data.
* If non given, the end block will be derived from the first inserted data packet.
*/
suspend fun insertData(
dataName: Name,
startBlockId: Int? = null,
endBlockId: Int? = null
): DataIOOperation
/**
* Start the deletion process for the given data name.
* See https://redmine.named-data.net/projects/repo-ng/wiki/Repo_Deletion_Protocol for a more detailed description of the whole process.
*
* @param dataName The name of the data which should be deleted.
* @param startBlockId (Optional) The start block for the data.
* Will be combined with the data name, e.g. "/prefix/data-name/0". Default 0.
* @param endBlockId (Optional) The end block for the data.
* If non given, all data packets will be deleted
*/
suspend fun deleteData(
dataName: Name,
startBlockId: Int? = null,
endBlockId: Int? = null,
): DataIOOperation
// TODO is this used?
suspend fun deleteDataInProgress(dataName: Name, startBlockId: Int?, endBlockId: Int?): Boolean
}
\ No newline at end of file
package de.kthesis.lib.domain.verifiable_data_registry.service
import net.named_data.jndn.Name
import net.named_data.jndn.security.v2.CertificateV2
class RegistrationService {
fun addCertificate(certificateV2: CertificateV2) {
TODO()
}
fun removeCertificate(name: Name) {
TODO()
}
}
\ No newline at end of file
package de.kthesis.lib.domain.verifiable_data_registry.trust
import net.named_data.jndn.Name
import net.named_data.jndn.Signature
data class TrustEntry(
val dataName : Name,
val signature : Signature
)
\ No newline at end of file
package de.kthesis.lib.domain.verifiable_data_registry.trust
class TrustList(val trustEntries : List<TrustEntry>)
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment