forwarder_guest_launcher can execute forwarder_guest

Bug: 340126051
Test: Prepare server running in the port number 12345 in the guest, and
run `forwarder_guest_launcher --host 192.168.0.1`.

Change-Id: If4f5523a285382341615b669eed0492f493b7577
diff --git a/android/forwarder_host/src/forwarder_host.rs b/android/forwarder_host/src/forwarder_host.rs
index a32ce20..78f3555 100644
--- a/android/forwarder_host/src/forwarder_host.rs
+++ b/android/forwarder_host/src/forwarder_host.rs
@@ -29,6 +29,7 @@
 
 use forwarder::forwarder::ForwarderSession;
 use jni::objects::{JObject, JValue};
+use jni::sys::jint;
 use jni::JNIEnv;
 use log::{debug, error, info, warn};
 use nix::sys::eventfd::EventFd;
@@ -380,13 +381,14 @@
 fn update_listening_ports(
     update_queue: &Arc<Mutex<VecDeque<TcpForwardTarget>>>,
     update_evt: &EventFd,
+    cid: i32,
 ) -> Result<()> {
     let mut update_queue = update_queue.lock().unwrap();
 
     // TODO(b/340126051): Bring listening ports from the guest.
     update_queue.push_back(TcpForwardTarget {
-        port: 12345,    /* Example value for testing */
-        vsock_cid: 157, /* Placeholder value */
+        port: 12345, /* Example value for testing */
+        vsock_cid: cid as u32,
     });
 
     update_evt.write(1).map_err(Error::UpdateEventWrite)?;
@@ -394,14 +396,13 @@
 }
 
 // TODO(b/340126051): Host can receive opened ports from the guest.
