VSCode Remote需求分析

需求分析

Visual Studio Code Remote Development是一个允许用户使用容器、远程计算机或Windows Linux子系统来搭建开发环境的重要功能拓展。实际开发工作中,一个项目可能需要在特定的环境下进行调试与运行,或者需要共享开发环境以提升团队合作的效率。

该扩展设定用户在使用时,会有以下的基本需求:

`远程连接`:用户通过VSCode远程连接插件,与远程服务器建立连接。

`建立远程工作区`:用户在本地的VSCode界面中打开远程工作区,可以编辑、调试和运行远程服务器上的代码。

`文件传输`:用户具有从本机上传文件、从远程OS下载文件的能力,可以在远程主机中编辑、保存文件。

`终端访问`:用户可以使用VSCode 的`集成终端`功能访问命令行终端

`远程调试`:用户能够在远程服务器上进行代码运行和调试。

用例分析

需求用例通常有以下三种类型::

`抽象用例`(Abstract use case)。用简单的动名词短语精简地指明一个用例,在本扩展程序中是打开、编辑文件、调试代码、上传与下载文件等动作。

`高层用例`(High level use case)。划定一个边界,指明用例在何时何地开始,在何时何地结束,又叫起始边界(TUCBW) 和结束边界 (TUCEW)。

例如,编剧文件的高层用例为:

TUCBW:远程网络检测,检测是否成功连接到远程OS.

TUCEW:编辑效果检测,检测用户期望的编辑是否被落实到远程OS中。

`扩展用例`(Expanded use case)。将业务任务的交互过程详细地描述出来,包含所有的交互步骤。

例如,编剧文件的拓展用例为:

远程网络检测,检测是否成功连接到远程OS.

用户进行编辑,VSCode为用户提供编辑器的相关功能。

编辑效果检测,检测用户期望的编辑是否被落实到远程OS中。

逆向工程

VSCode基于Electron实现,主要使用的语言是TypeScript,下面对Remote Development的重要源码进行分析。

workbench存放了VSCode的界面参数,其数据结构如下,包含了远程链接中的权限、令牌,网络连接、资源定位,文件系统、工作区服务等参数。

interface IWorkbenchConstructionOptions {
	/**
	 * The remote authority is the IP:PORT from where the workbench is served
	 * from. It is for example being used for the websocket connections as address.
	 */
	readonly remoteAuthority?: string;
	/**
	 * The connection token to send to the server.
	 */
	readonly connectionToken?: string;
	/**
	 * An endpoint to serve iframe content ("webview") from. This is required
	 * to provide full security isolation from the workbench host.
	 */
	readonly webviewEndpoint?: string;
	/**
	 * A handler for opening workspaces and providing the initial workspace.
	 */
	readonly workspaceProvider?: IWorkspaceProvider;
	/**
	 * The user data provider is used to handle user specific application
	 * state like settings, keybindings, UI state (e.g. opened editors) and snippets.
	 */
	userDataProvider?: IFileSystemProvider;
	/**
	 * A factory for web sockets.
	 */
	readonly webSocketFactory?: IWebSocketFactory;
	/**
	 * A provider for resource URIs.
	 */
	readonly resourceUriProvider?: IResourceUriProvider;
	/**
	 * The credentials provider to store and retrieve secrets.
	 */
	readonly credentialsProvider?: ICredentialsProvider;
	/**
	 * Add static extensions that cannot be uninstalled but only be disabled.
	 */
	readonly staticExtensions?: ReadonlyArray<IStaticExtension>;
	/**
	 * Support for URL callbacks.
	 */
	readonly urlCallbackProvider?: IURLCallbackProvider;
	/**
	 * Support for update reporting.
	 */
	readonly updateProvider?: IUpdateProvider;
	/**
	 * Support adding additional properties to telemetry.
	 */
	readonly resolveCommonTelemetryProperties?: ICommontTelemetryPropertiesResolver;
	/**
	 * Resolves an external uri before it is opened.
	 */
	readonly resolveExternalUri?: IExternalUriResolver;
	/**
	 * Current logging level. Default is `LogLevel.Info`.
	 */
	readonly logLevel?: LogLevel;
	/**
	 * Whether to enable the smoke test driver.
	 */
	readonly driver?: boolean;
}

远程开发需要开启三种服务:远程权限管理`remoteAuthorityResolverService`;远程代理服务`remoteAgentService`;文件系统服务`fileSystemProvider`

// Remote
const remoteAuthorityResolverService = new RemoteAuthorityResolverService(this.configuration.resourceUriProvider);
serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService);

// Remote Agent
const remoteAgentService = this._register(new RemoteAgentService(this.configuration.webSocketFactory, environmentService, productService, remoteAuthorityResolverService, signService, logService));
serviceCollection.set(IRemoteAgentService, remoteAgentService);

// Files
const fileService = this._register(new FileService(logService));
serviceCollection.set(IFileService, fileService);
this.registerFileSystemProviders(environmentService, fileService, remoteAgentService, logService, logsPath);

设置全局变量 RemoteAuthorities,以方便进行资源定位符的解析。

resolveAuthority(authority: string): Promise<ResolverResult> {
		if (authority.indexOf(':') >= 0) {
			const pieces = authority.split(':');
			return  Promise.resolve(this._createResolvedAuthority(authority, pieces[0], parseInt(pieces[1], 10)));
		} else {
		    return Promise.resolve(this._createResolvedAuthority(authority, authority, 80));
		}
	}
	private _createResolvedAuthority(authority: string, host: string, port: number): ResolverResult {
		RemoteAuthorities.set(authority, host, port);
		return { authority: { authority, host, port } };
}

连接进程remoteExtensionHost,在获取足够权限的前提下,操作远程OS上运行的插件,其本质是进程的通信。

const options: IConnectionOptions = {
    commit: this._productService.commit,
    socketFactory: this._socketFactory,
    addressProvider: {
        getAddress: async () => {
            const { authority } = await this.remoteAuthorityResolverService.resolveAuthority(this._initDataProvider.remoteAuthority);
            return { host: authority.host, port: authority.port };
        }
    },
    signService: this._signService,
    logService: this._logService
};

采用IPC进程通信可以对远程OS上的文件系统进行获取状态、打开、关闭等操作。

stat(resource: URI): Promise<IStat> {
    return this.channel.call('stat', [resource]);
}
open(resource: URI, opts: FileOpenOptions): Promise<number> {
    return this.channel.call('open', [resource, opts]);
}
close(fd: number): Promise<void> {
    return this.channel.call('close', [fd]);
}

参考资料

孟宁 / 软件工程

vscode remote 实现原理

VS Code Remote Development

microsoft/vscode

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值