split traffic

This commit is contained in:
Kr328 committed 2019-11-30 14:43:07 +08:00
1 parent fa99b3f981
commit f418a3649e
26 files changed
+321 -172

No files matched your search

@@ -106,14 +106,15 @@ abstract class BaseActivity : AppCompatActivity(), IClashEventObserver {
override fun onProcessEvent(event: ProcessEvent?) =
this@BaseActivity.onProcessEvent(event)
override fun onProxyChangedEvent(event: ProxyChangedEvent?) =
this@BaseActivity.onProxyChangedEvent(event)
override fun onErrorEvent(event: ErrorEvent?) =
this@BaseActivity.onErrorEvent(event)
override fun onTrafficEvent(event: TrafficEvent?) =
this@BaseActivity.onTrafficEvent(event)
override fun onSpeedEvent(event: SpeedEvent?) =
this@BaseActivity.onSpeedEvent(event)
override fun onBandwidthEvent(event: BandwidthEvent?) {
this@BaseActivity.onBandwidthEvent(event)
}
override fun onProfileChanged(event: ProfileChangedEvent?) =
this@BaseActivity.onProfileChanged(event)
@@ -123,8 +124,8 @@ abstract class BaseActivity : AppCompatActivity(), IClashEventObserver {
override fun onErrorEvent(event: ErrorEvent?) {}
override fun onProfileChanged(event: ProfileChangedEvent?) {}
override fun onProcessEvent(event: ProcessEvent?) {}
override fun onProxyChangedEvent(event: ProxyChangedEvent?) {}
override fun onTrafficEvent(event: TrafficEvent?) {}
override fun onSpeedEvent(event: SpeedEvent?) {}
override fun onBandwidthEvent(event: BandwidthEvent?) {}
override fun asBinder(): IBinder {
return observerBinder
}
@@ -2,14 +2,10 @@ package com.github.kr328.clash
import android.app.Activity
import android.content.Intent
import android.graphics.Color
import android.net.VpnService
import android.os.Bundle
import android.view.View
import com.github.kr328.clash.core.event.Event
import com.github.kr328.clash.core.event.ProcessEvent
import com.github.kr328.clash.core.event.ProfileChangedEvent
import com.github.kr328.clash.core.event.TrafficEvent
import com.github.kr328.clash.core.event.*
import com.github.kr328.clash.core.utils.ByteFormatter
import com.github.kr328.clash.service.TunService
import kotlinx.android.synthetic.main.activity_main.*
@@ -92,7 +88,7 @@ class MainActivity : BaseActivity() {
}
}
override fun onTrafficEvent(event: TrafficEvent?) {
override fun onBandwidthEvent(event: BandwidthEvent?) {
runOnUiThread {
if (lastEvent == ProcessEvent.STARTED) {
activity_main_clash_status_summary.text =
@@ -115,7 +111,7 @@ class MainActivity : BaseActivity() {
it.eventService.registerEventObserver(
MainActivity::class.java.simpleName,
this,
intArrayOf(Event.EVENT_TRAFFIC)
intArrayOf(Event.EVENT_BANDWIDTH)
)
}
@@ -21,13 +21,27 @@ class ProxyActivity : BaseActivity() {
it.visibility = View.GONE
}
activity_proxies_swipe.setOnRefreshListener {
refreshList()
}
refreshList()
}
private fun refreshList() {
if (!activity_proxies_swipe.isRefreshing)
activity_proxies_swipe.isRefreshing = true
runClash { clash ->
val proxies = clash.queryAllProxies().proxies
val packet = clash.queryAllProxies()
val proxies = packet.proxies
val adapterProxies = proxies
.mapValues {
ListProxyGroup.ListProxy(it.value.name,
ListProxyGroup.ListProxy(
it.value.name,
it.value.type.toString(),
it.value.delay)
it.value.delay
)
}
val listData = proxies
@@ -41,16 +55,24 @@ class ProxyActivity : BaseActivity() {
else -> false
}
}
.filter {
when (packet.mode) {
"Global" -> it.value.name == "GLOBAL"
"Rule" -> it.value.name != "GLOBAL"
else -> false
}
}
.sortedWith(compareBy(
{
it.value.type != ProxyPacket.Type.SELECT
}, {
it.value.name
}))
})
)
.map {
ListProxyGroup(
it.value.name,
it.value.type.toString(),
it.value.type,
it.value.all.mapNotNull { hash ->
adapterProxies[hash]
},
@@ -65,6 +87,7 @@ class ProxyActivity : BaseActivity() {
notifyDataSetChanged()
}
activity_proxies_list.visibility = View.VISIBLE
activity_proxies_swipe.isRefreshing = false
}
}
}
@@ -11,9 +11,10 @@ import com.github.kr328.clash.R
import com.github.kr328.clash.model.ListProxyGroup
import com.google.android.material.card.MaterialCardView
class ProxyAdapter(private val context: Context): RecyclerView.Adapter<ProxyAdapter.Holder>() {
class ProxyAdapter(private val context: Context) : RecyclerView.Adapter<ProxyAdapter.Holder>() {
var proxies: List<ListProxyGroup.ListProxy> = emptyList()
var now: ListProxyGroup.ListProxy? = null
var clickable: Boolean = false
class Holder(view: View) : RecyclerView.ViewHolder(view) {
val name: TextView = view.findViewById(R.id.adapter_proxy_name)
@@ -33,21 +34,32 @@ class ProxyAdapter(private val context: Context): RecyclerView.Adapter<ProxyAdap
override fun onBindViewHolder(holder: Holder, position: Int) {
val current = proxies[position]
if ( current === now ) {
if (current === now) {
holder.card.setCardBackgroundColor(context.getColor(R.color.colorAccent))
holder.name.setTextColor(Color.WHITE)
holder.type.setTextColor(Color.WHITE - 0x22222222)
holder.delay.setTextColor(Color.WHITE - 0x11111111)
}
else{
} else {
holder.card.setCardBackgroundColor(Color.WHITE)
holder.name.setTextColor(Color.BLACK)
holder.type.setTextColor(Color.LTGRAY)
holder.delay.setTextColor(Color.DKGRAY)
}
holder.card.isFocusable = clickable
holder.card.isClickable = clickable
holder.name.text = current.name
holder.type.text = current.type
holder.delay.text = if ( current.delay > 0 ) current.delay.toString() else ""
holder.delay.text = if (current.delay > 0) current.delay.toString() else ""
if (clickable) {
holder.card.setOnClickListener {
notifyItemChanged(proxies.indexOf(now))
notifyItemChanged(position)
now = current
}
}
}
}
@@ -8,22 +8,25 @@ import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.kr328.clash.R
import com.github.kr328.clash.core.utils.Log
import com.github.kr328.clash.core.model.ProxyPacket
import com.github.kr328.clash.model.ListProxyGroup
class ProxyGroupAdapter(private val context: Context) : RecyclerView.Adapter<ProxyGroupAdapter.Holder>() {
class ProxyGroupAdapter(private val context: Context) :
RecyclerView.Adapter<ProxyGroupAdapter.Holder>() {
var data: List<ListProxyGroup> = emptyList()
class Holder(view: View) : RecyclerView.ViewHolder(view) {
val name: TextView = view.findViewById(R.id.adapter_proxy_group_name)
val list: RecyclerView = view.findViewById(R.id.adapter_proxy_group_list)
val expend: View = view.findViewById(R.id.adapter_proxy_group_expand)
val test: View = view.findViewById(R.id.adapter_proxy_group_url_test)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
return Holder(LayoutInflater.from(context)
.inflate(R.layout.adapter_proxy_group, parent, false)).apply {
list.layoutManager = object: GridLayoutManager(context, 2) {
return Holder(
LayoutInflater.from(context)
.inflate(R.layout.adapter_proxy_group, parent, false)
).apply {
list.layoutManager = object : GridLayoutManager(context, 2) {
override fun canScrollHorizontally(): Boolean = false
override fun canScrollVertically(): Boolean = false
}
@@ -38,19 +41,16 @@ class ProxyGroupAdapter(private val context: Context) : RecyclerView.Adapter<Pro
override fun onBindViewHolder(holder: Holder, position: Int) {
val current = data[position]
holder.test.visibility =
if (current.type == ProxyPacket.Type.SELECT) View.VISIBLE else View.GONE
holder.name.text = current.name
holder.list.visibility = if (current.hide) View.GONE else View.VISIBLE
Log.i("${current.hide}")
(holder.list.adapter as ProxyAdapter).apply {
proxies = current.proxies
now = current.now
clickable = current.type == ProxyPacket.Type.SELECT
holder.expend.setOnClickListener {
current.hide = !current.hide
this@ProxyGroupAdapter.notifyItemChanged(position)
}
notifyDataSetChanged()
}
}
}
@@ -1,5 +1,12 @@
package com.github.kr328.clash.model
data class ListProxyGroup(val name: String, val type: String, val proxies: List<ListProxy>, var now: ListProxy?, var hide: Boolean = false) {
import com.github.kr328.clash.core.model.ProxyPacket
data class ListProxyGroup(
val name: String,
val type: ProxyPacket.Type,
val proxies: List<ListProxy>,
var now: ListProxy?
) {
data class ListProxy(val name: String, val type: String, val delay: Long)
}
+8 -3
View File
@@ -15,8 +15,13 @@
android:layout_height="60dp" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/activity_proxies_list"
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/activity_proxies_swipe"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/activity_proxies_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout>
+5 -6
View File
@@ -8,6 +8,7 @@
android:id="@+id/adapter_proxy_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?attr/selectableItemBackground"
app:cardUseCompatPadding="true"
app:cardElevation="2dp"
app:cardCornerRadius="5dp">
@@ -19,10 +20,11 @@
<TextView
android:id="@+id/adapter_proxy_name"
android:textColor="@android:color/black"
android:text="@string/app_name"
android:maxLines="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content"
android:layout_toStartOf="@id/adapter_proxy_delay"
android:layout_alignParentStart="true"/>
<TextView
android:id="@+id/adapter_proxy_type"
@@ -30,7 +32,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:text="@string/app_name"
android:maxLines="1"/>
<TextView
@@ -39,11 +40,9 @@
android:textSize="12sp"
android:id="@+id/adapter_proxy_delay"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/adapter_proxy_name"
android:layout_marginStart="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="30dp"/>
android:layout_height="wrap_content" />
</RelativeLayout>
</com.google.android.material.card.MaterialCardView>
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/adapter_proxy_group_root"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="12dp">
android:paddingStart="15dp"
android:paddingEnd="15dp"
android:paddingTop="15dp">
<TextView
android:padding="2dp"
@@ -18,19 +18,14 @@
android:layout_height="wrap_content" />
<View
android:id="@+id/adapter_proxy_group_url_test"
android:focusable="true"
android:clickable="true"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_marginEnd="5dp"
android:background="@drawable/ic_url_test"
android:layout_toStartOf="@id/adapter_proxy_group_expand"/>
<View
android:id="@+id/adapter_proxy_group_expand"
android:layout_alignParentEnd="true"
android:layout_marginEnd="5dp"
android:layout_width="22dp"
android:layout_height="22dp"
android:background="@drawable/ic_expand_more"/>
android:background="@drawable/ic_url_test" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/adapter_proxy_group_list"
+51 -8
View File
@@ -16,7 +16,6 @@ func handlePullTrafficEvent(client *net.UnixConn) {
traffic := tunnel.DefaultManager
buf := &bytes.Buffer{}
defer close(trafficExit)
defer ticker.Stop()
go func() {
@@ -26,7 +25,7 @@ func handlePullTrafficEvent(client *net.UnixConn) {
_, err := client.Read(buf[:])
if err != nil {
trafficExit <- 0
close(trafficExit)
return
}
}
@@ -38,23 +37,67 @@ func handlePullTrafficEvent(client *net.UnixConn) {
buf.Reset()
var Packet struct {
Up int64 `json:"up"`
Down int64 `json:"down"`
Total int64 `json:"total"`
Up int64 `json:"up"`
Down int64 `json:"down"`
}
up, down := traffic.Now()
snapshot := traffic.Snapshot()
Packet.Up = up
Packet.Down = down
Packet.Total = snapshot.DownloadTotal + snapshot.UploadTotal
json.NewEncoder(buf).Encode(&Packet)
writeCommandPacket(client, buf.Bytes())
if writeCommandPacket(client, buf.Bytes()) != nil {
return
}
case <-trafficExit:
return
}
}
}
func handlePullBandwidthEvent(client *net.UnixConn) {
bandWidthExit := make(chan int)
ticker := time.NewTicker(time.Second)
mgr := tunnel.DefaultManager
buf := &bytes.Buffer{}
defer ticker.Stop()
go func() {
for {
var buf [4]byte
_, err := client.Read(buf[:])
if err != nil {
close(bandWidthExit)
return
}
}
}()
for {
select {
case <-ticker.C:
buf.Reset()
var Packet struct {
Total int64 `json:"total"`
}
sp := mgr.Snapshot()
Packet.Total = sp.DownloadTotal + sp.UploadTotal
json.NewEncoder(buf).Encode(&Packet)
if writeCommandPacket(client, buf.Bytes()) != nil {
return
}
}
}
}
+2
View File
@@ -12,9 +12,11 @@ func handleQueryProxies(client *net.UnixConn) {
proxies := tunnel.Instance().Proxies()
var root struct {
Mode string `json:"mode"`
Proxies map[string]interface{} `json:"proxies"`
}
root.Mode = tunnel.Instance().Mode().String()
root.Proxies = make(map[string]interface{})
for k, p := range proxies {
+11 -8
View File
@@ -16,19 +16,22 @@ const (
commandQueryProxies uint32 = 5
commandPullTraffic uint32 = 6
commandPullLog uint32 = 7
commandPullBandwidth uint32 = 8
commandSetProxy uint32 = 9
)
var handlers map[uint32]func(*net.UnixConn) = make(map[uint32]func(*net.UnixConn))
func init() {
handlers[commandPing] = handlePing // ping.go
handlers[commandTunStart] = handleTunStart // tun.go
handlers[commandTunStop] = handleTunStop // tun.go
handlers[commandProfileDefault] = handleProfileDefault // profile.go
handlers[commandProfileReload] = handleProfileReload // profile.go
handlers[commandQueryProxies] = handleQueryProxies // proxies.go
handlers[commandPullTraffic] = handlePullTrafficEvent // event.go
handlers[commandPullLog] = nil // event.go
handlers[commandPing] = handlePing // ping.go
handlers[commandTunStart] = handleTunStart // tun.go
handlers[commandTunStop] = handleTunStop // tun.go
handlers[commandProfileDefault] = handleProfileDefault // profile.go
handlers[commandProfileReload] = handleProfileReload // profile.go
handlers[commandQueryProxies] = handleQueryProxies // proxies.go
handlers[commandPullTraffic] = handlePullTrafficEvent // event.go
handlers[commandPullLog] = nil // event.go
handlers[commandPullBandwidth] = handlePullBandwidthEvent // event.go
}
// Start local control server
@@ -4,10 +4,10 @@ import android.content.Context
import android.net.LocalSocket
import android.util.Log
import com.github.kr328.clash.core.Constants.TAG
import com.github.kr328.clash.core.event.BandwidthEvent
import com.github.kr328.clash.core.event.LogEvent
import com.github.kr328.clash.core.event.ProcessEvent
import com.github.kr328.clash.core.event.ProxyChangedEvent
import com.github.kr328.clash.core.event.TrafficEvent
import com.github.kr328.clash.core.event.SpeedEvent
import com.github.kr328.clash.core.model.RawProxyPacket
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
@@ -28,9 +28,10 @@ class Clash(
const val COMMAND_TUN_STOP = 2
const val COMMAND_PROFILE_RELOAD = 4
const val COMMAND_QUERY_PROXIES = 5
const val COMMAND_PULL_TRAFFIC = 6
const val COMMAND_PULL_SPEED = 6
const val COMMAND_PULL_LOG = 7
const val COMMAND_PULL_PROXY_CHANGED = 8
const val COMMAND_PULL_BANDWIDTH = 8
const val COMMAND_SET_PROXY = 9
const val PING_REPLY = 233
}
@@ -60,21 +61,19 @@ class Clash(
return runControl(COMMAND_QUERY_PROXIES) { _, input, _ ->
val data = input.readString()
Log.d(TAG, data)
Json(JsonConfiguration.Stable.copy(strictMode = false))
.parse(RawProxyPacket.serializer(), data)
}
}
fun pullTrafficEvent(initial: (LocalSocket) -> Unit, callback: (TrafficEvent) -> Unit) {
runControlNoException(COMMAND_PULL_TRAFFIC) { socket, input, _ ->
fun pullSpeedEvent(initial: (LocalSocket) -> Unit, callback: (SpeedEvent) -> Unit) {
runControlNoException(COMMAND_PULL_SPEED) { socket, input, _ ->
initial(socket)
while (!Thread.currentThread().isInterrupted) {
callback(
Json(JsonConfiguration.Stable).parse(
TrafficEvent.serializer(),
SpeedEvent.serializer(),
input.readString()
)
)
@@ -97,17 +96,14 @@ class Clash(
}
}
fun pullProxyChangedEvent(
initial: (LocalSocket) -> Unit,
callback: (ProxyChangedEvent) -> Unit
) {
runControlNoException(COMMAND_PULL_PROXY_CHANGED) { socket, input, _ ->
fun pullBandwidthEvent(initial: (LocalSocket) -> Unit, callback: (BandwidthEvent) -> Unit) {
runControlNoException(COMMAND_PULL_BANDWIDTH) { socket, input, _ ->
initial(socket)
while (!Thread.currentThread().isInterrupted) {
callback(
Json(JsonConfiguration.Stable).parse(
ProxyChangedEvent.serializer(),
BandwidthEvent.serializer(),
input.readString()
)
)
@@ -6,7 +6,7 @@ import com.github.kr328.clash.core.serialization.Parcels
import kotlinx.serialization.Serializable
@Serializable
data class TrafficEvent(val down: Long, val up: Long, val total: Long) : Event, Parcelable {
data class BandwidthEvent(val total: Long): Parcelable {
override fun writeToParcel(parcel: Parcel, flags: Int) {
Parcels.dump(serializer(), this, parcel)
}
@@ -15,13 +15,14 @@ data class TrafficEvent(val down: Long, val up: Long, val total: Long) : Event,
return 0
}
companion object CREATOR : Parcelable.Creator<TrafficEvent> {
override fun createFromParcel(parcel: Parcel): TrafficEvent {
companion object CREATOR : Parcelable.Creator<BandwidthEvent> {
override fun createFromParcel(parcel: Parcel): BandwidthEvent {
return Parcels.load(serializer(), parcel)
}
override fun newArray(size: Int): Array<TrafficEvent?> {
override fun newArray(size: Int): Array<BandwidthEvent?> {
return arrayOfNulls(size)
}
}
}
@@ -2,9 +2,8 @@ package com.github.kr328.clash.core.event
interface Event {
companion object {
const val EVENT_CLOSE = 0
const val EVENT_LOG = 1
const val EVENT_PROXY_CHANGED = 2
const val EVENT_TRAFFIC = 3
const val EVENT_SPEED = 3
const val EVENT_BANDWIDTH = 4
}
}
@@ -0,0 +1,27 @@
package com.github.kr328.clash.core.event
import android.os.Parcel
import android.os.Parcelable
import com.github.kr328.clash.core.serialization.Parcels
import kotlinx.serialization.Serializable
@Serializable
data class SpeedEvent(val down: Long, val up: Long) : Event, Parcelable {
override fun writeToParcel(parcel: Parcel, flags: Int) {
Parcels.dump(serializer(), this, parcel)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<SpeedEvent> {
override fun createFromParcel(parcel: Parcel): SpeedEvent {
return Parcels.load(serializer(), parcel)
}
override fun newArray(size: Int): Array<SpeedEvent?> {
return arrayOfNulls(size)
}
}
}
@@ -6,7 +6,7 @@ import com.github.kr328.clash.core.serialization.Parcels
import kotlinx.serialization.Serializable
@Serializable
data class ProxyPacket(val proxies: Map<Int, Proxy>): Parcelable {
data class ProxyPacket(val mode: String, val proxies: Map<Int, Proxy>): Parcelable {
@Serializable
data class Proxy(val name: String, val type: Type, val now: Int, val all: Set<Int>, val delay: Long)
@@ -84,7 +84,7 @@ data class ProxyPacket(val proxies: Map<Int, Proxy>): Parcelable {
entry.value.first to Proxy(entry.key, type, now, all, delay)
}
return ProxyPacket(proxies.toMap())
return ProxyPacket(rawProxy.mode, proxies.toMap())
}
@JvmField
@@ -3,7 +3,7 @@ package com.github.kr328.clash.core.model
import kotlinx.serialization.Serializable
@Serializable
data class RawProxyPacket(val proxies: Map<String, RawProxy>) {
data class RawProxyPacket(val mode: String, val proxies: Map<String, RawProxy>) {
@Serializable
data class RawProxy(val type: String,
val all: List<String> = emptyList(),
@@ -10,7 +10,7 @@ object ByteFormatter {
bytes > 1024 ->
String.format("%.2f KB", (bytes.toDouble() / 1024))
else ->
"$bytes Byte"
"$bytes Bytes"
}
}
@@ -2,7 +2,7 @@ package com.github.kr328.clash.core.event;
parcelable ProcessEvent;
parcelable LogEvent;
parcelable ProxyChangedEvent;
parcelable TrafficEvent;
parcelable SpeedEvent;
parcelable BandwidthEvent;
parcelable ErrorEvent;
parcelable ProfileChangedEvent;
parcelable ProfileChangedEvent;
@@ -4,9 +4,9 @@ import com.github.kr328.clash.core.event.Event;
interface IClashEventObserver {
void onProcessEvent(in ProcessEvent event);
void onProxyChangedEvent(in ProxyChangedEvent event);
void onLogEvent(in LogEvent event);
void onErrorEvent(in ErrorEvent event);
void onTrafficEvent(in TrafficEvent event);
void onSpeedEvent(in SpeedEvent event);
void onBandwidthEvent(in BandwidthEvent event);
void onProfileChanged(in ProfileChangedEvent event);
}
@@ -2,22 +2,22 @@ package com.github.kr328.clash.service
import android.net.LocalSocket
import com.github.kr328.clash.core.Clash
import com.github.kr328.clash.core.event.BandwidthEvent
import com.github.kr328.clash.core.event.LogEvent
import com.github.kr328.clash.core.event.ProxyChangedEvent
import com.github.kr328.clash.core.event.TrafficEvent
import com.github.kr328.clash.core.event.SpeedEvent
import com.github.kr328.clash.core.utils.Log
import kotlin.concurrent.thread
class ClashEventPuller(private val clash: Clash, private val master: Master) {
interface Master {
fun onLogPulled(event: LogEvent)
fun onTrafficPulled(event: TrafficEvent)
fun onProxyChangedPulled(event: ProxyChangedEvent)
fun onSpeedPulled(event: SpeedEvent)
fun onBandwidthPulled(event: BandwidthEvent)
}
private var logSocket: LocalSocket? = null
private var trafficSocket: LocalSocket? = null
private var proxyChangedSocket: LocalSocket? = null
private var speedSocket: LocalSocket? = null
private var bandwidthSocket: LocalSocket? = null
fun startLogPuller() {
synchronized(LogEvent::class) {
@@ -47,45 +47,81 @@ class ClashEventPuller(private val clash: Clash, private val master: Master) {
}
}
fun startSpeedPull() {
synchronized(SpeedEvent::class) {
if (speedSocket != null)
return
}
thread {
clash.pullSpeedEvent({
synchronized(SpeedEvent::class) {
if (speedSocket != null) {
it.close()
return@pullSpeedEvent
} else {
speedSocket = it
Log.i("Speed puller started")
}
}
}) {
master.onSpeedPulled(it)
}
synchronized(SpeedEvent::class) {
Log.i("Speed puller stopped")
speedSocket = null
}
}
}
fun startBandwidthPull() {
synchronized(BandwidthEvent::class) {
if (bandwidthSocket != null)
return
}
thread {
clash.pullBandwidthEvent({
synchronized(BandwidthEvent::class) {
if (bandwidthSocket != null) {
it.close()
return@pullBandwidthEvent
} else {
bandwidthSocket = it
Log.i("Bandwidth puller started")
}
}
}) {
master.onBandwidthPulled(it)
}
synchronized(BandwidthEvent::class) {
Log.i("Bandwidth puller stopped")
bandwidthSocket = null
}
}
}
fun stopLogPull() {
synchronized(LogEvent::class) {
logSocket.closeSilent()
}
}
fun startTrafficPull() {
synchronized(TrafficEvent::class) {
if (trafficSocket != null)
return
}
thread {
clash.pullTrafficEvent({
synchronized(TrafficEvent::class) {
if (trafficSocket != null) {
it.close()
return@pullTrafficEvent
} else {
trafficSocket = it
Log.i("Traffic puller started")
}
}
}) {
master.onTrafficPulled(it)
}
synchronized(TrafficEvent::class) {
Log.i("Traffic puller stopped")
trafficSocket = null
}
fun stopSpeedPull() {
synchronized(SpeedEvent::class) {
speedSocket.closeSilent()
}
}
fun stopTrafficPull() {
synchronized(TrafficEvent::class) {
trafficSocket.closeSilent()
fun stopBandwidthPull() {
synchronized(BandwidthEvent::class) {
bandwidthSocket.closeSilent()
}
}
@@ -11,7 +11,7 @@ class ClashEventService(private val master: Master) : IClashEventService.Stub()
companion object {
private val EVENT_SET =
setOf(Event.EVENT_LOG, Event.EVENT_TRAFFIC, Event.EVENT_PROXY_CHANGED)
setOf(Event.EVENT_LOG, Event.EVENT_SPEED, Event.EVENT_BANDWIDTH)
}
private data class EventObserverRecord(
@@ -23,7 +23,7 @@ class ClashEventService(private val master: Master) : IClashEventService.Stub()
private val handler = Executors.newSingleThreadExecutor()
private var currentProcessEvent = ProcessEvent.STOPPED
private var currentTrafficEvent = TrafficEvent(0, 0, 0)
private var currentBandwidthEvent = BandwidthEvent(0)
fun preformProcessEvent(event: ProcessEvent) {
handler.submit {
@@ -44,22 +44,22 @@ class ClashEventService(private val master: Master) : IClashEventService.Stub()
}
}
fun preformProxyChangedEvent(event: ProxyChangedEvent) {
fun preformSpeedEvent(event: SpeedEvent) {
handler.submit {
observers.values.forEach {
if (it.acquiredEvent.contains(Event.EVENT_PROXY_CHANGED))
it.observer.onProxyChangedEvent(event)
if (it.acquiredEvent.contains(Event.EVENT_SPEED))
it.observer.onSpeedEvent(event)
}
}
}
fun preformTrafficEvent(event: TrafficEvent) {
fun preformBandwidthEvent(event: BandwidthEvent) {
handler.submit {
currentTrafficEvent = event
currentBandwidthEvent = event
observers.values.forEach {
if (it.acquiredEvent.contains(Event.EVENT_TRAFFIC))
it.observer.onTrafficEvent(event)
if ( it.acquiredEvent.contains(Event.EVENT_BANDWIDTH) )
it.observer.onBandwidthEvent(event)
}
}
}
@@ -111,8 +111,8 @@ class ClashEventService(private val master: Master) : IClashEventService.Stub()
if (initial) {
observer.onProcessEvent(currentProcessEvent)
if (events.contains(Event.EVENT_TRAFFIC))
observer.onTrafficEvent(currentTrafficEvent)
if (events.contains(Event.EVENT_BANDWIDTH))
observer.onBandwidthEvent(currentBandwidthEvent)
}
}
}
@@ -10,7 +10,7 @@ class ClashProfileService(context: Context, private val master: Master) :
fun preformProfileChanged()
}
val database by lazy {
private val database by lazy {
ClashDatabase.getInstance(context).openClashProfileDao()
}
@@ -12,7 +12,6 @@ import android.os.ParcelFileDescriptor
import com.github.kr328.clash.core.Clash
import com.github.kr328.clash.core.event.*
import com.github.kr328.clash.core.model.ProxyPacket
import com.github.kr328.clash.core.model.RawProxyPacket
import com.github.kr328.clash.core.utils.Log
import com.github.kr328.clash.service.data.ClashDatabase
import java.io.File
@@ -45,7 +44,7 @@ class ClashService : Service(), IClashEventObserver, ClashEventService.Master,
this@ClashService.eventService.preformErrorEvent(
ErrorEvent(ErrorEvent.Type.QUERY_PROXY_FAILURE, e.toString())
)
ProxyPacket(emptyMap())
ProxyPacket("Unknown", emptyMap())
}
}
@@ -100,7 +99,7 @@ class ClashService : Service(), IClashEventObserver, ClashEventService.Master,
eventService.registerEventObserver(
ClashService::class.java.name,
this@ClashService,
intArrayOf(Event.EVENT_TRAFFIC)
intArrayOf(Event.EVENT_SPEED)
)
Intent.ACTION_SCREEN_OFF ->
eventService.registerEventObserver(
@@ -117,10 +116,12 @@ class ClashService : Service(), IClashEventObserver, ClashEventService.Master,
return
when (event) {
Event.EVENT_TRAFFIC ->
puller.startTrafficPull()
Event.EVENT_SPEED ->
puller.startSpeedPull()
Event.EVENT_LOG ->
puller.startLogPuller()
Event.EVENT_BANDWIDTH ->
puller.startBandwidthPull()
}
}
@@ -129,10 +130,12 @@ class ClashService : Service(), IClashEventObserver, ClashEventService.Master,
return
when (event) {
Event.EVENT_TRAFFIC ->
puller.stopTrafficPull()
Event.EVENT_SPEED ->
puller.stopSpeedPull()
Event.EVENT_LOG ->
puller.stopLogPull()
Event.EVENT_BANDWIDTH ->
puller.stopBandwidthPull()
}
}
@@ -155,7 +158,7 @@ class ClashService : Service(), IClashEventObserver, ClashEventService.Master,
eventService.registerEventObserver(
ClashService::class.java.name,
this@ClashService,
intArrayOf(Event.EVENT_TRAFFIC)
intArrayOf(Event.EVENT_SPEED)
)
registerReceiver(screenReceiver, IntentFilter().apply {
@@ -201,7 +204,8 @@ class ClashService : Service(), IClashEventObserver, ClashEventService.Master,
eventService.recastEventRequirement()
}
ProcessEvent.STOPPED -> {
eventService.preformTrafficEvent(TrafficEvent(0, 0, 0))
eventService.preformSpeedEvent(SpeedEvent(0, 0))
eventService.preformBandwidthEvent(BandwidthEvent(0))
notification.cancel()
}
@@ -230,7 +234,7 @@ class ClashService : Service(), IClashEventObserver, ClashEventService.Master,
}
}
override fun onTrafficEvent(event: TrafficEvent?) {
override fun onSpeedEvent(event: SpeedEvent?) {
notification.setSpeed(event?.up ?: 0, event?.down ?: 0)
}
@@ -242,15 +246,15 @@ class ClashService : Service(), IClashEventObserver, ClashEventService.Master,
eventService.preformLogEvent(event)
}
override fun onTrafficPulled(event: TrafficEvent) {
eventService.preformTrafficEvent(event)
override fun onSpeedPulled(event: SpeedEvent) {
eventService.preformSpeedEvent(event)
}
override fun onProxyChangedPulled(event: ProxyChangedEvent) {
eventService.preformProxyChangedEvent(event)
override fun onBandwidthPulled(event: BandwidthEvent) {
eventService.preformBandwidthEvent(event)
}
override fun onProxyChangedEvent(event: ProxyChangedEvent?) {}
override fun onBandwidthEvent(event: BandwidthEvent?) {}
override fun onLogEvent(event: LogEvent?) {}
override fun onErrorEvent(event: ErrorEvent?) {}
override fun asBinder(): IBinder = object : Binder() {
@@ -142,11 +142,11 @@ class TunService : VpnService(), IClashEventObserver {
return this
}
override fun onSpeedEvent(event: SpeedEvent?) {}
override fun onBandwidthEvent(event: BandwidthEvent?) {}
override fun onLogEvent(event: LogEvent?) {}
override fun onErrorEvent(event: ErrorEvent?) {}
override fun onProfileChanged(event: ProfileChangedEvent?) {}
override fun onProxyChangedEvent(event: ProxyChangedEvent?) {}
override fun onTrafficEvent(event: TrafficEvent?) {}
override fun asBinder(): IBinder = object : Binder() {
override fun queryLocalInterface(descriptor: String): IInterface? {
return this@TunService