-// TODO(b/340126051): Host can order executing chunnel on the guest.
-fn run_forwarder_host(jni_env: JNIEnv, jni_cb: JObject) -> Result<()> {
+fn run_forwarder_host(cid: i32, jni_env: JNIEnv, jni_cb: JObject) -> Result<()> {
     debug!("Starting forwarder_host");
     let update_evt = EventFd::new().map_err(Error::EventFdNew)?;
     let update_queue = Arc::new(Mutex::new(VecDeque::new()));
 
     // TODO(b/340126051): Instead of one-time execution, bring port info with separated thread.
-    update_listening_ports(&update_queue, &update_evt)?;
+    update_listening_ports(&update_queue, &update_evt, cid)?;
 
     let mut sessions = ForwarderSessions::new(update_evt, update_queue, jni_env, jni_cb)?;
     sessions.run()
@@ -412,9 +413,10 @@
 pub extern "C" fn Java_com_android_virtualization_vmlauncher_DebianServiceImpl_runForwarderHost(
     env: JNIEnv,
     _class: JObject,
+    cid: jint,
     callback: JObject,
 ) {
-    match run_forwarder_host(env, callback) {
+    match run_forwarder_host(cid, env, callback) {
         Ok(_) => {
             info!("forwarder_host is terminated");
         }
diff --git a/guest/forwarder_guest_launcher/Cargo.toml b/guest/forwarder_guest_launcher/Cargo.toml
index bf0c0ed..03d3f7f 100644
--- a/guest/forwarder_guest_launcher/Cargo.toml
+++ b/guest/forwarder_guest_launcher/Cargo.toml
@@ -4,10 +4,12 @@
 edition = "2021"
 
 [dependencies]
+anyhow = "1.0.91"
 clap = { version = "4.5.20", features = ["derive"] }
 prost = "0.13.3"
-tokio = { version = "1.40.0", features = ["rt-multi-thread"] }
+tokio = { version = "1.40.0", features = ["process", "rt-multi-thread"] }
 tonic = "0.12.3"
+vsock = "0.5.1"
 
 [build-dependencies]
 tonic-build = "0.12.3"
diff --git a/guest/forwarder_guest_launcher/src/main.rs b/guest/forwarder_guest_launcher/src/main.rs
index 4042fe5..59ee8c6 100644
--- a/guest/forwarder_guest_launcher/src/main.rs
+++ b/guest/forwarder_guest_launcher/src/main.rs
@@ -14,9 +14,11 @@
 
 //! Launcher of forwarder_guest
 
+use anyhow::Context;
 use clap::Parser;
 use debian_service::debian_service_client::DebianServiceClient;
-use debian_service::Empty;
+use debian_service::QueueOpeningRequest;
+use tokio::process::Command;
 use tonic::transport::Endpoint;
 use tonic::Request;
 
@@ -35,16 +37,34 @@
 
 #[tokio::main]
 async fn main() -> Result<(), Box<dyn std::error::Error>> {
+    println!("Starting forwarder_guest_launcher");
     let args = Args::parse();
     let addr = format!("https://{}:12000", args.host_addr);
 
     let channel = Endpoint::from_shared(addr)?.connect().await?;
     let mut client = DebianServiceClient::new(channel);
-    let mut res_stream =
-        client.open_forwarding_request_queue(Request::new(Empty {})).await?.into_inner();
+    let cid = vsock::get_local_cid().context("Failed to get CID of VM")?;
+    let mut res_stream = client
+        .open_forwarding_request_queue(Request::new(QueueOpeningRequest { cid: cid as i32 }))
+        .await?
+        .into_inner();
 
     while let Some(response) = res_stream.message().await? {
-        println!("Response from the host: {:?}", response);
+        let tcp_port = i16::try_from(response.guest_tcp_port)
+            .context("Failed to convert guest_tcp_port as i16")?;
+        let vsock_port = response.vsock_port as u32;
+
+        println!(
+            "executing forwarder_guest with guest_tcp_port: {:?}, vsock_port: {:?}",
+            &tcp_port, &vsock_port
+        );
+
+        let _ = Command::new("forwarder_guest")
+            .arg("--local")
+            .arg(format!("127.0.0.1:{}", tcp_port))
+            .arg("--remote")
+            .arg(format!("vsock:2:{}", vsock_port))
+            .spawn();
     }
     Ok(())
 }
diff --git a/libs/debian_service/proto/DebianService.proto b/libs/debian_service/proto/DebianService.proto
index 5e3286a..a887bf2 100644
--- a/libs/debian_service/proto/DebianService.proto
+++ b/libs/debian_service/proto/DebianService.proto
@@ -23,10 +23,12 @@
 
 service DebianService {
   rpc ReportVmIpAddr (IpAddr) returns (ReportVmIpAddrResponse) {}
-  rpc OpenForwardingRequestQueue (Empty) returns (stream ForwardingRequestItem) {}
+  rpc OpenForwardingRequestQueue (QueueOpeningRequest) returns (stream ForwardingRequestItem) {}
 }
 
-message Empty {}
+message QueueOpeningRequest {
+  int32 cid = 1;
+}
 
 message IpAddr {
   string addr = 1;
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/DebianServiceImpl.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/DebianServiceImpl.java
index d62ccfb..dcc8152 100644
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/DebianServiceImpl.java
+++ b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/DebianServiceImpl.java
@@ -21,9 +21,9 @@
 import androidx.annotation.Keep;
 
 import com.android.virtualization.vmlauncher.proto.DebianServiceGrpc;
-import com.android.virtualization.vmlauncher.proto.Empty;
 import com.android.virtualization.vmlauncher.proto.ForwardingRequestItem;
 import com.android.virtualization.vmlauncher.proto.IpAddr;
+import com.android.virtualization.vmlauncher.proto.QueueOpeningRequest;
 import com.android.virtualization.vmlauncher.proto.ReportVmIpAddrResponse;
 
 import io.grpc.stub.StreamObserver;
@@ -53,9 +53,9 @@
 
     @Override
     public void openForwardingRequestQueue(
-            Empty request, StreamObserver<ForwardingRequestItem> responseObserver) {
+            QueueOpeningRequest request, StreamObserver<ForwardingRequestItem> responseObserver) {
         Log.d(DebianServiceImpl.TAG, "OpenForwardingRequestQueue");
-        runForwarderHost(new ForwarderHostCallback(responseObserver));
+        runForwarderHost(request.getCid(), new ForwarderHostCallback(responseObserver));
         responseObserver.onCompleted();
     }
 
@@ -77,7 +77,7 @@
         }
     }
 
-    private static native void runForwarderHost(ForwarderHostCallback callback);
+    private static native void runForwarderHost(int cid, ForwarderHostCallback callback);
 
     protected interface DebianServiceCallback {
         void onIpAddressAvailable(String ipAddr);