# How vphone-cli Uses the vsock Protocol for Host-Guest Communication in Virtualized iOS

> Discover how vphone-cli uses the vsock protocol for seamless host-guest communication in virtualized iOS. Learn about its IP-free data streaming and control methods.

- Repository: [Lakr/vphone-cli](https://github.com/Lakr233/vphone-cli)
- Tags: internals
- Published: 2026-09-08

---

**vphone-cli leverages Apple’s Virtualization Framework vsock (virtual socket) to establish bidirectional, IP-free communication between the macOS host and iOS guest, using port 1337 for JSON-based control messages and port 1338 for raw camera frame streaming.**

vphone-cli is a command-line tool for running virtualized iOS devices on macOS using Apple's Virtualization Framework. At its core, the project relies on the **vsock protocol** to enable seamless host-guest communication without network bridging. This article examines how the Swift implementation configures virtual sockets, handles message framing, and manages multiple parallel data channels.

## Configuring the vsock Device in the Virtual Machine

### VM Setup and Socket Initialization

In [`VPhoneVirtualMachine.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneVirtualMachine.swift), the virtual machine configuration includes a `VZVirtioSocketDeviceConfiguration` instance to enable vsock communication. Lines 44-47 append this device to the VM's configuration, defining port 1337 as the primary control channel endpoint. This setup creates the foundation for the host-guest IPC mechanism.

```swift
// VM configuration excerpt from VPhoneVirtualMachine.swift
let socketDevice = VZVirtioSocketDeviceConfiguration()
// Device is added to VM configuration at lines 44-47

```

## Control Channel Architecture (Port 1337)

### Connection Establishment and Handshake

The [`VPhoneControl.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneControl.swift) file implements the host-side client for the control channel. The `connect(device:)` method stores the `VZVirtioSocketDevice` reference and initiates connection attempts via `attemptConnect()` (lines 45-57). Once connected, `performHandshake(fd:attemptToken:)` (lines 75-85) executes a protocol handshake where the host transmits a JSON "hello" message prefixed by a 32-bit big-endian length header.

```swift
// Establish control channel
let control = VPhoneControl(variant: .regular)
control.connect(device: vm.virtualMachine.socketDevices.first as! VZVirtioSocketDevice)

```

### Message Framing Protocol

Every packet exchanged over the vsock channel follows a strict binary format:

```

[uint32 big-endian length][UTF-8 JSON payload]

```

The JSON structure consistently includes three fields: `"v"` for protocol version, `"t"` for message type, and an optional `"id"` for request correlation. Helper functions `writeMessage(fd:dict:)` and `readMessage(fd:)` handle the length-prefixing logic, ensuring byte-stream boundary integrity.

### Asynchronous Request/Response Pattern

To support concurrent operations, the control channel implements an async request/response system. Each request carries a unique `"id"` generated from `nextRequestId`. The host stores pending callbacks in a thread-safe `pendingRequests` dictionary via `addPending` (lines 72-78). When responses arrive, `removePending` (lines 84-87) retrieves and invokes the appropriate callback before removing the entry. The `sendRequest` method (lines 52-78) orchestrates this flow.

### High-Level Control APIs

`VPhoneControl` exposes convenience methods that construct JSON payloads and transmit them over the vsock control channel:

- **HID Events**: `sendHIDPress`, `sendHIDDown`, and `sendHIDUp` transmit `"hid"` messages (lines 74-84) for simulating hardware button presses.
- **Touch Injection**: `sendTouch(phase:x:y:)` sends `"touch"` messages (lines 106-118) to inject touch events at normalized screen coordinates.
- **Developer Mode**: `sendDevModeStatus()` queries the guest's developer mode state (lines 124-133).
- **File Operations**: `listFiles`, `downloadFile`, and `uploadFile` utilize the generic `sendRequest` helper (lines 80-99) for filesystem management.

```swift
// Send HID key press (e.g., Home button)
control.sendHIDPress(page: 0x0C, usage: 0x01)

// Inject touch at screen center
control.sendTouch(phase: 0, x: 0.5, y: 0.5)

// Query files asynchronously
Task {
    let entries = try await control.listFiles(path: "/var/mobile/Containers/Data/Application")
}

```

## Binary Auto-Update Mechanism

When `guestBinaryURL` is configured, the host calculates the binary's SHA-256 hash and includes it in the initial handshake as `guestBinaryHash`. If the guest responds with `"need_update": true`, the `pushUpdate(fd:)` method (lines 40-70 in [`VPhoneControl.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneControl.swift)) streams the raw binary data after sending a header with `"t":"update"` and the payload size.

## Camera Streaming via Secondary vsock (Port 1338)

For high-throughput video data, [`VPhoneCameraServer.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneCameraServer.swift) establishes a secondary vsock connection on port 1338. Lines 7-16 configure this independent channel to avoid blocking the control socket. The host connects via `device.connect(toPort: Self.vsockPort)` and, once established, repeatedly generates BGRA frames. The `send(fd:frame:)` method (invoked in lines 24-44) transmits length-prefixed frame data using a format optimized for raw pixel buffers rather than JSON.

```swift
// Camera server setup
let camera = VPhoneCameraServer()
camera.setSource(.testPattern)
camera.connect(device: vm.virtualMachine.socketDevices.first as! VZVirtioSocketDevice)
camera.startStreaming()

```

## Resilience and Reconnection Logic

Both the control and camera components implement exponential back-off reconnection strategies through `scheduleReconnect` and `attemptConnect` methods. This ensures automatic recovery when the guest VM restarts or temporary vsocket interruptions occur, maintaining session continuity without manual intervention.

## Summary

- vphone-cli uses **Apple's Virtualization Framework vsock** to create isolated, high-performance communication channels between macOS host and iOS guest.
- The **control channel** (port 1337) in [`VPhoneControl.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneControl.swift) handles JSON-based RPC, binary updates, and device input simulation using length-prefixed message framing.
- A **dedicated camera channel** (port 1338) in [`VPhoneCameraServer.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneCameraServer.swift) streams raw BGRA frames independently from control traffic.
- **Asynchronous request/response** correlation uses unique IDs stored in thread-safe dictionaries to handle concurrent operations.
- **Exponential back-off reconnection** logic ensures robust communication across guest VM restarts.

## Frequently Asked Questions

### What port numbers does vphone-cli use for vsock communication?

vphone-cli allocates port 1337 for the control channel (JSON RPC and device commands) and port 1338 for the camera streaming channel. These are hardcoded in [`VPhoneVirtualMachine.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneVirtualMachine.swift) and [`VPhoneCameraServer.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneCameraServer.swift) respectively.

### How does vphone-cli handle message boundaries in the vsock byte stream?

The protocol uses a 32-bit big-endian length prefix followed by UTF-8 JSON data. This framing ensures that variable-length messages are correctly reconstructed from the sequential byte stream without TCP/IP-style packet boundaries.

### Can the host push updated binaries to the iOS guest automatically?

Yes. If `guestBinaryURL` is specified, the host includes the binary's SHA-256 hash in the initial handshake. The guest checks this against its current version and requests updates by responding with `"need_update": true`, triggering the `pushUpdate(fd:)` method to stream the new binary.

### What happens if the vsock connection drops during operation?

Both `VPhoneControl` and `VPhoneCameraServer` implement `scheduleReconnect` with exponential back-off. They automatically attempt to re-establish the vsock connection when the guest becomes available again, ensuring resilience against temporary disconnections or guest VM restarts.