async fn launch_v1_component(
        legacy_url: String,
        start_info: fcrunner::ComponentStartInfo,
        controller: ServerEnd<fcrunner::ComponentControllerMarker>,
    ) -> Result<(), Error> {
        let execution_scope = ExecutionScope::new();

        // We are going to create a new v1 nested environment that holds the component's incoming
        // svc contents along with fuchsia.sys.Loader. This is because fuchsia.sys.Loader must be
        // in the environment for us to be able to launch components within it.
        //
        // In order to accomplish this, we need to host an svc directory that holds this protocol
        // along with everything else in the component's incoming svc directory. When the
        // fuchsia.sys.Loader node in the directory is connected to, we forward the connection to
        // our own namespace, and for any other connection we forward to the component's incoming
        // svc.
        let namespace = start_info.ns.unwrap();
        if namespace.len() > 2 {
            return Err(format_err!("v1 component namespace contains unexpected directories"));
        }
        let mut svc_names = vec![];
        let mut svc_dir_proxy = None;
        for namespace_entry in namespace {
            match namespace_entry.path.as_ref().map(|s| s.as_str()) {
                Some("/pkg") => (),
                Some("/svc") => {
                    let dir_proxy = namespace_entry
                        .directory
                        .expect("missing directory handle")
                        .into_proxy()?;
                    svc_names = files_async::readdir(&dir_proxy)
                        .await?
                        .into_iter()
                        .map(|direntry| direntry.name)
                        .collect();
                    svc_dir_proxy = Some(dir_proxy);
                    break;
                }
                Some(p) => return Err(format_err!("unexpected item in namespace: {:?}", p)),
                _ => return Err(format_err!("malformed namespace")),
            }
        }

        let runner_svc_dir_proxy = io_util::open_directory_in_namespace(
            "/svc",
            fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_WRITABLE,
        )?;
        let host_pseudo_dir = pfs::simple();
        host_pseudo_dir.clone().add_entry(
            fsysv1::LoaderMarker::NAME,
            vfs::remote::remote_boxed(Box::new(
                move |_scope: ExecutionScope,
                      flags: u32,
                      mode: u32,
                      _relative_path: VfsPath,
                      server_end: ServerEnd<fio::NodeMarker>| {
                    if let Err(e) = runner_svc_dir_proxy.open(
                        flags,
                        mode,
                        fsysv1::LoaderMarker::NAME,
                        server_end,
                    ) {
                        error!("failed to forward service open to realm builder server namespace: {:?}", e);
                    }
                },
            )),
        )?;

        if let Some(svc_dir_proxy) = svc_dir_proxy {
            for svc_name in &svc_names {
                let svc_dir_proxy = Clone::clone(&svc_dir_proxy);
                let svc_name = svc_name.clone();
                let svc_name_for_err = svc_name.clone();
                if let Err(status) = host_pseudo_dir.clone().add_entry(
                    svc_name.clone().as_str(),
                    vfs::remote::remote_boxed(Box::new(
                        move |_scope: ExecutionScope,
                              flags: u32,
                              mode: u32,
                              _relative_path: VfsPath,
                              server_end: ServerEnd<fio::NodeMarker>| {
                            if let Err(e) =
                                svc_dir_proxy.open(flags, mode, svc_name.as_str(), server_end)
                            {
                                error!("failed to forward service open to v2 namespace: {:?}", e);
                            }
                        },
                    )),
                ) {
                    if status == fuchsia_zircon::Status::ALREADY_EXISTS {
                        log::error!(
                            "Service {} added twice to namespace of component {}",
                            svc_name_for_err,
                            legacy_url
                        );
                    }

                    return Err(status.into());
                }
            }
        }

        let (host_dir_client_end, host_dir_server_end) =
            create_endpoints::<fio::NodeMarker>().expect("could not create node proxy endpoints");
        host_pseudo_dir.clone().open(
            execution_scope.clone(),
            fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_WRITABLE,
            fio::MODE_TYPE_DIRECTORY,
            VfsPath::dot(),
            host_dir_server_end.into_channel().into(),
        );

        svc_names.push(fsysv1::LoaderMarker::NAME.into());
        let mut additional_services = fsysv1::ServiceList {
            names: svc_names,
            provider: None,
            host_directory: Some(host_dir_client_end.into_channel()),
        };

        // Our service list for the new nested environment is all set up, so we can proceed with
        // creating the v1 nested environment.

        let mut options = fsysv1::EnvironmentOptions {
            inherit_parent_services: false,
            use_parent_runners: false,
            kill_on_oom: true,
            delete_storage_on_death: true,
        };

        let id: u64 = rand::thread_rng().gen();
        let realm_label = format!("v2-bridge-{}", id);

        let (sub_env_proxy, sub_env_server_end) = create_proxy::<fsysv1::EnvironmentMarker>()?;
        let (sub_env_controller_proxy, sub_env_controller_server_end) =
            create_proxy::<fsysv1::EnvironmentControllerMarker>()?;

        let env_proxy = connect_to_protocol::<fsysv1::EnvironmentMarker>()?;
        env_proxy.create_nested_environment(
            sub_env_server_end,
            sub_env_controller_server_end,
            &realm_label,
            Some(&mut additional_services),
            &mut options,
        )?;

        // We have created the nested environment that holds exactly and only fuchsia.sys.Loader.
        //
        // Now we can create the component.

        // The directory request given to the v1 component launcher connects the given directory
        // handle to the v1 component's `svc` subdir of its outgoing directory, whereas the
        // directory request we got from component manager should connect to the top-level of the
        // outgoing directory.
        //
        // We can make the two work together by hosting our own vfs on `start_info.outgoing_dir`,
        // which forwards connections to `svc` into the v1 component's `directory_request`.

        let (outgoing_svc_dir_proxy, outgoing_svc_dir_server_end) =
            create_proxy::<fio::DirectoryMarker>()?;
        let out_pseudo_dir = pseudo_directory!(
            "svc" => vfs::remote::remote_dir(outgoing_svc_dir_proxy),
        );
        out_pseudo_dir.open(
            execution_scope.clone(),
            fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_WRITABLE,
            fio::MODE_TYPE_DIRECTORY,
            VfsPath::dot(),
            start_info.outgoing_dir.unwrap().into_channel().into(),
        );

        // We've got a nested environment and everything set up to get protocols into and out of
        // the v1 component. Time to launch it.
        let (sub_env_launcher_proxy, sub_env_launcher_server_end) =
            create_proxy::<fsysv1::LauncherMarker>()?;
        sub_env_proxy.get_launcher(sub_env_launcher_server_end)?;

        let mut launch_info = fsysv1::LaunchInfo {
            url: legacy_url.clone(),
            arguments: None,
            out: None,
            err: None,
            directory_request: Some(outgoing_svc_dir_server_end.into_channel()),
            flat_namespace: None,
            additional_services: None,
        };
        sub_env_launcher_proxy.create_component(&mut launch_info, None)?;

        fasync::Task::local(run_v1_controller(
            controller.into_stream()?,
            legacy_url,
            realm_label,
            start_info.runtime_dir.unwrap(),
            sub_env_controller_proxy,
            execution_scope,
        ))
        .detach();
        Ok(())
    }
