Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update IOSDeviceManager.ts #1392

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/device-managers/IOSDeviceManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { flatten, isEmpty } from 'lodash';
import { utilities as IOSUtils } from 'appium-ios-device';
import { IDevice } from '../interfaces/IDevice';
import { IDeviceManager } from '../interfaces/IDeviceManager';
import { asyncForEach, getFreePort } from '../helpers';
import { asyncForEach, getFreePort, getUnusedPortAtSessionCreation } from '../helpers';
import log from '../logger';
import os from 'os';
import path from 'path';
Expand Down Expand Up @@ -223,8 +223,8 @@ export default class IOSDeviceManager implements IDeviceManager {
} else {
host = `http://${pluginArgs.bindHostOrIp}:${hostPort}`;
}
const wdaLocalPort = await getFreePort();
const mjpegServerPort = await getFreePort();
const wdaLocalPort = await getUnusedPortAtSessionCreation();
const mjpegServerPort = await getUnusedPortAtSessionCreation();
const totalUtilizationTimeMilliSec = await getUtilizationTime(udid);
const [sdk, name] = await Promise.all([this.getOSVersion(udid), this.getDeviceName(udid)]);
const { ProductType } = await getDeviceInfo(udid);
Expand Down Expand Up @@ -296,8 +296,8 @@ export default class IOSDeviceManager implements IDeviceManager {
const deviceTypes = await list.devicetypes;
for await (const device of buildSimulators) {
const productModel = IOSDeviceManager.getProductModel(deviceTypes, device);
const wdaLocalPort = await getFreePort();
const mjpegServerPort = await getFreePort();
const wdaLocalPort = await getUnusedPortAtSessionCreation();
const mjpegServerPort = await getUnusedPortAtSessionCreation();
const totalUtilizationTimeMilliSec = await getUtilizationTime(device.udid);
const modelInfo = this.findKeyByValue(productModel) || { Width: '', Height: '' };
returnedSimulators.push(
Expand Down
36 changes: 36 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,42 @@ import asyncWait from 'async-wait-until';
import axios from 'axios';
import { FakeModuleLoader } from './fake-module-loader';
import { IExternalModuleLoader } from './interfaces/IExternalModule';
import net from 'net';

// Function to find a free port and check it
async function getFreePortWithCheck(): Promise<number> {
return new Promise<number>((resolve, reject) => {
const server = net.createServer();
server.unref(); // Avoid holding the program open
server.on('error', reject);
server.listen(0, () => {
const port = (server.address() as net.AddressInfo).port;
server.close(() => resolve(port));
});
});
}

// Function to check if a given port is available
async function checkIfPortIsAvailable(port: number): Promise<boolean> {
return new Promise<boolean>((resolve) => {
const tester = net.createServer()
.once('error', () => resolve(false)) // If there's an error, port is in use
.once('listening', () => tester.once('close', () => resolve(true)).close()) // If it starts listening, the port is free
.listen(port);
});
}

// Exported function to be used during session creation to get an available port
export async function getUnusedPortAtSessionCreation(): Promise<number> {
let port: number = 0; // Initialize port with a default value
let isPortAvailable = false;

while (!isPortAvailable) {
port = await getFreePortWithCheck();
isPortAvailable = await checkIfPortIsAvailable(port); // Check if the port is still available before assigning
}
return port;
}

const APPIUM_VENDOR_PREFIX = 'appium:';
export async function asyncForEach(
Expand Down
Loading