Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logger Observer core implementation #38

Merged
merged 1 commit into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()
}
}
4 changes: 3 additions & 1 deletion app/src/main/java/com/lvaccaro/lamp/util/Validator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ class Validator {

fun isCorrectNetwork(cli: LightningCli, context: Context, address: String): String? {
try {
cli.exec(context, arrayOf("txprepare", address, "10000"), true).toJSONObject()
val rpcResult = cli.exec(context, arrayOf("txprepare", address, "1000"), true).toJSONObject()
//release the input to see the correct balance inside the output
cli.exec(context, arrayOf("txdiscard", rpcResult["txid"].toString()), true).toJSONObject()
return null //Address correct
} catch (ex: Exception) {
//not enough bitcoin to create the transaction but the address was correct
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.lvaccaro.lamp.util.hendler

import android.content.Context

interface IEventHandler {

fun doReceive(context: Context, information: String)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.lvaccaro.lamp.util.hendler

import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.localbroadcastmanager.content.LocalBroadcastManager

class NewChannelPayment(val actionName: String): IEventHandler{

companion object{
val TAG = NewChannelPayment::class.java.canonicalName
val PATTERN_ONE = "DEBUG wallet: Owning output"
val PATTERN_TWO = "sendrawtx exit 0"
}

override fun doReceive(context: Context, information: String) {
if(information.contains(PATTERN_ONE) || information.contains(PATTERN_TWO)){
Log.e(TAG, "****** Action received ${actionName} ******")
val intent = Intent()
intent.action = actionName
intent.putExtra("message", "Payment sent") //FIXME(vincenzopalazzo): Fix the message
LocalBroadcastManager.getInstance(context).sendBroadcast(intent)
}
}

}
Loading