cli: add tcpConnect exec server command, add proposed methods to .d.ts (#197692)

This commit is contained in:
Connor Peet 2023-11-07 16:23:48 -08:00 committed by GitHub
parent 0f8d9033b4
commit 7771124ebd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 132 additions and 3 deletions

View file

@ -32,6 +32,7 @@ use opentelemetry::KeyValue;
use std::collections::HashMap;
use std::path::PathBuf;
use std::process::Stdio;
use tokio::net::TcpStream;
use tokio::pin;
use tokio::process::{ChildStderr, ChildStdin};
use tokio_util::codec::Decoder;
@ -55,9 +56,9 @@ use super::protocol::{
ChallengeIssueResponse, ChallengeVerifyParams, ClientRequestMethod, EmptyObject, ForwardParams,
ForwardResult, FsReadDirEntry, FsReadDirResponse, FsRenameRequest, FsSinglePathRequest,
FsStatResponse, GetEnvResponse, GetHostnameResponse, HttpBodyParams, HttpHeadersParams,
ServeParams, ServerLog, ServerMessageParams, SpawnParams, SpawnResult, SysKillRequest,
SysKillResponse, ToClientRequest, UnforwardParams, UpdateParams, UpdateResult, VersionResponse,
METHOD_CHALLENGE_VERIFY,
NetConnectRequest, ServeParams, ServerLog, ServerMessageParams, SpawnParams, SpawnResult,
SysKillRequest, SysKillResponse, ToClientRequest, UnforwardParams, UpdateParams, UpdateResult,
VersionResponse, METHOD_CHALLENGE_VERIFY,
};
use super::server_bridge::ServerBridge;
use super::server_multiplexer::ServerMultiplexer;
@ -341,6 +342,14 @@ fn make_socket_rpc(
handle_fs_connect(streams.remove(0), p.path).await
},
);
rpc.register_duplex(
"net_connect",
1,
move |mut streams, n: NetConnectRequest, c| async move {
ensure_auth(&c.auth_state)?;
handle_net_connect(streams.remove(0), n).await
},
);
rpc.register_async("fs_rm", move |p: FsSinglePathRequest, c| async move {
ensure_auth(&c.auth_state)?;
handle_fs_remove(p.path).await
@ -896,6 +905,20 @@ async fn handle_fs_write(mut input: DuplexStream, path: String) -> Result<EmptyO
Ok(EmptyObject {})
}
async fn handle_net_connect(
mut stream: DuplexStream,
req: NetConnectRequest,
) -> Result<EmptyObject, AnyError> {
let mut s = TcpStream::connect((req.host, req.port))
.await
.map_err(|e| wrap(e, "could not connect to address"))?;
tokio::io::copy_bidirectional(&mut stream, &mut s)
.await
.map_err(|e| wrap(e, "error copying stream data"))?;
Ok(EmptyObject {})
}
async fn handle_fs_connect(
mut stream: DuplexStream,
path: String,

View file

@ -209,6 +209,13 @@ pub struct FsRenameRequest {
pub to_path: String,
}
/// Method: `net_connect`. Connects to a port.
#[derive(Deserialize)]
pub struct NetConnectRequest {
pub port: u16,
pub host: String,
}
#[derive(Deserialize, Debug)]
pub struct CallServerHttpParams {
pub path: String,

View file

@ -191,6 +191,26 @@ declare module 'vscode' {
*/
env(): Thenable<ExecEnvironment>;
/**
* Kills a process with the given ID.
*
* @param processId process ID to kill.
*/
kill(processId: number): Thenable<void>;
/**
* Connects to the given TCP host/port on the remote.
*
* @param host The hostname or IP to connect to
* @param port The port number to connect to
* @returns a duplex stream, and a promise the resolves when both sides
* have closed.
*/
tcpConnect(
host: string,
port: number,
): Thenable<{ stream: WriteStream & ReadStream; done: Thenable<void> }>;
/**
* Access to the file system of the remote.
*/
@ -272,6 +292,85 @@ declare module 'vscode' {
* @throws an exception when `path` doesn't exist.
*/
stat(path: string): Thenable<FileStat>;
/**
* Recursively creates the given directory on the remote.
*
* @param path The path of the folder to create
* @throws an exception when `path` is a file, or other i/o operations happen
*/
mkdirp(path: string): Thenable<void>;
/**
* Recursively deletes the given path on the remote.
*
* @param path The path of the file or folder to delete.
* @throws if an i/o error happens during removal. It does not throw if
* the path already does not exist.
*/
rm(path: string): Thenable<void>;
/**
* Reads the given file from the remote.
*
* @param path The path of the file to read.
* @throws if the path doesn't exist or can't be accessed
* @returns a readable stream of the file data
*/
read(path: string): Thenable<ReadStream>;
/**
* Writes the given file on the remote. Truncates the file if it exists.
*
* @param path The path of the file to write.
* @throws if the path can't be accessed
* @returns a writable `stream` that accepts data, and a `done` promise that
* will resolve after `stream.end()` is called once the write is complete.
*/
write(path: string): Thenable<{ stream: WriteStream; done: Thenable<void> }>;
/**
* Connects to the given unix socket or named pipe on the remote.
*
* @param path The path of the unix socket or named pipe
* @throws if the path can't be accessed
* @returns a duplex stream, and a promise the resolves when both sides
* have closed.
*/
connect(path: string): Thenable<{ stream: WriteStream & ReadStream; done: Thenable<void> }>;
/**
* Renames the file.
*
* @param fromPath The existing file path.
* @param toPath The new file path.
* @throws if the original path doesn't exist, or the toPath can't be accessed
*/
rename(fromPath: string, toPath: string): Thenable<void>;
/**
* Reads the contents of a directory.
*
* @param path The path of the folder to read.
* @throws if the folder doesn't exist
* @returns a list of directory entries
*/
readdir(path: string): Thenable<DirectoryEntry[]>;
}
export interface DirectoryEntry {
/**
* The type of the file, e.g. is a regular file, a directory, or symbolic link
* to a file.
*
* *Note:* This value might be a bitmask, e.g. `FileType.File | FileType.SymbolicLink`.
*/
type: FileType;
/**
* Non-absolute name of the file in the directory.
*/
name: string;
}
export interface RemoteAuthorityResolver {