Skip to content

Commit

Permalink
Find free port in the host sample
Browse files Browse the repository at this point in the history
  • Loading branch information
IlyaBiryukov committed Nov 6, 2024
1 parent e4f416b commit db98e48
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 37 deletions.
2 changes: 1 addition & 1 deletion samples/ts/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ async function main() {

console.log("\nStopping tunnel client...");
client.dispose();

} catch (err) {
console.error(err);
}
Expand Down
108 changes: 72 additions & 36 deletions samples/ts/host/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,67 @@ import {
TunnelAccessScopes,
TunnelEndpoint,
} from "@microsoft/dev-tunnels-contracts";
import {
TunnelRelayTunnelHost,
} from "@microsoft/dev-tunnels-connections";
import * as http from 'http';
import { TunnelRelayTunnelHost } from "@microsoft/dev-tunnels-connections";
import * as http from "http";
import net from "net";

const portNumber = 8080;
let portNumber = 8090;
const protocol = "http";

function startServer(): Promise<http.Server> {
function findFreePort(startPort: number): Promise<number> {
return new Promise((resolve, reject) => {
const server = net.createServer();
server.once("error", (err: NodeJS.ErrnoException) => {
if (err.code === "EADDRINUSE") {
findFreePort(startPort + 1)
.then(resolve)
.catch(reject);
} else {
reject(err);
}
});
server.once("listening", () => server.close(() => resolve(startPort)));
server.listen(startPort);
});
};

async function startServer(): Promise<http.Server> {
portNumber = await findFreePort(portNumber);

const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, world!\n');
res.setHeader("Content-Type", "text/plain");
res.end("Hello, world!\n");
});
return new Promise((resolve) => {
server.listen(portNumber, () => {

await new Promise<void>((resolve) => {
server.listen({ port: portNumber, exclusive: true }, () => {
console.log(`Server running at ${protocol}://localhost:${portNumber}/`);
resolve(server);
})
});;
resolve();
});
});

return server;
}

async function createTunnelAndConnectHost(tunnelManagementClient: TunnelManagementHttpClient) {
async function createTunnelAndConnectHost(
tunnelManagementClient: TunnelManagementHttpClient
) {
const newTunnel: Tunnel = {
ports: [{
portNumber,
protocol,
}],
ports: [
{
portNumber,
protocol,
},
],
accessControl: {
entries: [{
type: TunnelAccessControlEntryType.Anonymous,
subjects: [],
scopes: [TunnelAccessScopes.Connect],
}],
entries: [
{
type: TunnelAccessControlEntryType.Anonymous,
subjects: [],
scopes: [TunnelAccessScopes.Connect],
},
],
},
};

Expand All @@ -65,21 +91,28 @@ async function createTunnelAndConnectHost(tunnelManagementClient: TunnelManageme

await host.connect(tunnel!);

console.log('Tunnel host connected:');
console.log("Tunnel host connected:");
console.log(` Tunnel ID: ${tunnel.tunnelId}`);
console.log(` Cluster ID: ${tunnel.clusterId}`);
const clientAccessToken = tunnel.accessTokens?.[TunnelAccessScopes.Connect];
if (clientAccessToken) {
console.log(` Client access token: ${clientAccessToken}`);
}

tunnel.ports?.forEach(({portNumber, portForwardingUris}) => {
tunnel.ports?.forEach(({ portNumber, portForwardingUris }) => {
console.log(` Tunnel port: ${portNumber}`);
if (portForwardingUris) {
portForwardingUris.forEach((uri) => console.log(` Port forwarding URI: ${uri}`));
portForwardingUris.forEach((uri) =>
console.log(` Port forwarding URI: ${uri}`)
);
} else {
newTunnel.endpoints?.forEach((endpoint) => {
console.log(` Port forwarding URI: ${TunnelEndpoint.getPortUri(endpoint, portNumber)}`);
console.log(
` Port forwarding URI: ${TunnelEndpoint.getPortUri(
endpoint,
portNumber
)}`
);
});
}
});
Expand All @@ -101,13 +134,15 @@ function readAnyKey() {
}

resolve();
});
});
});
}

const aadToken = process.env.AAD_TOKEN;
if (!aadToken) {
console.error("AAD_TOKEN environment variable is required. You can get your AAD token by running 'devtunnels login --verbose' and copying the token from the output.");
console.error(
"AAD_TOKEN environment variable is required. You can get your AAD token by running 'devtunnels login --verbose' and copying the token from the output."
);
process.exit(1);
}

Expand All @@ -125,7 +160,7 @@ function createTunnelManagementClient() {

tunnelManagementClient.trace = (msg) => {
console.log(`tunnel: ${msg}`);
}
};

return tunnelManagementClient;
}
Expand All @@ -135,24 +170,25 @@ async function main() {
const server = await startServer();

const tunnelManagementClient = createTunnelManagementClient();

console.log("\nCreating tunnel and starting host...");
const { tunnel, host } = await createTunnelAndConnectHost(tunnelManagementClient);
const { tunnel, host } = await createTunnelAndConnectHost(
tunnelManagementClient
);
console.log("\nPress any key to exit...\n");
await readAnyKey();

console.log("\nStopping tunnel host...");
console.log("\nStopping tunnel host...");
host.dispose();
server.close();

console.log("\nDeleting tunnel...");
await tunnelManagementClient.deleteTunnel(tunnel);

} catch (err) {
console.error(err);
}

process.exit();
}

main();
main();

0 comments on commit db98e48

Please sign in to comment.