Stub of ping object
This commit is contained in:
parent
bc9ba0ae54
commit
eb19b3e36a
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "libs/int-serializers"]
|
||||||
|
path = libs/int-serializers
|
||||||
|
url = https://git.landgrafhomyak.ru/xomrk/int-serializers.kt
|
1
libs/int-serializers
Submodule
1
libs/int-serializers
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 1d4b797c31e0fa622c2fb411c3e202de85b3aadc
|
@ -3,4 +3,6 @@ package ru.landgrafhomyak.bgtu.networks0.build_script
|
|||||||
object Dependencies {
|
object Dependencies {
|
||||||
val kotlin_atomicfu = "org.jetbrains.kotlinx:atomicfu:${Versions.kotlin_atomicfu}"
|
val kotlin_atomicfu = "org.jetbrains.kotlinx:atomicfu:${Versions.kotlin_atomicfu}"
|
||||||
val kotlin_coroutines_core = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlin_coroutines_core}"
|
val kotlin_coroutines_core = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlin_coroutines_core}"
|
||||||
|
val int_serializers = "ru.landgrafhomyak.utility:int-serializers:${Versions.int_serializers}"
|
||||||
|
val kotlin_datetime = "org.jetbrains.kotlinx:kotlinx-datetime:${Versions.kotlin_datetime}"
|
||||||
}
|
}
|
@ -4,4 +4,6 @@ package ru.landgrafhomyak.bgtu.networks0.build_script
|
|||||||
object Versions {
|
object Versions {
|
||||||
val kotlin_atomicfu = "0.27.0"
|
val kotlin_atomicfu = "0.27.0"
|
||||||
val kotlin_coroutines_core = "1.10.1"
|
val kotlin_coroutines_core = "1.10.1"
|
||||||
|
val int_serializers = "1.1"
|
||||||
|
val kotlin_datetime = "0.6.2"
|
||||||
}
|
}
|
27
modules/icmp/build.gradle.kts
Normal file
27
modules/icmp/build.gradle.kts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import ru.landgrafhomyak.bgtu.networks0.build_script.Dependencies
|
||||||
|
import ru.landgrafhomyak.kotlin.kmp_gradle_build_helper.defineAllMultiplatformTargets
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven("https://maven.landgrafhomyak.ru/")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
defineAllMultiplatformTargets()
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
implementation(Dependencies.kotlin_coroutines_core)
|
||||||
|
implementation(Dependencies.kotlin_datetime)
|
||||||
|
implementation(Dependencies.int_serializers)
|
||||||
|
implementation(project(":modules:low-level:sockets"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.networks0.icmp
|
||||||
|
|
||||||
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
|
interface IcmpHeader {
|
||||||
|
val type: UByte
|
||||||
|
val code: UByte
|
||||||
|
fun checksum(withData: UByteArray): UShort
|
||||||
|
|
||||||
|
fun serialize(withData: UByteArray): UByteArray
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.networks0.icmp
|
||||||
|
|
||||||
|
import ru.landgrafhomyak.utility.IntSerializers
|
||||||
|
|
||||||
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
|
class IcmpPingHeader(
|
||||||
|
val identifier_be: UShort,
|
||||||
|
val seqNo_be: UShort,
|
||||||
|
) : IcmpHeader {
|
||||||
|
override val type: UByte get() = 8u
|
||||||
|
override val code: UByte get() = 0u
|
||||||
|
|
||||||
|
override fun checksum(withData: UByteArray): UShort = Ipv4Checksum.calculate { c ->
|
||||||
|
c.addFirstByte(this.type)
|
||||||
|
c.addSecondByte(this.code)
|
||||||
|
c.addWord(this.identifier_be)
|
||||||
|
c.addWord(this.seqNo_be)
|
||||||
|
c.addTrailingData(withData)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(withData: UByteArray): UByteArray {
|
||||||
|
val serialized = UByteArray(withData.size + 8)
|
||||||
|
IntSerializers.encode8Bu(serialized, 0, this.type)
|
||||||
|
IntSerializers.encode8Bu(serialized, 1, this.code)
|
||||||
|
IntSerializers.encode16beHu(serialized, 2, this.checksum(withData))
|
||||||
|
IntSerializers.encode16beHu(serialized, 4, this.identifier_be)
|
||||||
|
IntSerializers.encode16beHu(serialized, 6, this.seqNo_be)
|
||||||
|
withData.copyInto(serialized, 8)
|
||||||
|
return serialized
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.networks0.icmp
|
||||||
|
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.InvocationKind
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
|
internal class Ipv4Checksum() {
|
||||||
|
private var _accumulator: UInt = 0u
|
||||||
|
|
||||||
|
fun addFirstByte(b: UByte) {
|
||||||
|
this._accumulator += (b.toUInt() shl 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addSecondByte(b: UByte) {
|
||||||
|
this._accumulator += b
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addWord(b: UShort) {
|
||||||
|
this._accumulator += b
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addLastByte(b: UByte) {
|
||||||
|
this._accumulator += b
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addTrailingData(data: UByteArray) {
|
||||||
|
for (i in data.indices step 2) {
|
||||||
|
this.addFirstByte(data[i])
|
||||||
|
this.addSecondByte(data[i + 1])
|
||||||
|
}
|
||||||
|
if (data.size % 2 != 0)
|
||||||
|
this.addLastByte(data.last())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun export(): UShort {
|
||||||
|
var out: UInt = this._accumulator
|
||||||
|
while (out > 0xFFFFu) {
|
||||||
|
out = (out and 0xFFFFu) + (out shr 16);
|
||||||
|
}
|
||||||
|
return out.toUShort().inv()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@OptIn(ExperimentalContracts::class)
|
||||||
|
inline fun calculate(builder: (Ipv4Checksum) -> Unit): UShort {
|
||||||
|
contract {
|
||||||
|
callsInPlace(builder, InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
val b = Ipv4Checksum()
|
||||||
|
builder(b)
|
||||||
|
return b.export()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.networks0.icmp
|
||||||
|
|
||||||
|
import kotlin.coroutines.Continuation
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.TimeoutCancellationException
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
import kotlinx.coroutines.withTimeout
|
||||||
|
import kotlinx.datetime.Clock
|
||||||
|
import kotlinx.datetime.Instant
|
||||||
|
import kotlinx.coroutines.sync.Mutex as CMutex
|
||||||
|
import ru.landgrafhomyak.bgtu.networks0.low_level.sockets.IcmpSocket
|
||||||
|
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose1
|
||||||
|
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose2
|
||||||
|
import ru.landgrafhomyak.utility.IntSerializers
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
|
class PingSocket : AutoCloseable {
|
||||||
|
private val _rawSocket: IcmpSocket
|
||||||
|
private val _mapSync: CMutex
|
||||||
|
private val _resumeMap: HashMap<ShortKeyPair, Continuation<Unit>>
|
||||||
|
private val _recvCoro: Job
|
||||||
|
|
||||||
|
internal constructor(rawSocket: IcmpSocket) {
|
||||||
|
safeAutoClose2(onAbort = rawSocket::close) {
|
||||||
|
this._rawSocket = rawSocket
|
||||||
|
this._resumeMap = HashMap()
|
||||||
|
this._mapSync = CMutex()
|
||||||
|
this._recvCoro = CoroutineScope(Dispatchers.Default).launch { this@PingSocket._recvRoutine() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ShortKeyPair(val identifier: UShort, val seqNo: UShort) {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other !is ShortKeyPair) return false
|
||||||
|
return this.identifier == other.identifier && this.seqNo == other.seqNo
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return ((this.identifier.toUInt() shl 16) or (this.seqNo).toUInt()).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = "<icmp ping key pair identifier=${this.identifier} seq_no=${this.seqNo}>"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun _generateKeyPair(): ShortKeyPair {
|
||||||
|
val timestamp = Clock.System.now()
|
||||||
|
return ShortKeyPair(
|
||||||
|
identifier = (timestamp.epochSeconds ushr 13).toULong().toUShort(),
|
||||||
|
seqNo = ((timestamp.epochSeconds shl 3) or ((((timestamp.nanosecondsOfSecond ushr 27) and 7).toLong())) and 0xFFFF).toULong().toUShort(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun ping(timeoutMillis: UInt): UInt? {
|
||||||
|
var isLocked = true
|
||||||
|
val start: Instant
|
||||||
|
this._mapSync.lock()
|
||||||
|
safeAutoClose1(finally = { if (isLocked) this._mapSync.unlock() }) {
|
||||||
|
val key = this._generateKeyPair()
|
||||||
|
val header = IcmpPingHeader(identifier_be = key.identifier, seqNo_be = key.seqNo)
|
||||||
|
val serialized = header.serialize(PingSocket.randomData)
|
||||||
|
start = Clock.System.now()
|
||||||
|
this._rawSocket.sendRaw(serialized)
|
||||||
|
try {
|
||||||
|
withTimeout(timeoutMillis.toULong().toLong()) {
|
||||||
|
suspendCancellableCoroutine<Unit> { continuation ->
|
||||||
|
if (key in this@PingSocket._resumeMap)
|
||||||
|
throw RuntimeException("Key duplication (shouldn't happen)")
|
||||||
|
this@PingSocket._resumeMap[key] = continuation
|
||||||
|
this@PingSocket._mapSync.unlock()
|
||||||
|
isLocked = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_: TimeoutCancellationException) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val td = Clock.System.now() - start
|
||||||
|
return td.inWholeMilliseconds.toUInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun _recvRoutine() {
|
||||||
|
try {
|
||||||
|
// todo handle errors
|
||||||
|
while (true) {
|
||||||
|
val raw = this._rawSocket.recvRaw()
|
||||||
|
if (raw.size < 8) continue
|
||||||
|
val key = ShortKeyPair(identifier = IntSerializers.decode16beHu(raw, 4), seqNo = IntSerializers.decode16beHu(raw, 6))
|
||||||
|
val continuation = this._mapSync.withLock { this._resumeMap.remove(key) }
|
||||||
|
if (continuation == null) continue
|
||||||
|
continuation.resume(Unit)
|
||||||
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Suppress("SpellCheckingInspection")
|
||||||
|
private val randomData = "abcdefghijklmnopqrstuvwabcdefghi".encodeToByteArray().asUByteArray()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package ru.landgrafhomyak.bgtu.networks0.icmp
|
||||||
|
|
||||||
|
import ru.landgrafhomyak.bgtu.networks0.low_level.sockets.SocketEventLoopScope
|
||||||
|
|
||||||
|
fun SocketEventLoopScope.pingSocket_IPv4(addr: String): PingSocket = PingSocket(this.icmp_IPv4(addr))
|
||||||
|
fun SocketEventLoopScope.pingSocket_IPv6(addr: String): PingSocket = PingSocket(this.icmp_IPv6(addr))
|
@ -12,6 +12,9 @@ import kotlinx.cinterop.cValue
|
|||||||
import kotlinx.cinterop.get
|
import kotlinx.cinterop.get
|
||||||
import kotlinx.cinterop.memScoped
|
import kotlinx.cinterop.memScoped
|
||||||
import kotlinx.cinterop.ptr
|
import kotlinx.cinterop.ptr
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import platform.linux.EPOLLERR
|
||||||
|
import platform.linux.EPOLLHUP
|
||||||
import platform.linux.EPOLLIN
|
import platform.linux.EPOLLIN
|
||||||
import platform.linux.EPOLLONESHOT
|
import platform.linux.EPOLLONESHOT
|
||||||
import platform.linux.EPOLLOUT
|
import platform.linux.EPOLLOUT
|
||||||
@ -32,6 +35,7 @@ import ru.landgrafhomyak.bgtu.networks0.low_level.multithreading.withLock
|
|||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.CloseableRefCounter
|
import ru.landgrafhomyak.bgtu.networks0.utilities.CloseableRefCounter
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose1
|
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose1
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose2
|
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose2
|
||||||
|
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose2e
|
||||||
|
|
||||||
@OptIn(ExperimentalForeignApi::class)
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
@Suppress("JoinDeclarationAndAssignment", "ConvertSecondaryConstructorToPrimary", "FunctionName")
|
@Suppress("JoinDeclarationAndAssignment", "ConvertSecondaryConstructorToPrimary", "FunctionName")
|
||||||
@ -66,7 +70,7 @@ class EpollSocketEventLoop : SocketEventLoopScope.Closeable {
|
|||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun _waitFor(metadata: _SocketMetadata) {
|
private fun _schedule(metadata: _SocketMetadata) {
|
||||||
val ee = cValue<epoll_event> {
|
val ee = cValue<epoll_event> {
|
||||||
this.events = ((if (metadata.read == null) 0 else EPOLLIN) or (if (metadata.write == null) 0 else EPOLLOUT) or EPOLLONESHOT).toUInt()
|
this.events = ((if (metadata.read == null) 0 else EPOLLIN) or (if (metadata.write == null) 0 else EPOLLOUT) or EPOLLONESHOT).toUInt()
|
||||||
this.data.fd = metadata.fd
|
this.data.fd = metadata.fd
|
||||||
@ -96,7 +100,7 @@ class EpollSocketEventLoop : SocketEventLoopScope.Closeable {
|
|||||||
if (metadata.read != null)
|
if (metadata.read != null)
|
||||||
throw IllegalStateException("Socket already waiting for read")
|
throw IllegalStateException("Socket already waiting for read")
|
||||||
metadata.read = continuation
|
metadata.read = continuation
|
||||||
this._waitFor(metadata)
|
this._schedule(metadata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +110,7 @@ class EpollSocketEventLoop : SocketEventLoopScope.Closeable {
|
|||||||
if (metadata.write != null)
|
if (metadata.write != null)
|
||||||
throw IllegalStateException("Socket already waiting for write")
|
throw IllegalStateException("Socket already waiting for write")
|
||||||
metadata.write = continuation
|
metadata.write = continuation
|
||||||
this._waitFor(metadata)
|
this._schedule(metadata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,11 +122,11 @@ class EpollSocketEventLoop : SocketEventLoopScope.Closeable {
|
|||||||
metadata.read = null
|
metadata.read = null
|
||||||
}
|
}
|
||||||
if ((ev.events and EPOLLOUT.toUInt()) != 0u) {
|
if ((ev.events and EPOLLOUT.toUInt()) != 0u) {
|
||||||
(metadata.write ?: throw RuntimeException("Socket ready for read, but nobody requests")).resume(Unit)
|
(metadata.write ?: throw RuntimeException("Socket ready for write, but nobody requests")).resume(Unit)
|
||||||
metadata.write = null
|
metadata.write = null
|
||||||
}
|
}
|
||||||
if (metadata.read != null || metadata.write != null)
|
if (metadata.read != null || metadata.write != null)
|
||||||
this._waitFor(metadata)
|
this._schedule(metadata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +121,7 @@ internal abstract class NonblockingIcmpSocketImpl : IcmpSocket {
|
|||||||
this._socketFd, null, 0u,
|
this._socketFd, null, 0u,
|
||||||
MSG_NOSIGNAL or MSG_PEEK or MSG_TRUNC
|
MSG_NOSIGNAL or MSG_PEEK or MSG_TRUNC
|
||||||
)
|
)
|
||||||
|
|
||||||
if (bytesAvailable == 0L) continue@polling
|
if (bytesAvailable == 0L) continue@polling
|
||||||
if (bytesAvailable < 0) {
|
if (bytesAvailable < 0) {
|
||||||
when (errno) {
|
when (errno) {
|
||||||
@ -130,16 +131,16 @@ internal abstract class NonblockingIcmpSocketImpl : IcmpSocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val data = UByteArray(bytesAvailable.toInt())
|
val data = UByteArray(bytesAvailable.toInt())
|
||||||
var sentCount = data.usePinned { pinnedData ->
|
var receivedCount = data.usePinned { pinnedData ->
|
||||||
return@usePinned recv_lowlevel(this._socketFd, pinnedData.addressOf(0), data.size.toULong(), MSG_NOSIGNAL)
|
return@usePinned recv_lowlevel(this._socketFd, pinnedData.addressOf(0), data.size.toULong(), MSG_NOSIGNAL)
|
||||||
}
|
}
|
||||||
if (sentCount < 0) {
|
if (receivedCount < 0) {
|
||||||
when (errno) {
|
when (errno) {
|
||||||
EAGAIN, EWOULDBLOCK -> continue@polling
|
EAGAIN, EWOULDBLOCK -> continue@polling
|
||||||
else -> PosixUtilities.throwErrno { d -> RuntimeException("Failed to send message over ICMP socket: $d") }
|
else -> PosixUtilities.throwErrno { d -> RuntimeException("Failed to send message over ICMP socket: $d") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data
|
return data.sliceArray(((data[0] and 0xFu).toUInt().toInt() + 15)..<data.size)
|
||||||
}
|
}
|
||||||
@Suppress("KotlinUnreachableCode")
|
@Suppress("KotlinUnreachableCode")
|
||||||
throw RuntimeException("unreachable")
|
throw RuntimeException("unreachable")
|
||||||
|
@ -92,7 +92,8 @@ inline fun <R> safeAutoClose3e(
|
|||||||
if (!wasError) {
|
if (!wasError) {
|
||||||
if (crossReturned)
|
if (crossReturned)
|
||||||
onCrossReturn()
|
onCrossReturn()
|
||||||
onSuccess()
|
else
|
||||||
|
onSuccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
|
@ -20,6 +20,7 @@ kotlin {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":modules:low-level:multithreading"))
|
implementation(project(":modules:low-level:multithreading"))
|
||||||
implementation(project(":modules:low-level:sockets"))
|
implementation(project(":modules:low-level:sockets"))
|
||||||
|
implementation(project(":modules:icmp"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import ru.landgrafhomyak.bgtu.networks0.icmp.pingSocket_IPv4
|
||||||
import ru.landgrafhomyak.bgtu.networks0.low_level.multithreading.Thread
|
import ru.landgrafhomyak.bgtu.networks0.low_level.multithreading.Thread
|
||||||
import ru.landgrafhomyak.bgtu.networks0.low_level.sockets.EpollSocketEventLoop
|
import ru.landgrafhomyak.bgtu.networks0.low_level.sockets.EpollSocketEventLoop
|
||||||
|
|
||||||
@ -24,48 +25,14 @@ fun main() {
|
|||||||
val loopThread = Thread(EventLoopRoutine(loop))
|
val loopThread = Thread(EventLoopRoutine(loop))
|
||||||
loopThread.start()
|
loopThread.start()
|
||||||
|
|
||||||
val googleSock = loop.icmp_IPv4("8.8.8.8")
|
val googleSock = loop.pingSocket_IPv4("8.8.8.8")
|
||||||
val yandexSock = loop.icmp_IPv4("5.255.255.70")
|
|
||||||
val phoneSock = loop.icmp_IPv4("192.168.43.1")
|
|
||||||
val pingData = ubyteArrayOf(
|
|
||||||
0x08u, 0x00u, 0x4Cu, 0xE4u, 0x00u, 0x01u, 0x00u, 0x77u,
|
|
||||||
0x61u, 0x62u, 0x63u, 0x64u, 0x65u, 0x66u, 0x67u, 0x68u,
|
|
||||||
0x69u, 0x6Au, 0x6Bu, 0x6Cu, 0x6Du, 0x6Eu, 0x6Fu, 0x70u,
|
|
||||||
0x71u, 0x72u, 0x73u, 0x74u, 0x75u, 0x76u, 0x77u, 0x61u,
|
|
||||||
0x62u, 0x63u, 0x64u, 0x65u, 0x66u, 0x67u, 0x68u, 0x69u
|
|
||||||
)
|
|
||||||
|
|
||||||
runBlocking {
|
runBlocking {
|
||||||
launch {
|
while (true) {
|
||||||
while (true) {
|
print("google: ${googleSock.ping(1000u)}ms\n")
|
||||||
googleSock.sendRaw(pingData)
|
delay(1000)
|
||||||
print("sent to google\n")
|
|
||||||
googleSock.recvRaw()
|
|
||||||
print("got from google\n")
|
|
||||||
delay(1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
launch {
|
|
||||||
while (true) {
|
|
||||||
yandexSock.sendRaw(pingData)
|
|
||||||
print("sent to yandex\n")
|
|
||||||
yandexSock.recvRaw()
|
|
||||||
print("got from yandex\n")
|
|
||||||
delay(2500)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
launch {
|
|
||||||
while (true) {
|
|
||||||
phoneSock.sendRaw(pingData)
|
|
||||||
print("sent to phone\n")
|
|
||||||
phoneSock.recvRaw()
|
|
||||||
print("got from phone\n")
|
|
||||||
delay(5500)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,12 @@ pluginManagement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
includeBuild("./libs/int-serializers")
|
||||||
include(":modules:utilities")
|
include(":modules:utilities")
|
||||||
include(":modules:low-level:c-interop-utilities")
|
include(":modules:low-level:c-interop-utilities")
|
||||||
include(":modules:low-level:multithreading")
|
include(":modules:low-level:multithreading")
|
||||||
include(":modules:low-level:sockets")
|
include(":modules:low-level:sockets")
|
||||||
|
include(":modules:icmp")
|
||||||
include(":programs:test")
|
include(":programs:test")
|
Loading…
Reference in New Issue
Block a user