1. added peers update in Mesh mode

This commit is contained in:
vadym 2020-07-01 01:53:34 -07:00
parent e597fff59b
commit bca4b88d3d
6 changed files with 159 additions and 15 deletions

View File

@ -2,10 +2,7 @@ package io.github.chronosx88.yggdrasil
import android.app.Activity
import android.app.ActivityManager
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.*
import android.net.VpnService
import android.os.Bundle
import android.util.Log
@ -18,17 +15,26 @@ import io.github.chronosx88.yggdrasil.models.DNSInfo
import io.github.chronosx88.yggdrasil.models.PeerInfo
import io.github.chronosx88.yggdrasil.models.config.DNSInfoListAdapter
import io.github.chronosx88.yggdrasil.models.config.PeerInfoListAdapter
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.deserializePeerStringList2PeerInfoSet
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.deserializeStringList2DNSInfoSet
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.deserializeStringList2PeerInfoSet
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.deserializeStringSet2DNSInfoSet
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.deserializeStringSet2PeerInfoSet
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.serializeDNSInfoSet2StringList
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.serializePeerInfoSet2StringList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.net.InetAddress
import kotlin.concurrent.thread
class MainActivity : AppCompatActivity() {
companion object {
const val STATUS_PEERS_UPDATE = 12
const val MESH_PEERS = "MESH_PEERS"
const val STATIC_IP = "STATIC_IP_FLAG"
const val signingPrivateKey = "signingPrivateKey"
const val signingPublicKey = "signingPublicKey"
@ -38,6 +44,7 @@ class MainActivity : AppCompatActivity() {
const val STOP = "STOP"
const val START = "START"
const val UPDATE_DNS = "UPDATE_DNS"
const val UPDATE_PEERS = "UPDATE_PEERS"
const val PARAM_PINTENT = "pendingIntent"
const val STATUS_START = 7
const val STATUS_FINISH = 8
@ -49,7 +56,7 @@ class MainActivity : AppCompatActivity() {
const val DNS_LIST_CODE = 2000
const val PEER_LIST = "PEERS_LIST"
const val DNS_LIST = "DNS_LIST"
const val CURRENT_PEERS = "CURRENT_PEERS_v1.2"
const val CURRENT_PEERS = "CURRENT_PEERS_v1.2.1"
const val CURRENT_DNS = "CURRENT_DNS_v1.2"
const val START_VPN = "START_VPN"
private const val TAG="Yggdrasil"
@ -62,6 +69,7 @@ class MainActivity : AppCompatActivity() {
private var currentPeers = setOf<PeerInfo>()
private var currentDNS = setOf<DNSInfo>()
private var meshPeersReceiver: BroadcastReceiver? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -169,6 +177,16 @@ class MainActivity : AppCompatActivity() {
startService(intent)
}
private fun updatePeers(){
Log.d(TAG,"Update Peers")
val intent = Intent(this, YggdrasilTunService::class.java)
val TASK_CODE = 100
val pi = createPendingResult(TASK_CODE, intent, 0)
intent.putExtra(PARAM_PINTENT, pi)
intent.putExtra(COMMAND, UPDATE_PEERS)
startService(intent)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
@ -244,7 +262,20 @@ class MainActivity : AppCompatActivity() {
}
when (resultCode) {
STATUS_START -> print("service started")
STATUS_START -> {
print("service started")
if(this.currentPeers.isEmpty()){
//this is Mesh mode, send Peers update every 5 sec
thread(start = true) {
while(true) {
Thread.sleep(5000)
if(isStarted) {
updatePeers()
}
}
}
}
}
STATUS_FINISH -> {
isStarted = true
val ipLayout = findViewById<LinearLayout>(R.id.ipLayout)
@ -257,6 +288,23 @@ class MainActivity : AppCompatActivity() {
val ipLayout = findViewById<LinearLayout>(R.id.ipLayout)
ipLayout.visibility = View.GONE
}
STATUS_PEERS_UPDATE ->{
if(data!!.extras!=null) {
thread(start = true) {
val meshPeers = deserializePeerStringList2PeerInfoSet(
data.extras!!.getStringArrayList(MESH_PEERS)
)
val listView = findViewById<ListView>(R.id.peers)
val adapter = PeerInfoListAdapter(
this@MainActivity,
meshPeers.sortedWith(compareBy { it.ping })
)
runOnUiThread {
listView.adapter = adapter
}
}
}
}
else -> { // Note the block
}
@ -290,4 +338,11 @@ class MainActivity : AppCompatActivity() {
preferences.getString(STATIC_IP, null) != null
}
override fun onDestroy() {
super.onDestroy()
if (meshPeersReceiver != null){
unregisterReceiver(meshPeersReceiver);
}
}
}

View File

@ -16,9 +16,12 @@ import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.preference.PreferenceManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import dummy.ConduitEndpoint
import io.github.chronosx88.yggdrasil.models.DNSInfo
import io.github.chronosx88.yggdrasil.models.PeerInfo
import io.github.chronosx88.yggdrasil.models.config.Peer
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.convertPeer2PeerStringList
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.convertPeerInfoSet2PeerIdSet
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.deserializeStringList2DNSInfoSet
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.deserializeStringList2PeerInfoSet
@ -27,6 +30,7 @@ import mobile.Mobile
import mobile.Yggdrasil
import java.io.*
import java.net.Inet6Address
import kotlin.concurrent.thread
class YggdrasilTunService : VpnService() {
@ -56,10 +60,9 @@ class YggdrasilTunService : VpnService() {
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val pi: PendingIntent? = intent?.getParcelableExtra(MainActivity.PARAM_PINTENT)
when(intent?.getStringExtra(MainActivity.COMMAND)){
MainActivity.STOP ->{
val pi: PendingIntent? = intent.getParcelableExtra(MainActivity.PARAM_PINTENT)
stopVpn(pi)
startForeground(FOREGROUND_ID, foregroundNotification("Yggdrasil service stopped"))
}
@ -67,7 +70,6 @@ class YggdrasilTunService : VpnService() {
val peers = deserializeStringList2PeerInfoSet(intent.getStringArrayListExtra(MainActivity.PEERS))
val dns = deserializeStringList2DNSInfoSet(intent.getStringArrayListExtra(MainActivity.DNS))
val staticIP: Boolean = intent.getBooleanExtra(MainActivity.STATIC_IP, false)
val pi: PendingIntent = intent.getParcelableExtra(MainActivity.PARAM_PINTENT)
ygg = Yggdrasil()
setupTunInterface(pi, peers, dns, staticIP)
startForeground(FOREGROUND_ID, foregroundNotification("Yggdrasil service started"))
@ -76,6 +78,9 @@ class YggdrasilTunService : VpnService() {
val dns = deserializeStringList2DNSInfoSet(intent.getStringArrayListExtra(MainActivity.DNS))
setupIOStreams(dns)
}
MainActivity.UPDATE_PEERS ->{
sendMeshPeerStatus(pi)
}
}
return START_NOT_STICKY
@ -141,11 +146,22 @@ class YggdrasilTunService : VpnService() {
writePacketsToTun(yggConduitEndpoint)
}
}
val intent: Intent = Intent().putExtra(MainActivity.IPv6, address)
pi.send(this, MainActivity.STATUS_FINISH, intent)
}
private fun sendMeshPeerStatus(pi: PendingIntent?){
class Token : TypeToken<List<Peer>>()
var add = ygg.addressString
var meshPeers: List<Peer> = gson.fromJson(ygg.peersJSON, Token().type)
val intent: Intent = Intent().putStringArrayListExtra(
MainActivity.MESH_PEERS,
convertPeer2PeerStringList(meshPeers)
);
pi?.send(this, MainActivity.STATUS_PEERS_UPDATE, intent)
}
private fun fixConfig(
config: MutableMap<Any?, Any?>,
peers: Set<PeerInfo>,
@ -231,7 +247,6 @@ class YggdrasilTunService : VpnService() {
private fun stopVpn(pi: PendingIntent?) {
isClosed = true;
tunInputStream!!.close()
tunOutputStream!!.close()
tunInterface!!.close()

View File

@ -19,12 +19,28 @@ class PeerInfo {
this.port = port
this.countryCode = countryCode
}
constructor(schema: String, address: InetAddress, port: Int, countryCode: String?, isMeshPeer: Boolean){
this.schema = schema
this.address = address
var a = address.toString();
if(a.lastIndexOf('/')>0){
this.hostName = a.split("/")[0]
} else {
this.hostName = a.substring(1)
}
this.port = port
this.countryCode = countryCode
this.isMeshPeer = isMeshPeer
}
var schema: String
var address: InetAddress
var hostName: String
var port = 0
var countryCode: String
var countryCode: String?=null
var ping: Int = Int.MAX_VALUE
var isMeshPeer = false
override fun toString(): String {
if(this.hostName.contains(":")) {
@ -39,7 +55,14 @@ class PeerInfo {
}
fun getCountry(context: Context): CCPCountry? {
return CCPCountry.getCountryForNameCodeFromLibraryMasterList(context, CountryCodePicker.Language.ENGLISH, countryCode)
if(countryCode==null){
return null
} else {
return CCPCountry.getCountryForNameCodeFromLibraryMasterList(
context,
CountryCodePicker.Language.ENGLISH,
countryCode
)
}
}
}

View File

@ -0,0 +1,13 @@
package io.github.chronosx88.yggdrasil.models.config
import com.google.gson.annotations.SerializedName
data class Peer (
//Example [{"PublicKey":[154,201,118,156,19,74,134,115,94,159,76,86,36,192,221,105,220,254,226,161,108,226,17,192,75,243,225,15,42,195,155,2],"Endpoint":"(self)","BytesSent":0,"BytesRecvd":0,"Protocol":"self","Port":0,"Uptime":209900460}]
@SerializedName("Endpoint") var endpoint : String,
@SerializedName("Port") var port : Int,
@SerializedName("Uptime") var uptime : Long,
@SerializedName("Protocol") var protocol : String,
@SerializedName("BytesSent") var bytesSent : Long,
@SerializedName("BytesRecvd") var bytesReceived : Long
)

View File

@ -31,7 +31,11 @@ class PeerInfoListAdapter(
peerInfoHolder = listItem.tag as PeerInfoHolder
}
val currentPeer = allPeers[position]
if(currentPeer.isMeshPeer){
//TODO set mesh icon
} else {
peerInfoHolder.countryFlag.setImageResource(currentPeer.getCountry(mContext)!!.flagID)
}
peerInfoHolder.peerInfoText.text = currentPeer.toString()
return listItem!!
}

View File

@ -99,5 +99,39 @@ class Utils {
return out
}
@JvmStatic
fun convertPeer2PeerStringList(list: List<Peer>): ArrayList<String> {
var out = ArrayList<String>()
var gson = Gson()
for(p in list) {
out.add(gson.toJson(p))
}
return out
}
@JvmStatic
fun deserializePeerStringList2PeerInfoSet(list: List<String>?): MutableSet<PeerInfo> {
var gson = Gson()
var out = mutableSetOf<PeerInfo>()
if (list != null) {
for(s in list) {
var p = gson.fromJson(s, Peer::class.java)
if(p.endpoint == "(self)"){
out.add(PeerInfo(p.protocol, InetAddress.getByName("localhost"), p.port, null, true))
} else {
out.add(
PeerInfo(
p.protocol,
InetAddress.getByName(p.endpoint),
p.port,
null,
true
)
)
}
}
}
return out
}
}
}