1. fixed service stop

2. created layout
This commit is contained in:
vadym 2020-06-13 02:14:45 -07:00
parent 04cc088f4d
commit eb480c2677
10 changed files with 137 additions and 64 deletions

View File

@ -6,7 +6,7 @@ android {
compileSdkVersion 29 compileSdkVersion 29
defaultConfig { defaultConfig {
applicationId "io.github.chronosx88.yggdrasil" applicationId "io.github.chronosx88.yggdrasil"
minSdkVersion 21 minSdkVersion 22
targetSdkVersion 29 targetSdkVersion 29
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"

View File

@ -24,10 +24,8 @@
<activity android:name=".MainActivity"> <activity android:name=".MainActivity">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
</application> </application>
</manifest> </manifest>

View File

@ -4,48 +4,55 @@ import android.app.Activity
import android.content.Intent import android.content.Intent
import android.net.VpnService import android.net.VpnService
import android.os.Bundle import android.os.Bundle
import android.widget.Button import android.util.Log
import android.widget.RadioGroup
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private var isYggStarted = false companion object {
private const val TAG="Yggdrasil";
private const val VPN_REQUEST_CODE = 0x0F
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
val connectRadioGroup = findViewById<RadioGroup>(R.id.connectRadioGroup)
connectRadioGroup.setOnCheckedChangeListener(
RadioGroup.OnCheckedChangeListener { group, checkedId ->
when (checkedId) {
R.id.disconnectButton -> stopVpn()
R.id.connectButton -> startVpn()
else -> { // Note the block
//print("x is neither 1 nor 2")
}
}
})
}
val connectButton = findViewById<Button>(R.id.connect_button) fun stopVpn(){
connectButton.setOnClickListener { Log.d(TAG,"Stop")
if(!isYggStarted) { val intent = Intent(this, YggdrasilTunService::class.java)
// Prepare to establish a VPN connection. intent.putExtra("COMMAND", "STOP")
// This method returns null if the VPN application is already prepared startService(intent)
// or if the user has previously consented to the VPN application. }
// Otherwise, it returns an Intent to a system activity.
val vpnIntent = VpnService.prepare(this) fun startVpn(){
if (vpnIntent != null) startActivityForResult( Log.d(TAG,"Start")
vpnIntent, val intent= VpnService.prepare(this)
0x0F if (intent!=null){
) startActivityForResult(intent, VPN_REQUEST_CODE);
else onActivityResult(0x0F, Activity.RESULT_OK, null) }else{
} else { onActivityResult(VPN_REQUEST_CODE, Activity.RESULT_OK, null);
// FIXME fix this shit, this code doesn't stop service for some reasons
val intent = Intent(this, YggdrasilTunService::class.java)
stopService(intent)
connectButton.text = "Connect"
isYggStarted = false
}
} }
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 0x0F && resultCode == Activity.RESULT_OK) { if (requestCode == VPN_REQUEST_CODE && resultCode== Activity.RESULT_OK){
val intent = Intent(this, YggdrasilTunService::class.java) val intent = Intent(this, YggdrasilTunService::class.java)
startService(intent) startService(intent)
val connectButton = findViewById<Button>(R.id.connect_button)
connectButton.text = "Disconnect"
isYggStarted = true
} }
} }
} }

View File

