Skip to content

Commit

Permalink
feat: Add a method to list device ports (#764)
Browse files Browse the repository at this point in the history
  • Loading branch information
mykola-mokhnach authored Sep 8, 2024
1 parent fa8e65f commit 01fff96
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
54 changes: 54 additions & 0 deletions lib/tools/adb-commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -2040,8 +2040,62 @@ methods.setDataState = async function setDataState (on, isEmulator = false) {
await this.shell(['cmd', 'phone', 'data', on ? 'enable' : 'disable']);
};

/**
* Returns the list of TCP port states of the given family.
* Could be empty if no ports are opened.
*
* @this {import('../adb.js').ADB}
* @param {PortFamily} [family='4']
* @returns {Promise<PortInfo[]>}
*/
methods.listPorts = async function listPorts(family = '4') {
const sourceProcName = `/proc/net/tcp${family === '6' ? '6' : ''}`;
const output = await this.shell(['cat', sourceProcName]);
const lines = output.split('\n');
if (_.isEmpty(lines)) {
log.debug(output);
throw new Error(`Cannot parse the payload of ${sourceProcName}`);
}
// sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
const colHeaders = lines[0].split(/\s+/).filter(Boolean);
const localAddressCol = colHeaders.findIndex((x) => x === 'local_address');
const stateCol = colHeaders.findIndex((x) => x === 'st');
if (localAddressCol < 0 || stateCol < 0) {
log.debug(lines[0]);
throw new Error(`Cannot parse the header row of ${sourceProcName} payload`);
}
/** @type {PortInfo[]} */
const result = [];
// 2: 1002000A:D036 24CE3AD8:01BB 08 00000000:00000000 00:00000000 00000000 10132 0 49104 1 0000000000000000 21 4 20 10 -1
for (const line of lines.slice(1)) {
const values = line.split(/\s+/).filter(Boolean);
const portStr = values[localAddressCol]?.split(':')?.[1];
const stateStr = values[stateCol];
if (!portStr || !stateStr) {
continue;
}
result.push({
port: parseInt(portStr, 16),
family,
state: parseInt(stateStr, 16),
});
};
return result;
};

export default methods;

/**
* @typedef {typeof methods} ADBCommands
*/

/**
* @typedef {'4'|'6'} PortFamily
*/

/**
* @typedef {Object} PortInfo
* @property {number} port The actual port number between 0 and 0xFFFF
* @property {PortFamily} family Either '4' or '6'
* @property {number} state See https://elixir.bootlin.com/linux/v4.14.42/source/include/net/tcp_states.h
*/
9 changes: 9 additions & 0 deletions test/functional/adb-commands-e2e-specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,13 @@ describe('adb commands', function () {
_.isEmpty(await adb.takeScreenshot()).should.be.false;
});
});

describe('listPorts', function () {
it('should list IPv4 ports', async function () {
_.isEmpty(await adb.listPorts()).should.be.false;
});
it('should list IPv6 ports', async function () {
_.isEmpty(await adb.listPorts('6')).should.be.false;
});
});
});

0 comments on commit 01fff96

Please sign in to comment.