Skip to content

Commit

Permalink
Merge pull request #46 from ravikp/one-based-sequence-number-for-vc-t…
Browse files Browse the repository at this point in the history
…ransfer

Update chunk sequence number to 1-based
  • Loading branch information
krishnakumar4a4 authored Apr 12, 2023
2 parents ab0caad + e92569c commit 431f380
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 63 deletions.
20 changes: 11 additions & 9 deletions android/src/main/java/io/mosip/tuvali/transfer/Assembler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import io.mosip.tuvali.transfer.Util.Companion.networkOrderedByteArrayToInt
import io.mosip.tuvali.verifier.exception.CorruptedChunkReceivedException
import io.mosip.tuvali.transfer.Util.Companion.getLogTag

class Assembler(private val totalSize: Int, private val maxDataBytes: Int ): ChunkerBase(maxDataBytes) {
class Assembler(totalSize: Int, private val maxDataBytes: Int ): ChunkerBase(maxDataBytes) {
private val logTag = getLogTag(javaClass.simpleName)
private var data: ByteArray = ByteArray(totalSize)
private var lastReadSeqNumber: Int? = null
Expand All @@ -27,7 +27,8 @@ class Assembler(private val totalSize: Int, private val maxDataBytes: Int ): Chu
Log.e(logTag, "received invalid chunk chunkSize: ${chunkData.size}, lastReadSeqNumber: $lastReadSeqNumber")
return 0
}
val seqNumberInMeta = networkOrderedByteArrayToInt(chunkData.copyOfRange(0, 2), TwoBytes)

val seqNumberInMeta: ChunkSeqNumber = networkOrderedByteArrayToInt(chunkData.copyOfRange(0, 2), TwoBytes)
val crcReceived = networkOrderedByteArrayToInt(chunkData.copyOfRange(2,4), TwoBytes).toUShort()

//Log.d(logTag, "received add chunk received chunkSize: ${chunkData.size}, seqNumberInMeta: $seqNumberInMeta")
Expand All @@ -40,8 +41,9 @@ class Assembler(private val totalSize: Int, private val maxDataBytes: Int ): Chu
return seqNumberInMeta
}
lastReadSeqNumber = seqNumberInMeta
System.arraycopy(chunkData, chunkMetaSize, data, seqNumberInMeta * effectivePayloadSize, (chunkData.size-chunkMetaSize))
chunkReceivedMarker[seqNumberInMeta] = chunkReceivedMarkerByte
val seqIndex = seqNumberInMeta.toSeqIndex()
System.arraycopy(chunkData, chunkMetaSize, data, seqIndex * effectivePayloadSize, (chunkData.size-chunkMetaSize))
chunkReceivedMarker[seqIndex] = chunkReceivedMarkerByte
//Log.d(logTag, "adding chunk complete at index(0-based): ${seqNumberInMeta}, received chunkSize: ${chunkData.size}")
return seqNumberInMeta
}
Expand All @@ -63,14 +65,14 @@ class Assembler(private val totalSize: Int, private val maxDataBytes: Int ): Chu
}