@ -1,7 +1,10 @@
package io.github.chronosx88.yggdrasil package io.github.chronosx88.yggdrasil
import android.app.Service import android.app.Service
import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.ConnectivityManager
import android.net.Network
import android.net.VpnService import android.net.VpnService
import android.os.ParcelFileDescriptor import android.os.ParcelFileDescriptor
import com.google.gson.Gson import com.google.gson.Gson
@ -36,7 +39,9 @@ class YggdrasilTunService : VpnService() {
private lateinit var writeCoroutine: CoroutineContext private lateinit var writeCoroutine: CoroutineContext
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId) if (intent?.getStringExtra("COMMAND") == "STOP") {
stopVpn()
}
return Service.START_STICKY return Service.START_STICKY
} }
@ -83,6 +88,22 @@ class YggdrasilTunService : VpnService() {
} }
} }
private fun getNonVpnNetworks(Address: String): Array<Network> {
val cm =
getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networks = cm.allNetworks
for (network in networks) {
val linkProperties = cm.getLinkProperties(network)
val addresses = linkProperties.linkAddresses
for (addr in addresses) {
if (addr.toString().startsWith(Address)) {
return arrayOf(network)
}
}
}
return emptyArray<Network>()
}
private fun fixConfig(config: MutableMap<Any?, Any?>): MutableMap<Any?, Any?> { private fun fixConfig(config: MutableMap<Any?, Any?>): MutableMap<Any?, Any?> {
val peers = arrayListOf<String>(); val peers = arrayListOf<String>();
peers.add("tcp://194.177.21.156:5066") peers.add("tcp://194.177.21.156:5066")
@ -123,28 +144,16 @@ class YggdrasilTunService : VpnService() {
// Read the outgoing packet from the input stream. // Read the outgoing packet from the input stream.
var length = tunInputStream!!.read(packet) var length = tunInputStream!!.read(packet)
//System.out.println("packet size:"+packet.size+" "+byteArrayToHex(packet))
//System.out.println("buffer size:"+buffer.array().size+" "+byteArrayToHex(buffer.array()))
if (length > 0) { if (length > 0) {
// Ignore control messages, which start with zero. var buffer = ByteBuffer.allocate(length);
if (packet.get(0).compareTo(0)!=0) { buffer.put(packet, 0, length)
var buffer = ByteBuffer.allocate(length); buffer.limit(length)
buffer.put(packet, 0, length) yggConduitEndpoint.send(buffer.array())
buffer.limit(length)
yggConduitEndpoint.send(buffer.array())
}
} }
} }
} }
private fun isBufferEmpty(buffer: ByteArray): Boolean {
var sum: Byte = 0
for (i in buffer) {
sum.or(i)
}
return sum == 0.toByte()
}
private fun writePacketsToTun() { private fun writePacketsToTun() {
if(tunOutputStream != null) { if(tunOutputStream != null) {
val buffer = yggConduitEndpoint.recv() val buffer = yggConduitEndpoint.recv()
@ -152,12 +161,17 @@ class YggdrasilTunService : VpnService() {
} }
} }
override fun onRevoke() { fun stopVpn() {
super.onRevoke()
isRunning = false isRunning = false
readCoroutine.cancel() readCoroutine.cancel()
writeCoroutine.cancel() writeCoroutine.cancel()
tunInterface!!.close() tunInterface!!.close()
tunInterface = null tunInterface = null
stopSelf()
}
override fun onDestroy() {
super.onDestroy()
stopSelf()
} }
} }

View File

@ -0,0 +1,8 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="2dp" />
<solid android:color="#80000000" />
<stroke
android:width="1dp"
android:color="@color/green" />
</shape>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/pink" android:state_checked="true" />
<item android:drawable="@color/dark_pink" android:state_pressed="true" />
<item android:drawable="@color/transparent" />
</selector>

View File

@ -1,18 +1,51 @@
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".MainActivity" android:orientation="vertical" android:background="@color/grey"
android:gravity="center"> tools:context=".MainActivity">
<Button <RadioGroup
android:id="@+id/connect_button" android:id="@+id/connectRadioGroup"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="60dp"
android:text="@string/connect_button" android:background="@drawable/pink_out_line"
android:layout_gravity="center"/> android:checkedButton="@+id/offer"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="50dp">
</LinearLayout> <RadioButton
android:id="@+id/disconnectButton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="1dp"
android:layout_marginTop="1dp"
android:layout_marginBottom="1dp"
android:layout_weight="1"
android:background="@drawable/toggle_widget_background"
android:button="@null"
android:gravity="center"
android:text="@string/disconnect_button"
android:textColor="@color/white"
android:checked="true"/>
<RadioButton
android:id="@+id/connectButton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginTop="1dp"
android:layout_marginRight="1dp"
android:layout_marginBottom="1dp"
android:layout_weight="1"
android:background="@drawable/toggle_widget_background"
android:button="@null"
android:gravity="center"
android:text="@string/connect_button"
android:textColor="@color/white" />
</RadioGroup>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="colorPrimary">#008577</color> <color name="colorPrimary">#555555</color>
<color name="colorPrimaryDark">#00574B</color> <color name="colorPrimaryDark">#343334</color>
<color name="colorAccent">#D81B60</color> <color name="colorAccent">#D81B60</color>
<color name="white">#ffffff</color>
<color name="green">#83cf03</color>
<color name="grey">#343334</color>
<color name="transparent">#555555</color>
<color name="dark_pink">#666666</color>
<color name="pink">#777777</color>
</resources> </resources>

View File

@ -1,4 +1,5 @@
<resources> <resources>
<string name="app_name">Yggdrasil</string> <string name="app_name">Yggdrasil</string>
<string name="connect_button">Connect</string> <string name="connect_button">Connect</string>
<string name="disconnect_button">Disconnect</string>
</resources> </resources>

View File

@ -1,7 +1,7 @@
<resources> <resources>
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light"> <style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item>