Skip to content

Commit

Permalink
Changes for updating to Yggdrasil 0.5. (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
Revertron authored Oct 28, 2023
1 parent 9df80c0 commit f4e1a75
Show file tree
Hide file tree
Showing 16 changed files with 189 additions and 78 deletions.
23 changes: 11 additions & 12 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ plugins {
}

android {
compileSdkVersion 29
buildToolsVersion "30.0.3"
compileSdkVersion 33

defaultConfig {
applicationId "eu.neilalexander.yggdrasil"
minSdkVersion 21
targetSdkVersion 29
versionCode 13
versionName "0.1-013"
targetSdkVersion 33
versionCode 14
versionName "0.1-014"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down Expand Up @@ -51,12 +50,12 @@ android {
dependencies {
implementation fileTree(include: ['*.aar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.preference:preference-ktx:1.1.0'
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.preference:preference-ktx:1.2.1'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
5 changes: 3 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application
Expand All @@ -23,8 +24,8 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SettingsActivity" android:parentActivityName=".MainActivity" />
<activity android:name=".PeersActivity" android:parentActivityName=".MainActivity" />
<activity android:name=".SettingsActivity" android:parentActivityName=".MainActivity" android:exported="false" />
<activity android:name=".PeersActivity" android:parentActivityName=".MainActivity" android:exported="false" />
<activity android:name=".DnsActivity" android:exported="false" />
<activity android:name=".TileServiceActivity" android:theme="@android:style/Theme.NoDisplay"
android:allowTaskReparenting="true"
Expand Down
15 changes: 11 additions & 4 deletions app/src/main/java/eu/neilalexander/yggdrasil/ConfigurationProxy.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,12 @@ object ConfigurationProxy {
val newJson = JSONObject(String(Mobile.generateConfigJSON()))
updateJSON { json ->
json.put("PrivateKey", newJson.getString("PrivateKey"))
json.put("PublicKey", newJson.getString("PublicKey"))
}
}

fun setKeys(privateKey: String, publicKey: String) {
fun setKeys(privateKey: String) {
updateJSON { json ->
json.put("PrivateKey", privateKey)
json.put("PublicKey", publicKey)
}
}

Expand All @@ -62,7 +60,8 @@ object ConfigurationProxy {
{
"Regex": ".*",
"Beacon": true,
"Listen": true
"Listen": true,
"Password": ""
}
""".trimIndent()))
json.put("MulticastInterfaces", ar)
Expand Down Expand Up @@ -94,4 +93,12 @@ object ConfigurationProxy {
(json.getJSONArray("MulticastInterfaces").get(0) as JSONObject).put("Beacon", value)
}
}

var multicastPassword: String
get() = (json.getJSONArray("MulticastInterfaces").get(0) as JSONObject).getString("Password")
set(value) {
updateJSON { json ->
(json.getJSONArray("MulticastInterfaces").get(0) as JSONObject).put("Password", value)
}
}
}
18 changes: 14 additions & 4 deletions app/src/main/java/eu/neilalexander/yggdrasil/GlobalApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ class GlobalApplication: Application(), YggStateReceiver.StateReceiver {
@RequiresApi(Build.VERSION_CODES.N)
override fun onStateChange(state: State) {
if (state != currentState) {
val componentName = ComponentName(this, YggTileService::class.java)
TileService.requestListeningState(this, componentName)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val componentName = ComponentName(this, YggTileService::class.java)
TileService.requestListeningState(this, componentName)
}

if (state != State.Disabled) {
val notification = createServiceNotification(this, state)
Expand All @@ -68,7 +70,11 @@ fun createServiceNotification(context: Context, state: State): Notification {
val intent = Intent(context, MainActivity::class.java).apply {
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
var flags = PendingIntent.FLAG_UPDATE_CURRENT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, flags)

val text = when (state) {
State.Disabled -> context.getText(R.string.tile_disabled)
Expand All @@ -91,7 +97,11 @@ fun createPermissionMissingNotification(context: Context): Notification {
val intent = Intent(context, MainActivity::class.java).apply {
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
var flags = PendingIntent.FLAG_UPDATE_CURRENT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, flags)

return NotificationCompat.Builder(context, MAIN_CHANNEL_ID)
.setShowWhen(false)
Expand Down
16 changes: 8 additions & 8 deletions app/src/main/java/eu/neilalexander/yggdrasil/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class MainActivity : AppCompatActivity() {
private lateinit var enabledLabel: TextView
private lateinit var ipAddressLabel: TextView
private lateinit var subnetLabel: TextView
private lateinit var coordinatesLabel: TextView
private lateinit var treeLengthLabel: TextView
private lateinit var peersLabel: TextView
private lateinit var peersRow: LinearLayoutCompat
private lateinit var dnsLabel: TextView
Expand Down Expand Up @@ -53,7 +53,7 @@ class MainActivity : AppCompatActivity() {
enabledLabel = findViewById(R.id.yggdrasilStatusLabel)
ipAddressLabel = findViewById(R.id.ipAddressValue)
subnetLabel = findViewById(R.id.subnetValue)
coordinatesLabel = findViewById(R.id.coordinatesValue)
treeLengthLabel = findViewById(R.id.treeLengthValue)
peersLabel = findViewById(R.id.peersValue)
peersRow = findViewById(R.id.peersTableRow)
dnsLabel = findViewById(R.id.dnsValue)
Expand Down Expand Up @@ -155,11 +155,11 @@ class MainActivity : AppCompatActivity() {
"state" -> {
enabledLabel.text = if (intent.getBooleanExtra("started", false)) {
var count = 0
if (intent.hasExtra("dht")) {
val dht = intent.getStringExtra("dht")
if (dht != null && dht != "null") {
val dhtState = JSONArray(dht)
count = dhtState.length()
if (intent.hasExtra("tree")) {
val tree = intent.getStringExtra("tree")
if (tree != null && tree != "null") {
val treeState = JSONArray(tree)
count = treeState.length()
}
}
if (count == 0) {
Expand All @@ -175,7 +175,7 @@ class MainActivity : AppCompatActivity() {
}
ipAddressLabel.text = intent.getStringExtra("ip") ?: "N/A"
subnetLabel.text = intent.getStringExtra("subnet") ?: "N/A"
coordinatesLabel.text = intent.getStringExtra("coords") ?: "[]"
treeLengthLabel.text = intent.getStringExtra("coords") ?: "0"
if (intent.hasExtra("peers")) {
val peerState = JSONArray(intent.getStringExtra("peers") ?: "[]")
peersLabel.text = when (val count = peerState.length()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package eu.neilalexander.yggdrasil

import android.content.*
import android.content.Intent
import android.net.VpnService
import android.net.wifi.WifiManager
import android.os.Build
import android.os.ParcelFileDescriptor
import android.system.OsConstants
Expand Down Expand Up @@ -42,6 +43,7 @@ open class PacketTunnelProvider: VpnService() {
private var parcel: ParcelFileDescriptor? = null
private var readerStream: FileInputStream? = null
private var writerStream: FileOutputStream? = null
private var multicastLock: WifiManager.MulticastLock? = null

override fun onCreate() {
super.onCreate()
Expand Down Expand Up @@ -101,6 +103,13 @@ open class PacketTunnelProvider: VpnService() {
val notification = createServiceNotification(this, State.Enabled)
startForeground(SERVICE_NOTIFICATION_ID, notification)

// Acquire multicast lock
val wifi = applicationContext.getSystemService(WIFI_SERVICE) as WifiManager
multicastLock = wifi.createMulticastLock("Yggdrasil").apply {
setReferenceCounted(false)
acquire()
}

Log.d(TAG, config.getJSON().toString())
yggdrasil.startJSON(config.getJSONByteArray())

Expand Down Expand Up @@ -163,16 +172,7 @@ open class PacketTunnelProvider: VpnService() {
updater()
}

var intent = Intent(STATE_INTENT)
intent.putExtra("type", "state")
intent.putExtra("started", true)
intent.putExtra("ip", yggdrasil.addressString)
intent.putExtra("subnet", yggdrasil.subnetString)
intent.putExtra("coords", yggdrasil.coordsString)
intent.putExtra("peers", yggdrasil.peersJSON)
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)

intent = Intent(YGG_STATE_INTENT)
var intent = Intent(YGG_STATE_INTENT)
intent.putExtra("state", STATE_ENABLED)
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
}
Expand Down Expand Up @@ -221,6 +221,7 @@ open class PacketTunnelProvider: VpnService() {

stopForeground(true)
stopSelf()
multicastLock?.release()
}

private fun connect() {
Expand All @@ -231,27 +232,37 @@ open class PacketTunnelProvider: VpnService() {
}

private fun updater() {
Thread.sleep(500)
var lastStateUpdate = System.currentTimeMillis()
updates@ while (started.get()) {
val treeJSON = yggdrasil.treeJSON
var treeLength = 0
if (treeJSON != null && treeJSON != "null") {
val treeState = JSONArray(treeJSON)
treeLength = treeState.length()
}
if ((application as GlobalApplication).needUiUpdates()) {
val intent = Intent(STATE_INTENT)
intent.putExtra("type", "state")
intent.putExtra("started", true)
intent.putExtra("ip", yggdrasil.addressString)
intent.putExtra("subnet", yggdrasil.subnetString)
intent.putExtra("coords", yggdrasil.coordsString)
intent.putExtra("pubkey", yggdrasil.publicKeyString)
intent.putExtra("coords", "$treeLength")
intent.putExtra("peers", yggdrasil.peersJSON)
intent.putExtra("dht", yggdrasil.dhtjson)
intent.putExtra("tree", treeJSON)
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
}
val curTime = System.currentTimeMillis()
if (lastStateUpdate + 10000 < curTime) {
val intent = Intent(YGG_STATE_INTENT)
var state = STATE_ENABLED
val dht = yggdrasil.dhtjson
if (dht != null && dht != "null") {
val dhtState = JSONArray(dht)
val count = dhtState.length()
if (yggdrasil.routingEntries > 0) {
state = STATE_CONNECTED
}
if (treeJSON != null && treeJSON != "null") {
val treeState = JSONArray(treeJSON)
val count = treeState.length()
if (count > 1)
state = STATE_CONNECTED
}
Expand Down
34 changes: 32 additions & 2 deletions app/src/main/java/eu/neilalexander/yggdrasil/PeersActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ import android.content.Intent
import android.content.IntentFilter
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.ContextThemeWrapper
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.widget.*
import androidx.core.widget.doOnTextChanged
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.google.android.material.textfield.TextInputEditText
import org.json.JSONArray
Expand All @@ -27,6 +30,7 @@ class PeersActivity : AppCompatActivity() {
private lateinit var configuredTableLabel: TextView
private lateinit var multicastListenSwitch: Switch
private lateinit var multicastBeaconSwitch: Switch
private lateinit var passwordEdit: EditText
private lateinit var addPeerButton: ImageButton

override fun onCreate(savedInstanceState: Bundle?) {
Expand Down Expand Up @@ -62,6 +66,30 @@ class PeersActivity : AppCompatActivity() {
multicastListenPanel.setOnClickListener {
multicastListenSwitch.toggle()
}
passwordEdit = findViewById(R.id.passwordEdit)
passwordEdit.setText(config.multicastPassword)

passwordEdit.doOnTextChanged { text, _, _, _ ->
config.multicastPassword = text.toString()
}

passwordEdit.setOnKeyListener { _, keyCode, _ ->
(keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER)
}

findViewById<View>(R.id.passwordTableRow).setOnKeyListener { _, keyCode, event ->
Log.i("Key", keyCode.toString())
if (event.action == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) {
passwordEdit.requestFocus()
true
} else {
false
}
} else {
false
}
}

addPeerButton = findViewById(R.id.addPeerButton)
addPeerButton.setOnClickListener {
Expand Down Expand Up @@ -156,7 +184,7 @@ class PeersActivity : AppCompatActivity() {
val view = inflater.inflate(R.layout.peers_connected, null)
val ip = peer.getString("IP")
view.findViewById<TextView>(R.id.addressLabel).text = ip
view.findViewById<TextView>(R.id.detailsLabel).text = peer.getString("Remote")
view.findViewById<TextView>(R.id.detailsLabel).text = peer.getString("URI")
connectedTableLayout.addView(view)
}
}
Expand All @@ -168,7 +196,9 @@ class PeersActivity : AppCompatActivity() {
when (intent.getStringExtra("type")) {
"state" -> {
if (intent.hasExtra("peers")) {
val peersArray = JSONArray(intent.getStringExtra("peers") ?: "[]")
val peers1 = intent.getStringExtra("peers")
//Log.i("PeersActivity", "Peers json: $peers1")
val peersArray = JSONArray(peers1 ?: "[]")
val array = Array(peersArray.length()) { i ->
peersArray.getJSONObject(i)
}
Expand Down
Loading

0 comments on commit f4e1a75

Please sign in to comment.