Skip to content

Conversation

@harsha509
Copy link
Member

Creates a tunnel for paired appletv connections. The code uses pair-record from strongbox -> validates (uses pair verification protocol) and creates the tunnel

  • Add pair verification protocol for already-paired devices
  • Extend pairing storage with load and list device methods
  • Add CLI script to start Apple TV tunnel connections
  • Migrate to internal logger from @appium/support
  • Remove unused code and adjust logging levels

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Apple TV tunnel service functionality with pair verification protocol support for already-paired devices. The implementation extends the pairing storage system with device loading/listing capabilities, introduces a new CLI script for establishing Apple TV tunnel connections, migrates logging from @appium/support to an internal logger, and removes unused code.

  • Implements pair verification protocol for secure tunnel establishment with previously-paired Apple TV devices
  • Adds X25519 key exchange and ChaCha20-Poly1305 encryption for tunnel security
  • Extends pairing storage with load() and getAvailableDeviceIds() methods

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
src/services/ios/mobile-config/index.ts Replaces unused error variable with catch-all and improves logging level for profile removal
src/services/ios/afc/stream-utils.ts Removes unused totalRead tracking variable
src/services/ios/afc/index.ts Removes unused imports buildReadPayload and nextReadChunkSize
src/lib/tunnel/packet-stream-server.ts Removes unused SerializedPacketMessage interface
src/lib/tunnel/index.ts Removes unused TunnelResult interface
src/lib/plist/length-based-splitter.ts Removes dead code for XML/binary plist detection that was never used
src/lib/lockdown/index.ts Removes unused StartSessionRequest interface
src/lib/bonjour/bonjour-discovery.ts Adjusts logging levels to reduce verbosity of discovery operations
src/lib/apple-tv/tunnel/types.ts Defines TcpListenerInfo interface for tunnel service responses
src/lib/apple-tv/tunnel/tunnel-service.ts Implements TLS-PSK tunnel connection and encrypted TCP listener creation
src/lib/apple-tv/tunnel/index.ts Exports tunnel service components
src/lib/apple-tv/storage/types.ts Adds PairRecord interface and extends storage interface with load/list methods
src/lib/apple-tv/storage/pairing-storage.ts Implements pair record loading, device ID enumeration, and migrates to internal logger
src/lib/apple-tv/storage/index.ts Exports PairRecord type
src/lib/apple-tv/pairing/user-input-service.ts Migrates from @appium/support logger to internal logger
src/lib/apple-tv/pairing-protocol/pairing-protocol.ts Migrates to internal logger
src/lib/apple-tv/pairing-protocol/pair-verification-protocol.ts Implements 4-step pair verification protocol with X25519 key exchange
src/lib/apple-tv/pairing-protocol/index.ts Exports pair verification protocol components
src/lib/apple-tv/pairing-protocol/constants.ts Adds constants for pair verification, encryption messages, and states
src/lib/apple-tv/network/network-client.ts Migrates to internal logger
src/lib/apple-tv/index.ts Exports tunnel service module
src/lib/apple-tv/encryption/x25519.ts Implements X25519 key pair generation and Diffie-Hellman exchange
src/lib/apple-tv/encryption/index.ts Exports X25519 encryption utilities
src/lib/apple-tv/discovery/device-discovery.ts Migrates to internal logger
scripts/start-appletv-tunnel.ts CLI script for establishing Apple TV tunnels with pair verification and registry server
scripts/pair-appletv.ts Migrates to internal logger
package.json Adds start-appletv-tunnel npm script

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const PACKET_STREAM_PORT = 50100;

class AppleTVTunnelService {
private logger = getLogger('AppleTVTunnelService');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if it make sense to make the logger to an instance variable. We do not want different class instances to have different loggers. Consider moving it to module level/making static

private logger = getLogger('AppleTVTunnelService');
private networkClient: NetworkClient;
private storage: PairingStorage;
private sequenceNumber = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

number?

const devices = await this.discoverDevices();

this.logger.debug('Step 1: Device Discovery success');
this.logger.debug(`Found ${devices.length} device(s) via Bonjour`);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider using util.pluralize helper from @appium/support

@@ -0,0 +1,416 @@
#!/usr/bin/env tsx
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider refactoring this script and move appropriate APIs to their (potentially reusable) libraries. The script itself should only contain the client code.


constructor(
private readonly networkClient: NetworkClientInterface,
sequenceNumber: number,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sequenceNumber might also be defined here

pairRecord: PairRecord,
deviceId: string,
): Promise<VerificationKeys> {
PairVerificationProtocol.log.debug(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having class name as a prefix is redundant. Consider moving the logger instance to the module root

const errorCode = state4TLV[PairingDataComponentType.ERROR] as Buffer;
const errorDecimal = errorCode[0];

const errorDescriptions: Record<number, string> = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be a global constant?

},
]);

const payload: PairingRequest = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see some unnecessary duplication while building this payload

let item = this.box.getItem(itemName);

if (!item) {
item = await this.box.createItem(itemName);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be simplified to const item = this.box.getItem(itemName) ?? await this.box.createItem(itemName)

);
return deviceIds;
} catch (error) {
this.log.error('Error getting available device IDs:', error);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any reason to mute this error?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants