1. added DNS form. iteration 1.

This commit is contained in:
vadym 2020-06-25 13:09:24 -07:00
parent aec660bff0
commit 3db311c4d2
18 changed files with 486 additions and 39 deletions

View File

@ -18,7 +18,10 @@
android:name=".PeerListActivity"
android:label="@string/title_activity_peer_list"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".DNSListActivity"
android:label="@string/title_activity_dns_list"
android:theme="@style/AppTheme.NoActionBar" />
<service
android:name=".YggdrasilTunService"
android:enabled="true"

View File

@ -0,0 +1,109 @@
package io.github.chronosx88.yggdrasil
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import android.widget.Button
import android.widget.ListView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import io.github.chronosx88.yggdrasil.models.DNSInfo
import io.github.chronosx88.yggdrasil.models.config.SelectDNSInfoListAdapter
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.ping
import kotlinx.coroutines.*
import java.net.*
import kotlin.concurrent.thread
class DNSListActivity : AppCompatActivity() {
companion object {
val allDNS = arrayListOf(
DNSInfo(
InetAddress.getByName("[301:2522::53]"),
"CZ",
"DNS implementation for Yggdrasil. https://github.com/Revertron/wyrd"),
DNSInfo(InetAddress.getByName("[301:2923::53]"),
"SK",
"DNS implementation for Yggdrasil. https://github.com/Revertron/wyrd"),
DNSInfo(InetAddress.getByName("[300:4523::53]"),
"DE",
"DNS implementation for Yggdrasil. https://github.com/Revertron/wyrd"),
DNSInfo(InetAddress.getByName("[303:8b1a::53]"),
"RU",
"DNS implementation for Yggdrasil. https://github.com/Revertron/wyrd")
)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dns_list)
setSupportActionBar(findViewById(R.id.toolbar))
findViewById<FloatingActionButton>(R.id.fab).setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
var extras = intent.extras
var dnsList = findViewById<ListView>(R.id.dnsList)
var adapter = SelectDNSInfoListAdapter(this, arrayListOf(), mutableSetOf())
dnsList.adapter = adapter
thread(start = true) {
try {
var cd = MainActivity.deserializeStringList2DNSInfoSet(
extras!!.getStringArrayList(MainActivity.DNS_LIST)!!
)
for (d in cd) {
var ping = ping(d.address, 53)
d.ping = ping
}
for (dns in allDNS) {
if (cd.contains(dns)) {
continue
}
var ping = ping(dns.address, 53)
dns.ping = ping
adapter.addItem(dns)
runOnUiThread(
Runnable
{
adapter.sort()
}
)
}
} catch (e: Throwable) {
e.printStackTrace()
}
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.save, menu)
val item = menu.findItem(R.id.saveItem) as MenuItem
item.setActionView(R.layout.menu_save)
val saveButton = item
.actionView.findViewById<Button>(R.id.saveButton)
saveButton.setOnClickListener {
val result = Intent(this, MainActivity::class.java)
var adapter = findViewById<ListView>(R.id.dnsList).adapter as SelectDNSInfoListAdapter
val selectedDNS = adapter.getSelectedDNS()
if(selectedDNS.size>0) {
result.putExtra(MainActivity.DNS_LIST, MainActivity.serializeDNSInfoSet2StringList(selectedDNS))
setResult(Activity.RESULT_OK, result)
finish()
} else {
val text = "Select at least one DNS"
val duration = Toast.LENGTH_SHORT
val toast = Toast.makeText(applicationContext, text, duration)
toast.setGravity(Gravity.CENTER, 0, 0)
toast.show()
}
}
return true
}
}

View File

