Compare commits

...

3 Commits

8 changed files with 96 additions and 72 deletions

View File

@ -80,13 +80,13 @@ kotlin {
fun KotlinNativeTargetWithHostTests.phoenixBinaries() { fun KotlinNativeTargetWithHostTests.phoenixBinaries() {
binaries { binaries {
executable("phoenixd") { executable("phoenixd") {
entryPoint = "fr.acinq.lightning.bin.main" entryPoint = "fr.acinq.lightning.bin.MainKt"
optimized = false // without this, release mode throws 'Index 0 out of bounds for length 0' in StaticInitializersOptimization.kt optimized = false // without this, release mode throws 'Index 0 out of bounds for length 0' in StaticInitializersOptimization.kt
} }
executable("phoenix-cli") { /*executable("phoenix-cli") {
entryPoint = "fr.acinq.lightning.cli.main" entryPoint = "fr.acinq.lightning.cli.main"
optimized = false // without this, release mode throws 'Index 0 out of bounds for length 0' in StaticInitializersOptimization.kt optimized = false // without this, release mode throws 'Index 0 out of bounds for length 0' in StaticInitializersOptimization.kt
} }*/
} }
} }
@ -111,23 +111,17 @@ kotlin {
} }
sourceSets { sourceSets {
val jvmMain by getting {
// Include the native source directory if needed
resources.srcDirs("src/commonMain/kotlin/fr/acinq/lightning/vsock/native")
}
commonMain { commonMain {
kotlin.srcDir(buildVersionsTask.map { it.destinationDir }) kotlin.srcDir(buildVersionsTask.map { it.destinationDir })
dependencies { dependencies {
implementation("com.github.raymond98.lightning-kmp:lightning-kmp:v1.6.2-FEECREDIT-8") implementation("com.github.raymond98.lightning-kmp:lightning-kmp:v1.6.2-FEECREDIT-8")
implementation("org.bytedeco:javacpp:1.5.10") //implementation("org.bytedeco:javacpp:1.5.10")
implementation(kotlin("stdlib-jdk8")) //implementation("com.github.maven-nar:nar-maven-plugin:3.10.1")
implementation("org.bytedeco:javacv-platform:1.5.10")
implementation("org.bytedeco:javacpp-presets:1.5.10")
api("fr.acinq.bitcoin:bitcoin-kmp:${Versions.bitcoinKmpVersion}") //api("fr.acinq.bitcoin:bitcoin-kmp:${Versions.bitcoinKmpVersion}")
api("co.touchlab:kermit:${Versions.kermitLoggerVersion}") //api("co.touchlab:kermit:${Versions.kermitLoggerVersion}")
api("org.jetbrains.kotlinx:kotlinx-datetime:${Versions.datetimeVersion}") //api("org.jetbrains.kotlinx:kotlinx-datetime:${Versions.datetimeVersion}")
api(ktor("network")) api(ktor("network"))
api(ktor("network-tls")) api(ktor("network-tls"))
@ -154,7 +148,7 @@ kotlin {
jvmMain { jvmMain {
dependencies { dependencies {
implementation("app.cash.sqldelight:sqlite-driver:${Versions.sqlDelight}") implementation("app.cash.sqldelight:sqlite-driver:${Versions.sqlDelight}")
implementation("fr.acinq.secp256k1:secp256k1-kmp-jni-jvm:${Versions.secpJniJvmVersion}") //implementation("fr.acinq.secp256k1:secp256k1-kmp-jni-jvm:${Versions.secpJniJvmVersion}")
implementation(ktor("client-okhttp")) implementation(ktor("client-okhttp"))
implementation("ch.qos.logback:logback-classic:1.2.3") implementation("ch.qos.logback:logback-classic:1.2.3")
} }
@ -190,10 +184,10 @@ kotlin {
include("*.kexe") include("*.kexe")
rename("phoenixd.kexe", "phoenixd") rename("phoenixd.kexe", "phoenixd")
} }
from("$projectDir/build/bin/$dir/phoenix-cliReleaseExecutable") { /*from("$projectDir/build/bin/$dir/phoenix-cliReleaseExecutable") {
include("*.kexe") include("*.kexe")
rename("phoenix-cli.kexe", "phoenix-cli") rename("phoenix-cli.kexe", "phoenix-cli")
} }*/
into("${archiveBaseName.get()}-${archiveVersion.get()}-${archiveClassifier.get()}") into("${archiveBaseName.get()}-${archiveVersion.get()}-${archiveClassifier.get()}")
} }
@ -220,10 +214,10 @@ application {
mainClass = "fr.acinq.lightning.bin.MainKt" mainClass = "fr.acinq.lightning.bin.MainKt"
// Set java.library.path to include the directory where the shared library is generated // Set java.library.path to include the directory where the shared library is generated
applicationDefaultJvmArgs = listOf("-Djava.library.path=${project.buildDir}/libs") applicationDefaultJvmArgs = listOf("-Djava.library.path=${layout.buildDirectory.dir("libs").get().asFile.absolutePath}")
} }
val cliScripts by tasks.register("cliScripts", CreateStartScripts::class) { /*val cliScripts by tasks.register("cliScripts", CreateStartScripts::class) {
mainClass.set("fr.acinq.lightning.cli.PhoenixCliKt") mainClass.set("fr.acinq.lightning.cli.PhoenixCliKt")
outputDir = tasks.startScripts.get().outputDir outputDir = tasks.startScripts.get().outputDir
classpath = tasks.startScripts.get().classpath classpath = tasks.startScripts.get().classpath
@ -232,13 +226,13 @@ val cliScripts by tasks.register("cliScripts", CreateStartScripts::class) {
tasks.startScripts { tasks.startScripts {
dependsOn(cliScripts) dependsOn(cliScripts)
} }*/
val compileNative by tasks.register<Exec>("compileNative") { val compileNative by tasks.register<Exec>("compileNative") {
group = "build" group = "build"
description = "Compile the native C++ code into a shared library" description = "Compile the native C++ code into a shared library and package it into a .nar file"
val outputDir = file("${project.buildDir}/libs") val outputDir = layout.buildDirectory.dir("libs").get().asFile
val nativeSourceDir = file("src/commonMain/kotlin/fr/acinq/lightning/vsock/native") val nativeSourceDir = file("src/commonMain/kotlin/fr/acinq/lightning/vsock/native")
// Locate the JNI headers - adjust these paths based on your actual JDK location // Locate the JNI headers - adjust these paths based on your actual JDK location
@ -249,9 +243,11 @@ val compileNative by tasks.register<Exec>("compileNative") {
inputs.dir(nativeSourceDir) inputs.dir(nativeSourceDir)
outputs.dir(outputDir) outputs.dir(outputDir)
// Compile the shared library
commandLine("g++", "-I$jniIncludeDir", "-I$jniPlatformIncludeDir", "-shared", "-o", outputDir.resolve("libjniVSockImpl.so"), nativeSourceDir.resolve("VSockImpl.cpp"), "-fPIC") commandLine("g++", "-I$jniIncludeDir", "-I$jniPlatformIncludeDir", "-shared", "-o", outputDir.resolve("libjniVSockImpl.so"), nativeSourceDir.resolve("VSockImpl.cpp"), "-fPIC")
} }
// Ensure the native library is compiled before creating the distribution // Ensure the native library is compiled before creating the distribution
tasks.withType<Tar> { tasks.withType<Tar> {
dependsOn(compileNative) dependsOn(compileNative)

View File

@ -133,8 +133,8 @@ class Phoenixd : CliktCommand() {
private val electrumServerPort by option("--electrum-server-port", help = "Port for the electrum server").int().default(50002) private val electrumServerPort by option("--electrum-server-port", help = "Port for the electrum server").int().default(50002)
private val startVsock by option("--start-vsock-server", help = "Start the vsock server for API calls").boolean().default(true) private val startVsock by option("--start-vsock-server", help = "Start the vsock server for API calls").boolean().default(true)
private val vsockCID by option("--vsock-server-cid", help = "CID for the Vsock server").int().default(4) private val vsockCID by option("--vsock-server-cid", help = "CID for the Vsock server").int().default(4) //enclave cid is 4 i think
private val vsockPort by option("--vsock-server-port", help = "Port for the Vsock server").int().default(9001) private val vsockPort by option("--vsock-server-port", help = "Port for the Vsock server").int().default(9002)
class LiquidityOptions : OptionGroup(name = "Liquidity Options") { class LiquidityOptions : OptionGroup(name = "Liquidity Options") {
val autoLiquidity by option("--auto-liquidity", help = "Amount automatically requested when inbound liquidity is needed").choice( val autoLiquidity by option("--auto-liquidity", help = "Amount automatically requested when inbound liquidity is needed").choice(
@ -393,9 +393,12 @@ class Phoenixd : CliktCommand() {
} }
var vsockServer: VsockServer? = null var vsockServer: VsockServer? = null
if(startVsock){ if (startVsock) {
vsockServer = VsockServer(vsockCID, vsockPort, httpBindPort, httpBindIp, loggerFactory) vsockServer = VsockServer(vsockCID, vsockPort, httpBindPort, httpBindIp, loggerFactory)
vsockServer.start() GlobalScope.launch {
consoleLog(yellow("Vsock Server Binding to Port: $vsockPort"))
vsockServer.start()
}
} }
val server = embeddedServer(CIO, port = httpBindPort, host = httpBindIp, val server = embeddedServer(CIO, port = httpBindPort, host = httpBindIp,

View File

@ -43,7 +43,7 @@ abstract class BaseVSock : Closeable {
fun bind(address: VSockAddress?, backlog: Int = DEFAULT_BACKLOG) { fun bind(address: VSockAddress?, backlog: Int = DEFAULT_BACKLOG) {
var backlog = backlog var backlog = backlog
if (isClosed) { if (isClosed) {
throw SocketException("Socket closed") throw SocketException("Socket closed thrown in Base Vsock")
} }
if (bound) { if (bound) {
throw SocketException("Socket already bound") throw SocketException("Socket already bound")

View File

@ -6,7 +6,9 @@ import java.net.SocketException
class ServerVSock : BaseVSock() { class ServerVSock : BaseVSock() {
@Throws(IOException::class) @Throws(IOException::class)
fun accept(): VSock { fun accept(): VSock {
if (isClosed) throw SocketException("Socket closed") if (isClosed) {
throw SocketException("Socket closed")
}
if (!bound) throw SocketException("Socket not bound") if (!bound) throw SocketException("Socket not bound")
val socket = VSock() val socket = VSock()
socket.setImplementation() socket.setImplementation()

View File

@ -12,7 +12,7 @@ class VSock : BaseVSock, Closeable {
var outputStream: VSockOutputStream? = null var outputStream: VSockOutputStream? = null
get() { get() {
if (isClosed) { if (isClosed) {
throw SocketException("VSock is closed") throw SocketException("VSock is closed thrown in Vsock")
} }
if (field == null) { if (field == null) {
field = getImplementation()?.let { VSockOutputStream(it) } field = getImplementation()?.let { VSockOutputStream(it) }
@ -26,7 +26,9 @@ class VSock : BaseVSock, Closeable {
var inputStream: VSockInputStream? = null var inputStream: VSockInputStream? = null
get() { get() {
if (isClosed) { if (isClosed) {
throw SocketException("VSock is closed") getImplementation()!!.create()
isClosed = false;
//throw SocketException("VSock is closed thrown in Vsock")
} }
if (field == null) { if (field == null) {
field = getImplementation()?.let { VSockInputStream(it) } field = getImplementation()?.let { VSockInputStream(it) }

View File

@ -2,7 +2,7 @@ package fr.acinq.lightning.vsock
import fr.acinq.lightning.bin.json.ApiType.* import fr.acinq.lightning.bin.json.ApiType.*
import fr.acinq.lightning.logging.LoggerFactory import fr.acinq.lightning.logging.LoggerFactory
import fr.acinq.lightning.logging.debug import fr.acinq.lightning.logging.info
import fr.acinq.lightning.logging.error import fr.acinq.lightning.logging.error
import io.ktor.client.* import io.ktor.client.*
import io.ktor.client.request.* import io.ktor.client.request.*
@ -16,7 +16,7 @@ import java.io.IOException
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.util.Base64 import java.util.Base64
class VsockServer(private val CID: Int, private val port: Int, httpBindPort: Int, host: String, loggerFactory: LoggerFactory) { class VsockServer(private val cid: Int, private val port: Int, httpBindPort: Int, host: String, loggerFactory: LoggerFactory) {
private var server: ServerVSock? = null private var server: ServerVSock? = null
private val logger = loggerFactory.newLogger(this::class) private val logger = loggerFactory.newLogger(this::class)
private val client = HttpClient() private val client = HttpClient()
@ -27,8 +27,8 @@ class VsockServer(private val CID: Int, private val port: Int, httpBindPort: Int
fun start() { fun start() {
server = ServerVSock() server = ServerVSock()
try { try {
server?.bind(VSockAddress(CID, port)) //For any CID use VSockAddress.VMADDR_CID_ANY server?.bind(VSockAddress(VSockAddress.VMADDR_CID_ANY, port)) //For any CID use VSockAddress.VMADDR_CID_ANY
logger.debug { "Vsock Bound on Cid: ${server?.localCid}" } logger.info { "Vsock Bound on Cid: ${server?.localCid}" }
server?.accept()?.use { peerVSock -> server?.accept()?.use { peerVSock ->
val buffer = ByteArray(bufferSize) val buffer = ByteArray(bufferSize)
@ -36,14 +36,15 @@ class VsockServer(private val CID: Int, private val port: Int, httpBindPort: Int
if (bytesRead != null) { if (bytesRead != null) {
if (bytesRead > 0) { if (bytesRead > 0) {
val receivedData = String(buffer, 0, bytesRead, StandardCharsets.UTF_8).trim() val receivedData = String(buffer, 0, bytesRead, StandardCharsets.UTF_8).trim()
logger.debug { "Received Data: $receivedData" } logger.info { "Received Data: $receivedData" }
// Parse the received data into a http request // Parse the received data into a http request
val apiRequest = try { val apiRequest = try {
Json.decodeFromString<VsockApiRequest>(receivedData) Json.decodeFromString<VsockApiRequest>(receivedData)
} catch (e: Exception) { } catch (e: Exception) {
logger.error { "Failed to parse JSON: ${e.message}" } logger.error { "Failed to parse JSON: ${e.message}" }
peerVSock.outputStream?.write("Invalid JSON format".toByteArray(StandardCharsets.UTF_8)) val errorMessage = "{\"error\":\"Invalid JSON format\", \"received\":\"${receivedData}\"}"
peerVSock.outputStream?.write(errorMessage.toByteArray(StandardCharsets.UTF_8))
return return
} }
@ -57,9 +58,10 @@ class VsockServer(private val CID: Int, private val port: Int, httpBindPort: Int
} }
} catch (ex: IOException) { } catch (ex: IOException) {
logger.error { "Error starting Vsock: ${ex.message}" } logger.error { "Error starting Vsock: ${ex.message}" }
} finally {
stop()
} }
/*finally { // We have to keep the server running
stop()
}*/
} }
private suspend fun handleApiCall(request: VsockApiRequest): String { private suspend fun handleApiCall(request: VsockApiRequest): String {
@ -90,7 +92,7 @@ class VsockServer(private val CID: Int, private val port: Int, httpBindPort: Int
} }
fun stop() { fun stop() {
logger.debug { "Stopping Vsock Server" } logger.info { "Stopping Vsock Server" }
server?.close() server?.close()
} }
} }

View File

@ -12,20 +12,28 @@
#define BUFFER_LEN 65536 #define BUFFER_LEN 65536
#define min(a, b) ((a) < (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b))
// Make sure to wrap all your JNI functions with extern "C" to avoid name mangling
extern "C" { extern "C" {
// Native method implementations matching the JNI header
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_fr_acinq_lightning_vsock_native_VSockImpl_socketCreate(JNIEnv *env, jobject thisObj) { Java_fr_acinq_lightning_vsock_native_VSockImpl_socketCreate(JNIEnv *env, jobject thisObj) {
int fd = socket(AF_VSOCK, SOCK_STREAM, 0); int fd = socket(AF_VSOCK, SOCK_STREAM, 0);
// Optionally store the socket descriptor in the Java object's field if (fd < 0) {
env->ThrowNew(env->FindClass("java/net/SocketException"), "Failed to create socket");
return;
}
// Store the socket descriptor in the Java object's field
jclass thisClass = env->GetObjectClass(thisObj);
jfieldID fdField = env->GetFieldID(thisClass, "fd", "I");
env->SetIntField(thisObj, fdField, fd);
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_fr_acinq_lightning_vsock_native_VSockImpl_connect(JNIEnv *env, jobject thisObj, jobject addr) { Java_fr_acinq_lightning_vsock_native_VSockImpl_connect(JNIEnv *env, jobject thisObj, jobject addr) {
int fd = -1; // Assuming you have stored the fd somewhere accessible jclass thisClass = env->GetObjectClass(thisObj);
jfieldID fdField = env->GetFieldID(thisClass, "fd", "I");
int fd = env->GetIntField(thisObj, fdField);
if (fd == -1) { if (fd == -1) {
env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed"); env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed");
return; return;
@ -41,6 +49,7 @@ std::memset(&sock_addr, 0, sizeof(struct sockaddr_vm));
sock_addr.svm_family = AF_VSOCK; sock_addr.svm_family = AF_VSOCK;
sock_addr.svm_port = env->GetIntField(addr, portField); sock_addr.svm_port = env->GetIntField(addr, portField);
sock_addr.svm_cid = env->GetIntField(addr, cidField); sock_addr.svm_cid = env->GetIntField(addr, cidField);
int status = ::connect(fd, (struct sockaddr *)&sock_addr, sizeof(struct sockaddr_vm)); int status = ::connect(fd, (struct sockaddr *)&sock_addr, sizeof(struct sockaddr_vm));
if (status != 0) { if (status != 0) {
@ -51,23 +60,30 @@ env->ThrowNew(env->FindClass("java/net/ConnectException"),
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_fr_acinq_lightning_vsock_native_VSockImpl_close(JNIEnv *env, jobject thisObj) { Java_fr_acinq_lightning_vsock_native_VSockImpl_close(JNIEnv *env, jobject thisObj) {
int fd = -1; // Assuming you have stored the fd somewhere accessible jclass thisClass = env->GetObjectClass(thisObj);
jfieldID fdField = env->GetFieldID(thisClass, "fd", "I");
int fd = env->GetIntField(thisObj, fdField);
if (fd == -1) { if (fd == -1) {
return; return; // Socket is already closed
} }
int status = ::close(fd); int status = ::close(fd);
fd = -1;
if (status != 0) { if (status != 0) {
env->ThrowNew(env->FindClass("java/net/SocketException"), env->ThrowNew(env->FindClass("java/net/SocketException"),
("Close failed with error no: " + std::to_string(errno)).c_str()); ("Close failed with error no: " + std::to_string(errno)).c_str());
} }
// Mark the socket as closed
env->SetIntField(thisObj, fdField, -1);
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_fr_acinq_lightning_vsock_native_VSockImpl_write(JNIEnv *env, jobject thisObj, jbyteArray b, jint offset, jint len) { Java_fr_acinq_lightning_vsock_native_VSockImpl_write(JNIEnv *env, jobject thisObj, jbyteArray b, jint offset, jint len) {
int fd = -1; // Assuming you have stored the fd somewhere accessible jclass thisClass = env->GetObjectClass(thisObj);
jfieldID fdField = env->GetFieldID(thisClass, "fd", "I");
int fd = env->GetIntField(thisObj, fdField);
if (fd == -1) { if (fd == -1) {
env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed"); env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed");
return; return;
@ -91,7 +107,10 @@ offset += chunkLen;
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_fr_acinq_lightning_vsock_native_VSockImpl_read(JNIEnv *env, jobject thisObj, jbyteArray b, jint offset, jint len) { Java_fr_acinq_lightning_vsock_native_VSockImpl_read(JNIEnv *env, jobject thisObj, jbyteArray b, jint offset, jint len) {
int fd = -1; // Assuming you have stored the fd somewhere accessible jclass thisClass = env->GetObjectClass(thisObj);
jfieldID fdField = env->GetFieldID(thisClass, "fd", "I");
int fd = env->GetIntField(thisObj, fdField);
if (fd == -1) { if (fd == -1) {
env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed"); env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed");
return -1; return -1;
@ -114,7 +133,10 @@ return nread;
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_fr_acinq_lightning_vsock_native_VSockImpl_bind(JNIEnv *env, jobject thisObj, jobject addr) { Java_fr_acinq_lightning_vsock_native_VSockImpl_bind(JNIEnv *env, jobject thisObj, jobject addr) {
int fd = -1; // Assuming you have stored the fd somewhere accessible jclass thisClass = env->GetObjectClass(thisObj);
jfieldID fdField = env->GetFieldID(thisClass, "fd", "I");
int fd = env->GetIntField(thisObj, fdField);
if (fd == -1) { if (fd == -1) {
env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed"); env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed");
return; return;
@ -141,7 +163,10 @@ env->ThrowNew(env->FindClass("java/net/BindException"),
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_fr_acinq_lightning_vsock_native_VSockImpl_listen(JNIEnv *env, jobject thisObj, jint backlog) { Java_fr_acinq_lightning_vsock_native_VSockImpl_listen(JNIEnv *env, jobject thisObj, jint backlog) {
int fd = -1; // Assuming you have stored the fd somewhere accessible jclass thisClass = env->GetObjectClass(thisObj);
jfieldID fdField = env->GetFieldID(thisClass, "fd", "I");
int fd = env->GetIntField(thisObj, fdField);
if (fd == -1) { if (fd == -1) {
env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed"); env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed");
return; return;
@ -157,7 +182,10 @@ env->ThrowNew(env->FindClass("java/net/SocketException"),
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_fr_acinq_lightning_vsock_native_VSockImpl_accept(JNIEnv *env, jobject thisObj, jobject connectionVSock) { Java_fr_acinq_lightning_vsock_native_VSockImpl_accept(JNIEnv *env, jobject thisObj, jobject connectionVSock) {
int fd = -1; // Assuming you have stored the fd somewhere accessible jclass thisClass = env->GetObjectClass(thisObj);
jfieldID fdField = env->GetFieldID(thisClass, "fd", "I");
int fd = env->GetIntField(thisObj, fdField);
if (fd == -1) { if (fd == -1) {
env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed"); env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed");
return; return;
@ -175,13 +203,16 @@ return;
// Set the peer_fd in the Java connectionVSock object // Set the peer_fd in the Java connectionVSock object
jclass VSockImplClass = env->GetObjectClass(connectionVSock); jclass VSockImplClass = env->GetObjectClass(connectionVSock);
jfieldID fdField = env->GetFieldID(VSockImplClass, "fd", "I"); jfieldID peerFdField = env->GetFieldID(VSockImplClass, "fd", "I");
env->SetIntField(connectionVSock, fdField, peer_fd); env->SetIntField(connectionVSock, peerFdField, peer_fd);
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_fr_acinq_lightning_vsock_native_VSockImpl_getLocalCid(JNIEnv *env, jobject thisObj) { Java_fr_acinq_lightning_vsock_native_VSockImpl_getLocalCid(JNIEnv *env, jobject thisObj) {
int fd = -1; // Assuming you have stored the fd somewhere accessible jclass thisClass = env->GetObjectClass(thisObj);
jfieldID fdField = env->GetFieldID(thisClass, "fd", "I");
int fd = env->GetIntField(thisObj, fdField);
if (fd == -1) { if (fd == -1) {
env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed"); env->ThrowNew(env->FindClass("java/net/SocketException"), "Socket is closed");
return -1; return -1;

View File

@ -1,25 +1,13 @@
package fr.acinq.lightning.vsock.native package fr.acinq.lightning.vsock.native
import fr.acinq.lightning.vsock.VSockAddress import fr.acinq.lightning.vsock.VSockAddress
import org.bytedeco.javacpp.Loader
import org.bytedeco.javacpp.Pointer
import org.bytedeco.javacpp.annotation.Namespace
import org.bytedeco.javacpp.annotation.Platform
import java.net.SocketException import java.net.SocketException
class VSockImpl() {
@Platform(include = [
"<sys/socket.h>",
"<sys/ioctl.h>",
"<linux/vm_sockets.h>",
"<unistd.h>",
"<errno.h>"
])
@Namespace("vsock")
class VSockImpl() : Pointer() {
init { init {
Loader.load() //load the native library System.load("${System.getProperty("user.dir")}/build/libs/libjniVSockImpl.so")
//NarSystem.loadLibrary() // Load the native library from the .nar file
} }
var fd: Int = -1 var fd: Int = -1
@ -37,7 +25,7 @@ class VSockImpl() : Pointer() {
external fun connect(address: VSockAddress?) external fun connect(address: VSockAddress?)
@Throws(Exception::class) @Throws(Exception::class)
external override fun close() external fun close()
@Throws(Exception::class) @Throws(Exception::class)
external fun write(b: ByteArray, offset: Int, len: Int) external fun write(b: ByteArray, offset: Int, len: Int)