Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/microsoft/dev-tunnels into …
Browse files Browse the repository at this point in the history
…dev/jfullerton/rustNewVersion
  • Loading branch information
jfullerton44 committed Oct 11, 2023
2 parents 2fbc63b + 1c8fcc2 commit 5733b7f
Show file tree
Hide file tree
Showing 16 changed files with 117 additions and 43 deletions.
2 changes: 1 addition & 1 deletion cs/build/build.props
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<ReportGeneratorVersion>4.8.13</ReportGeneratorVersion>
<SystemTextEncodingsWebPackageVersion>4.7.2</SystemTextEncodingsWebPackageVersion>
<VisualStudioValidationVersion>15.5.31</VisualStudioValidationVersion>
<DevTunnelsSshPackageVersion>3.11.28</DevTunnelsSshPackageVersion>
<DevTunnelsSshPackageVersion>3.11.31</DevTunnelsSshPackageVersion>
<XunitRunnerVisualStudioVersion>2.4.0</XunitRunnerVisualStudioVersion>
<XunitVersion>2.4.0</XunitVersion>
</PropertyGroup>
Expand Down
9 changes: 9 additions & 0 deletions cs/src/Contracts/TunnelAccessControlEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@ public TunnelAccessControlEntry()
[ArrayStringLength(TunnelAccessScopes.MaxLength)]
public string[] Scopes { get; set; }

/// <summary>
/// Gets or sets the expiration for an access control entry.
/// </summary>
/// <remarks>
/// If no value is set then this value is null.
/// </remarks>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTime? Expiration { get; set; }

/// <summary>
/// Gets a compact textual representation of the access control entry.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions cs/src/Management/IdGeneration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ namespace Microsoft.DevTunnels.Management;
/// </summary>
public static class IdGeneration
{
private static string[] nouns = { "pond", "hill", "mountain", "field", "fog", "ant", "dog", "cat", "rabbit", "shoe", "campsite", "plane", "sofa", "chair", "library", "book", "ocean", "lake", "river" , "horse" };
private static string[] adjectives = { "fun", "happy", "interesting", "neat", "peaceful", "puzzeled", "thoughtful", "kind", "joyful", "overjoyed", "new", "giant", "sneaky", "quick", "majestic", "gleaming", "jolly" , "fancy", "tidy", "marvelous", "glamorous", "swift", "silent", "amusing", "spiffy", };
private static string[] nouns = { "pond", "hill", "mountain", "field", "fog", "ant", "dog", "cat", "shoe", "plane", "chair", "book", "ocean", "lake", "river" , "horse" };
private static string[] adjectives = { "fun", "happy", "interesting", "neat", "peaceful", "puzzled", "kind", "joyful", "new", "giant", "sneaky", "quick", "majestic", "jolly" , "fancy", "tidy", "swift", "silent", "amusing", "spiffy" };
/// <summary>
/// Generate valid tunnelIds
/// </summary>
Expand Down
7 changes: 3 additions & 4 deletions cs/src/Management/TunnelManagementClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -852,13 +852,12 @@ public async Task<Tunnel[]> ListTunnelsAsync(
query,
options,
cancellation);
var tunnels = new List<Tunnel>();
if (result?.Value != null)
{
result.Value = result.Value.Where(t => t.Value != null).ToArray();
tunnels = result.Value.SelectMany(t => t.Value!).ToList();
return result.Value.Where(t => t.Value != null).SelectMany(t => t.Value!).ToArray();
}
return tunnels.ToArray();

return Array.Empty<Tunnel>();
}

/// <inheritdoc />
Expand Down
58 changes: 39 additions & 19 deletions go/tunnels/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,33 +136,26 @@ func (c *Client) Connect(ctx context.Context, hostID string) error {
return nil
}