fun getMissedSequenceNumbers(): IntArray {
var missedSeqNumbers = intArrayOf()
chunkReceivedMarker.forEachIndexed() { i, elem ->
var missedSeqNumberList = intArrayOf()
chunkReceivedMarker.forEachIndexed() { missedChunkSeqIndex: ChunkSeqIndex, elem ->
if (elem != chunkReceivedMarkerByte) {
//Log.d(logTag, "getMissedSequenceNumbers: adding missed sequence number $i")
missedSeqNumbers += i
//Log.d(logTag, "getMissedSequenceNumbers: adding missed sequence number $missedChunkSeqIndex")
missedSeqNumberList += missedChunkSeqIndex.toSeqNumber()
}
}
return missedSeqNumbers
return missedSeqNumberList
}

fun data(): ByteArray {
Expand Down
32 changes: 17 additions & 15 deletions android/src/main/java/io/mosip/tuvali/transfer/Chunker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,36 @@ class Chunker(private val data: ByteArray, private val maxDataBytes: Int) :

init {
Log.i(logTag, "Total number of chunks calculated: $totalChunkCount")
val startTime = System.currentTimeMillis()
// val startTime = System.currentTimeMillis()
for (idx in 0 until totalChunkCount) {
preSlicedChunks[idx] = chunk(idx)
}
//Log.d(logTag, "Chunks pre-populated in ${System.currentTimeMillis() - startTime} ms time")
}

fun next(): ByteArray {
val seqNumber = chunksReadCounter
chunksReadCounter++
return preSlicedChunks[seqNumber]!!
return preSlicedChunks[chunksReadCounter++]!!
}

fun chunkBySequenceNumber(num: Int): ByteArray {
return preSlicedChunks[num]!!
fun chunkBySequenceNumber(missedSeqNumber: ChunkSeqNumber): ByteArray {
return preSlicedChunks[missedSeqNumber.toSeqIndex()]!!
}

private fun chunk(seqNumber: Int): ByteArray {
val fromIndex = seqNumber * effectivePayloadSize

return if (seqNumber == (totalChunkCount - 1).toInt() && lastChunkByteCount > 0) {
Log.d(logTag, "fetching last chunk")
frameChunk(seqNumber, fromIndex, fromIndex + lastChunkByteCount)
private fun chunk(seqIndex: ChunkSeqIndex): ByteArray {
val fromIndex = seqIndex * effectivePayloadSize
return if (isLastChunkSmallerSize(seqIndex)) {
frameChunk(seqIndex.toSeqNumber(), fromIndex, fromIndex + lastChunkByteCount)
} else {
val toIndex = (seqNumber + 1) * effectivePayloadSize
frameChunk(seqNumber, fromIndex, toIndex)
val toIndex = fromIndex + effectivePayloadSize
frameChunk(seqIndex.toSeqNumber(), fromIndex, toIndex)
}
}

private fun isLastChunkSmallerSize(seqIndex: Int) =
isLastChunkIndex(seqIndex) && lastChunkByteCount > 0

private fun isLastChunkIndex(seqIndex: Int) = seqIndex == (totalChunkCount - 1)

/*
<--------------------------------------------------Max Data Bytes -------------------------------------------------------------->
+-----------------------+-----------------------------+-------------------------------------------------------------------------+
Expand All @@ -64,7 +65,8 @@ class Chunker(private val data: ByteArray, private val maxDataBytes: Int) :
}

fun isComplete(): Boolean {
val isComplete = chunksReadCounter > (totalChunkCount - 1).toInt()
Log.i(logTag,"chunksReadCounter: $chunksReadCounter")
val isComplete = chunksReadCounter >= totalChunkCount
if (isComplete) {
Log.d(
logTag,
Expand Down
11 changes: 11 additions & 0 deletions android/src/main/java/io/mosip/tuvali/transfer/ChunkerBase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ package io.mosip.tuvali.transfer

import kotlin.math.ceil

typealias ChunkSeqIndex = Int
typealias ChunkSeqNumber = Int

fun ChunkSeqIndex.toSeqNumber(): ChunkSeqNumber {
return this + 1
}

fun ChunkSeqNumber.toSeqIndex(): ChunkSeqIndex {
return this - 1
}

open class ChunkerBase(maxDataBytes: Int) {
private val seqNumberReservedByteSize = 2
private val crcChecksumValueByteSize = 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ class RetryChunker(private val chunker: Chunker, private val missedSequences: In
}

fun next(): ByteArray {
val missedSeqNo = missedSequences[seqCounter]
val missedSeqNumber = missedSequences[seqCounter]
seqCounter++

return chunker.chunkBySequenceNumber(missedSeqNo)
return chunker.chunkBySequenceNumber(missedSeqNumber)
}

fun isComplete(): Boolean {
Expand Down
5 changes: 5 additions & 0 deletions docs/one-based-counter-for-sequence-number.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# One-based Counter for Sequence Number in VC Chunk

The VC is divided into multiple chunks and stored in an array initially. While creating a chunk we add the sequence number to it. Initially, we used the array index as the sequence number which was added in the chunks making it a 0-based counter.

Now, we are adding 1 to the array index when using it as a sequence number on the chunk making it a 1-based counter. After we read the chunk on the verifier side, we are decrementing the sequence number by 1 and then store in back in the array.
4 changes: 2 additions & 2 deletions ios/ble/Utility/TransferHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ class TransferHandler {
}

private func sendRetryRespChunk(missingChunks: [Int]) {
for chunkIndex in missingChunks {
if let chunk = chunker?.getChunkWithIndex(index: chunkIndex) {
for missedSeqNumber in missingChunks {
if let chunk = chunker?.chunkBySequenceNumber(missedSeqNumber: missedSeqNumber) {
delegate?.write(serviceUuid: Peripheral.SERVICE_UUID, charUUID: NetworkCharNums.SUBMIT_RESPONSE_CHAR_UUID, data: chunk, withResponse: true)
}
// checks if no more missing chunks exist on verifier
Expand Down
15 changes: 8 additions & 7 deletions ios/ble/Utility/TransferReport.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import Foundation

/*
+---------+------------------+---------------------+-------------------+-------------------+-------------------+
| | | | | | |
| type | total pages | missed seq no.0 | missed seq no. 1 | missed seq no.2 | . . . . . |
|(1 byte) | (2 bytes) | (2 bytes) | (2 bytes) | (2 bytes) | |
+---------+------------------+---------------------+-------------------+-------------------+-------------------+
*/
class TransferReport {
var type: ReportType
var totalPages: Int
Expand Down Expand Up @@ -35,10 +42,4 @@ class TransferReport {
}
}
}
/*
+---------+------------------+---------------------+-------------------+-------------------+-------------------+
| | | | | | |
| type | total pages | missed seq no.0 | missed seq no. 1 | missed seq no.2 | . . . . . |
|(1 byte) | (2 bytes) | (2 bytes) | (2 bytes) | (2 bytes) | |
+---------+------------------+---------------------+-------------------+-------------------+-------------------+
*/

65 changes: 37 additions & 28 deletions ios/ble/Utility/chunker.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
import Foundation

typealias ChunkSeqIndex = Int
typealias ChunkSeqNumber = Int

extension ChunkSeqIndex {
func toSeqNumber() -> ChunkSeqNumber {
return self + 1
}
}

extension ChunkSeqNumber {
func toSeqIndex() -> ChunkSeqIndex {
return self - 1
}
}

class Chunker {

private var logTag = "Chunker"
Expand All @@ -15,22 +30,14 @@ class Chunker {
assignPreSlicedChunks()
}

func getChunkWithIndex(index: Int) -> Data {
if index < self.preSlicedChunks.count {
return self.preSlicedChunks[index]
}
// TODO: Figure out how to throw errors!
return Data()
}

func getLastChunkByteCount(dataSize: Int) -> Int {
return dataSize % effectivePayloadSize
}

func assignPreSlicedChunks(){
os_log(.info, "expected total data size: %{public}d and totalChunkCount: %{public}d ", (chunkData?.count)!, totalChunkCount)
for i in 0..<totalChunkCount {
preSlicedChunks.append(chunk(seqNumber: i))
for i: ChunkSeqIndex in 0..<totalChunkCount {
preSlicedChunks.append(chunk(seqIndex: i))
}
}

Expand All @@ -52,32 +59,34 @@ class Chunker {
}

func next() -> Data {
var seqNumber = chunksReadCounter
let chunkIndex = chunksReadCounter
chunksReadCounter += 1
if seqNumber <= totalChunkCount - 1 {
return (preSlicedChunks[seqNumber])
}
else
{
return Data()
}
return preSlicedChunks[chunkIndex]
}

func chunkBySequenceNumber(num: Int) -> Data {
return (preSlicedChunks[num])
func chunkBySequenceNumber(missedSeqNumber: ChunkSeqNumber) -> Data {
return (preSlicedChunks[missedSeqNumber.toSeqIndex()])
}

private func chunk(seqNumber: Int) -> Data {
let fromIndex = seqNumber * effectivePayloadSize
if (seqNumber == (totalChunkCount - 1) && lastChunkByteCount > 0) {
private func chunk(seqIndex: ChunkSeqIndex) -> Data {
let fromIndex = seqIndex * effectivePayloadSize
if isLastChunkSmallerSize(seqIndex: seqIndex) {
let chunkLength = lastChunkByteCount + chunkMetaSize
return frameChunk(seqNumber: seqNumber, chunkLength: chunkLength, fromIndex: fromIndex, toIndex: fromIndex + lastChunkByteCount)
return frameChunk(seqNumber: seqIndex.toSeqNumber(), chunkLength: chunkLength, fromIndex: fromIndex, toIndex: fromIndex + lastChunkByteCount)
} else {
let toIndex = (seqNumber + 1) * effectivePayloadSize
return frameChunk(seqNumber: seqNumber, chunkLength: mtuSize, fromIndex: fromIndex, toIndex: toIndex)
let toIndex = fromIndex + effectivePayloadSize
return frameChunk(seqNumber: seqIndex.toSeqNumber(), chunkLength: mtuSize, fromIndex: fromIndex, toIndex: toIndex)
}
}

private func isLastChunkSmallerSize(seqIndex: Int) -> Bool {
return isLastChunkIndex(seqIndex: seqIndex) && lastChunkByteCount > 0
}

private func isLastChunkIndex(seqIndex: Int) -> Bool {
return seqIndex == (totalChunkCount - 1)
}

/*
<------------------------------------------------------- MTU ------------------------------------------------------------------->
+-----------------------+-----------------------------+-------------------------------------------------------------------------+
Expand All @@ -88,7 +97,7 @@ class Chunker {
+-----------------------+-----------------------------+-------------------------------------------------------------------------+
*/

private func frameChunk(seqNumber: Int, chunkLength: Int, fromIndex: Int, toIndex: Int) -> Data {
private func frameChunk(seqNumber: ChunkSeqNumber, chunkLength: Int, fromIndex: Int, toIndex: Int) -> Data {
if let chunkData = chunkData {
let payload = chunkData.subdata(in: fromIndex + chunkData.startIndex..<chunkData.startIndex + toIndex)
let payloadCRC = CRC.evaluate(d: payload)
Expand All @@ -98,7 +107,7 @@ class Chunker {
}

func isComplete() -> Bool {
let isComplete = chunksReadCounter > (totalChunkCount - 1)
let isComplete = chunksReadCounter >= totalChunkCount
if isComplete {
os_log(.info, "isComplete: true, totalChunks: %{public}d , chunkReadCounter(1-indexed): %{public}d", totalChunkCount, chunksReadCounter)
}
Expand Down

0 comments on commit 431f380

Please sign in to comment.