Skip to content

Commit

Permalink
Logger Observer core implementation
Browse files Browse the repository at this point in the history
Signed-off-by: Vincenzo Palazzo <[email protected]>
  • Loading branch information
vincenzopalazzo committed Aug 13, 2020
1 parent 7282c81 commit f119439
Show file tree
Hide file tree
Showing 14 changed files with 256 additions and 21 deletions.
6 changes: 5 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ android {
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.lvaccaro.lamp"
minSdkVersion 19
minSdkVersion 24
targetSdkVersion 28
versionCode 34
versionName "3.4"
Expand All @@ -33,6 +33,10 @@ android {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}

lintOptions {
abortOnError false
}
}

dependencies {
Expand Down
10 changes: 5 additions & 5 deletions app/src/main/java/com/lvaccaro/lamp/InvoiceActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import java.util.*

class InvoiceActivity : AppCompatActivity() {

val cli = LightningCli()
private val cli = LightningCli()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand Down Expand Up @@ -47,7 +47,7 @@ class InvoiceActivity : AppCompatActivity() {
}


fun decodeInvoice(bolt11: String) {
private fun decodeInvoice(bolt11: String) {
val res = cli.exec(this, arrayOf("decodepay", bolt11), true)
.toJSONObject()
val amountMsat = res["amount_msat"] as String
Expand All @@ -60,7 +60,7 @@ class InvoiceActivity : AppCompatActivity() {
}
}

fun waitInvoice(label: String) {
private fun waitInvoice(label: String) {
try {
cli.exec(this, arrayOf("waitinvoice", label), true).toJSONObject()
runOnUiThread {
Expand All @@ -83,14 +83,14 @@ class InvoiceActivity : AppCompatActivity() {
}


fun copyToClipboard(key: String, text: String) {
private fun copyToClipboard(key: String, text: String) {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip: ClipData = ClipData.newPlainText(key, text)
clipboard.setPrimaryClip(clip)
Toast.makeText(this, "Copied to clipboard", Toast.LENGTH_LONG).show()
}

fun getQrCode(text: String): Bitmap {
private fun getQrCode(text: String): Bitmap {
val SCALE = 16
try {
val matrix = Encoder.encode(text, ErrorCorrectionLevel.M).getMatrix()
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/java/com/lvaccaro/lamp/InvoiceBuildFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import java.lang.Exception

class InvoiceBuildFragment: BottomSheetDialogFragment() {

val cli = LightningCli()
private val cli = LightningCli()

override fun onCreateView(
inflater: LayoutInflater,
Expand Down Expand Up @@ -42,7 +42,6 @@ class InvoiceBuildFragment: BottomSheetDialogFragment() {
description
), true
).toJSONObject()
val bolt11 = res["bolt11"].toString()
activity?.runOnUiThread {
val intent = Intent(activity, InvoiceActivity::class.java)
intent.putExtra("bolt11", res["bolt11"] as String)
Expand Down
1 change: 0 additions & 1 deletion app/src/main/java/com/lvaccaro/lamp/Services/Globber.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.lvaccaro.lamp.Services

import android.util.Log
import java.io.*
import java.util.logging.Logger

Expand Down
19 changes: 12 additions & 7 deletions app/src/main/java/com/lvaccaro/lamp/Services/LightningService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Environment
import android.os.FileObserver
import androidx.preference.PreferenceManager
import com.lvaccaro.lamp.MainActivity
import com.lvaccaro.lamp.R
import com.lvaccaro.lamp.rootDir
import com.lvaccaro.lamp.util.LogObserver
import java.io.File
import java.util.logging.Logger

Expand All @@ -19,14 +21,14 @@ class LightningService : IntentService("LightningService") {
var globber: Globber? = null
val NOTIFICATION_ID = 573948
val daemon = "lightningd"
lateinit var logObserver: FileObserver

override fun onHandleIntent(workIntent: Intent?) {
val dataString = workIntent!!.dataString
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND)

log.info("start $daemon service")
val lightningDir = File(rootDir(), ".lightning")
val bitcoinDir = File(rootDir(), ".bitcoin")
Expand Down Expand Up @@ -60,7 +62,7 @@ class LightningService : IntentService("LightningService") {
// 10 days to catch a cheating attempt
String.format("--watchtime-blocks=%s", 10 * 24 * 6))

if (!alias.isEmpty()) {
if (alias.isNotEmpty()) {
options.add(String.format("--alias=%s", alias))
}

Expand Down Expand Up @@ -96,22 +98,23 @@ class LightningService : IntentService("LightningService") {
options.add("--always-use-proxy=true")
}

if (!proxy.isEmpty()) {
if (proxy.isNotEmpty()) {
options.add(String.format("--proxy=%s", proxy))
}
if (!announceaddr.isEmpty()) {
if (announceaddr.isNotEmpty()) {
options.add(String.format("--announce-addr=%s", announceaddr))
}
if (!bindaddr.isEmpty()) {
if (bindaddr.isNotEmpty()) {
options.add(String.format("--bind-addr=%s", bindaddr))
}
if (!addr.isEmpty()) {
if (addr.isNotEmpty()) {
options.add(String.format("--addr=%s", addr))
}

val pb = ProcessBuilder(options)
pb.directory(binaryDir)
pb.redirectErrorStream(true)
logObserver = LogObserver(applicationContext, rootDir().absolutePath,"$daemon.log")
val logFile = File(rootDir(),"$daemon.log")
if(logFile.exists()){
logFile.delete()
Expand All @@ -130,10 +133,11 @@ class LightningService : IntentService("LightningService") {
log.info("exit $daemon service")

startForeground()
logObserver.startWatching();
return Service.START_STICKY
}

fun startForeground() {
private fun startForeground() {
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
Expand Down Expand Up @@ -170,6 +174,7 @@ class LightningService : IntentService("LightningService") {
globber?.interrupt()
process = null
globber = null
logObserver.startWatching()
cancelNotification()
}
}
8 changes: 6 additions & 2 deletions app/src/main/java/com/lvaccaro/lamp/Services/TorService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ class TorService : IntentService("TorService") {
process = pb.start()
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
// Redirection output to file
globber = Globber(process!!.inputStream, logFile);
globber = Globber(
process!!.inputStream,
logFile
);
globber?.start()
}

Expand All @@ -77,7 +80,8 @@ class TorService : IntentService("TorService") {
fun startForeground() {
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(this, NOTIFICATION_ID, intent, PendingIntent.FLAG_ONE_SHOT)
val pendingIntent = PendingIntent.getActivity(this,
NOTIFICATION_ID, intent, PendingIntent.FLAG_ONE_SHOT)

val notification = Notification.Builder(this)
.setContentTitle("$daemon is running")
Expand Down
6 changes: 4 additions & 2 deletions app/src/main/java/com/lvaccaro/lamp/UriResultActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ open class UriResultActivity() : AppCompatActivity() {
}
var amount = ""
if(param!!.contains(LampKeys.AMOUNT_KEY)){
//FIXME(vincenzopalazzo): create a converted class to set the set the correct ammounet.
//For instance, Validator.toMilliSatoshi()
amount = (param!![LampKeys.AMOUNT_KEY]!!.toDouble() * 100000000).toLong().toString()
}
bundle.putString(LampKeys.ADDRESS_KEY, address)
Expand All @@ -152,15 +154,15 @@ open class UriResultActivity() : AppCompatActivity() {
bottomSheetDialog.show(supportFragmentManager, "WithdrawFragment")
}

protected fun showToastMessage(message: String, duration: Int) {
protected fun showToastMessage(message: String, duration: Int = Toast.LENGTH_LONG) {
if(message.isEmpty()) return
Toast.makeText(
this, message,
duration
).show()
}

protected fun showSnackBar(message: String, duration: Int){
protected fun showSnackBar(message: String, duration: Int = Snackbar.LENGTH_LONG){
Snackbar.make(findViewById(android.R.id.content), message, duration).show()
}
}
5 changes: 5 additions & 0 deletions app/src/main/java/com/lvaccaro/lamp/util/LampKeys.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,10 @@ class LampKeys {
val DECODEPAY_COMMAND = "decodepay"
val CONNECT_COMMAND = "connect"
val MESSAGE_JSON_KEY = "message"


//Key notification
val NODE_NOTIFICATION_SHUTDOWN: String = "SHUTDOWN_NODE_NOTIFICATION"
val NODE_NOTIFICATION_FUNDCHANNEL: String = "NODE_NOTIFICATION_FUNDCHANNEL"
}
}
98 changes: 98 additions & 0 deletions app/src/main/java/com/lvaccaro/lamp/util/LogObserver.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.lvaccaro.lamp.util

import android.content.Context
import android.os.FileObserver
import android.util.Log
import com.lvaccaro.lamp.util.hendler.IEventHandler
import com.lvaccaro.lamp.util.hendler.NewChannelPayment
import com.lvaccaro.lamp.util.hendler.ShutdownNode
import java.io.File
import java.io.LineNumberReader

/**
* This class is an implementation of FileObserver discussed inside the PRs XX
* The ideas is from @lvaccaro
*
* Info about the clightning node
*
* ---- Node create a transaction (with fundchannel or when I receive the onchain tx)----
* Pattern log: DEBUG wallet: Owning output 1 89846sat (SEGWIT) txid 33c1f5d2df4f425898dc6eb49dae51aaab1d430ee7c0da2cab18123d5c1192f0
* ---- Node make a withdraw action
* Patter log: DEBUG lightningd: sendrawtransaction
*
* --- Node adding block
* Pattern log: DEBUG lightningd: Adding block
*
* --- Node sendrawtransaction
* Pattern log: DEBUG plugin-esplora: sendrawtx exit 0
*
* ---- Shutdown node with command close----
* Pattern log: 2020-08-03T15:38:38.812Z UNUSUAL lightningd: JSON-RPC shutdown
*
* ------ Node receive transaction to blockchain ----
* Pattern log: No debug log
*
* ---- Node receive a lightning payment (keysend, pay)
* Pattern log:
*
* @author https://github.com/vincenzopalazzo
*/
class LogObserver(val context: Context, val path: String, val nameFile: String) : FileObserver(path) {

init {
initHandler()
}

companion object {
val TAG = LogObserver::class.java.canonicalName
}

private lateinit var actionHandler: ArrayList<IEventHandler>
private lateinit var logFile: File
private var actualLine = 0
private var lineNumberReader: LineNumberReader? = null


fun initHandler() {
actionHandler = ArrayList<IEventHandler>()
actionHandler.add(NewChannelPayment(LampKeys.NODE_NOTIFICATION_FUNDCHANNEL))
actionHandler.add(ShutdownNode(LampKeys.NODE_NOTIFICATION_SHUTDOWN))
}

override fun onEvent(event: Int, file: String?) {
if(file == null) return
if (file?.equals(nameFile)) {
when (event) {
FileObserver.MODIFY -> readNewLines()
}
}
}

private fun readNewLines() {
if(lineNumberReader == null)
initFileLog()

//FIXME(vicenzopalazzo): This is real util?
if(lineNumberReader == null) return
lineNumberReader?.lineNumber = actualLine
var line: String? = lineNumberReader?.readLine()
while (line != null){
readLogLine(line)
Log.d(TAG, line)
line = lineNumberReader?.readLine()
}
}

private fun readLogLine(line: String) {
actionHandler.forEach { it -> it.doReceive(context, line) }
actualLine++
}

private fun initFileLog() {
logFile = File(path, nameFile)
lineNumberReader = LineNumberReader(logFile.reader())
//FIXME: level api that are enable this line about is Android nougat
// for the actual version of lightning_ndk I don't need to insert the check of the version
actualLine = lineNumberReader!!.lines().count().toInt()
}
}
58 changes: 58 additions & 0 deletions app/src/main/java/com/lvaccaro/lamp/util/SimulatorPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.lvaccaro.lamp.util

import android.util.Log
import org.json.JSONArray
import org.json.JSONObject

class SimulatorPlugin{

companion object{

val TAG = SimulatorPlugin::class.java.canonicalName

fun funds(jsonObject: JSONObject): JSONObject{
val response = JSONObject()
var onChainFunds = 0
var offChainFunds = 0
var fundsToUs = 0
if(jsonObject.has("outputs")){
val outputs: JSONArray = jsonObject["outputs"] as JSONArray
for (i in 0 until outputs.length()){
val output = outputs.getJSONObject(i)
onChainFunds += output["value"] as Int
Log.d(TAG, "****** On chain fund ${onChainFunds}")
}
}
//FIXME(vicenzopalazzo) maybe in this section is possible add more
// information about status of channels, if the channel is ONCHAIN
// is not correct calculate the sat here, right?
if(jsonObject.has("channels")){
val channels: JSONArray = jsonObject["channels"] as JSONArray
for(i in 0 until channels.length()){
val channel = channels.getJSONObject(i)
offChainFunds = channel["channel_sat"] as Int
Log.d(TAG, "****** Off chain fund ${offChainFunds}")
}
}
response.put("on_chain", onChainFunds.toString())
response.put("off_chain", offChainFunds.toString())
return response
}

fun fundsInChannel(listFunds: JSONObject): Any {
var fundsToUs = 0
val peers = listFunds["peers"] as JSONArray
for (i in 0 until peers.length()) {
val peer = peers.get(i) as? JSONObject
val peerChannels = peer?.get("channels") as JSONArray
for (j in 0 until peerChannels.length()) {
val channel = peerChannels.get(j) as JSONObject
fundsToUs += channel["msatoshi_to_us"] as Int
}
}
val response = JSONObject()
response.put("to_us", fundsToUs.toString())
return response
}
}
}
Loading

0 comments on commit f119439

Please sign in to comment.