/// Launches a new v1 component. This is done by using fuchsia.sys.Environment to create a new
/// nested environment and then launching a v1 component into that environment, using the "svc"
/// entry from `start_info.ns` as the v1 component's additional services. The v1 component's
/// outgoing directory is likewise connected to `start_info.outgoing_directory`, allowing
/// protocol capabilities to flow in either direction.
Launches a new v1 component. This is done by using fuchsia.sys.Environment to create a new
nested environment and then launching a v1 component into that environment, using the "svc"
entry from `start_info.ns` as the v1 component's additional services. The v1 component's
outgoing directory is likewise connected to `start_info.outgoing_directory`, allowing
protocol capabilities to flow in either direction.
Launches a new v1 component . This is done by using fuchsia . sys . Environment to create a new nested environment and then launching a v1 component into that environment using the " svc " entry from ` start_info . ns ` as the v1 component ' s additional services . The v1 component ' s outgoing directory is likewise connected to ` start_info . outgoing_directory ` allowing protocol capabilities to flow in either direction .
async fn launch_v1_component(
        legacy_url: String,
        start_info: fcrunner::ComponentStartInfo,
        controller: ServerEnd<fcrunner::ComponentControllerMarker>,
    ) -> Result<(), Error> {
        let execution_scope = ExecutionScope::new();
        // We are going to create a new v1 nested environment that holds the component's incoming
        // svc contents along with fuchsia.sys.Loader. This is because fuchsia.sys.Loader must be
        // in the environment for us to be able to launch components within it.
        //
        // In order to accomplish this, we need to host an svc directory that holds this protocol
        // along with everything else in the component's incoming svc directory. When the
        // fuchsia.sys.Loader node in the directory is connected to, we forward the connection to
        // our own namespace, and for any other connection we forward to the component's incoming
        // svc.
        let namespace = start_info.ns.unwrap();
        if namespace.len() > 2 {
            return Err(format_err!("v1 component namespace contains unexpected directories"));
        }
        let mut svc_names = vec![];
        let mut svc_dir_proxy = None;
        for namespace_entry in namespace {
            match namespace_entry.path.as_ref().map(|s| s.as_str()) {
                Some("/pkg") => (),
                Some("/svc") => {
                    let dir_proxy = namespace_entry
                        .directory
                        .expect("missing directory handle")
                        .into_proxy()?;
                    svc_names = files_async::readdir(&dir_proxy)
                        .await?
                        .into_iter()
                        .map(|direntry| direntry.name)
                        .collect();
                    svc_dir_proxy = Some(dir_proxy);
                    break;
                }
                Some(p) => return Err(format_err!("unexpected item in namespace: {:?}", p)),
                _ => return Err(format_err!("malformed namespace")),
            }
        }
        let runner_svc_dir_proxy = io_util::open_directory_in_namespace(
            "/svc",
            fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_WRITABLE,
        )?;
        let host_pseudo_dir = pfs::simple();
        host_pseudo_dir.clone().add_entry(
            fsysv1::LoaderMarker::NAME,
            vfs::remote::remote_boxed(Box::new(
                move |_scope: ExecutionScope,
                      flags: u32,
                      mode: u32,
                      _relative_path: VfsPath,
                      server_end: ServerEnd<fio::NodeMarker>| {
                    if let Err(e) = runner_svc_dir_proxy.open(
                        flags,
                        mode,
                        fsysv1::LoaderMarker::NAME,
                        server_end,
                    ) {
                        error!("failed to forward service open to realm builder server namespace: {:?}", e);
                    }
                },
            )),
        )?;
        if let Some(svc_dir_proxy) = svc_dir_proxy {
            for svc_name in &svc_names {
                let svc_dir_proxy = Clone::clone(&svc_dir_proxy);
                let svc_name = svc_name.clone();
                let svc_name_for_err = svc_name.clone();
                if let Err(status) = host_pseudo_dir.clone().add_entry(
                    svc_name.clone().as_str(),
                    vfs::remote::remote_boxed(Box::new(
                        move |_scope: ExecutionScope,
                              flags: u32,
                              mode: u32,
                              _relative_path: VfsPath,
                              server_end: ServerEnd<fio::NodeMarker>| {
                            if let Err(e) =
                                svc_dir_proxy.open(flags, mode, svc_name.as_str(), server_end)
                            {
                                error!("failed to forward service open to v2 namespace: {:?}", e);
                            }
                        },
                    )),
                ) {
                    if status == fuchsia_zircon::Status::ALREADY_EXISTS {
                        log::error!(
                            "Service {} added twice to namespace of component {}",
                            svc_name_for_err,
                            legacy_url
                        );
                    }
                    return Err(status.into());
                }
            }
        }
        let (host_dir_client_end, host_dir_server_end) =
            create_endpoints::<fio::NodeMarker>().expect("could not create node proxy endpoints");
        host_pseudo_dir.clone().open(
            execution_scope.clone(),
            fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_WRITABLE,
            fio::MODE_TYPE_DIRECTORY,
            VfsPath::dot(),
            host_dir_server_end.into_channel().into(),
        );
        svc_names.push(fsysv1::LoaderMarker::NAME.into());
        let mut additional_services = fsysv1::ServiceList {
            names: svc_names,
            provider: None,
            host_directory: Some(host_dir_client_end.into_channel()),
        };
        // Our service list for the new nested environment is all set up, so we can proceed with
        // creating the v1 nested environment.
        let mut options = fsysv1::EnvironmentOptions {
            inherit_parent_services: false,
            use_parent_runners: false,
            kill_on_oom: true,
            delete_storage_on_death: true,
        };
        let id: u64 = rand::thread_rng().gen();
        let realm_label = format!("v2-bridge-{}", id);
        let (sub_env_proxy, sub_env_server_end) = create_proxy::<fsysv1::EnvironmentMarker>()?;
        let (sub_env_controller_proxy, sub_env_controller_server_end) =
            create_proxy::<fsysv1::EnvironmentControllerMarker>()?;
        let env_proxy = connect_to_protocol::<fsysv1::EnvironmentMarker>()?;
        env_proxy.create_nested_environment(
            sub_env_server_end,
            sub_env_controller_server_end,
            &realm_label,
            Some(&mut additional_services),
            &mut options,
        )?;
        // We have created the nested environment that holds exactly and only fuchsia.sys.Loader.
        //
        // Now we can create the component.
        // The directory request given to the v1 component launcher connects the given directory
        // handle to the v1 component's `svc` subdir of its outgoing directory, whereas the
        // directory request we got from component manager should connect to the top-level of the
        // outgoing directory.
        //
        // We can make the two work together by hosting our own vfs on `start_info.outgoing_dir`,
        // which forwards connections to `svc` into the v1 component's `directory_request`.
        let (outgoing_svc_dir_proxy, outgoing_svc_dir_server_end) =
            create_proxy::<fio::DirectoryMarker>()?;
        let out_pseudo_dir = pseudo_directory!(
            "svc" => vfs::remote::remote_dir(outgoing_svc_dir_proxy),
        );
        out_pseudo_dir.open(
            execution_scope.clone(),
            fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_WRITABLE,
            fio::MODE_TYPE_DIRECTORY,
            VfsPath::dot(),
            start_info.outgoing_dir.unwrap().into_channel().into(),
        );
        // We've got a nested environment and everything set up to get protocols into and out of
        // the v1 component. Time to launch it.
        let (sub_env_launcher_proxy, sub_env_launcher_server_end) =
            create_proxy::<fsysv1::LauncherMarker>()?;
        sub_env_proxy.get_launcher(sub_env_launcher_server_end)?;
        let mut launch_info = fsysv1::LaunchInfo {
            url: legacy_url.clone(),
            arguments: None,
            out: None,
            err: None,
            directory_request: Some(outgoing_svc_dir_server_end.into_channel()),
            flat_namespace: None,
            additional_services: None,
        };
        sub_env_launcher_proxy.create_component(&mut launch_info, None)?;
        fasync::Task::local(run_v1_controller(
            controller.into_stream()?,
            legacy_url,
            realm_label,
            start_info.runtime_dir.unwrap(),
            sub_env_controller_proxy,
            execution_scope,
        ))
        .detach();
        Ok(())
    }