@ -13,7 +13,9 @@ import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceManager
import com.google.gson.Gson
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 kotlin.collections.ArrayList
import kotlin.collections.HashSet
@ -31,9 +33,13 @@ class MainActivity : AppCompatActivity() {
const val STATUS_STOP = 9
const val IPv6: String = "IPv6"
const val PEERS: String = "PEERS"
const val DNS: String = "DNS"
const val PEER_LIST_CODE = 1000
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.1"
const val CURRENT_DNS = "CURRENT_DNS_v1.1"
const val START_VPN = "START_VPN"
private const val TAG="Yggdrasil"
private const val VPN_REQUEST_CODE = 0x0F
@ -48,6 +54,16 @@ class MainActivity : AppCompatActivity() {
return out
}
@JvmStatic
fun deserializeStringList2DNSInfoSet(list: List<String>): MutableSet<DNSInfo> {
var gson = Gson()
var out = mutableSetOf<DNSInfo>()
for(s in list) {
out.add(gson.fromJson(s, DNSInfo::class.java))
}
return out
}
@JvmStatic
fun deserializeStringSet2PeerInfoSet(list: Set<String>): MutableSet<PeerInfo> {
var gson = Gson()
@ -58,6 +74,16 @@ class MainActivity : AppCompatActivity() {
return out
}
@JvmStatic
fun deserializeStringSet2DNSInfoSet(list: Set<String>): MutableSet<DNSInfo> {
var gson = Gson()
var out = mutableSetOf<DNSInfo>()
for(s in list) {
out.add(gson.fromJson(s, DNSInfo::class.java))
}
return out
}
@JvmStatic
fun serializePeerInfoSet2StringList(list: Set<PeerInfo>): ArrayList<String> {
var gson = Gson()
@ -67,10 +93,21 @@ class MainActivity : AppCompatActivity() {
}
return out
}
@JvmStatic
fun serializeDNSInfoSet2StringList(list: Set<DNSInfo>): ArrayList<String> {
var gson = Gson()
var out = ArrayList<String>()
for(p in list) {
out.add(gson.toJson(p))
}
return out
}
}
private var startVpnFlag = false
private var currentPeers = setOf<PeerInfo>()
private var currentDNS = setOf<DNSInfo>()
private var isStarted = false
override fun onCreate(savedInstanceState: Bundle?) {
@ -82,7 +119,7 @@ class MainActivity : AppCompatActivity() {
PreferenceManager.getDefaultSharedPreferences(this.baseContext)
currentPeers = deserializeStringSet2PeerInfoSet(preferences.getStringSet(CURRENT_PEERS, HashSet())!!)
val adapter = PeerInfoListAdapter(this, ArrayList(currentPeers))
val adapter = PeerInfoListAdapter(this, currentPeers.sortedWith(compareBy { it.ping }))
listView.adapter = adapter
val editPeersButton = findViewById<Button>(R.id.edit)
editPeersButton.setOnClickListener {
@ -90,10 +127,25 @@ class MainActivity : AppCompatActivity() {
showToast("Service is running. Please stop service before edit Peers list")
return@setOnClickListener
}
val intent = Intent(this, PeerListActivity::class.java)
val intent = Intent(this@MainActivity, PeerListActivity::class.java)
intent.putStringArrayListExtra(PEER_LIST, serializePeerInfoSet2StringList(currentPeers))
startActivityForResult(intent, PEER_LIST_CODE)
}
val listViewDNS = findViewById<ListView>(R.id.dns)
currentDNS = deserializeStringSet2DNSInfoSet(preferences.getStringSet(CURRENT_DNS, HashSet())!!)
val adapterDns = DNSInfoListAdapter(this, currentDNS.sortedWith(compareBy { it.ping }))
listViewDNS.adapter = adapterDns
val editDnsButton = findViewById<Button>(R.id.editDNS)
editDnsButton.setOnClickListener {
if(!isStarted){
showToast("Service is not running. DNS ping will not be run")
return@setOnClickListener
}
val intent = Intent(this@MainActivity, DNSListActivity::class.java)
intent.putStringArrayListExtra(DNS_LIST, serializeDNSInfoSet2StringList(currentDNS))
startActivityForResult(intent, DNS_LIST_CODE)
}
if(intent.extras!==null) {
startVpnFlag = intent.extras!!.getBoolean(START_VPN, false)
}
@ -123,6 +175,7 @@ class MainActivity : AppCompatActivity() {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == VPN_REQUEST_CODE && resultCode== Activity.RESULT_OK){
if(currentPeers.isEmpty()){
showToast("No peers selected!")
@ -134,8 +187,10 @@ class MainActivity : AppCompatActivity() {
intent.putExtra(PARAM_PINTENT, pi)
intent.putExtra(COMMAND, START)
intent.putStringArrayListExtra(PEERS, serializePeerInfoSet2StringList(currentPeers))
intent.putStringArrayListExtra(DNS, serializeDNSInfoSet2StringList(currentDNS))
startService(intent)
}
if (requestCode == PEER_LIST_CODE && resultCode== Activity.RESULT_OK){
if(data!!.extras!=null){
var currentPeers = data.extras!!.getStringArrayList(PEER_LIST)
@ -152,7 +207,7 @@ class MainActivity : AppCompatActivity() {
PreferenceManager.getDefaultSharedPreferences(this.baseContext)
preferences.edit().putStringSet(CURRENT_PEERS, HashSet(currentPeers)).apply()
if(isStarted){
//TODO implement UpdateConfig methon in native interface and apply peer changes
//TODO implement UpdateConfig method in native interface and apply peer changes
stopVpn()
val i = baseContext.packageManager
.getLaunchIntentForPackage(baseContext.packageName)
@ -165,6 +220,36 @@ class MainActivity : AppCompatActivity() {
}
}
}
if (requestCode == DNS_LIST_CODE && resultCode== Activity.RESULT_OK){
if(data!!.extras!=null){
var currentDNS = data.extras!!.getStringArrayList(DNS_LIST)
if(currentDNS==null || currentDNS.size==0){
showToast("No DNS selected!")
} else {
this.currentDNS = deserializeStringList2DNSInfoSet(currentDNS)
val adapter = DNSInfoListAdapter(this, this.currentDNS.sortedWith(compareBy { it.ping }))
val listView = findViewById<ListView>(R.id.dns)
listView.adapter = adapter
//save to shared preferences
val preferences =
PreferenceManager.getDefaultSharedPreferences(this.baseContext)
preferences.edit().putStringSet(CURRENT_DNS, HashSet(currentDNS)).apply()
if(isStarted){
//TODO implement UpdateConfig method in native interface and apply peer changes
stopVpn()
val i = baseContext.packageManager
.getLaunchIntentForPackage(baseContext.packageName)
i!!.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
i.putExtra(START_VPN, true)
finish()
startActivity(i)
}
}
}
}
when (resultCode) {
STATUS_START -> print("service started")
STATUS_FINISH -> {

View File

@ -18,6 +18,7 @@ import com.hbb20.CCPCountry
import io.github.chronosx88.yggdrasil.models.PeerInfo
import io.github.chronosx88.yggdrasil.models.Status
import io.github.chronosx88.yggdrasil.models.config.SelectPeerInfoListAdapter
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.ping
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
@ -44,19 +45,6 @@ class PeerListActivity : AppCompatActivity() {
}
}
fun ping(address: InetAddress, port:Int): Int {
val start = System.currentTimeMillis()
val socket = Socket()
try {
socket.connect(InetSocketAddress(address, port), 5000)
socket.close()
} catch (e: Exception) {
//silently pass
return Int.MAX_VALUE
}
return (System.currentTimeMillis() - start).toInt()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_peer_list)
@ -67,8 +55,7 @@ class PeerListActivity : AppCompatActivity() {
}
var extras = intent.extras
var peerList = findViewById<ListView>(R.id.peerList)
var allPeers = arrayListOf<PeerInfo>()
var adapter = SelectPeerInfoListAdapter(this, allPeers, mutableSetOf())
var adapter = SelectPeerInfoListAdapter(this, arrayListOf(), mutableSetOf())
peerList.adapter = adapter
GlobalScope.launch {
@ -103,7 +90,7 @@ class PeerListActivity : AppCompatActivity() {
var ping = ping(address, url.port)
peerInfo.ping = ping
adapter.addItem(peerInfo)
if(peerList.adapter.count % 5 == 0) {
if(adapter.count % 5 == 0) {
withContext(Dispatchers.Main) {
adapter.sort()
}
@ -128,7 +115,7 @@ class PeerListActivity : AppCompatActivity() {
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.save_peers, menu)
menuInflater.inflate(R.menu.save, menu)
val item = menu.findItem(R.id.saveItem) as MenuItem
item.setActionView(R.layout.menu_save)
val saveButton = item

View File

@ -7,6 +7,7 @@ import android.os.ParcelFileDescriptor
import android.system.OsConstants
import com.google.gson.Gson
import dummy.ConduitEndpoint
import io.github.chronosx88.yggdrasil.models.DNSInfo
import io.github.chronosx88.yggdrasil.models.PeerInfo
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.cancel
@ -53,18 +54,21 @@ class YggdrasilTunService : VpnService() {
}
if (intent?.getStringExtra(MainActivity.COMMAND) == MainActivity.START) {
val peers = MainActivity.deserializeStringList2PeerInfoSet(intent.getStringArrayListExtra(MainActivity.PEERS))
val dns = MainActivity.deserializeStringList2DNSInfoSet(intent.getStringArrayListExtra(MainActivity.DNS))
val pi: PendingIntent = intent.getParcelableExtra(MainActivity.PARAM_PINTENT)
ygg = Yggdrasil()
setupTunInterface(pi, peers)
setupTunInterface(pi, peers, dns)
}
return super.onStartCommand(intent, flags, startId)
}
private fun setupTunInterface(pi: PendingIntent, peers: Set<PeerInfo>) {
private fun setupTunInterface(
pi: PendingIntent,
peers: Set<PeerInfo>,
dns: MutableSet<DNSInfo>
) {
pi.send(MainActivity.STATUS_START)
val builder = Builder()
var configJson = Mobile.generateConfigJSON()
val gson = Gson()
var config = gson.fromJson(String(configJson), Map::class.java).toMutableMap()
@ -74,12 +78,16 @@ class YggdrasilTunService : VpnService() {
yggConduitEndpoint = ygg.startJSON(configJson)
val address = ygg.addressString // hack for getting generic ipv6 string from NodeID
tunInterface = builder
var builder = Builder()
.addAddress(address, 7)
.allowFamily(OsConstants.AF_INET)
.setMtu(MAX_PACKET_SIZE)
.establish()
if(dns.size>0){
for (d in dns){
builder.addDnsServer(d.address)
}
}
tunInterface = builder.establish()
tunInputStream = FileInputStream(tunInterface!!.fileDescriptor)
tunOutputStream = FileOutputStream(tunInterface!!.fileDescriptor)
readCoroutine = GlobalScope.launch {

View File

@ -0,0 +1,34 @@
package io.github.chronosx88.yggdrasil.models
import android.content.Context
import com.hbb20.CCPCountry
import com.hbb20.CountryCodePicker
import java.net.InetAddress
class DNSInfo {
constructor(address: InetAddress, countryCode: String, description: String){
this.address = address
this.countryCode = countryCode
this.description = description
}
var address: InetAddress
var countryCode: String
var description: String
var ping: Int = Int.MAX_VALUE
override fun toString(): String {
return "[" + address.toString().substring(1) + "]"
}
override fun equals(other: Any?): Boolean {
return toString() == other.toString()
}
fun getCountry(context: Context): CCPCountry? {
return CCPCountry.getCountryForNameCodeFromLibraryMasterList(context, CountryCodePicker.Language.ENGLISH, countryCode)
}
}

View File

@ -0,0 +1,44 @@
package io.github.chronosx88.yggdrasil.models.config
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.ImageView
import android.widget.TextView
import io.github.chronosx88.yggdrasil.R
import io.github.chronosx88.yggdrasil.models.DNSInfo
class DNSInfoListAdapter(
context: Context,
allDNS: List<DNSInfo>
) : ArrayAdapter<DNSInfo?> (context, 0, allDNS) {
private val mContext: Context = context
private var allDNS: List<DNSInfo> = allDNS
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var dnsInfoHolder = DNSInfoHolder()
var listItem: View? = convertView
if (listItem == null) {
listItem = LayoutInflater.from(mContext).inflate(R.layout.host_list_item, parent, false)
dnsInfoHolder.countryFlag = listItem.findViewById(R.id.countryFlag) as ImageView
dnsInfoHolder.dnsInfoText = listItem.findViewById(R.id.hostInfoText) as TextView
listItem.tag = dnsInfoHolder
} else {
dnsInfoHolder = listItem.tag as DNSInfoHolder
}
val currentDNS = allDNS[position]
dnsInfoHolder.countryFlag.setImageResource(currentDNS.getCountry(mContext)!!.flagID)
dnsInfoHolder.dnsInfoText.text = currentDNS.toString()
return listItem!!
}
class DNSInfoHolder {
lateinit var countryFlag: ImageView
lateinit var dnsInfoText: TextView
}
}

View File

@ -5,12 +5,10 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.CheckBox
import android.widget.ImageView
import android.widget.TextView
import io.github.chronosx88.yggdrasil.R
import io.github.chronosx88.yggdrasil.models.PeerInfo
import java.util.ArrayList
class PeerInfoListAdapter(
@ -25,17 +23,16 @@ class PeerInfoListAdapter(
var peerInfoHolder = PeerInfoHolder()
var listItem: View? = convertView
if (listItem == null) {
listItem = LayoutInflater.from(mContext).inflate(R.layout.peers_list_item, parent, false)
listItem = LayoutInflater.from(mContext).inflate(R.layout.host_list_item, parent, false)
peerInfoHolder.countryFlag = listItem.findViewById(R.id.countryFlag) as ImageView
peerInfoHolder.peerInfoText = listItem.findViewById(R.id.peerInfoText) as TextView
peerInfoHolder.peerInfoText = listItem.findViewById(R.id.hostInfoText) as TextView
listItem.tag = peerInfoHolder
} else {
peerInfoHolder = listItem.tag as PeerInfoHolder
}
val currentPeer = allPeers[position]
peerInfoHolder.countryFlag.setImageResource(currentPeer.getCountry(mContext)!!.flagID)
val peerId = currentPeer.toString()
peerInfoHolder.peerInfoText.text = peerId
peerInfoHolder.peerInfoText.text = currentPeer.toString()
return listItem!!
}

View File

@ -0,0 +1,99 @@
package io.github.chronosx88.yggdrasil.models.config
import android.content.Context
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.CheckBox
import android.widget.ImageView
import android.widget.TextView
import io.github.chronosx88.yggdrasil.R
import io.github.chronosx88.yggdrasil.models.DNSInfo
class SelectDNSInfoListAdapter(
context: Context,
allDNS: List<DNSInfo>,
currentDNS: MutableSet<DNSInfo>
) : ArrayAdapter<DNSInfo?> (context, 0, allDNS) {
private val mContext: Context = context
private var allDNS: MutableList<DNSInfo> = allDNS as MutableList<DNSInfo>
private var currentDNS: MutableSet<DNSInfo> = currentDNS
override fun getItem(position: Int): DNSInfo? {
return allDNS.get(position)
}
override fun getCount(): Int {
return allDNS.size
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var dnsInfoHolder = DNSInfoHolder()
var listItem: View? = convertView
if (listItem == null) {
listItem = LayoutInflater.from(mContext).inflate(R.layout.host_list_item_edit, parent, false)
dnsInfoHolder.checkbox = listItem.findViewById(R.id.checkbox) as CheckBox
dnsInfoHolder.countryFlag = listItem.findViewById(R.id.countryFlag) as ImageView
dnsInfoHolder.dnsInfoText = listItem.findViewById(R.id.hostInfoText) as TextView
dnsInfoHolder.ping = listItem.findViewById(R.id.ping) as TextView
listItem.tag = dnsInfoHolder
} else {
dnsInfoHolder = listItem.tag as DNSInfoHolder
}
val currentDNS = allDNS[position]
dnsInfoHolder.countryFlag.setImageResource(currentDNS.getCountry(mContext)!!.flagID)
val dnsId = currentDNS.toString()
if(currentDNS.ping == Int.MAX_VALUE){
dnsInfoHolder.dnsInfoText.text = dnsId
dnsInfoHolder.ping.text=""
dnsInfoHolder.dnsInfoText.setTextColor(Color.GRAY)
} else {
dnsInfoHolder.dnsInfoText.text = dnsId
dnsInfoHolder.ping.text = currentDNS.ping.toString() + " ms"
dnsInfoHolder.dnsInfoText.setTextColor(Color.WHITE)
}
dnsInfoHolder.checkbox.setOnCheckedChangeListener { _, isChecked ->
if(isChecked){
if(!this.currentDNS.contains(currentDNS)){
this.currentDNS.add(currentDNS)
}
} else {
if(this.currentDNS.contains(currentDNS)){
this.currentDNS.remove(currentDNS)
}
}
}
dnsInfoHolder.checkbox.isChecked = this.currentDNS.contains(currentDNS)
return listItem!!
}
fun getSelectedDNS(): Set<DNSInfo> {
return currentDNS
}
fun addItem(peerInfo: DNSInfo){
allDNS.add(peerInfo)
}
fun addAll(index: Int, peerInfo: ArrayList<DNSInfo>){
currentDNS.addAll(peerInfo)
allDNS.removeAll(peerInfo)
allDNS.addAll(index, peerInfo)
this.notifyDataSetChanged()
}
fun sort(){
allDNS = ArrayList(allDNS.sortedWith(compareBy { it.ping }))
this.notifyDataSetChanged()
}
class DNSInfoHolder {
lateinit var checkbox: CheckBox
lateinit var countryFlag: ImageView
lateinit var dnsInfoText: TextView
lateinit var ping: TextView
}
}

View File

@ -34,10 +34,10 @@ class SelectPeerInfoListAdapter(
var peerInfoHolder = PeerInfoHolder()
var listItem: View? = convertView
if (listItem == null) {
listItem = LayoutInflater.from(mContext).inflate(R.layout.peers_list_item_edit, parent, false)
listItem = LayoutInflater.from(mContext).inflate(R.layout.host_list_item_edit, parent, false)
peerInfoHolder.checkbox = listItem.findViewById(R.id.checkbox) as CheckBox
peerInfoHolder.countryFlag = listItem.findViewById(R.id.countryFlag) as ImageView
peerInfoHolder.peerInfoText = listItem.findViewById(R.id.peerInfoText) as TextView
peerInfoHolder.peerInfoText = listItem.findViewById(R.id.hostInfoText) as TextView
peerInfoHolder.ping = listItem.findViewById(R.id.ping) as TextView
listItem.tag = peerInfoHolder
} else {

View File

@ -0,0 +1,27 @@
package io.github.chronosx88.yggdrasil.models.config
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.Socket
class Utils {
companion object {
@JvmStatic
fun ping(address: InetAddress, port:Int): Int {
val start = System.currentTimeMillis()
val socket = Socket()
try {
socket.connect(InetSocketAddress(address, port), 5000)
socket.close()
} catch (e: Exception) {
e.printStackTrace()
print(address)
return Int.MAX_VALUE
}
return (System.currentTimeMillis() - start).toInt()
}
}
}

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DNSListActivity"
android:background="@color/grey">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_dns_list" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_margin="@dimen/fab_margin"
app:backgroundTint="@color/green"
app:tint="@color/white"
app:borderWidth="0dp"
app:elevation="6dp"
app:fabSize="normal"
app:srcCompat="@android:drawable/ic_input_add"
android:visibility="gone"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -131,7 +131,7 @@
</androidx.constraintlayout.widget.ConstraintLayout>
<ListView
android:id="@+id/dnsList"
android:id="@+id/dns"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<ListView
android:id="@+id/dnsList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/dark_20"
android:dividerHeight="2px"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -15,7 +15,7 @@
android:scaleType="fitStart"/>
</FrameLayout>
<TextView
android:id="@+id/peerInfoText"
android:id="@+id/hostInfoText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"

View File

@ -31,7 +31,7 @@
android:layout_toEndOf="@+id/frame"
android:layout_centerInParent="true"/>
<TextView
android:id="@+id/peerInfoText"
android:id="@+id/hostInfoText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"

View File

@ -4,4 +4,5 @@
<string name="disconnect_button">Disconnect</string>
<string name="switch_button_title">SwitchOn</string>
<string name="title_activity_peer_list">Edit peers</string>
<string name="title_activity_dns_list">Edit DNS</string>
</resources>