-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathScanner.kt
59 lines (47 loc) · 1.89 KB
/
Scanner.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
@file:Include("ScanResult.kt")
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import java.io.IOException
import java.net.InetAddress
import java.net.NetworkInterface
import java.time.LocalDateTime
fun ping(ipAddress: String): Boolean {
val address = InetAddress.getByName(ipAddress)
return try {
address.isReachable(2000)
} catch (e: IOException) {
println("Could not reach IP address: $ipAddress. Reason: $e")
false
}
}
suspend fun ping(addresses: List<String>): List<ScanResult> = coroutineScope {
val res = addresses.map { ipAddress ->
println("Pinging IP address: $ipAddress...")
val deferred = async(Dispatchers.IO) {
ScanResult(ipAddress = ipAddress, up = ping(ipAddress), scannedAt = LocalDateTime.now())
}
println("Done")
deferred
}
res.map { it.await() }
}
suspend fun pingNetwork(broadcastAddress: String): List<ScanResult> {
val endIpAddress = broadcastAddress.substring(broadcastAddress.length - 3, broadcastAddress.length)
val ipStartRange = broadcastAddress.substring(0, broadcastAddress.length - 3)
println("Pinging network with broadcast address: $broadcastAddress")
val addresses = IntRange(start = 1, endInclusive = endIpAddress.toInt() - 1).map { "$ipStartRange$it" }
return ping(addresses)
}
fun findBroadcastAddresses() = NetworkInterface.getNetworkInterfaces().toList()
.filterNotNull()
.filter { !it.isLoopback && it.isUp }
.flatMap { it.interfaceAddresses }
.mapNotNull { it.broadcast }
.map { it.hostAddress }
.toList()
suspend fun scan(): List<ScanResult> {
val broadcastAddressesToScan = findBroadcastAddresses()
println("Ranges to scan: $broadcastAddressesToScan")
return broadcastAddressesToScan.flatMap { pingNetwork(it) }.filter { it.up }
}