async fn launch_v1_component ( legacy_url : String , start_info : fcrunner :: ComponentStartInfo , controller : ServerEnd < fcrunner :: ComponentControllerMarker > , ) -> Result < ( ) , Error > { let execution_scope = ExecutionScope :: new ( ) ; // We are going to create a new v1 nested environment that holds the component's incoming // svc contents along with fuchsia.sys.Loader. This is because fuchsia.sys.Loader must be // in the environment for us to be able to launch components within it. // // In order to accomplish this, we need to host an svc directory that holds this protocol // along with everything else in the component's incoming svc directory. When the // fuchsia.sys.Loader node in the directory is connected to, we forward the connection to // our own namespace, and for any other connection we forward to the component's incoming // svc. let namespace = start_info . ns . unwrap ( ) ; if namespace . len ( ) > 2 { return Err ( format_err ! ( " " ) ) ; } let mut svc_names = vec ! [ ] ; let mut svc_dir_proxy = None ; for namespace_entry in namespace { match namespace_entry . path . as_ref ( ) . map ( | s | s . as_str ( ) ) { Some ( " " ) => ( ) , Some ( " " ) => { let dir_proxy = namespace_entry . directory . expect ( " " ) . into_proxy ( ) ? ; svc_names = files_async :: readdir ( & dir_proxy ) . await ? . into_iter ( ) . map ( | direntry | direntry . name ) . collect ( ) ; svc_dir_proxy = Some ( dir_proxy ) ; break ; } Some ( p ) => return Err ( format_err ! ( " " p ) ) , _ => return Err ( format_err ! ( " " ) ) , } } let runner_svc_dir_proxy = io_util :: open_directory_in_namespace ( " " , fio :: OPEN_RIGHT_READABLE | fio :: OPEN_RIGHT_WRITABLE , ) ? ; let host_pseudo_dir = pfs :: simple ( ) ; host_pseudo_dir . clone ( ) . add_entry ( fsysv1 :: LoaderMarker :: NAME , vfs :: remote :: remote_boxed ( Box :: new ( move | _scope : ExecutionScope , flags : u32 , mode : u32 , _relative_path : VfsPath , server_end : ServerEnd < fio :: NodeMarker > | { if let Err ( e ) = runner_svc_dir_proxy . open ( flags , mode , fsysv1 :: LoaderMarker :: NAME , server_end , ) { error ! ( " " e ) ; } } , ) ) , ) ? ; if let Some ( svc_dir_proxy ) = svc_dir_proxy { for svc_name in & svc_names { let svc_dir_proxy = Clone :: clone ( & svc_dir_proxy ) ; let svc_name = svc_name . clone ( ) ; let svc_name_for_err = svc_name . clone ( ) ; if let Err ( status ) = host_pseudo_dir . clone ( ) . add_entry ( svc_name . clone ( ) . as_str ( ) , vfs :: remote :: remote_boxed ( Box :: new ( move | _scope : ExecutionScope , flags : u32 , mode : u32 , _relative_path : VfsPath , server_end : ServerEnd < fio :: NodeMarker > | { if let Err ( e ) = svc_dir_proxy . open ( flags , mode , svc_name . as_str ( ) , server_end ) { error ! ( " " e ) ; } } , ) ) , ) { if status == fuchsia_zircon :: Status :: ALREADY_EXISTS { log :: error ! ( " " svc_name_for_err legacy_url ) ; } return Err ( status . into ( ) ) ; } } } let ( host_dir_client_end , host_dir_server_end ) = create_endpoints :: < fio :: NodeMarker > ( ) . expect ( " " ) ; host_pseudo_dir . clone ( ) . open ( execution_scope . clone ( ) , fio :: OPEN_RIGHT_READABLE | fio :: OPEN_RIGHT_WRITABLE , fio :: MODE_TYPE_DIRECTORY , VfsPath :: dot ( ) , host_dir_server_end . into_channel ( ) . into ( ) , ) ; svc_names . push ( fsysv1 :: LoaderMarker :: NAME . into ( ) ) ; let mut additional_services = fsysv1 :: ServiceList { names : svc_names , provider : None , host_directory : Some ( host_dir_client_end . into_channel ( ) ) , } ; // Our service list for the new nested environment is all set up, so we can proceed with // creating the v1 nested environment. let mut options = fsysv1 :: EnvironmentOptions { inherit_parent_services : false , use_parent_runners : false , kill_on_oom : true , delete_storage_on_death : true , } ; let id : u64 = rand :: thread_rng ( ) . gen ( ) ; let realm_label = format ! ( " " id ) ; let ( sub_env_proxy , sub_env_server_end ) = create_proxy :: < fsysv1 :: EnvironmentMarker > ( ) ? ; let ( sub_env_controller_proxy , sub_env_controller_server_end ) = create_proxy :: < fsysv1 :: EnvironmentControllerMarker > ( ) ? ; let env_proxy = connect_to_protocol :: < fsysv1 :: EnvironmentMarker > ( ) ? ; env_proxy . create_nested_environment ( sub_env_server_end , sub_env_controller_server_end , & realm_label , Some ( & mut additional_services ) , & mut options , ) ? ; // We have created the nested environment that holds exactly and only fuchsia.sys.Loader. // // Now we can create the component. // The directory request given to the v1 component launcher connects the given directory // handle to the v1 component's `svc` subdir of its outgoing directory, whereas the // directory request we got from component manager should connect to the top-level of the // outgoing directory. // // We can make the two work together by hosting our own vfs on `start_info.outgoing_dir`, // which forwards connections to `svc` into the v1 component's `directory_request`. let ( outgoing_svc_dir_proxy , outgoing_svc_dir_server_end ) = create_proxy :: < fio :: DirectoryMarker > ( ) ? ; let out_pseudo_dir = pseudo_directory ! ( " " vfs remote remote_dir ( outgoing_svc_dir_proxy ) ) ; out_pseudo_dir . open ( execution_scope . clone ( ) , fio :: OPEN_RIGHT_READABLE | fio :: OPEN_RIGHT_WRITABLE , fio :: MODE_TYPE_DIRECTORY , VfsPath :: dot ( ) , start_info . outgoing_dir . unwrap ( ) . into_channel ( ) . into ( ) , ) ; // We've got a nested environment and everything set up to get protocols into and out of // the v1 component. Time to launch it. let ( sub_env_launcher_proxy , sub_env_launcher_server_end ) = create_proxy :: < fsysv1 :: LauncherMarker > ( ) ? ; sub_env_proxy . get_launcher ( sub_env_launcher_server_end ) ? ; let mut launch_info = fsysv1 :: LaunchInfo { url : legacy_url . clone ( ) , arguments : None , out : None , err : None , directory_request : Some ( outgoing_svc_dir_server_end . into_channel ( ) ) , flat_namespace : None , additional_services : None , } ; sub_env_launcher_proxy . create_component ( & mut launch_info , None ) ? ; fasync :: Task :: local ( run_v1_controller ( controller . into_stream ( ) ? , legacy_url , realm_label , start_info . runtime_dir . unwrap ( ) , sub_env_controller_proxy , execution_scope , ) ) . detach ( ) ; Ok ( ( ) ) }
Launches a new v1 component.
Launches a new v1 component .
legacy_url
String
start_info
fcrunner::ComponentStartInfo
controller
ServerEnd<fcrunner::ComponentControllerMarker>
legacy_url
String
start_info
fcrunner::ComponentStartInfo
controller
ServerEnd<fcrunner::ComponentControllerMarker>