zoukankan      html  css  js  c++  java
  • chrome remoting/ chromoting 分析#1

    源码查找关键词

    serviceUrls
    StartHostMain


    switches 进程类型开关

    namespace remoting {

    const char kElevateSwitchName[] = "elevate";
    const char kHelpSwitchName[] = "help";
    const char kProcessTypeSwitchName[] = "type";
    const char kQuestionSwitchName[] = "?";
    const char kVersionSwitchName[] = "version";

    const char kProcessTypeController[] = "controller";
    const char kProcessTypeDaemon[] = "daemon";
    const char kProcessTypeDesktop[] = "desktop";
    const char kProcessTypeHost[] = "host";
    const char kProcessTypeRdpDesktopSession[] = "rdp_desktop_session";
    const char kProcessTypeEvaluateCapability[] = "evaluate_capability";

    const char kEvaluateCapabilitySwitchName[] = "evaluate-type";

    #if defined(OS_WIN)
    const char kEvaluateD3D[] = "d3d-support";
    const char kEvaluate3dDisplayMode[] = "3d-display-mode";
    #endif

    const char kParentWindowSwitchName[] = "parent-window";

    const char kInputSwitchName[] = "input";
    const char kOutputSwitchName[] = "output";

    const char kMojoPipeToken[] = "mojo-pipe-token";

    } // namespace remoting

    不同开关执行不同流程
    HostMain->SelectMainRoutine(process_type)

    // Select the entry point corresponding to the process type.
    MainRoutineFn SelectMainRoutine(const std::string& process_type) {
    MainRoutineFn main_routine = nullptr;

    if (process_type == kProcessTypeHost) {
    main_routine = &HostProcessMain;
    #if defined(OS_WIN)
    } else if (process_type == kProcessTypeDaemon) {
    main_routine = &DaemonProcessMain;
    } else if (process_type == kProcessTypeDesktop) {
    main_routine = &DesktopProcessMain;
    } else if (process_type == kProcessTypeRdpDesktopSession) {
    main_routine = &RdpDesktopSessionMain;
    #endif // defined(OS_WIN)
    }

    return main_routine;
    }

    } // namespace

    因此通过process_type来指定启动的进程类型
    而每个对应的进程应该有自己特有的参数

    HostProcessMain->HostProcess->StartOnUiThread->StartOnNetworkThread 单进程条件下-> 使用kStdinConfigPath->OnConfigUpdated->ApplyConfig()
    kStdinConfigPath有是命令行传的,分两种情况,当值是-时,表示从stdin读取,否则从C:ProgramDataChromotinghost.json读取

    可以通过参数host-config 指定路径

    const char kHostEnabledConfigPath[] = "enabled";
    const char kHostOwnerConfigPath[] = "host_owner";
    const char kHostOwnerEmailConfigPath[] = "host_owner_email";
    const char kXmppLoginConfigPath[] = "xmpp_login";
    const char kOAuthRefreshTokenConfigPath[] = "oauth_refresh_token";
    const char kHostIdConfigPath[] = "host_id";
    const char kHostNameConfigPath[] = "host_name";
    const char kHostSecretHashConfigPath[] = "host_secret_hash";
    const char kPrivateKeyConfigPath[] = "private_key";
    const char kUsageStatsConsentConfigPath[] = "usage_stats_consent";
    const char kEnableVp9ConfigPath[] = "enable_vp9";
    const char kEnableH264ConfigPath[] = "enable_h264";
    const char kFrameRecorderBufferKbConfigPath[] = "frame-recorder-buffer-kb";


    DesktopSessionWin 启动HostService,带有参数 --console 表示以命令行模式启动HostService

    DesktopProcessMain 启动后初始化视频捕获线程等,然后连接到以下参数指定的通道
    const char PlatformChannel::kHandleSwitch[] = "mojo-platform-channel-handle";
    如果时无效的,那么连接到以下参数指定的服务器
    const char NamedPlatformChannel::kNamedHandleSwitch[] ="mojo-named-platform-channel-pipe";

    由上述远程端点创建的连接以及各个线程(视频捕获,输入,。。。)被作为DesktopProcess.Start函数的参数

    RdpDesktopSessionMain COM组件,只给了组件ID,然后Run
    组件id对应的类是RdpDesktopSession


    gaia_switches.cc
    通过参数替换google服务地址,如果服务使用的接口不多,可以采用identityserver做一些兼容
    const char kGoogleUrl[] = "google-url";
    const char kGaiaUrl[] = "gaia-url";
    const char kGoogleApisUrl[] = "google-apis-url";
    const char kLsoUrl[] = "lso-url";
    const char kOAuth2ClientID[] = "oauth2-client-id";
    const char kOAuth2ClientSecret[] = "oauth2-client-secret";

    gaia_urls.cc

    // Gaia service constants
    const char kDefaultGoogleUrl[] = "http://google.com";
    const char kDefaultGaiaUrl[] = "https://accounts.google.com";
    const char kDefaultGoogleApisBaseUrl[] = "https://www.googleapis.com";

    // API calls from accounts.google.com
    const char kClientLoginUrlSuffix[] = "ClientLogin";
    const char kServiceLoginUrlSuffix[] = "ServiceLogin";
    const char kEmbeddedSetupChromeOsUrlSuffixV1[] = "embedded/setup/chromeos";
    const char kEmbeddedSetupChromeOsUrlSuffixV2[] = "embedded/setup/v2/chromeos";
    // Parameter "ssp=1" is used to skip showing the password bubble when a user
    // signs in to Chrome. Note that Gaia will pass this client specified parameter
    // to all URLs that are loaded as part of thi sign-in flow.
    const char kSigninChromeSyncDice[] = "signin/chrome/sync?ssp=1";
    const char kServiceLoginAuthUrlSuffix[] = "ServiceLoginAuth";
    const char kServiceLogoutUrlSuffix[] = "Logout";
    const char kGetUserInfoUrlSuffix[] = "GetUserInfo";
    const char kTokenAuthUrlSuffix[] = "TokenAuth";
    const char kMergeSessionUrlSuffix[] = "MergeSession";
    const char kOAuthGetAccessTokenUrlSuffix[] = "OAuthGetAccessToken";
    const char kOAuthWrapBridgeUrlSuffix[] = "OAuthWrapBridge";
    const char kOAuth1LoginUrlSuffix[] = "OAuthLogin";
    const char kOAuthMultiloginSuffix[] = "oauth/multilogin";
    const char kOAuthRevokeTokenUrlSuffix[] = "AuthSubRevokeToken";
    const char kListAccountsSuffix[] = "ListAccounts?json=standard";
    const char kEmbeddedSigninSuffix[] = "embedded/setup/chrome/usermenu";
    const char kAddAccountSuffix[] = "AddSession";
    const char kGetCheckConnectionInfoSuffix[] = "GetCheckConnectionInfo";

    // API calls from accounts.google.com (LSO)
    const char kGetOAuthTokenUrlSuffix[] = "o/oauth/GetOAuthToken/";
    const char kOAuth2AuthUrlSuffix[] = "o/oauth2/auth";
    const char kOAuth2RevokeUrlSuffix[] = "o/oauth2/revoke";

    // API calls from www.googleapis.com
    const char kOAuth2TokenUrlSuffix[] = "oauth2/v4/token";
    const char kOAuth2IssueTokenUrlSuffix[] = "oauth2/v2/IssueToken";
    const char kOAuth2TokenInfoUrlSuffix[] = "oauth2/v2/tokeninfo";
    const char kOAuthUserInfoUrlSuffix[] = "oauth2/v1/userinfo";


    架设一个伪造的oauth主机
    [RoutePrefix("oauth2")]
    public class OAuth2Controller : ApiController
    {
    [Route("v4/token")]
    [HttpGet]
    [HttpPost]
    public object Token()
    {
    return new
    {
    access_token = "ya29.a0Ae4lvC1zRoiR8rIdd2WzN0XC1Q7X9N7DOfIcUVxuCJf2WmluzKd4PYdz0CEClvtiQCEnVU5SgpbWS4dc_DhdVuy5PaLVm4a8fiTe2_COo_sEyuA_wyG2T_ypUORhXBrsfiBPm9nluXeoYhs-qyUrZfRkP4-E0z0Viww",
    id_token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjI4Yjc0MWU4ZGU5ODRhNDcxNTlmMTllNmQ3NzgzZTlkNGZhODEwZGIiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI0MDc0MDg3MTgxOTIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI0MDc0MDg3MTgxOTIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMTc4MzMyODI2Mzk1ODY2Njg1ODIiLCJlbWFpbCI6InNhbmRzZWEuaW5mb0BnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6ImQwU3hSOUU0WC1jcFRQd2JLdXl1NmciLCJuYW1lIjoi6YGT5pyoIiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hLS9BT2gxNEdqQTJEZjZlT3c5VWJqSVhwcEdJdEdmQnFkX2Y4VzU4Q183RFhhWT1zOTYtYyIsImdpdmVuX25hbWUiOiLmnKgiLCJmYW1pbHlfbmFtZSI6IumBkyIsImxvY2FsZSI6InpoLUNOIiwiaWF0IjoxNTg4NDA1MTI3LCJleHAiOjE1ODg0MDg3Mjd9.GbG4mSstq3KL0ctamKQKqaTPL-Z2V8OPo7UBQWwKU2YvcC--I_h9_L7WuWqmKWv8T9zIcOOHkprVFk-6L4_5L-qgkilLKDi0Fe-lRx1J7KvegrVf00r3ZNU-i17TQ7OuKwYqIpEg_I9XjlpyN2BVzLDj3UaQeBnprdsfoWYH0vdBgPhGlRnNlAEb_SUeTg38blelh_1LECK2acG8XtBazF6aNDCGKtr40sHCh7Z0VyuZIFJOZnWqHEC7zKATXmCRNdYNxEEXR-IQHsWyRv37KRPFz36l9xZberj-kkEeE5M7ZzeHcOl6ke6yn3MnPjvgqRZ1kK6C93UcVH75dccAZw",
    expires_in = 3599,
    token_type = "Bearer",
    scope = "https://www.googleapis.com/auth/userinfo.profile openid https://www.googleapis.com/auth/userinfo.email",
    refresh_token = "1//04xpHGkbhp-tqCgYIARAAGAQSNwF-L9IrJGfc0d0BEMUi5T2FSFmkb4TFOFfgTBTg7J9HbFSmj-fZCrY1MvqMPjiQ5hEN-dgpAtA"
    };
    }

    [Route("v1/userinfo")]
    [HttpGet]
    [HttpPost]
    public object UserInfo()
    {
    return new
    {
    email = "tiny@sandsea.info"
    };
    }
    }


    public class ValuesController : ApiController
    {


    [Route("@me/hosts")]
    [HttpGet]
    [HttpPost]
    public object MeHosts()
    {
    //remoting_start_host.exe--name = locaa--code = 123456--pin = 123456--redirect - url = http://localhost:1024/oauth/callback --gaia-url=http://localhost:64358  --google-apis-url=http://localhost:64358 --oauth2-clent-secret=oyJky7Ul7Tub6+ZQEx4c1Q== --directory-base-url=http://localhost:64358
    return JsonConvert.DeserializeObject(
    "{"
    + " "data":{"
    + " "kind":"chromoting#hostList","
    + " "items":["
    + " {"
    + " "tokenUrlPatterns":["
    + " "tokenUrlPattern_1A","
    + " "tokenUrlPattern_1B","
    + " "tokenUrlPattern_1C""
    + " ],"
    + " "kind":"chromoting#host","
    + " "hostId":"test_host_id_1","
    + " "hostName":"test_host_name_1","
    + " "publicKey":"test_public_key_1","
    + " "jabberId":"test_jabber_id_1","
    + " "createdTime":"test_created_time_1","
    + " "updatedTime":"test_updated_time_1","
    + " "status":"ONLINE","
    + " "hostOfflineReason":"","
    + " "hostVersion":"test_host_version_1""
    + " },"
    + " {"
    + " "kind":"chromoting#host","
    + " "hostId":"test_host_id_2","
    + " "hostName":"test_host_name_2","
    + " "publicKey":"test_public_key_2","
    + " "jabberId":"test_jabber_id_2","
    + " "createdTime":"test_created_time_2","
    + " "updatedTime":"test_updated_time_2","
    + " "status":"OFFLINE","
    + " "hostOfflineReason":"test_host_offline_reason_2","
    + " "hostVersion":"test_host_version_2""
    + " }"
    + " ]"
    + " }"
    + "}");
    }

    然后使用这个主机执行以下命令
    remoting_start_host.exe --name=locaa --code=123456 --pin=123456 --redirect-url=http://localhost:1024/oauth/callback --gaia-url=http://localhost:64358  --google-apis-url=http://localhost:64358 --oauth2-clent-secret=oyJky7Ul7Tub6+ZQEx4c1Q== --directory-base-url=http://localhost:64358
    directory-base-url并不生效,需要修改源码让其生效
    service_urls.cc 第44行 以及后面有个类似的 ,将其注释掉 //#if !defined(NDEBUG)

    这个命令会启动一个服务,

    "C:Program Files (x86)GoogleChrome Remote Desktop83.0.4103.2 emoting_host.exe" --type=daemon --host-config="C:ProgramDataGoogleChrome Remote Desktophost.json"
    名称为chromoting,displayName=Chrome Remote Desktop Service

    以及一个主机进程
    remoting_host.exe" --type=host --mojo-pipe-token=xxxx --mojo-platform-channel-handle=xxxx


    这两个对应上面的HostProcessMain和DaemonProcessMain
    功能是管理客户端到服务端的会话


    貌似remoting的windows服务端直接用的微软rdp
    rdp_desktop_session->rdp_client->rdp_client_window -> Microsoft RDP ActiveX control


    原生客户端
    JniClient/IosClient ->ChromotingSession->ChromotingClientRuntime

    //网页客户端 ppapi
    pp_instance->ChromotingInstance->ChromotingClient

    下一步需要分析客户端与主机之间连接的创建是怎么实现的。

  • 相关阅读:
    用友 t6 凭证http API
    vue 解决 跳转外部地址携带根路径问题
    JavaScript之assign()——对象浅拷贝 (ES6)
    JavaScript之splice 添加或删除元素
    JavaScript之“==”和“===”
    C#——获取阶乘(递归、循环)
    C#——简单的表示两个数中的(三目运算)
    JavaScript 字符串之截取字符串 ——(substring、substr、slice)
    JavaScrpit之Json实现深拷贝
    Vue之this.$forceUpdate——强制更新数据
  • 原文地址:https://www.cnblogs.com/mrtiny/p/12819432.html
Copyright © 2011-2022 走看看