Код: Выделить всё
class DPNService : VpnService() {
private val currentConnection = AtomicReference()
private val handshakeServiceListener = object : HandshakeService.Listener {
override fun onError(exception: Exception) {
Log.e(TAG, "Handshake error", exception)
}
override fun onSuccess(params: ServerParams, tunnel: DatagramChannel) {
protect(tunnel.socket())
updateNotification("VPN is connecting...")
val vpnInterface = configureVpnService(params)
vpnInterface?.let {
connect(tunnel, it)
}
}
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
if (intent.action == ACTION_CONNECT) {
val tunnel = DatagramChannel.open()
if (protect(tunnel.socket())) {
val handshakeService = HandshakeService(tunnel, handshakeServiceListener)
handshakeService.sendHandshake()
}
return START_STICKY
}
if (intent.action == ACTION_DISCONNECT){
disconnect()
return START_NOT_STICKY
}
return super.onStartCommand(intent, flags, startId)
}
private fun connect(tunnel: DatagramChannel, vpnInterface: ParcelFileDescriptor?) {
val connection = DPNConnection(tunnel, vpnInterface)
val thread = Thread(connection, "DPN Connection")
setCurrentConnection(thread)
thread.start()
updateNotification("VPN is connected")
}
private fun configureVpnService(serverParams: ServerParams): ParcelFileDescriptor? {
val builder = this.Builder()
builder.addAddress(serverParams.address, serverParams.addressPrefixLength)
builder.addDnsServer(serverParams.dns)
builder.addRoute(serverParams.route, serverParams.routePrefixLength)
builder.setMtu(serverParams.mtu)
builder.addDisallowedApplication("com.google.chrome")
builder.addDisallowedApplication("com.werebug.androidnetcat")
builder.setSession(serverParams.address)
return builder.establish()
}
private fun disconnect() {
setCurrentConnection(null)
stopSelf()
}
override fun onDestroy() {
disconnect()
}
private fun setCurrentConnection(thread: Thread?) {
// set new thread and interrupt old
currentConnection.getAndSet(thread)?.interrupt()
}
private fun updateNotification(message: String) {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val notificationChannel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_ID,
NotificationManager.IMPORTANCE_HIGH,
)
val notification = Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_vpn_key)
.setContentText(message)
.build()
notificationManager.createNotificationChannel(notificationChannel)
notificationManager.notify(1, notification)
}
companion object {
const val TAG = "DPNService"
const val ACTION_CONNECT = "DPNService.CONNECT"
const val ACTION_DISCONNECT = "DPNService.DISCONNECT"
const val NOTIFICATION_CHANNEL_ID = "DPN"
}
}
class DPNConnection(
private val tunnel: DatagramChannel,
private val vpnInterface: ParcelFileDescriptor?,
) : Runnable {
override fun run() {
var iteration = 0
while (iteration < 100) {
iteration++
try {
tunnel.sendMessage("Hello DPN Server Side".toByteArray())
} catch (e: Exception) {
Log.e(TAG, "DPNConnection", e)
}
}
tunnel.close()
}
private fun DatagramChannel.sendMessage(byteArray: ByteArray) {
val buffer = ByteBuffer.allocate(1024)
buffer.put(byteArray)
buffer.flip()
write(buffer)
}
companion object {
private const val TAG = "DPNConnection"
}
}
Код: Выделить всё
DPNConnection
java.net.PortUnreachableException
at sun.nio.ch.DatagramDispatcher.write0(Native Method)
at sun.nio.ch.DatagramDispatcher.write(DatagramDispatcher.java:60)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:65)
at sun.nio.ch.DatagramChannelImpl.write(DatagramChannelImpl.java:649)
at com.example.dpn.data.DPNConnection.sendMessage(DPNConnection.kt:35)
at com.example.dpn.data.DPNConnection.run(DPNConnection.kt:20)
at java.lang.Thread.run(Thread.java:1012)
Подробнее здесь: https://stackoverflow.com/questions/785 ... g-vpnservi