// Opens a stream connected to a remote port for clients which cannot or do not want to forward local TCP ports.
// Returns a readWriteCloser which can be used to read and write to the remote port.
// Set AcceptLocalConnectionsForForwardedPorts to false in ConnectAsync to ensure TCP listeners are not created
// This will return an error if the port is not yet forwarded,
// the caller should first call WaitForForwardedPort.
func (c *Client) ConnectToForwardedPort(ctx context.Context, listenerIn *net.TCPListener, port uint16) error {
// ConnectListenerToForwardedPort opens a stream to a remote port and connects it to a given listener.
//
// Ensure that the port is already forwarded before calling this function
// by calling WaitForForwardedPort. Otherwise, this will return an error.
//
// Set acceptLocalConnectionsForForwardedPorts to false when creating the client to ensure
// TCP listeners are not created for all ports automatically when the client connects.
func (c *Client) ConnectListenerToForwardedPort(ctx context.Context, listenerIn net.Listener, port uint16) error {
errc := make(chan error, 1)
sendError := func(err error) {
// Use non-blocking send, to avoid goroutines getting
// stuck in case of concurrent or sequential errors.
select {
case errc <- err:
default:
}
}

go func() {
for {
conn, err := listenerIn.AcceptTCP()
conn, err := listenerIn.Accept()
if err != nil {
sendError(err)
sendError(err, errc)
return
}

go func() {
if err := c.handleConnection(ctx, conn, port); err != nil {
sendError(err)
if err := c.ConnectToForwardedPort(ctx, conn, port); err != nil {
sendError(err, errc)
}
}()
}
Expand All @@ -171,6 +164,24 @@ func (c *Client) ConnectToForwardedPort(ctx context.Context, listenerIn *net.TCP
return awaitError(ctx, errc)
}

// ConnectToForwardedPort opens a stream to a remote port and connects it to a given connection.
//
// Ensure that the port is already forwarded before calling this function
// by calling WaitForForwardedPort. Otherwise, this will return an error.
//
// Set acceptLocalConnectionsForForwardedPorts to false when creating the client to ensure
// TCP listeners are not created for all ports automatically when the client connects.
func (c *Client) ConnectToForwardedPort(ctx context.Context, conn io.ReadWriteCloser, port uint16) error {
errc := make(chan error, 1)
go func() {
if err := c.handleConnection(ctx, conn, port); err != nil {
sendError(err, errc)
}
}()

return awaitError(ctx, errc)
}

// WaitForForwardedPort waits for the specified port to be forwarded.
// It is common practice to call this function before ConnectToForwardedPort.
func (c *Client) WaitForForwardedPort(ctx context.Context, port uint16) error {
Expand Down Expand Up @@ -207,6 +218,15 @@ func (c *Client) RefreshPorts(ctx context.Context) error {
return err
}

func sendError(err error, errc chan error) {
// Use non-blocking send, to avoid goroutines getting
// stuck in case of concurrent or sequential errors.
select {
case errc <- err:
default:
}
}

func awaitError(ctx context.Context, errc chan error) error {
select {
case err := <-errc:
Expand Down
17 changes: 16 additions & 1 deletion go/tunnels/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,22 @@ func TestPortForwarding(t *testing.T) {
done <- fmt.Errorf("wait for forwarded port failed: %v", err)
return
}
err = c.ConnectToForwardedPort(ctx, listen, streamPort)

// Test connecting with a listener
err = c.ConnectListenerToForwardedPort(ctx, listen, streamPort)
if err != nil {
done <- fmt.Errorf("connect to forwarded port failed: %v", err)
return
}

// Connect to the listener and and test connecting with the given connection
conn, err := listen.Accept()
if err != nil {
done <- fmt.Errorf("accept connection failed: %v", err)
return
}

err = c.ConnectToForwardedPort(ctx, conn, streamPort)
if err != nil {
done <- fmt.Errorf("connect to forwarded port failed: %v", err)
return
Expand Down
4 changes: 2 additions & 2 deletions go/tunnels/id_generation.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"time"
)

var nouns = []string{"pond", "hill", "mountain", "field", "fog", "ant", "dog", "cat", "rabbit", "shoe", "campsite", "plane", "sofa", "chair", "library", "book", "ocean", "lake", "river", "horse"}
var adjectives = []string{"fun", "happy", "interesting", "neat", "peaceful", "puzzeled", "thoughtful", "kind", "joyful", "overjoyed", "new", "giant", "sneaky", "quick", "majestic", "gleaming", "jolly", "fancy", "tidy", "marvelous", "glamorous", "swift", "silent", "amusing", "spiffy"}
var nouns = []string{"pond", "hill", "mountain", "field", "fog", "ant", "dog", "cat", "shoe", "plane", "chair", "book", "ocean", "lake", "river", "horse"}
var adjectives = []string{"fun", "happy", "interesting", "neat", "peaceful", "puzzled", "kind", "joyful", "new", "giant", "sneaky", "quick", "majestic", "jolly", "fancy", "tidy", "swift", "silent", "amusing", "spiffy"}

func generateTunnelId() string {
rand.Seed(time.Now().UnixNano())
Expand Down
9 changes: 9 additions & 0 deletions go/tunnels/tunnel_access_control_entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

package tunnels

import (
"time"
)

// Data contract for an access control entry on a `Tunnel` or `TunnelPort`.
//
// An access control entry (ACE) grants or denies one or more access scopes to one or more
Expand Down Expand Up @@ -68,6 +72,11 @@ type TunnelAccessControlEntry struct {
//
// These must be one or more values from `TunnelAccessScopes`.
Scopes []string `json:"scopes"`

// Gets or sets the expiration for an access control entry.
//
// If no value is set then this value is null.
Expiration *time.Time `json:"expiration,omitempty"`
}

// Constants for well-known identity providers.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package com.microsoft.tunnels.contracts;

import com.google.gson.annotations.Expose;
import java.util.Date;

/**
* Data contract for an access control entry on a {@link Tunnel} or {@link TunnelPort}.
Expand Down Expand Up @@ -99,6 +100,14 @@ public class TunnelAccessControlEntry {
@Expose
public String[] scopes;

/**
* Gets or sets the expiration for an access control entry.
*
* If no value is set then this value is null.
*/
@Expose
public Date expiration;

/**
* Constants for well-known identity providers.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import java.util.Random;

public class IdGeneration {
private static String[] nouns = {"pond", "hill", "mountain", "field", "fog", "ant", "dog", "cat", "rabbit", "shoe", "campsite", "plane", "sofa", "chair", "library", "book", "ocean", "lake", "river", "horse"};
private static String[] adjectives = {"fun", "happy", "interesting", "neat", "peaceful", "puzzeled", "thoughtful", "kind", "joyful", "overjoyed", "new", "giant", "sneaky", "quick", "majestic", "gleaming", "jolly", "fancy", "tidy", "marvelous", "glamorous", "swift", "silent", "amusing", "spiffy"};
private static String[] nouns = { "pond", "hill", "mountain", "field", "fog", "ant", "dog", "cat", "shoe", "plane", "chair", "book", "ocean", "lake", "river" , "horse" };
private static String[] adjectives = {"fun", "happy", "interesting", "neat", "peaceful", "puzzled", "kind", "joyful", "new", "giant", "sneaky", "quick", "majestic", "jolly" , "fancy", "tidy", "swift", "silent", "amusing", "spiffy"};
private static Random rand = new Random();

public static String generateTunnelId() {
Expand Down
6 changes: 6 additions & 0 deletions rs/src/contracts/tunnel_access_control_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT license.
// Generated from ../../../cs/src/Contracts/TunnelAccessControlEntry.cs

use chrono::{DateTime, Utc};
use crate::contracts::TunnelAccessControlEntryType;
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -77,6 +78,11 @@ pub struct TunnelAccessControlEntry {
//
// These must be one or more values from `TunnelAccessScopes`.
pub scopes: Vec<String>,

// Gets or sets the expiration for an access control entry.
//
// If no value is set then this value is null.
pub expiration: Option<DateTime<Utc>>,
}

// Constants for well-known identity providers.
Expand Down
12 changes: 6 additions & 6 deletions ts/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
"build-pack-publish": "npm run build && npm run pack && npm run publish"
},
"dependencies": {
"@microsoft/dev-tunnels-ssh": "^3.11.26",
"@microsoft/dev-tunnels-ssh-tcp": "^3.11.26",
"@microsoft/dev-tunnels-ssh": "^3.11.31",
"@microsoft/dev-tunnels-ssh-tcp": "^3.11.31",
"await-semaphore": "^0.1.3",
"axios": "^0.21.1",
"buffer": "^5.2.1",
Expand Down
4 changes: 2 additions & 2 deletions ts/src/connections/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
"vscode-jsonrpc": "^4.0.0",
"@microsoft/dev-tunnels-contracts": "^1.0.0",
"@microsoft/dev-tunnels-management": "^1.0.0",
"@microsoft/dev-tunnels-ssh": "^3.11.26",
"@microsoft/dev-tunnels-ssh-tcp": "^3.11.26",
"@microsoft/dev-tunnels-ssh": "^3.11.31",
"@microsoft/dev-tunnels-ssh-tcp": "^3.11.31",
"uuid": "^3.3.3",
"await-semaphore": "^0.1.3",
"websocket": "^1.0.28",
Expand Down
7 changes: 7 additions & 0 deletions ts/src/contracts/tunnelAccessControlEntry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ export interface TunnelAccessControlEntry {
* These must be one or more values from {@link TunnelAccessScopes}.
*/
scopes: string[];

/**
* Gets or sets the expiration for an access control entry.
*
* If no value is set then this value is null.
*/
expiration?: Date;
}

export namespace TunnelAccessControlEntry {
Expand Down
4 changes: 2 additions & 2 deletions ts/src/management/idGeneration.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { TunnelConstraints } from "../contracts/tunnelConstraints"

export class IdGeneration {
private static nouns: string[] = ["pond", "hill", "mountain", "field", "fog", "ant", "dog", "cat", "rabbit", "shoe", "campsite", "plane", "sofa", "chair", "library", "book", "ocean", "lake", "river", "horse"];
private static adjectives: string[] = ["fun", "happy", "interesting", "neat", "peaceful", "puzzeled", "thoughtful", "kind", "joyful", "overjoyed", "new", "giant", "sneaky", "quick", "majestic", "gleaming", "jolly", "fancy", "tidy", "marvelous", "glamorous", "swift", "silent", "amusing", "spiffy"];
private static nouns: string[] = [ "pond", "hill", "mountain", "field", "fog", "ant", "dog", "cat", "shoe", "plane", "chair", "book", "ocean", "lake", "river" , "horse"];
private static adjectives: string[] = ["fun", "happy", "interesting", "neat", "peaceful", "puzzled", "kind", "joyful", "new", "giant", "sneaky", "quick", "majestic", "jolly" , "fancy", "tidy", "swift", "silent", "amusing", "spiffy"];

public static generateTunnelId(): string {
let tunnelId = "";
Expand Down

0 comments on commit 5733b7f

Please sign in to comment.