Problems making a "proxy" for Android with VPNService - android

For some reason I can't understand, when I'm parsing the buffer values, I almost never get the version as 4 (which would be the default for IPv4), and most of the time I get some random value like 10 or 0 instead. The same is true with the protocol, even though it is parsing exactly as it is specified on the wiki, it never comes up precisely with something that says it's TCP or UDP, just 0 (which would map to HOPOPT) or a random value. I believe the parsing is at least correct because when I debug, the source address resolves to the DNS I specified (8.8.4.4), which shouldn't happen if I was parsing the wrong way (at least, it seems to me that no).
val (version, internetHeaderLength) = buffer.get().toUByte().split()
// Differentiated Services Code Point, Explicit Congestion Notification (TOS)
val (dscp, ecn) = buffer.get().toUByte().extract(2)
val totalLength = buffer.short.toUShort()
val identification = buffer.short.toUShort()
val (flags, fragmentOffset) = buffer.short.toUShort().extract(3)
val timeToLive = buffer.get().toUByte()
val protocol = buffer.get().toUByte()
val headerChecksum = buffer.short.toUShort()
val sourceAddress = buffer.int
val destinationAddress = buffer.int
val options = buffer.array().sliceArray(0 until internetHeaderLength.toInt() * 4 - 20)
val data =
buffer.array().sliceArray(internetHeaderLength.toInt() * 4 until totalLength.toInt())
Below is the code I use to get the packet data
fun receivePackets(input: FileInputStream, output: FileOutputStream, buffer: ByteBuffer) {
val read = input.read(buffer.array())
if (read > 0) {
buffer.limit(read)
val packet = IpDatagram(buffer)
Log.d(Tag, "Received packet: $packet which is " +
if (packet.valid) "valid" else "invalid"
)
(the code I wrote for handling numbers bits)
fun UShort.getBit(position: Int): Int {
return (this.toInt() shr position) and 1;
}
fun UShort.setBit(position: Int, value: Int): UShort {
return (this.toInt() or (value shl position)).toUShort();
}
fun UShort.setBit(position: Int, value: Boolean): UShort {
return (this.toInt() or ((if (value) 1 else 0) shl position)).toUShort();
}
fun UShort.split(): Pair<UShort, UShort> {
return Pair((this.toInt() shr 4).toUShort(), (this.toInt() and 0x0F).toUShort());
}
fun UShort.extract(count: Int): Pair<UShort, UShort> {
return Pair(this.extractFirst(count), this.extractLast(count))
}
fun UShort.extractFirst(count: Int): UShort {
return (this.toInt() shr count).toUShort();
}
fun UShort.extractLast(count: Int): UShort {
return (this.toInt() and ((1 shl count) - 1)).toUShort();
}
I've been debugging this for a while, and I've already tried some things like decomposing the numbers that result to try to see if there are any errors in the methods I created to decompose the integers or if they present patterns like 0100 that I want for IPv4 identification.
Example of one packet after being parsed:
{
"destinationAddress":"95.53.97.33",
"dscp":9,
"ecn":0,
"flags":0,
"fragmentOffset":0,
"headerChecksum":0,
"identification":-384,
"internetHeaderLength":0,
"options":[],
"payload":[96],
"protocol":"HOPOPT" // 0,
"sourceAddress":"101.94.226.95",
"timeToLive":0,
"totalLength":1,
"valid":true,
"version":0
}

Related

Kotlin - retrieve bit position from byte and convert it as int

I've a byte. What I want to do is access bit position to retrieve boolean (0 or 1). How can I do that in Kotlin?
fun getBit(b: Byte, bitNumber: Int): Boolean {
val shift: Int = 7 - bitNumber
val bitMask = (1 shl shift).toByte()
val masked = (b and bitMask)
return masked.toInt() != 0
}
This for some reason return incorrect value of false when it should return true
Your algorithm seems OK, I think you just made an off by one error (although you didn't say if you are counting from 0 or 1). If I change it to
val shift: Int = 8 - bitNumber
It seems to work fine for me:
fun getBit(b: Byte, bitNumber: Int): Boolean {
require(bitNumber in 1..8)
val shift: Int = 8 - bitNumber
val bitMask = (1 shl shift).toByte()
val masked = (b and bitMask)
return masked.toInt() != 0
}
fun main() {
println(getBit(0b10000000.toByte(), 1))
println(getBit(0b10000000.toByte(), 2))
println(getBit(0b01000000, 2))
}
Output:
true
false
true
Note: you can avoid the experimental Byte.and() by using Int.and() instead:
val bitMask = (0b1 shl shift)
val masked = (b.toInt() and bitMask)
return masked != 0

Code inside Kotlin's GlobalScope (Coroutine) is not working properly

I'm trying to make visualizer of quicksort algorithm, the functionality of alogrithm is fine but when i put the code in GlobalScope so that i can use delay to visulize things, the algorithm behaves differently.
Here are my functions....
//Quick Sort Part
private suspend fun partition(arr: MutableList<Button>, low: Int, high: Int): Int {
//If I comment this job, and run the code the algorithm works
val job2 = GlobalScope.launch(Dispatchers.Main) {
var low = low
var high = high
var pivot = arr[(low + high) / 2].layoutParams.height
while (low <= high) {
Log.d(TAG, "partition: $low $high")
while (arr[low].layoutParams.height < pivot) {
low++
}
while (arr[high].layoutParams.height > pivot) {
high--
}
if (low <= high) {
val temp = arr[low].layoutParams.height
arr[low].layoutParams.height = arr[high].layoutParams.height
arr[high].layoutParams.height = temp
root_layout.requestLayout()
low++
high--
}
}
}
job2.join()
return low
}
private fun quickSort(arr: MutableList<Button>, low: Int, high: Int) {
val job1 = GlobalScope.launch(Dispatchers.Main) {
val pi = partition(arr, low, high)
if (low < pi - 1) {
quickSort(arr, low, pi - 1)
}
if (pi < high) {
quickSort(arr, pi, high)
}
}
}
This is the result of that function, and if i don't use coroutine, this works fine, all the bars gets sorted in increasing order..
Because you have defined the low and high variables inside the launch scope, and updating it there but still returning the variable which was received as parameter.
Define it in the outerscope:
var low = low // define the variable in the outer scope
val job2 = GlobalScope.launch(Dispatchers.Main) { // ...
But shadowing isn't the best way (it is error prone as it tricked you), just name it something else for simplicity.
Tip: Use of Main thread is usually for less CPU intensive tasks and should be used mainly for displaying stuffs and updating UI. For computational tasks feel free to use the Dispatchers.Default!
Also using Jobs for doing tasks and joining them isn't that optimized than withContext which is intended for returning the result from another Dispatching thread easily, use it instead!
private suspend fun partition(arr: MutableList<Button>, low: Int, high: Int): Int {
return withContext(Dispatchers.Default) {
var low = low
var high = high
var pivot = arr[(low + high) / 2].layoutParams.height
while (low <= high) {
Log.d(TAG, "partition: $low $high")
while (arr[low].layoutParams.height < pivot) {
low++
}
while (arr[high].layoutParams.height > pivot) {
high--
}
if (low <= high) {
val temp = arr[low].layoutParams.height
arr[low].layoutParams.height = arr[high].layoutParams.height
arr[high].layoutParams.height = temp
root_layout.requestLayout()
low++
high--
}
}
low //^withContext
}
}

What to use in Kotlin/Java for effective float collections handling?

I'm working on an audio editing app, and I need to store the samples as floats in an efficient way - memory as well as performance-wise. Right now I'm using simply Kotlin's List, but I've heard about potential gains from using FloatArray type. I made a synthetic test to see the benefits and the results are a bit weird. Any advice on the techniques and collections I should use for large datasets of this nature could earn you a cookie, if I had one and knew your location.
So I have two alternative channel implementations (as in - channel in an audio file), to hold my data.
Here is my code for the channel based on FloatArray:
class ArrayChannel {
private var mData : FloatArray = FloatArray(0)
private var mLastWrittenIndex = 0
fun getSamples(startIndex : Int = 0, endIndex : Int = mLastWrittenIndex) : FloatArray
= mData.sliceArray(IntRange(0, endIndex - 1))
fun insertSamples(samples : FloatArray, startIndex : Int = mLastWrittenIndex) {
if (mData.size - mLastWrittenIndex < samples.size) {
val newData = FloatArray(mData.size + samples.size )
mData.copyInto(newData, 0, 0, startIndex)
samples.copyInto(newData, startIndex)
mData.copyInto(newData, startIndex + samples.size, startIndex)
mData = newData
} else {
mData.copyInto(mData, startIndex + samples.size, startIndex, mLastWrittenIndex)
samples.copyInto(mData, startIndex)
}
mLastWrittenIndex += samples.size
}
fun getSamplesSize(): Int = mLastWrittenIndex
}
And here is my code for the channel based on List:
class Channel {
private var mData = mutableListOf<Float>()
fun getSamples(startIndex : Int = 0, endIndex : Int = mData.size) : List<Float>
= mData.slice(IntRange(0, endIndex - 1))
fun insertSamples(samples : List<Float>, startIndex : Int = mData.size) {
mData.addAll(startIndex, samples)
}
fun getSamplesSize() : Int = mData.size
}
Here is the measuring code:
val initialValuesArray = FloatArray(1000000) {Random.nextFloat()}
val valuesToAddArray = FloatArray(1000000) {Random.nextFloat()}
val initialValuesList = MutableList(1000000) {Random.nextFloat()}
val valuesToAddList = MutableList(1000000) {Random.nextFloat()}
var startTime = System.currentTimeMillis()
val arrayChannel = ArrayChannel()
arrayChannel.insertSamples(initialValuesArray)
arrayChannel.insertSamples(valuesToAddArray, 0)
println("Array time: ${System.currentTimeMillis() - startTime}")
startTime = System.currentTimeMillis()
val listChannel = Channel()
listChannel.insertSamples(initialValuesList)
listChannel.insertSamples(valuesToAddList, 0)
println("List time: ${System.currentTimeMillis() - startTime}")
Now, the average results from a direct fun main() call in Android studio are as following:
Array time: 56
List time: 6
A change in the allocation of the array, instead of mData.size + samples.size to mData.size + samples.size * 2, makes these different, in a very weird way:
Array time: 17
List time: 48
When I run the same code inside of an Activity instead of some main Kotlin function, the results match more what I was expecting and are promising:
2020-08-17 21:15:33.325 D/ARRAY_TIME: 15
2020-08-17 21:15:33.481 D/LIST_TIME: 156
Why the code behaves this way and what do you think would be a good way of handling lots of numerical data in the Android environment?

HERE SDK Prem - how to get compressedRoute?

I am trying to get hotels to the length of the route, using REST request
The request has a parameter compressedRoute, but the conversion algorithm in Java script language.
Is there such an algorithm in Java or Kotlin? Maybe such a request is in the SDK, but I do not see it?
points to take from route.routeElements.geometry.allPoints?
I managed to compress the route. The problem was in the error of the example on JS.
First you need to go through to limit the number of points in the route, I set 120. If you do more, 414 errors may occur
fun execute(route: Route, categoryName: String, radiusInMeters: Int): Single<List<ItemPlaceByCorridor>> {
val allPointList = route.routeGeometry
val pointList = ArrayList<GeoCoordinate>()
for ((index, elem) in allPointList.withIndex()) {
if (index % (allPointList.size / POINTS_IN_ROUTE) == 0 || (index == 0) || (index == allPointList.lastIndex)) {
pointList.add(elem)
}
}
var routeStr = hereEncodePolyline(pointList)
routeStr += ";w=$radiusInMeters"
return mHereMapsApi.getPlacesByCorridor(categoryName, routeStr)
.map { response -> response.results.listItems }
}
Algorithm transferred from JS to Kotlin
private fun hereEncodePolyline(positions: List<GeoCoordinate>): String {
var lastLat = 0.0
var lastLon = 0.0
var result = ""
for (i in 1..positions.lastIndex) {
val elem = positions[i]
result += hereEncodeFloat(elem.latitude - lastLat)
result += hereEncodeFloat(elem.longitude - lastLon)
lastLat = elem.latitude
lastLon = elem.longitude
}
return result
}
private fun hereEncodeFloat(value: Double): String {
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
var result = ""
// convert to fixed point
var fixedPoint = Math.round(value * 100000)
// make room on the lowest bit
fixedPoint = fixedPoint shl (1)
// flip bits of negative numbers and ensure that the last bit is set
// (should actually always be the case, but for readability it is ok to do it explicitly)
if (fixedPoint < 0) {
fixedPoint = (fixedPoint.inv()) or 0x01
}
// var-length encode the number in chunks of 5 bits starting with the least significant
// to the most significant
while (fixedPoint > 0x1F) {
result += (chars[((fixedPoint and 0x1F) or 0x20).toInt()]).toString()
fixedPoint = fixedPoint shr (5)
}
result += (chars[fixedPoint.toInt()])
return result
}

In Kotlin, whats the cleanest way to convert a Long to uint32 ByteArray and an Int to uint8?

fun longToByteArray(value: Long): ByteArray {
val bytes = ByteArray(8)
ByteBuffer.wrap(bytes).putLong(value)
return Arrays.copyOfRange(bytes, 4, 8)
}
fun intToUInt8(value: Int): ByteArray {
val bytes = ByteArray(4)
ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).putInt(value and 0xff)
var array = Arrays.copyOfRange(bytes, 0, 1)
return array
}
I think these are the Kotlin equivalents of some Java ways, but I'm wondering if these approaches are correct/necessary in Kotlin.
Edit: Fixing examples per comments, also demonstrating changing byte order. Thank you for the feedback. I'm going to accept the answer that demonstrated how to do this without ByteBuffer.
I prefer not to use ByteBuffer because it adds a dependency to the JVM. Instead I use:
fun longToUInt32ByteArray(value: Long): ByteArray {
val bytes = ByteArray(4)
bytes[3] = (value and 0xFFFF).toByte()
bytes[2] = ((value ushr 8) and 0xFFFF).toByte()
bytes[1] = ((value ushr 16) and 0xFFFF).toByte()
bytes[0] = ((value ushr 24) and 0xFFFF).toByte()
return bytes
}

Categories

Resources