Skip to content

Commit 7771124

Browse files
authored
cli: add tcpConnect exec server command, add proposed methods to .d.ts (#197692)
1 parent 0f8d903 commit 7771124

File tree

3 files changed

+132
-3
lines changed

3 files changed

+132
-3
lines changed

cli/src/tunnels/control_server.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use opentelemetry::KeyValue;
3232
use std::collections::HashMap;
3333
use std::path::PathBuf;
3434
use std::process::Stdio;
35+
use tokio::net::TcpStream;
3536
use tokio::pin;
3637
use tokio::process::{ChildStderr, ChildStdin};
3738
use tokio_util::codec::Decoder;
@@ -55,9 +56,9 @@ use super::protocol::{
5556
ChallengeIssueResponse, ChallengeVerifyParams, ClientRequestMethod, EmptyObject, ForwardParams,
5657
ForwardResult, FsReadDirEntry, FsReadDirResponse, FsRenameRequest, FsSinglePathRequest,
5758
FsStatResponse, GetEnvResponse, GetHostnameResponse, HttpBodyParams, HttpHeadersParams,
58-
ServeParams, ServerLog, ServerMessageParams, SpawnParams, SpawnResult, SysKillRequest,
59-
SysKillResponse, ToClientRequest, UnforwardParams, UpdateParams, UpdateResult, VersionResponse,
60-
METHOD_CHALLENGE_VERIFY,
59+
NetConnectRequest, ServeParams, ServerLog, ServerMessageParams, SpawnParams, SpawnResult,
60+
SysKillRequest, SysKillResponse, ToClientRequest, UnforwardParams, UpdateParams, UpdateResult,
61+
VersionResponse, METHOD_CHALLENGE_VERIFY,
6162
};
6263
use super::server_bridge::ServerBridge;
6364
use super::server_multiplexer::ServerMultiplexer;
@@ -341,6 +342,14 @@ fn make_socket_rpc(
341342
handle_fs_connect(streams.remove(0), p.path).await
342343
},
343344
);
345+
rpc.register_duplex(
346+
"net_connect",
347+
1,
348+
move |mut streams, n: NetConnectRequest, c| async move {
349+
ensure_auth(&c.auth_state)?;
350+
handle_net_connect(streams.remove(0), n).await
351+
},
352+
);
344353
rpc.register_async("fs_rm", move |p: FsSinglePathRequest, c| async move {
345354
ensure_auth(&c.auth_state)?;
346355
handle_fs_remove(p.path).await
@@ -896,6 +905,20 @@ async fn handle_fs_write(mut input: DuplexStream, path: String) -> Result<EmptyO
896905
Ok(EmptyObject {})
897906
}
898907

908+
async fn handle_net_connect(
909+
mut stream: DuplexStream,
910+
req: NetConnectRequest,
911+
) -> Result<EmptyObject, AnyError> {
912+
let mut s = TcpStream::connect((req.host, req.port))
913+
.await
914+
.map_err(|e| wrap(e, "could not connect to address"))?;
915+
916+
tokio::io::copy_bidirectional(&mut stream, &mut s)
917+
.await
918+
.map_err(|e| wrap(e, "error copying stream data"))?;
919+
920+
Ok(EmptyObject {})
921+
}
899922
async fn handle_fs_connect(
900923
mut stream: DuplexStream,
901924
path: String,

cli/src/tunnels/protocol.rs

+7
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,13 @@ pub struct FsRenameRequest {
209209
pub to_path: String,
210210
}
211211

212+
/// Method: `net_connect`. Connects to a port.
213+
#[derive(Deserialize)]
214+
pub struct NetConnectRequest {
215+
pub port: u16,
216+
pub host: String,
217+
}
218+
212219
#[derive(Deserialize, Debug)]
213220
pub struct CallServerHttpParams {
214221
pub path: String,

src/vscode-dts/vscode.proposed.resolvers.d.ts

+99
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,26 @@ declare module 'vscode' {
191191
*/
192192
env(): Thenable<ExecEnvironment>;
193193

194+
/**
195+
* Kills a process with the given ID.
196+
*
197+
* @param processId process ID to kill.
198+
*/
199+
kill(processId: number): Thenable<void>;
200+
201+
/**
202+
* Connects to the given TCP host/port on the remote.
203+
*
204+
* @param host The hostname or IP to connect to
205+
* @param port The port number to connect to
206+
* @returns a duplex stream, and a promise the resolves when both sides
207+
* have closed.
208+
*/
209+
tcpConnect(
210+
host: string,
211+
port: number,
212+
): Thenable<{ stream: WriteStream & ReadStream; done: Thenable<void> }>;
213+
194214
/**
195215
* Access to the file system of the remote.
196216
*/
@@ -272,6 +292,85 @@ declare module 'vscode' {
272292
* @throws an exception when `path` doesn't exist.
273293
*/
274294
stat(path: string): Thenable<FileStat>;
295+
296+
/**
297+
* Recursively creates the given directory on the remote.
298+
*
299+
* @param path The path of the folder to create
300+
* @throws an exception when `path` is a file, or other i/o operations happen
301+
*/
302+
mkdirp(path: string): Thenable<void>;
303+
304+
/**
305+
* Recursively deletes the given path on the remote.
306+
*
307+
* @param path The path of the file or folder to delete.
308+
* @throws if an i/o error happens during removal. It does not throw if
309+
* the path already does not exist.
310+
*/
311+
rm(path: string): Thenable<void>;
312+
313+
/**
314+
* Reads the given file from the remote.
315+
*
316+
* @param path The path of the file to read.
317+
* @throws if the path doesn't exist or can't be accessed
318+
* @returns a readable stream of the file data
319+
*/
320+
read(path: string): Thenable<ReadStream>;
321+
322+
/**
323+
* Writes the given file on the remote. Truncates the file if it exists.
324+
*
325+
* @param path The path of the file to write.
326+
* @throws if the path can't be accessed
327+
* @returns a writable `stream` that accepts data, and a `done` promise that
328+
* will resolve after `stream.end()` is called once the write is complete.
329+
*/
330+
write(path: string): Thenable<{ stream: WriteStream; done: Thenable<void> }>;
331+
332+
/**
333+
* Connects to the given unix socket or named pipe on the remote.
334+
*
335+
* @param path The path of the unix socket or named pipe
336+
* @throws if the path can't be accessed
337+
* @returns a duplex stream, and a promise the resolves when both sides
338+
* have closed.
339+
*/
340+
connect(path: string): Thenable<{ stream: WriteStream & ReadStream; done: Thenable<void> }>;
341+
342+
/**
343+
* Renames the file.
344+
*
345+
* @param fromPath The existing file path.
346+
* @param toPath The new file path.
347+
* @throws if the original path doesn't exist, or the toPath can't be accessed
348+
*/
349+
rename(fromPath: string, toPath: string): Thenable<void>;
350+
351+
/**
352+
* Reads the contents of a directory.
353+
*
354+
* @param path The path of the folder to read.
355+
* @throws if the folder doesn't exist
356+
* @returns a list of directory entries
357+
*/
358+
readdir(path: string): Thenable<DirectoryEntry[]>;
359+
}
360+
361+
export interface DirectoryEntry {
362+
/**
363+
* The type of the file, e.g. is a regular file, a directory, or symbolic link
364+
* to a file.
365+
*
366+
* *Note:* This value might be a bitmask, e.g. `FileType.File | FileType.SymbolicLink`.
367+
*/
368+
type: FileType;
369+
370+
/**
371+
* Non-absolute name of the file in the directory.
372+
*/
373+
name: string;
275374
}
276375

277376
export interface RemoteAuthorityResolver {

0 commit comments

Comments
 (0)