@basmilius/apple-companion-link 0.8.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +605 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,606 @@
|
|
|
1
|
-
import{randomInt as e}from"node:crypto";import{AccessoryPair as t,AccessoryVerify as n,Context as r,ENCRYPTION as i,EncryptionAwareConnection as a,waitFor as o}from"@basmilius/apple-common";import{OPack as s,Plist as c}from"@basmilius/apple-encoding";import{Chacha20 as l,hkdf as u}from"@basmilius/apple-encryption";const d={Up:1,Down:2,Left:3,Right:4,Menu:5,Select:6,Home:7,VolumeUp:8,VolumeDown:9,Siri:10,Screensaver:11,Sleep:12,Wake:13,PlayPause:14,ChannelIncrement:15,ChannelDecrement:16,Guide:17,PageUp:18,PageDown:19},f={Play:1,Pause:2,NextTrack:3,PreviousTrack:4,GetVolume:5,SetVolume:6,SkipBy:7,FastForwardBegin:8,FastForwardEnd:9,RewindBegin:10,RewindEnd:11,GetCaptionSettings:12,SetCaptionSettings:13},p={Unknown:0,NoOp:1,PairSetupStart:3,PairSetupNext:4,PairVerifyStart:5,PairVerifyNext:6,OPackUnencrypted:7,OPackEncrypted:8,OPackPacked:9,PairingRequest:10,PairingResponse:11,SessionStartRequest:16,SessionStartResponse:17,SessionData:18,FamilyIdentityRequest:32,FamilyIdentityResponse:33,FamilyIdentityUpdate:34},m={Event:1,Request:2,Response:3},h=[p.PairSetupStart,p.PairSetupNext,p.PairVerifyStart,p.PairVerifyNext,p.OPackUnencrypted,p.OPackEncrypted,p.OPackPacked],g=[p.PairSetupStart,p.PairSetupNext,p.PairVerifyStart,p.PairVerifyNext];var _=class{get internal(){return this.#e}get stream(){return this.#t}#e;#t;constructor(e){this.#e=new t(e.context,this.#n.bind(this)),this.#t=e.stream}async start(){await this.#e.start()}async pin(e){return this.#e.pin(e)}async transient(){return this.#e.transient()}async#n(e,t){let n=e===`m1`?p.PairSetupStart:p.PairSetupNext,[,r]=await this.#t.exchange(n,{_pd:t,_pwTy:1});if(typeof r!=`object`||!r)throw Error(`Invalid response from receiver.`);return r._pd}},v=class{get internal(){return this.#e}get stream(){return this.#t}#e;#t;constructor(e){this.#e=new n(e.context,this.#n.bind(this)),this.#t=e.stream}async start(e){let t=await this.#e.start(e);return{accessoryToControllerKey:u({hash:`sha512`,key:t.sharedSecret,length:32,salt:Buffer.alloc(0),info:Buffer.from(`ServerEncrypt-main`)}),controllerToAccessoryKey:u({hash:`sha512`,key:t.sharedSecret,length:32,salt:Buffer.alloc(0),info:Buffer.from(`ClientEncrypt-main`)}),pairingId:t.pairingId,sharedSecret:t.sharedSecret}}async#n(e,t){let n=e===`m1`?p.PairVerifyStart:p.PairVerifyNext,[,r]=await this.#t.exchange(n,{_pd:t,_auTy:4});if(typeof r!=`object`||!r)throw Error(`Invalid response from receiver.`);return r._pd}};function y(e){switch(e){case 1:return`asleep`;case 2:return`screensaver`;case 3:return`awake`;case 4:return`idle`;default:return`unknown`}}var b=class extends a{get#e(){return this[i]}#t=new Map;#n=Buffer.alloc(0);#r;constructor(t,n,r){super(t,n,r),this.debug(!0),this.#r=e(0,2**16),this.on(`close`,this.#a.bind(this)),this.on(`data`,this.#o.bind(this)),this.on(`error`,this.#s.bind(this))}async disconnect(){this.#i(),await super.disconnect()}async exchange(e,t){let n=this.#r;return new Promise((r,i)=>{g.includes(e)?this.#t.set(-1,[r,i]):this.#t.set(n,[r,i]),this.sendOPack(e,t)})}send(e,t){let n=this.isEncrypted&&e!==p.NoOp,r=t.byteLength;n&&(r+=l.CHACHA20_AUTH_TAG_LENGTH);let i=Buffer.allocUnsafe(4);i.writeUint8(e,0),i.writeUintBE(r,1,3);let a;if(n){let e=Buffer.alloc(12);e.writeBigUInt64LE(BigInt(this.#e.writeCount++),0);let n=l.encrypt(this.#e.writeKey,e,i,t);a=Buffer.concat([i,n.ciphertext,n.authTag])}else a=Buffer.concat([i,t]);this.context.logger.raw(`[companion-link]`,`Sending data frame`,this.isEncrypted,e),this.write(a)}sendOPack(e,t){let n=this.#r++;t._x??=s.sizedInteger(n,8),this.context.logger.raw(`[companion-link]`,`Sending opack frame`,e,this.isEncrypted,t),this.send(e,Buffer.from(s.encode(t)))}#i(){this.#n=Buffer.alloc(0);let e=Error(`Stream cleanup`);for(let[,t]of this.#t.values())t(e);this.#t.clear()}#a(){let e=Error(`Connection closed while waiting for response`);for(let[,t]of this.#t.values())t(e);this.#t.clear(),this.#i()}async#o(e){this.#n=Buffer.concat([this.#n,e]);try{for(;this.#n.byteLength>=4;){let t=this.#n.subarray(0,4),n=4+t.readUintBE(1,3);if(this.#n.byteLength<n){this.context.logger.warn(`[companion-link]`,`Data packet is too short needed=${n} available=${this.#n.byteLength} receivedLength=${e.byteLength}`);return}this.context.logger.raw(`[companion-link]`,`Received frame length=${n} availableLength=${this.#n.byteLength} receivedLength=${e.byteLength}`);let r=Buffer.from(this.#n.subarray(0,n));this.#n=this.#n.subarray(n),this.context.logger.raw(`[companion-link]`,`Handle frame, ${this.#n.byteLength} bytes left...`),this.isEncrypted&&(r=this.#c(r));let i=r.subarray(4,n);this.#l(t,i)}}catch(e){this.context.logger.error(`[companion-link]`,`#onData()`,e),this.emit(`error`,e)}}#s(e){for(let[,t]of this.#t.values())t(e);this.#t.clear()}#c(e){let t=e.subarray(0,4),n=t.readUintBE(1,3),r=e.subarray(4,4+n),i=r.subarray(r.byteLength-16),a=r.subarray(0,r.byteLength-16),o=Buffer.alloc(12);o.writeBigUint64LE(BigInt(this.#e.readCount++),0);let s=l.decrypt(this.#e.readKey,o,t,a,i);return Buffer.concat([t,s,i])}#l(e,t){let n=e.readInt8();if(!h.includes(n)){this.context.logger.warn(`[companion-link]`,`Packet not handled, no opack frame.`);return}if(t=s.decode(t),this.context.logger.raw(`[companion-link]`,`Decoded OPACK`,{header:e,payload:t}),`_x`in t){let n=Number(t._x);if(this.#t.has(n)){let[r]=this.#t.get(n);r([e,t]),this.#t.delete(n)}else if(`_i`in t)this.emit(t._i,t._c);else{let e=t._c,n=Object.keys(e).map(e=>e.slice(0,-3));for(let t of n)this.emit(t,e[t])}}else if(this.#t.has(-1)){let[n]=this.#t.get(-1);n([e,t]),this.#t.delete(-1)}else this.context.logger.warn(`[companion-link]`,`No handler for message`,[e,t])}},x=class{get context(){return this.#e}get discoveryResult(){return this.#t}get pairing(){return this.#n}get stream(){return this.#r}get verify(){return this.#i}#e;#t;#n;#r;#i;constructor(e){this.#e=new r(e.id),this.#t=e,this.#r=new b(this.#e,e.address,e.service.port),this.#n=new _(this),this.#i=new v(this)}async connect(){await this.#r.connect()}destroy(){this.#r.destroy()}async disconnect(){await this.#r.disconnect()}async fetchMediaControlStatus(){await this.#r.exchange(p.OPackEncrypted,{_i:`FetchMediaControlStatus`,_t:m.Request,_c:{}})}async fetchNowPlayingInfo(){await this.#r.exchange(p.OPackEncrypted,{_i:`FetchCurrentNowPlayingInfoEvent`,_t:m.Request,_c:{}})}async fetchSupportedActions(){await this.#r.exchange(p.OPackEncrypted,{_i:`FetchSupportedActionsEvent`,_t:m.Request,_c:{}})}async getAttentionState(){let[,e]=await this.#r.exchange(p.OPackEncrypted,{_i:`FetchAttentionState`,_t:m.Request,_c:{}}),{_c:t}=S(e);return y(t.state)}async getLaunchableApps(){let[,e]=await this.#r.exchange(p.OPackEncrypted,{_i:`FetchLaunchableApplicationsEvent`,_t:m.Request,_c:{}}),{_c:t}=S(e);return Object.entries(t).map(([e,t])=>({bundleId:e,name:t}))}async getSiriRemoteInfo(){let[,e]=await this.#r.exchange(p.OPackEncrypted,{_i:`FetchSiriRemoteInfo`,_t:m.Request,_c:{}});return c.parse(Buffer.from(e._c.SiriRemoteInfoKey).buffer)}async getUserAccounts(){let[,e]=await this.#r.exchange(p.OPackEncrypted,{_i:`FetchUserAccountsEvent`,_t:m.Request,_c:{}}),{_c:t}=S(e);return Object.entries(t).map(([e,t])=>({accountId:e,name:t}))}async hidCommand(e,t=!1){await this.#r.exchange(p.OPackEncrypted,{_i:`_hidC`,_t:m.Request,_c:{_hBtS:t?1:2,_hidC:d[e]}})}async launchApp(e){await this.#r.exchange(p.OPackEncrypted,{_i:`_launchApp`,_t:m.Request,_c:{_bundleID:e}})}async launchUrl(e){await this.#r.exchange(p.OPackEncrypted,{_i:`_launchApp`,_t:m.Request,_c:{_urlS:e}})}async mediaControlCommand(e,t){let[,n]=await this.#r.exchange(p.OPackEncrypted,{_i:`_mcc`,_t:m.Request,_c:{_mcc:f[e],...t||{}}});return S(n)}async pressButton(e,t=`SingleTap`,n=500){switch(t){case`DoubleTap`:await this.hidCommand(e,!0),await this.hidCommand(e,!1),await this.hidCommand(e,!0),await this.hidCommand(e,!1);break;case`Hold`:await this.hidCommand(e,!0),await o(n),await this.hidCommand(e,!1);break;case`SingleTap`:await this.hidCommand(e,!0),await this.hidCommand(e,!1);break}}async switchUserAccount(e){await this.#r.exchange(p.OPackEncrypted,{_i:`SwitchUserAccountEvent`,_t:m.Request,_c:{SwitchAccountID:e}})}async subscribe(e,t){this.#r.on(e,t),this.#r.sendOPack(p.OPackEncrypted,{_i:`_interest`,_t:m.Event,_c:{_regEvents:[e]}})}async unsubscribe(e,t){this.#r.isConnected&&(t&&this.#r.off(e,t),this.#r.sendOPack(p.OPackEncrypted,{_i:`_interest`,_t:m.Event,_c:{_deregEvents:[e]}}))}async sessionStart(){let[,t]=await this.#r.exchange(p.OPackEncrypted,{_i:`_sessionStart`,_t:m.Request,_btHP:!1,_c:{_srvT:`com.apple.tvremoteservices`,_sid:e(0,2**32-1),_btHP:!1}});return S(t)}async systemInfo(e){let[,t]=await this.#r.exchange(p.OPackEncrypted,{_i:`_systemInfo`,_t:m.Request,_btHP:!1,_c:{_bf:0,_cf:512,_clFl:128,_i:`b561af32aea6`,_idsID:e.toString(),_pubID:`DA:6D:1E:D8:A0:4F`,_sf:1099511628032,_sv:`715.2`,model:`iPhone16,2`,name:`AP Companion Link`,_lP:50402,_dC:`1`,_stA:`com.apple.sharingd.AirDrop,SymptomNetworkDiagnostics,com.apple.photosface.network-service,com.apple.ApplicationService.chrono,com.apple.DDUI-Picker,com.apple.biomesyncd.cascade.rapport,com.apple.SeymourSession,com.apple.workflow.remotewidgets,com.apple.ApplicationService.chrono,SCD.MessageCenter.remoteIntelligence,DeviceSharingDaemonApplicationService,com.apple.biomesyncd.rapport,com.apple.devicediscoveryui.rapportwake,com.apple.healthd.rapport,com.apple.dropin.setup,com.apple.coreduet.sync,com.apple.siri.wakeup,com.apple.wifivelocityd.rapportWake,com.apple.Seymour,CPSRemoteLLM,com.apple.networkrelay.on-demand-setup,com.apple.home.messaging,com.apple.accessibility.axremoted.rapportWake,com.apple.continuitycapture.sideband,com.apple.announce,com.apple.coreidv.coreidvd.handoff`.split(`,`)}});return S(t)}async tiStart(){let[,e]=await this.#r.exchange(p.OPackEncrypted,{_i:`_tiStart`,_t:m.Request,_btHP:!1,_c:{}});return S(e)}async touchStart(){let[,e]=await this.#r.exchange(p.OPackEncrypted,{_i:`_touchStart`,_t:m.Request,_btHP:!1,_c:{_height:s.float(1e3),_tFl:0,_width:s.float(1e3)}});return S(e)}async tvrcSessionStart(){let[,e]=await this.#r.exchange(p.OPackEncrypted,{_i:`TVRCSessionStart`,_t:m.Request,_btHP:!1,_inUseProc:`tvremoted`,_c:{}});return S(e)}noOp(){this.#e.logger.debug(`Sending no-op operation.`),this.#r.send(p.NoOp,Buffer.allocUnsafe(0))}};function S(e){if(typeof e==`object`&&e)return e;throw TypeError(`Expected an object.`)}export{d as HidCommand,f as MediaControlCommand,_ as Pairing,x as Protocol,b as Stream,v as Verify,y as convertAttentionState};
|
|
1
|
+
import { randomInt } from "node:crypto";
|
|
2
|
+
import { AccessoryPair, AccessoryVerify, Context, ENCRYPTION, EncryptionAwareConnection, waitFor } from "@basmilius/apple-common";
|
|
3
|
+
import { OPack, Plist } from "@basmilius/apple-encoding";
|
|
4
|
+
import { Chacha20, hkdf } from "@basmilius/apple-encryption";
|
|
5
|
+
|
|
6
|
+
//#region src/const.ts
|
|
7
|
+
const HidCommand = {
|
|
8
|
+
Up: 1,
|
|
9
|
+
Down: 2,
|
|
10
|
+
Left: 3,
|
|
11
|
+
Right: 4,
|
|
12
|
+
Menu: 5,
|
|
13
|
+
Select: 6,
|
|
14
|
+
Home: 7,
|
|
15
|
+
VolumeUp: 8,
|
|
16
|
+
VolumeDown: 9,
|
|
17
|
+
Siri: 10,
|
|
18
|
+
Screensaver: 11,
|
|
19
|
+
Sleep: 12,
|
|
20
|
+
Wake: 13,
|
|
21
|
+
PlayPause: 14,
|
|
22
|
+
ChannelIncrement: 15,
|
|
23
|
+
ChannelDecrement: 16,
|
|
24
|
+
Guide: 17,
|
|
25
|
+
PageUp: 18,
|
|
26
|
+
PageDown: 19
|
|
27
|
+
};
|
|
28
|
+
const MediaControlCommand = {
|
|
29
|
+
Play: 1,
|
|
30
|
+
Pause: 2,
|
|
31
|
+
NextTrack: 3,
|
|
32
|
+
PreviousTrack: 4,
|
|
33
|
+
GetVolume: 5,
|
|
34
|
+
SetVolume: 6,
|
|
35
|
+
SkipBy: 7,
|
|
36
|
+
FastForwardBegin: 8,
|
|
37
|
+
FastForwardEnd: 9,
|
|
38
|
+
RewindBegin: 10,
|
|
39
|
+
RewindEnd: 11,
|
|
40
|
+
GetCaptionSettings: 12,
|
|
41
|
+
SetCaptionSettings: 13
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/frame.ts
|
|
46
|
+
const FrameType = {
|
|
47
|
+
Unknown: 0,
|
|
48
|
+
NoOp: 1,
|
|
49
|
+
PairSetupStart: 3,
|
|
50
|
+
PairSetupNext: 4,
|
|
51
|
+
PairVerifyStart: 5,
|
|
52
|
+
PairVerifyNext: 6,
|
|
53
|
+
OPackUnencrypted: 7,
|
|
54
|
+
OPackEncrypted: 8,
|
|
55
|
+
OPackPacked: 9,
|
|
56
|
+
PairingRequest: 10,
|
|
57
|
+
PairingResponse: 11,
|
|
58
|
+
SessionStartRequest: 16,
|
|
59
|
+
SessionStartResponse: 17,
|
|
60
|
+
SessionData: 18,
|
|
61
|
+
FamilyIdentityRequest: 32,
|
|
62
|
+
FamilyIdentityResponse: 33,
|
|
63
|
+
FamilyIdentityUpdate: 34
|
|
64
|
+
};
|
|
65
|
+
const MessageType = {
|
|
66
|
+
Event: 1,
|
|
67
|
+
Request: 2,
|
|
68
|
+
Response: 3
|
|
69
|
+
};
|
|
70
|
+
const OPackFrameTypes = [
|
|
71
|
+
FrameType.PairSetupStart,
|
|
72
|
+
FrameType.PairSetupNext,
|
|
73
|
+
FrameType.PairVerifyStart,
|
|
74
|
+
FrameType.PairVerifyNext,
|
|
75
|
+
FrameType.OPackUnencrypted,
|
|
76
|
+
FrameType.OPackEncrypted,
|
|
77
|
+
FrameType.OPackPacked
|
|
78
|
+
];
|
|
79
|
+
const PairingFrameTypes = [
|
|
80
|
+
FrameType.PairSetupStart,
|
|
81
|
+
FrameType.PairSetupNext,
|
|
82
|
+
FrameType.PairVerifyStart,
|
|
83
|
+
FrameType.PairVerifyNext
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/pairing.ts
|
|
88
|
+
var Pairing = class {
|
|
89
|
+
get internal() {
|
|
90
|
+
return this.#internal;
|
|
91
|
+
}
|
|
92
|
+
get stream() {
|
|
93
|
+
return this.#stream;
|
|
94
|
+
}
|
|
95
|
+
#internal;
|
|
96
|
+
#stream;
|
|
97
|
+
constructor(protocol) {
|
|
98
|
+
this.#internal = new AccessoryPair(protocol.context, this.#request.bind(this));
|
|
99
|
+
this.#stream = protocol.stream;
|
|
100
|
+
}
|
|
101
|
+
async start() {
|
|
102
|
+
await this.#internal.start();
|
|
103
|
+
}
|
|
104
|
+
async pin(askPin) {
|
|
105
|
+
return this.#internal.pin(askPin);
|
|
106
|
+
}
|
|
107
|
+
async transient() {
|
|
108
|
+
return this.#internal.transient();
|
|
109
|
+
}
|
|
110
|
+
async #request(step, data) {
|
|
111
|
+
const frameType = step === "m1" ? FrameType.PairSetupStart : FrameType.PairSetupNext;
|
|
112
|
+
const [, response] = await this.#stream.exchange(frameType, {
|
|
113
|
+
_pd: data,
|
|
114
|
+
_pwTy: 1
|
|
115
|
+
});
|
|
116
|
+
if (typeof response !== "object" || response === null) throw new Error("Invalid response from receiver.");
|
|
117
|
+
return response["_pd"];
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
var Verify = class {
|
|
121
|
+
get internal() {
|
|
122
|
+
return this.#internal;
|
|
123
|
+
}
|
|
124
|
+
get stream() {
|
|
125
|
+
return this.#stream;
|
|
126
|
+
}
|
|
127
|
+
#internal;
|
|
128
|
+
#stream;
|
|
129
|
+
constructor(protocol) {
|
|
130
|
+
this.#internal = new AccessoryVerify(protocol.context, this.#request.bind(this));
|
|
131
|
+
this.#stream = protocol.stream;
|
|
132
|
+
}
|
|
133
|
+
async start(credentials) {
|
|
134
|
+
const keys = await this.#internal.start(credentials);
|
|
135
|
+
return {
|
|
136
|
+
accessoryToControllerKey: hkdf({
|
|
137
|
+
hash: "sha512",
|
|
138
|
+
key: keys.sharedSecret,
|
|
139
|
+
length: 32,
|
|
140
|
+
salt: Buffer.alloc(0),
|
|
141
|
+
info: Buffer.from("ServerEncrypt-main")
|
|
142
|
+
}),
|
|
143
|
+
controllerToAccessoryKey: hkdf({
|
|
144
|
+
hash: "sha512",
|
|
145
|
+
key: keys.sharedSecret,
|
|
146
|
+
length: 32,
|
|
147
|
+
salt: Buffer.alloc(0),
|
|
148
|
+
info: Buffer.from("ClientEncrypt-main")
|
|
149
|
+
}),
|
|
150
|
+
pairingId: keys.pairingId,
|
|
151
|
+
sharedSecret: keys.sharedSecret
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
async #request(step, data) {
|
|
155
|
+
const frameType = step === "m1" ? FrameType.PairVerifyStart : FrameType.PairVerifyNext;
|
|
156
|
+
const [, response] = await this.#stream.exchange(frameType, {
|
|
157
|
+
_pd: data,
|
|
158
|
+
_auTy: 4
|
|
159
|
+
});
|
|
160
|
+
if (typeof response !== "object" || response === null) throw new Error("Invalid response from receiver.");
|
|
161
|
+
return response["_pd"];
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region src/utils.ts
|
|
167
|
+
function convertAttentionState(state) {
|
|
168
|
+
switch (state) {
|
|
169
|
+
case 1: return "asleep";
|
|
170
|
+
case 2: return "screensaver";
|
|
171
|
+
case 3: return "awake";
|
|
172
|
+
case 4: return "idle";
|
|
173
|
+
default: return "unknown";
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
//#endregion
|
|
178
|
+
//#region src/stream.ts
|
|
179
|
+
const HEADER_SIZE = 4;
|
|
180
|
+
const PAIRING_QUEUE_IDENTIFIER = -1;
|
|
181
|
+
var Stream = class extends EncryptionAwareConnection {
|
|
182
|
+
get #encryptionState() {
|
|
183
|
+
return this[ENCRYPTION];
|
|
184
|
+
}
|
|
185
|
+
#queue = /* @__PURE__ */ new Map();
|
|
186
|
+
#buffer = Buffer.alloc(0);
|
|
187
|
+
#xid;
|
|
188
|
+
constructor(context, address, port) {
|
|
189
|
+
super(context, address, port);
|
|
190
|
+
this.debug(true);
|
|
191
|
+
this.#xid = randomInt(0, 2 ** 16);
|
|
192
|
+
this.on("close", this.#onClose.bind(this));
|
|
193
|
+
this.on("data", this.#onData.bind(this));
|
|
194
|
+
this.on("error", this.#onError.bind(this));
|
|
195
|
+
}
|
|
196
|
+
async disconnect() {
|
|
197
|
+
this.#cleanup();
|
|
198
|
+
await super.disconnect();
|
|
199
|
+
}
|
|
200
|
+
async exchange(type, obj) {
|
|
201
|
+
const _x = this.#xid;
|
|
202
|
+
return new Promise((resolve, reject) => {
|
|
203
|
+
if (PairingFrameTypes.includes(type)) this.#queue.set(PAIRING_QUEUE_IDENTIFIER, [resolve, reject]);
|
|
204
|
+
else this.#queue.set(_x, [resolve, reject]);
|
|
205
|
+
this.sendOPack(type, obj);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
send(type, payload) {
|
|
209
|
+
const encrypt = this.isEncrypted && type !== FrameType.NoOp;
|
|
210
|
+
let payloadLength = payload.byteLength;
|
|
211
|
+
if (encrypt) payloadLength += Chacha20.CHACHA20_AUTH_TAG_LENGTH;
|
|
212
|
+
const header = Buffer.allocUnsafe(4);
|
|
213
|
+
header.writeUint8(type, 0);
|
|
214
|
+
header.writeUintBE(payloadLength, 1, 3);
|
|
215
|
+
let data;
|
|
216
|
+
if (encrypt) {
|
|
217
|
+
const nonce = Buffer.alloc(12);
|
|
218
|
+
nonce.writeBigUInt64LE(BigInt(this.#encryptionState.writeCount++), 0);
|
|
219
|
+
const encrypted = Chacha20.encrypt(this.#encryptionState.writeKey, nonce, header, payload);
|
|
220
|
+
data = Buffer.concat([
|
|
221
|
+
header,
|
|
222
|
+
encrypted.ciphertext,
|
|
223
|
+
encrypted.authTag
|
|
224
|
+
]);
|
|
225
|
+
} else data = Buffer.concat([header, payload]);
|
|
226
|
+
this.context.logger.raw("[companion-link]", "Sending data frame", this.isEncrypted, type);
|
|
227
|
+
this.write(data);
|
|
228
|
+
}
|
|
229
|
+
sendOPack(type, obj) {
|
|
230
|
+
const _x = this.#xid++;
|
|
231
|
+
obj._x ??= OPack.sizedInteger(_x, 8);
|
|
232
|
+
this.context.logger.raw("[companion-link]", "Sending opack frame", type, this.isEncrypted, obj);
|
|
233
|
+
this.send(type, Buffer.from(OPack.encode(obj)));
|
|
234
|
+
}
|
|
235
|
+
#cleanup() {
|
|
236
|
+
this.#buffer = Buffer.alloc(0);
|
|
237
|
+
const error = /* @__PURE__ */ new Error("Stream cleanup");
|
|
238
|
+
for (const [, reject] of this.#queue.values()) reject(error);
|
|
239
|
+
this.#queue.clear();
|
|
240
|
+
}
|
|
241
|
+
#onClose() {
|
|
242
|
+
const error = /* @__PURE__ */ new Error("Connection closed while waiting for response");
|
|
243
|
+
for (const [, reject] of this.#queue.values()) reject(error);
|
|
244
|
+
this.#queue.clear();
|
|
245
|
+
this.#cleanup();
|
|
246
|
+
}
|
|
247
|
+
async #onData(data) {
|
|
248
|
+
this.#buffer = Buffer.concat([this.#buffer, data]);
|
|
249
|
+
try {
|
|
250
|
+
while (this.#buffer.byteLength >= HEADER_SIZE) {
|
|
251
|
+
const header = this.#buffer.subarray(0, HEADER_SIZE);
|
|
252
|
+
const totalLength = HEADER_SIZE + header.readUintBE(1, 3);
|
|
253
|
+
if (this.#buffer.byteLength < totalLength) {
|
|
254
|
+
this.context.logger.warn("[companion-link]", `Data packet is too short needed=${totalLength} available=${this.#buffer.byteLength} receivedLength=${data.byteLength}`);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
this.context.logger.raw("[companion-link]", `Received frame length=${totalLength} availableLength=${this.#buffer.byteLength} receivedLength=${data.byteLength}`);
|
|
258
|
+
let frame = Buffer.from(this.#buffer.subarray(0, totalLength));
|
|
259
|
+
this.#buffer = this.#buffer.subarray(totalLength);
|
|
260
|
+
this.context.logger.raw("[companion-link]", `Handle frame, ${this.#buffer.byteLength} bytes left...`);
|
|
261
|
+
if (this.isEncrypted) frame = this.#decrypt(frame);
|
|
262
|
+
const payload = frame.subarray(HEADER_SIZE, totalLength);
|
|
263
|
+
this.#handle(header, payload);
|
|
264
|
+
}
|
|
265
|
+
} catch (err) {
|
|
266
|
+
this.context.logger.error("[companion-link]", "#onData()", err);
|
|
267
|
+
this.emit("error", err);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
#onError(err) {
|
|
271
|
+
for (const [, reject] of this.#queue.values()) reject(err);
|
|
272
|
+
this.#queue.clear();
|
|
273
|
+
}
|
|
274
|
+
#decrypt(data) {
|
|
275
|
+
const header = data.subarray(0, 4);
|
|
276
|
+
const payloadLength = header.readUintBE(1, 3);
|
|
277
|
+
const payload = data.subarray(4, 4 + payloadLength);
|
|
278
|
+
const authTag = payload.subarray(payload.byteLength - 16);
|
|
279
|
+
const ciphertext = payload.subarray(0, payload.byteLength - 16);
|
|
280
|
+
const nonce = Buffer.alloc(12);
|
|
281
|
+
nonce.writeBigUint64LE(BigInt(this.#encryptionState.readCount++), 0);
|
|
282
|
+
const decrypted = Chacha20.decrypt(this.#encryptionState.readKey, nonce, header, ciphertext, authTag);
|
|
283
|
+
return Buffer.concat([
|
|
284
|
+
header,
|
|
285
|
+
decrypted,
|
|
286
|
+
authTag
|
|
287
|
+
]);
|
|
288
|
+
}
|
|
289
|
+
#handle(header, payload) {
|
|
290
|
+
const type = header.readInt8();
|
|
291
|
+
if (!OPackFrameTypes.includes(type)) {
|
|
292
|
+
this.context.logger.warn("[companion-link]", "Packet not handled, no opack frame.");
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
payload = OPack.decode(payload);
|
|
296
|
+
this.context.logger.raw("[companion-link]", "Decoded OPACK", {
|
|
297
|
+
header,
|
|
298
|
+
payload
|
|
299
|
+
});
|
|
300
|
+
if ("_x" in payload) {
|
|
301
|
+
const _x = Number(payload["_x"]);
|
|
302
|
+
if (this.#queue.has(_x)) {
|
|
303
|
+
const [resolve] = this.#queue.get(_x);
|
|
304
|
+
resolve([header, payload]);
|
|
305
|
+
this.#queue.delete(_x);
|
|
306
|
+
} else if ("_i" in payload) this.emit(payload["_i"], payload["_c"]);
|
|
307
|
+
else {
|
|
308
|
+
const content = payload["_c"];
|
|
309
|
+
const keys = Object.keys(content).map((k) => k.slice(0, -3));
|
|
310
|
+
for (const key of keys) this.emit(key, content[key]);
|
|
311
|
+
}
|
|
312
|
+
} else if (this.#queue.has(PAIRING_QUEUE_IDENTIFIER)) {
|
|
313
|
+
const [resolve] = this.#queue.get(PAIRING_QUEUE_IDENTIFIER);
|
|
314
|
+
resolve([header, payload]);
|
|
315
|
+
this.#queue.delete(PAIRING_QUEUE_IDENTIFIER);
|
|
316
|
+
} else this.context.logger.warn("[companion-link]", "No handler for message", [header, payload]);
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
//#endregion
|
|
321
|
+
//#region src/protocol.ts
|
|
322
|
+
var Protocol = class {
|
|
323
|
+
get context() {
|
|
324
|
+
return this.#context;
|
|
325
|
+
}
|
|
326
|
+
get discoveryResult() {
|
|
327
|
+
return this.#discoveryResult;
|
|
328
|
+
}
|
|
329
|
+
get pairing() {
|
|
330
|
+
return this.#pairing;
|
|
331
|
+
}
|
|
332
|
+
get stream() {
|
|
333
|
+
return this.#stream;
|
|
334
|
+
}
|
|
335
|
+
get verify() {
|
|
336
|
+
return this.#verify;
|
|
337
|
+
}
|
|
338
|
+
#context;
|
|
339
|
+
#discoveryResult;
|
|
340
|
+
#pairing;
|
|
341
|
+
#stream;
|
|
342
|
+
#verify;
|
|
343
|
+
constructor(discoveryResult) {
|
|
344
|
+
this.#context = new Context(discoveryResult.id);
|
|
345
|
+
this.#discoveryResult = discoveryResult;
|
|
346
|
+
this.#stream = new Stream(this.#context, discoveryResult.address, discoveryResult.service.port);
|
|
347
|
+
this.#pairing = new Pairing(this);
|
|
348
|
+
this.#verify = new Verify(this);
|
|
349
|
+
}
|
|
350
|
+
async connect() {
|
|
351
|
+
await this.#stream.connect();
|
|
352
|
+
}
|
|
353
|
+
destroy() {
|
|
354
|
+
this.#stream.destroy();
|
|
355
|
+
}
|
|
356
|
+
async disconnect() {
|
|
357
|
+
await this.#stream.disconnect();
|
|
358
|
+
}
|
|
359
|
+
async fetchMediaControlStatus() {
|
|
360
|
+
await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
361
|
+
_i: "FetchMediaControlStatus",
|
|
362
|
+
_t: MessageType.Request,
|
|
363
|
+
_c: {}
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
async fetchNowPlayingInfo() {
|
|
367
|
+
await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
368
|
+
_i: "FetchCurrentNowPlayingInfoEvent",
|
|
369
|
+
_t: MessageType.Request,
|
|
370
|
+
_c: {}
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
async fetchSupportedActions() {
|
|
374
|
+
await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
375
|
+
_i: "FetchSupportedActionsEvent",
|
|
376
|
+
_t: MessageType.Request,
|
|
377
|
+
_c: {}
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
async getAttentionState() {
|
|
381
|
+
const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
382
|
+
_i: "FetchAttentionState",
|
|
383
|
+
_t: MessageType.Request,
|
|
384
|
+
_c: {}
|
|
385
|
+
});
|
|
386
|
+
const { _c } = objectOrFail(payload);
|
|
387
|
+
return convertAttentionState(_c.state);
|
|
388
|
+
}
|
|
389
|
+
async getLaunchableApps() {
|
|
390
|
+
const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
391
|
+
_i: "FetchLaunchableApplicationsEvent",
|
|
392
|
+
_t: MessageType.Request,
|
|
393
|
+
_c: {}
|
|
394
|
+
});
|
|
395
|
+
const { _c } = objectOrFail(payload);
|
|
396
|
+
return Object.entries(_c).map(([bundleId, name]) => ({
|
|
397
|
+
bundleId,
|
|
398
|
+
name
|
|
399
|
+
}));
|
|
400
|
+
}
|
|
401
|
+
async getSiriRemoteInfo() {
|
|
402
|
+
const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
403
|
+
_i: "FetchSiriRemoteInfo",
|
|
404
|
+
_t: MessageType.Request,
|
|
405
|
+
_c: {}
|
|
406
|
+
});
|
|
407
|
+
return Plist.parse(Buffer.from(payload["_c"]["SiriRemoteInfoKey"]).buffer);
|
|
408
|
+
}
|
|
409
|
+
async getUserAccounts() {
|
|
410
|
+
const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
411
|
+
_i: "FetchUserAccountsEvent",
|
|
412
|
+
_t: MessageType.Request,
|
|
413
|
+
_c: {}
|
|
414
|
+
});
|
|
415
|
+
const { _c } = objectOrFail(payload);
|
|
416
|
+
return Object.entries(_c).map(([accountId, name]) => ({
|
|
417
|
+
accountId,
|
|
418
|
+
name
|
|
419
|
+
}));
|
|
420
|
+
}
|
|
421
|
+
async hidCommand(command, down = false) {
|
|
422
|
+
await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
423
|
+
_i: "_hidC",
|
|
424
|
+
_t: MessageType.Request,
|
|
425
|
+
_c: {
|
|
426
|
+
_hBtS: down ? 1 : 2,
|
|
427
|
+
_hidC: HidCommand[command]
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
async launchApp(bundleId) {
|
|
432
|
+
await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
433
|
+
_i: "_launchApp",
|
|
434
|
+
_t: MessageType.Request,
|
|
435
|
+
_c: { _bundleID: bundleId }
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
async launchUrl(url) {
|
|
439
|
+
await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
440
|
+
_i: "_launchApp",
|
|
441
|
+
_t: MessageType.Request,
|
|
442
|
+
_c: { _urlS: url }
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
async mediaControlCommand(command, content) {
|
|
446
|
+
const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
447
|
+
_i: "_mcc",
|
|
448
|
+
_t: MessageType.Request,
|
|
449
|
+
_c: {
|
|
450
|
+
_mcc: MediaControlCommand[command],
|
|
451
|
+
...content || {}
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
return objectOrFail(payload);
|
|
455
|
+
}
|
|
456
|
+
async pressButton(command, type = "SingleTap", holdDelayMs = 500) {
|
|
457
|
+
switch (type) {
|
|
458
|
+
case "DoubleTap":
|
|
459
|
+
await this.hidCommand(command, true);
|
|
460
|
+
await this.hidCommand(command, false);
|
|
461
|
+
await this.hidCommand(command, true);
|
|
462
|
+
await this.hidCommand(command, false);
|
|
463
|
+
break;
|
|
464
|
+
case "Hold":
|
|
465
|
+
await this.hidCommand(command, true);
|
|
466
|
+
await waitFor(holdDelayMs);
|
|
467
|
+
await this.hidCommand(command, false);
|
|
468
|
+
break;
|
|
469
|
+
case "SingleTap":
|
|
470
|
+
await this.hidCommand(command, true);
|
|
471
|
+
await this.hidCommand(command, false);
|
|
472
|
+
break;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
async switchUserAccount(accountId) {
|
|
476
|
+
await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
477
|
+
_i: "SwitchUserAccountEvent",
|
|
478
|
+
_t: MessageType.Request,
|
|
479
|
+
_c: { SwitchAccountID: accountId }
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
async subscribe(event, fn) {
|
|
483
|
+
this.#stream.on(event, fn);
|
|
484
|
+
this.#stream.sendOPack(FrameType.OPackEncrypted, {
|
|
485
|
+
_i: "_interest",
|
|
486
|
+
_t: MessageType.Event,
|
|
487
|
+
_c: { _regEvents: [event] }
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
async unsubscribe(event, fn) {
|
|
491
|
+
if (!this.#stream.isConnected) return;
|
|
492
|
+
if (fn) this.#stream.off(event, fn);
|
|
493
|
+
this.#stream.sendOPack(FrameType.OPackEncrypted, {
|
|
494
|
+
_i: "_interest",
|
|
495
|
+
_t: MessageType.Event,
|
|
496
|
+
_c: { _deregEvents: [event] }
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
async sessionStart() {
|
|
500
|
+
const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
501
|
+
_i: "_sessionStart",
|
|
502
|
+
_t: MessageType.Request,
|
|
503
|
+
_btHP: false,
|
|
504
|
+
_c: {
|
|
505
|
+
_srvT: "com.apple.tvremoteservices",
|
|
506
|
+
_sid: randomInt(0, 2 ** 32 - 1),
|
|
507
|
+
_btHP: false
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
return objectOrFail(payload);
|
|
511
|
+
}
|
|
512
|
+
async systemInfo(pairingId) {
|
|
513
|
+
const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
514
|
+
_i: "_systemInfo",
|
|
515
|
+
_t: MessageType.Request,
|
|
516
|
+
_btHP: false,
|
|
517
|
+
_c: {
|
|
518
|
+
_bf: 0,
|
|
519
|
+
_cf: 512,
|
|
520
|
+
_clFl: 128,
|
|
521
|
+
_i: "b561af32aea6",
|
|
522
|
+
_idsID: pairingId.toString(),
|
|
523
|
+
_pubID: "DA:6D:1E:D8:A0:4F",
|
|
524
|
+
_sf: 1099511628032,
|
|
525
|
+
_sv: "715.2",
|
|
526
|
+
model: "iPhone16,2",
|
|
527
|
+
name: "AP Companion Link",
|
|
528
|
+
_lP: 50402,
|
|
529
|
+
_dC: "1",
|
|
530
|
+
_stA: [
|
|
531
|
+
"com.apple.sharingd.AirDrop",
|
|
532
|
+
"SymptomNetworkDiagnostics",
|
|
533
|
+
"com.apple.photosface.network-service",
|
|
534
|
+
"com.apple.ApplicationService.chrono",
|
|
535
|
+
"com.apple.DDUI-Picker",
|
|
536
|
+
"com.apple.biomesyncd.cascade.rapport",
|
|
537
|
+
"com.apple.SeymourSession",
|
|
538
|
+
"com.apple.workflow.remotewidgets",
|
|
539
|
+
"com.apple.ApplicationService.chrono",
|
|
540
|
+
"SCD.MessageCenter.remoteIntelligence",
|
|
541
|
+
"DeviceSharingDaemonApplicationService",
|
|
542
|
+
"com.apple.biomesyncd.rapport",
|
|
543
|
+
"com.apple.devicediscoveryui.rapportwake",
|
|
544
|
+
"com.apple.healthd.rapport",
|
|
545
|
+
"com.apple.dropin.setup",
|
|
546
|
+
"com.apple.coreduet.sync",
|
|
547
|
+
"com.apple.siri.wakeup",
|
|
548
|
+
"com.apple.wifivelocityd.rapportWake",
|
|
549
|
+
"com.apple.Seymour",
|
|
550
|
+
"CPSRemoteLLM",
|
|
551
|
+
"com.apple.networkrelay.on-demand-setup",
|
|
552
|
+
"com.apple.home.messaging",
|
|
553
|
+
"com.apple.accessibility.axremoted.rapportWake",
|
|
554
|
+
"com.apple.continuitycapture.sideband",
|
|
555
|
+
"com.apple.announce",
|
|
556
|
+
"com.apple.coreidv.coreidvd.handoff"
|
|
557
|
+
]
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
return objectOrFail(payload);
|
|
561
|
+
}
|
|
562
|
+
async tiStart() {
|
|
563
|
+
const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
564
|
+
_i: "_tiStart",
|
|
565
|
+
_t: MessageType.Request,
|
|
566
|
+
_btHP: false,
|
|
567
|
+
_c: {}
|
|
568
|
+
});
|
|
569
|
+
return objectOrFail(payload);
|
|
570
|
+
}
|
|
571
|
+
async touchStart() {
|
|
572
|
+
const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
573
|
+
_i: "_touchStart",
|
|
574
|
+
_t: MessageType.Request,
|
|
575
|
+
_btHP: false,
|
|
576
|
+
_c: {
|
|
577
|
+
_height: OPack.float(1e3),
|
|
578
|
+
_tFl: 0,
|
|
579
|
+
_width: OPack.float(1e3)
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
return objectOrFail(payload);
|
|
583
|
+
}
|
|
584
|
+
async tvrcSessionStart() {
|
|
585
|
+
const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {
|
|
586
|
+
_i: "TVRCSessionStart",
|
|
587
|
+
_t: MessageType.Request,
|
|
588
|
+
_btHP: false,
|
|
589
|
+
_inUseProc: "tvremoted",
|
|
590
|
+
_c: {}
|
|
591
|
+
});
|
|
592
|
+
return objectOrFail(payload);
|
|
593
|
+
}
|
|
594
|
+
noOp() {
|
|
595
|
+
this.#context.logger.debug("Sending no-op operation.");
|
|
596
|
+
this.#stream.send(FrameType.NoOp, Buffer.allocUnsafe(0));
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
function objectOrFail(obj) {
|
|
600
|
+
if (obj !== null && typeof obj === "object") return obj;
|
|
601
|
+
throw new TypeError("Expected an object.");
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
//#endregion
|
|
605
|
+
export { HidCommand, MediaControlCommand, Pairing, Protocol, Stream, Verify, convertAttentionState };
|
|
2
606
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["#internal","#stream","#request","#encryptionState","#queue","#xid","#onClose","#onData","#onError","#cleanup","#buffer","#decrypt","#handle","#context","#discoveryResult","#pairing","#stream","#verify"],"sources":["../src/const.ts","../src/frame.ts","../src/pairing.ts","../src/utils.ts","../src/stream.ts","../src/protocol.ts"],"sourcesContent":["export const HidCommand = {\n Up: 1,\n Down: 2,\n Left: 3,\n Right: 4,\n Menu: 5,\n Select: 6,\n Home: 7,\n VolumeUp: 8,\n VolumeDown: 9,\n Siri: 10,\n Screensaver: 11,\n Sleep: 12,\n Wake: 13,\n PlayPause: 14,\n ChannelIncrement: 15,\n ChannelDecrement: 16,\n Guide: 17,\n PageUp: 18,\n PageDown: 19\n} as const;\n\nexport const MediaControlCommand = {\n Play: 1,\n Pause: 2,\n NextTrack: 3,\n PreviousTrack: 4,\n GetVolume: 5,\n SetVolume: 6,\n SkipBy: 7,\n FastForwardBegin: 8,\n FastForwardEnd: 9,\n RewindBegin: 10,\n RewindEnd: 11,\n GetCaptionSettings: 12,\n SetCaptionSettings: 13\n} as const;\n\nexport type HidCommandKey = keyof typeof HidCommand;\nexport type MediaControlCommandKey = keyof typeof MediaControlCommand;\n","export const FrameType = {\n Unknown: 0,\n NoOp: 1,\n\n PairSetupStart: 3,\n PairSetupNext: 4,\n\n PairVerifyStart: 5,\n PairVerifyNext: 6,\n\n OPackUnencrypted: 7,\n OPackEncrypted: 8,\n OPackPacked: 9,\n\n PairingRequest: 10,\n PairingResponse: 11,\n\n SessionStartRequest: 16,\n SessionStartResponse: 17,\n SessionData: 18,\n\n FamilyIdentityRequest: 32,\n FamilyIdentityResponse: 33,\n FamilyIdentityUpdate: 34\n} as const;\n\nexport const MessageType = {\n Event: 1,\n Request: 2,\n Response: 3\n} as const;\n\nexport const OPackFrameTypes: number[] = [\n FrameType.PairSetupStart,\n FrameType.PairSetupNext,\n FrameType.PairVerifyStart,\n FrameType.PairVerifyNext,\n\n FrameType.OPackUnencrypted,\n FrameType.OPackEncrypted,\n FrameType.OPackPacked\n];\n\nexport const PairingFrameTypes: number[] = [\n FrameType.PairSetupStart,\n FrameType.PairSetupNext,\n FrameType.PairVerifyStart,\n FrameType.PairVerifyNext\n];\n","import { type AccessoryCredentials, type AccessoryKeys, AccessoryPair, AccessoryVerify } from '@basmilius/apple-common';\nimport { hkdf } from '@basmilius/apple-encryption';\nimport { FrameType } from './frame';\nimport type Protocol from './protocol';\nimport type Stream from './stream';\n\nexport class Pairing {\n get internal(): AccessoryPair {\n return this.#internal;\n }\n\n get stream(): Stream {\n return this.#stream;\n }\n\n readonly #internal: AccessoryPair;\n readonly #stream: Stream;\n\n constructor(protocol: Protocol) {\n this.#internal = new AccessoryPair(protocol.context, this.#request.bind(this));\n this.#stream = protocol.stream;\n }\n\n async start(): Promise<void> {\n await this.#internal.start();\n }\n\n async pin(askPin: () => Promise<string>): Promise<AccessoryCredentials> {\n return this.#internal.pin(askPin);\n }\n\n async transient(): Promise<AccessoryKeys> {\n return this.#internal.transient();\n }\n\n async #request(step: 'm1' | 'm3' | 'm5', data: Buffer): Promise<Buffer> {\n const frameType = step === 'm1'\n ? FrameType.PairSetupStart\n : FrameType.PairSetupNext;\n\n const [, response] = await this.#stream.exchange(frameType, {\n _pd: data,\n _pwTy: 1\n });\n\n if (typeof response !== 'object' || response === null) {\n throw new Error('Invalid response from receiver.');\n }\n\n return response['_pd'];\n }\n}\n\nexport class Verify {\n get internal(): AccessoryVerify {\n return this.#internal;\n }\n\n get stream(): Stream {\n return this.#stream;\n }\n\n readonly #internal: AccessoryVerify;\n readonly #stream: Stream;\n\n constructor(protocol: Protocol) {\n this.#internal = new AccessoryVerify(protocol.context, this.#request.bind(this));\n this.#stream = protocol.stream;\n }\n\n async start(credentials: AccessoryCredentials): Promise<AccessoryKeys> {\n const keys = await this.#internal.start(credentials);\n\n const accessoryToControllerKey = hkdf({\n hash: 'sha512',\n key: keys.sharedSecret,\n length: 32,\n salt: Buffer.alloc(0),\n info: Buffer.from('ServerEncrypt-main')\n });\n\n const controllerToAccessoryKey = hkdf({\n hash: 'sha512',\n key: keys.sharedSecret,\n length: 32,\n salt: Buffer.alloc(0),\n info: Buffer.from('ClientEncrypt-main')\n });\n\n return {\n accessoryToControllerKey,\n controllerToAccessoryKey,\n pairingId: keys.pairingId,\n sharedSecret: keys.sharedSecret\n };\n }\n\n async #request(step: 'm1' | 'm3' | 'm5', data: Buffer): Promise<Buffer> {\n const frameType = step === 'm1'\n ? FrameType.PairVerifyStart\n : FrameType.PairVerifyNext;\n\n const [, response] = await this.#stream.exchange(frameType, {\n _pd: data,\n _auTy: 4\n });\n\n if (typeof response !== 'object' || response === null) {\n throw new Error('Invalid response from receiver.');\n }\n\n return response['_pd'];\n }\n}\n","import type { AttentionState } from './types';\n\nexport function convertAttentionState(state: number): AttentionState {\n switch (state) {\n case 0x01:\n return 'asleep';\n\n case 0x02:\n return 'screensaver';\n\n case 0x03:\n return 'awake';\n\n case 0x04:\n return 'idle';\n\n default:\n return 'unknown';\n }\n}\n","import { randomInt } from 'node:crypto';\nimport { type Context, ENCRYPTION, EncryptionAwareConnection, EncryptionState } from '@basmilius/apple-common';\nimport { OPack } from '@basmilius/apple-encoding';\nimport { Chacha20 } from '@basmilius/apple-encryption';\nimport { FrameType, OPackFrameTypes, PairingFrameTypes } from './frame';\n\nconst HEADER_SIZE = 4;\nconst PAIRING_QUEUE_IDENTIFIER = -1;\n\nexport default class Stream extends EncryptionAwareConnection<Record<string, [unknown]>> {\n get #encryptionState(): EncryptionState {\n return this[ENCRYPTION];\n }\n\n readonly #queue: Map<number, [Function, Function]> = new Map();\n #buffer: Buffer = Buffer.alloc(0);\n #xid: number;\n\n constructor(context: Context, address: string, port: number) {\n super(context, address, port);\n\n this.debug(true);\n\n this.#xid = randomInt(0, 2 ** 16);\n\n this.on('close', this.#onClose.bind(this));\n this.on('data', this.#onData.bind(this));\n this.on('error', this.#onError.bind(this));\n }\n\n async disconnect(): Promise<void> {\n this.#cleanup();\n await super.disconnect();\n }\n\n async exchange(type: number, obj: Record<string, unknown>): Promise<[number, unknown]> {\n const _x = this.#xid;\n\n return new Promise<[number, number]>((resolve, reject) => {\n if (PairingFrameTypes.includes(type)) {\n this.#queue.set(PAIRING_QUEUE_IDENTIFIER, [resolve, reject]);\n } else {\n this.#queue.set(_x, [resolve, reject]);\n }\n\n this.sendOPack(type, obj);\n });\n }\n\n send(type: number, payload: Buffer): void {\n const encrypt = this.isEncrypted && type !== FrameType.NoOp;\n let payloadLength = payload.byteLength;\n\n if (encrypt) {\n payloadLength += Chacha20.CHACHA20_AUTH_TAG_LENGTH;\n }\n\n const header = Buffer.allocUnsafe(4);\n header.writeUint8(type, 0);\n header.writeUintBE(payloadLength, 1, 3);\n\n let data: Buffer;\n\n if (encrypt) {\n const nonce = Buffer.alloc(12);\n nonce.writeBigUInt64LE(BigInt(this.#encryptionState.writeCount++), 0);\n\n const encrypted = Chacha20.encrypt(this.#encryptionState.writeKey, nonce, header, payload);\n data = Buffer.concat([header, encrypted.ciphertext, encrypted.authTag]);\n } else {\n data = Buffer.concat([header, payload]);\n }\n\n this.context.logger.raw('[companion-link]', 'Sending data frame', this.isEncrypted, type);\n\n this.write(data);\n }\n\n sendOPack(type: number, obj: Record<string, unknown>): void {\n const _x = this.#xid++;\n obj._x ??= OPack.sizedInteger(_x, 8);\n\n this.context.logger.raw('[companion-link]', 'Sending opack frame', type, this.isEncrypted, obj);\n\n this.send(type, Buffer.from(OPack.encode(obj)));\n }\n\n #cleanup(): void {\n this.#buffer = Buffer.alloc(0);\n\n const error = new Error('Stream cleanup');\n\n for (const [, reject] of this.#queue.values()) {\n reject(error);\n }\n\n this.#queue.clear();\n }\n\n #onClose(): void {\n const error = new Error('Connection closed while waiting for response');\n\n for (const [, reject] of this.#queue.values()) {\n reject(error);\n }\n\n this.#queue.clear();\n this.#cleanup();\n }\n\n async #onData(data: Buffer): Promise<void> {\n this.#buffer = Buffer.concat([this.#buffer, data]);\n\n try {\n while (this.#buffer.byteLength >= HEADER_SIZE) {\n const header = this.#buffer.subarray(0, HEADER_SIZE);\n const payloadLength = header.readUintBE(1, 3);\n const totalLength = HEADER_SIZE + payloadLength;\n\n if (this.#buffer.byteLength < totalLength) {\n this.context.logger.warn('[companion-link]', `Data packet is too short needed=${totalLength} available=${this.#buffer.byteLength} receivedLength=${data.byteLength}`);\n return;\n }\n\n this.context.logger.raw('[companion-link]', `Received frame length=${totalLength} availableLength=${this.#buffer.byteLength} receivedLength=${data.byteLength}`);\n\n let frame: Buffer = Buffer.from(this.#buffer.subarray(0, totalLength));\n this.#buffer = this.#buffer.subarray(totalLength);\n\n this.context.logger.raw('[companion-link]', `Handle frame, ${this.#buffer.byteLength} bytes left...`);\n\n if (this.isEncrypted) {\n frame = this.#decrypt(frame);\n }\n\n const payload = frame.subarray(HEADER_SIZE, totalLength);\n this.#handle(header, payload);\n }\n } catch (err) {\n this.context.logger.error('[companion-link]', '#onData()', err);\n this.emit('error', err);\n }\n }\n\n #onError(err: Error): void {\n for (const [, reject] of this.#queue.values()) {\n reject(err);\n }\n\n this.#queue.clear();\n }\n\n #decrypt(data: Buffer): Buffer {\n const header = data.subarray(0, 4);\n const payloadLength = header.readUintBE(1, 3);\n\n const payload = data.subarray(4, 4 + payloadLength);\n const authTag = payload.subarray(payload.byteLength - 16);\n const ciphertext = payload.subarray(0, payload.byteLength - 16);\n\n const nonce = Buffer.alloc(12);\n nonce.writeBigUint64LE(BigInt(this.#encryptionState.readCount++), 0);\n\n const decrypted = Chacha20.decrypt(this.#encryptionState.readKey, nonce, header, ciphertext, authTag);\n\n return Buffer.concat([header, decrypted, authTag]);\n }\n\n #handle(header: Buffer, payload: Buffer): void {\n const type = header.readInt8();\n\n if (!OPackFrameTypes.includes(type)) {\n this.context.logger.warn('[companion-link]', 'Packet not handled, no opack frame.');\n return;\n }\n\n payload = OPack.decode(payload);\n\n this.context.logger.raw('[companion-link]', 'Decoded OPACK', {header, payload});\n\n if ('_x' in payload) {\n const _x = Number(payload['_x']);\n\n if (this.#queue.has(_x)) {\n const [resolve] = this.#queue.get(_x);\n resolve([header, payload]);\n\n this.#queue.delete(_x);\n } else if ('_i' in payload) {\n this.emit(payload['_i'] as string, payload['_c']);\n } else {\n // probably an event\n const content = payload['_c'];\n const keys = Object.keys(content).map(k => k.slice(0, -3));\n\n for (const key of keys) {\n this.emit(key, content[key]);\n }\n }\n } else if (this.#queue.has(PAIRING_QUEUE_IDENTIFIER)) {\n const [resolve] = this.#queue.get(PAIRING_QUEUE_IDENTIFIER);\n resolve([header, payload]);\n\n this.#queue.delete(PAIRING_QUEUE_IDENTIFIER);\n } else {\n this.context.logger.warn('[companion-link]', 'No handler for message', [header, payload]);\n }\n }\n}\n","import { randomInt } from 'node:crypto';\nimport { Context, type DiscoveryResult, waitFor } from '@basmilius/apple-common';\nimport { OPack, Plist } from '@basmilius/apple-encoding';\nimport { HidCommand, type HidCommandKey, MediaControlCommand, type MediaControlCommandKey } from './const';\nimport { FrameType, MessageType } from './frame';\nimport { Pairing, Verify } from './pairing';\nimport type { AttentionState, ButtonPressType, LaunchableApp, UserAccount } from './types';\nimport { convertAttentionState } from './utils';\nimport Stream from './stream';\n\nexport default class Protocol {\n get context(): Context {\n return this.#context;\n }\n\n get discoveryResult(): DiscoveryResult {\n return this.#discoveryResult;\n }\n\n get pairing(): Pairing {\n return this.#pairing;\n }\n\n get stream(): Stream {\n return this.#stream;\n }\n\n get verify(): Verify {\n return this.#verify;\n }\n\n readonly #context: Context;\n readonly #discoveryResult: DiscoveryResult;\n readonly #pairing: Pairing;\n readonly #stream: Stream;\n readonly #verify: Verify;\n\n constructor(discoveryResult: DiscoveryResult) {\n this.#context = new Context(discoveryResult.id);\n this.#discoveryResult = discoveryResult;\n this.#stream = new Stream(this.#context, discoveryResult.address, discoveryResult.service.port);\n this.#pairing = new Pairing(this);\n this.#verify = new Verify(this);\n }\n\n async connect(): Promise<void> {\n await this.#stream.connect();\n }\n\n destroy(): void {\n this.#stream.destroy();\n }\n\n async disconnect(): Promise<void> {\n await this.#stream.disconnect();\n }\n\n async fetchMediaControlStatus(): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchMediaControlStatus',\n _t: MessageType.Request,\n _c: {}\n });\n }\n\n async fetchNowPlayingInfo(): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchCurrentNowPlayingInfoEvent',\n _t: MessageType.Request,\n _c: {}\n });\n }\n\n async fetchSupportedActions(): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchSupportedActionsEvent',\n _t: MessageType.Request,\n _c: {}\n });\n }\n\n async getAttentionState(): Promise<AttentionState> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchAttentionState',\n _t: MessageType.Request,\n _c: {}\n });\n\n const {_c} = objectOrFail<AttentionStateResponse>(payload);\n\n return convertAttentionState(_c.state);\n }\n\n async getLaunchableApps(): Promise<LaunchableApp[]> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchLaunchableApplicationsEvent',\n _t: MessageType.Request,\n _c: {}\n });\n\n const {_c} = objectOrFail<LaunchableAppsResponse>(payload);\n\n return Object.entries(_c).map(([bundleId, name]) => ({\n bundleId,\n name\n }));\n }\n\n async getSiriRemoteInfo(): Promise<any> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchSiriRemoteInfo',\n _t: MessageType.Request,\n _c: {}\n });\n\n return Plist.parse(Buffer.from(payload['_c']['SiriRemoteInfoKey']).buffer);\n }\n\n async getUserAccounts(): Promise<UserAccount[]> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchUserAccountsEvent',\n _t: MessageType.Request,\n _c: {}\n });\n\n const {_c} = objectOrFail<UserAccountsResponse>(payload);\n\n return Object.entries(_c).map(([accountId, name]) => ({\n accountId,\n name\n }));\n }\n\n async hidCommand(command: HidCommandKey, down = false): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_hidC',\n _t: MessageType.Request,\n _c: {\n _hBtS: down ? 1 : 2,\n _hidC: HidCommand[command]\n }\n });\n }\n\n async launchApp(bundleId: string): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_launchApp',\n _t: MessageType.Request,\n _c: {\n _bundleID: bundleId\n }\n });\n }\n\n async launchUrl(url: string): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_launchApp',\n _t: MessageType.Request,\n _c: {\n _urlS: url\n }\n });\n }\n\n async mediaControlCommand(command: MediaControlCommandKey, content?: object): Promise<object> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_mcc',\n _t: MessageType.Request,\n _c: {\n _mcc: MediaControlCommand[command],\n ...(content || {})\n }\n });\n\n return objectOrFail(payload);\n }\n\n async pressButton(command: HidCommandKey, type: ButtonPressType = 'SingleTap', holdDelayMs = 500): Promise<void> {\n switch (type) {\n case 'DoubleTap':\n await this.hidCommand(command, true);\n await this.hidCommand(command, false);\n\n await this.hidCommand(command, true);\n await this.hidCommand(command, false);\n break;\n\n case 'Hold':\n await this.hidCommand(command, true);\n await waitFor(holdDelayMs);\n await this.hidCommand(command, false);\n break;\n\n case 'SingleTap':\n await this.hidCommand(command, true);\n await this.hidCommand(command, false);\n break;\n }\n }\n\n async switchUserAccount(accountId: string): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'SwitchUserAccountEvent',\n _t: MessageType.Request,\n _c: {\n SwitchAccountID: accountId\n }\n });\n }\n\n async subscribe(event: string, fn: (data: unknown) => void): Promise<void> {\n this.#stream.on(event, fn);\n\n this.#stream.sendOPack(FrameType.OPackEncrypted, {\n _i: '_interest',\n _t: MessageType.Event,\n _c: {\n _regEvents: [event]\n }\n });\n }\n\n async unsubscribe(event: string, fn?: (data: unknown) => void): Promise<void> {\n if (!this.#stream.isConnected) {\n return;\n }\n\n if (fn) {\n this.#stream.off(event, fn);\n }\n\n this.#stream.sendOPack(FrameType.OPackEncrypted, {\n _i: '_interest',\n _t: MessageType.Event,\n _c: {\n _deregEvents: [event]\n }\n });\n }\n\n async sessionStart(): Promise<object> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_sessionStart',\n _t: MessageType.Request,\n _btHP: false,\n _c: {\n _srvT: 'com.apple.tvremoteservices',\n _sid: randomInt(0, 2 ** 32 - 1),\n _btHP: false\n }\n });\n\n return objectOrFail(payload);\n }\n\n async systemInfo(pairingId: Buffer): Promise<object> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_systemInfo',\n _t: MessageType.Request,\n _btHP: false,\n _c: {\n _bf: 0,\n _cf: 512,\n _clFl: 128,\n _i: 'b561af32aea6',\n _idsID: pairingId.toString(),\n _pubID: 'DA:6D:1E:D8:A0:4F',\n _sf: 1099511628032,\n _sv: '715.2',\n model: 'iPhone16,2',\n name: 'AP Companion Link',\n _lP: 50402,\n _dC: '1',\n _stA: [\n 'com.apple.sharingd.AirDrop',\n 'SymptomNetworkDiagnostics',\n 'com.apple.photosface.network-service',\n 'com.apple.ApplicationService.chrono',\n 'com.apple.DDUI-Picker',\n 'com.apple.biomesyncd.cascade.rapport',\n 'com.apple.SeymourSession',\n 'com.apple.workflow.remotewidgets',\n 'com.apple.ApplicationService.chrono',\n 'SCD.MessageCenter.remoteIntelligence',\n 'DeviceSharingDaemonApplicationService',\n 'com.apple.biomesyncd.rapport',\n 'com.apple.devicediscoveryui.rapportwake',\n 'com.apple.healthd.rapport',\n 'com.apple.dropin.setup',\n 'com.apple.coreduet.sync',\n 'com.apple.siri.wakeup',\n 'com.apple.wifivelocityd.rapportWake',\n 'com.apple.Seymour',\n 'CPSRemoteLLM',\n 'com.apple.networkrelay.on-demand-setup',\n 'com.apple.home.messaging',\n 'com.apple.accessibility.axremoted.rapportWake',\n 'com.apple.continuitycapture.sideband',\n 'com.apple.announce',\n 'com.apple.coreidv.coreidvd.handoff'\n ]\n }\n });\n\n return objectOrFail(payload);\n }\n\n async tiStart(): Promise<object> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_tiStart',\n _t: MessageType.Request,\n _btHP: false,\n _c: {}\n });\n\n return objectOrFail(payload);\n }\n\n async touchStart(): Promise<object> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_touchStart',\n _t: MessageType.Request,\n _btHP: false,\n _c: {\n _height: OPack.float(1000.0),\n _tFl: 0,\n _width: OPack.float(1000.0)\n }\n });\n\n return objectOrFail(payload);\n }\n\n async tvrcSessionStart(): Promise<object> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'TVRCSessionStart',\n _t: MessageType.Request,\n _btHP: false,\n _inUseProc: 'tvremoted',\n _c: {}\n });\n\n return objectOrFail(payload);\n }\n\n noOp(): void {\n this.#context.logger.debug('Sending no-op operation.');\n\n this.#stream.send(FrameType.NoOp, Buffer.allocUnsafe(0));\n }\n}\n\nfunction objectOrFail<T = object>(obj: unknown): T {\n if (obj !== null && typeof obj === 'object') {\n return obj as T;\n }\n\n throw new TypeError('Expected an object.');\n}\n\ntype AttentionStateResponse = {\n readonly _c: {\n readonly state: number;\n };\n};\n\ntype LaunchableAppsResponse = {\n readonly _c: Record<string, string>;\n};\n\ntype UserAccountsResponse = {\n readonly _c: Record<string, string>;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["#internal","#stream","#request","#encryptionState","#queue","#xid","#onClose","#onData","#onError","#cleanup","#buffer","#decrypt","#handle","#context","#discoveryResult","#pairing","#stream","#verify"],"sources":["../src/const.ts","../src/frame.ts","../src/pairing.ts","../src/utils.ts","../src/stream.ts","../src/protocol.ts"],"sourcesContent":["export const HidCommand = {\n Up: 1,\n Down: 2,\n Left: 3,\n Right: 4,\n Menu: 5,\n Select: 6,\n Home: 7,\n VolumeUp: 8,\n VolumeDown: 9,\n Siri: 10,\n Screensaver: 11,\n Sleep: 12,\n Wake: 13,\n PlayPause: 14,\n ChannelIncrement: 15,\n ChannelDecrement: 16,\n Guide: 17,\n PageUp: 18,\n PageDown: 19\n} as const;\n\nexport const MediaControlCommand = {\n Play: 1,\n Pause: 2,\n NextTrack: 3,\n PreviousTrack: 4,\n GetVolume: 5,\n SetVolume: 6,\n SkipBy: 7,\n FastForwardBegin: 8,\n FastForwardEnd: 9,\n RewindBegin: 10,\n RewindEnd: 11,\n GetCaptionSettings: 12,\n SetCaptionSettings: 13\n} as const;\n\nexport type HidCommandKey = keyof typeof HidCommand;\nexport type MediaControlCommandKey = keyof typeof MediaControlCommand;\n","export const FrameType = {\n Unknown: 0,\n NoOp: 1,\n\n PairSetupStart: 3,\n PairSetupNext: 4,\n\n PairVerifyStart: 5,\n PairVerifyNext: 6,\n\n OPackUnencrypted: 7,\n OPackEncrypted: 8,\n OPackPacked: 9,\n\n PairingRequest: 10,\n PairingResponse: 11,\n\n SessionStartRequest: 16,\n SessionStartResponse: 17,\n SessionData: 18,\n\n FamilyIdentityRequest: 32,\n FamilyIdentityResponse: 33,\n FamilyIdentityUpdate: 34\n} as const;\n\nexport const MessageType = {\n Event: 1,\n Request: 2,\n Response: 3\n} as const;\n\nexport const OPackFrameTypes: number[] = [\n FrameType.PairSetupStart,\n FrameType.PairSetupNext,\n FrameType.PairVerifyStart,\n FrameType.PairVerifyNext,\n\n FrameType.OPackUnencrypted,\n FrameType.OPackEncrypted,\n FrameType.OPackPacked\n];\n\nexport const PairingFrameTypes: number[] = [\n FrameType.PairSetupStart,\n FrameType.PairSetupNext,\n FrameType.PairVerifyStart,\n FrameType.PairVerifyNext\n];\n","import { type AccessoryCredentials, type AccessoryKeys, AccessoryPair, AccessoryVerify } from '@basmilius/apple-common';\nimport { hkdf } from '@basmilius/apple-encryption';\nimport { FrameType } from './frame';\nimport type Protocol from './protocol';\nimport type Stream from './stream';\n\nexport class Pairing {\n get internal(): AccessoryPair {\n return this.#internal;\n }\n\n get stream(): Stream {\n return this.#stream;\n }\n\n readonly #internal: AccessoryPair;\n readonly #stream: Stream;\n\n constructor(protocol: Protocol) {\n this.#internal = new AccessoryPair(protocol.context, this.#request.bind(this));\n this.#stream = protocol.stream;\n }\n\n async start(): Promise<void> {\n await this.#internal.start();\n }\n\n async pin(askPin: () => Promise<string>): Promise<AccessoryCredentials> {\n return this.#internal.pin(askPin);\n }\n\n async transient(): Promise<AccessoryKeys> {\n return this.#internal.transient();\n }\n\n async #request(step: 'm1' | 'm3' | 'm5', data: Buffer): Promise<Buffer> {\n const frameType = step === 'm1'\n ? FrameType.PairSetupStart\n : FrameType.PairSetupNext;\n\n const [, response] = await this.#stream.exchange(frameType, {\n _pd: data,\n _pwTy: 1\n });\n\n if (typeof response !== 'object' || response === null) {\n throw new Error('Invalid response from receiver.');\n }\n\n return response['_pd'];\n }\n}\n\nexport class Verify {\n get internal(): AccessoryVerify {\n return this.#internal;\n }\n\n get stream(): Stream {\n return this.#stream;\n }\n\n readonly #internal: AccessoryVerify;\n readonly #stream: Stream;\n\n constructor(protocol: Protocol) {\n this.#internal = new AccessoryVerify(protocol.context, this.#request.bind(this));\n this.#stream = protocol.stream;\n }\n\n async start(credentials: AccessoryCredentials): Promise<AccessoryKeys> {\n const keys = await this.#internal.start(credentials);\n\n const accessoryToControllerKey = hkdf({\n hash: 'sha512',\n key: keys.sharedSecret,\n length: 32,\n salt: Buffer.alloc(0),\n info: Buffer.from('ServerEncrypt-main')\n });\n\n const controllerToAccessoryKey = hkdf({\n hash: 'sha512',\n key: keys.sharedSecret,\n length: 32,\n salt: Buffer.alloc(0),\n info: Buffer.from('ClientEncrypt-main')\n });\n\n return {\n accessoryToControllerKey,\n controllerToAccessoryKey,\n pairingId: keys.pairingId,\n sharedSecret: keys.sharedSecret\n };\n }\n\n async #request(step: 'm1' | 'm3' | 'm5', data: Buffer): Promise<Buffer> {\n const frameType = step === 'm1'\n ? FrameType.PairVerifyStart\n : FrameType.PairVerifyNext;\n\n const [, response] = await this.#stream.exchange(frameType, {\n _pd: data,\n _auTy: 4\n });\n\n if (typeof response !== 'object' || response === null) {\n throw new Error('Invalid response from receiver.');\n }\n\n return response['_pd'];\n }\n}\n","import type { AttentionState } from './types';\n\nexport function convertAttentionState(state: number): AttentionState {\n switch (state) {\n case 0x01:\n return 'asleep';\n\n case 0x02:\n return 'screensaver';\n\n case 0x03:\n return 'awake';\n\n case 0x04:\n return 'idle';\n\n default:\n return 'unknown';\n }\n}\n","import { randomInt } from 'node:crypto';\nimport { type Context, ENCRYPTION, EncryptionAwareConnection, EncryptionState } from '@basmilius/apple-common';\nimport { OPack } from '@basmilius/apple-encoding';\nimport { Chacha20 } from '@basmilius/apple-encryption';\nimport { FrameType, OPackFrameTypes, PairingFrameTypes } from './frame';\n\nconst HEADER_SIZE = 4;\nconst PAIRING_QUEUE_IDENTIFIER = -1;\n\nexport default class Stream extends EncryptionAwareConnection<Record<string, [unknown]>> {\n get #encryptionState(): EncryptionState {\n return this[ENCRYPTION];\n }\n\n readonly #queue: Map<number, [Function, Function]> = new Map();\n #buffer: Buffer = Buffer.alloc(0);\n #xid: number;\n\n constructor(context: Context, address: string, port: number) {\n super(context, address, port);\n\n this.debug(true);\n\n this.#xid = randomInt(0, 2 ** 16);\n\n this.on('close', this.#onClose.bind(this));\n this.on('data', this.#onData.bind(this));\n this.on('error', this.#onError.bind(this));\n }\n\n async disconnect(): Promise<void> {\n this.#cleanup();\n await super.disconnect();\n }\n\n async exchange(type: number, obj: Record<string, unknown>): Promise<[number, unknown]> {\n const _x = this.#xid;\n\n return new Promise<[number, number]>((resolve, reject) => {\n if (PairingFrameTypes.includes(type)) {\n this.#queue.set(PAIRING_QUEUE_IDENTIFIER, [resolve, reject]);\n } else {\n this.#queue.set(_x, [resolve, reject]);\n }\n\n this.sendOPack(type, obj);\n });\n }\n\n send(type: number, payload: Buffer): void {\n const encrypt = this.isEncrypted && type !== FrameType.NoOp;\n let payloadLength = payload.byteLength;\n\n if (encrypt) {\n payloadLength += Chacha20.CHACHA20_AUTH_TAG_LENGTH;\n }\n\n const header = Buffer.allocUnsafe(4);\n header.writeUint8(type, 0);\n header.writeUintBE(payloadLength, 1, 3);\n\n let data: Buffer;\n\n if (encrypt) {\n const nonce = Buffer.alloc(12);\n nonce.writeBigUInt64LE(BigInt(this.#encryptionState.writeCount++), 0);\n\n const encrypted = Chacha20.encrypt(this.#encryptionState.writeKey, nonce, header, payload);\n data = Buffer.concat([header, encrypted.ciphertext, encrypted.authTag]);\n } else {\n data = Buffer.concat([header, payload]);\n }\n\n this.context.logger.raw('[companion-link]', 'Sending data frame', this.isEncrypted, type);\n\n this.write(data);\n }\n\n sendOPack(type: number, obj: Record<string, unknown>): void {\n const _x = this.#xid++;\n obj._x ??= OPack.sizedInteger(_x, 8);\n\n this.context.logger.raw('[companion-link]', 'Sending opack frame', type, this.isEncrypted, obj);\n\n this.send(type, Buffer.from(OPack.encode(obj)));\n }\n\n #cleanup(): void {\n this.#buffer = Buffer.alloc(0);\n\n const error = new Error('Stream cleanup');\n\n for (const [, reject] of this.#queue.values()) {\n reject(error);\n }\n\n this.#queue.clear();\n }\n\n #onClose(): void {\n const error = new Error('Connection closed while waiting for response');\n\n for (const [, reject] of this.#queue.values()) {\n reject(error);\n }\n\n this.#queue.clear();\n this.#cleanup();\n }\n\n async #onData(data: Buffer): Promise<void> {\n this.#buffer = Buffer.concat([this.#buffer, data]);\n\n try {\n while (this.#buffer.byteLength >= HEADER_SIZE) {\n const header = this.#buffer.subarray(0, HEADER_SIZE);\n const payloadLength = header.readUintBE(1, 3);\n const totalLength = HEADER_SIZE + payloadLength;\n\n if (this.#buffer.byteLength < totalLength) {\n this.context.logger.warn('[companion-link]', `Data packet is too short needed=${totalLength} available=${this.#buffer.byteLength} receivedLength=${data.byteLength}`);\n return;\n }\n\n this.context.logger.raw('[companion-link]', `Received frame length=${totalLength} availableLength=${this.#buffer.byteLength} receivedLength=${data.byteLength}`);\n\n let frame: Buffer = Buffer.from(this.#buffer.subarray(0, totalLength));\n this.#buffer = this.#buffer.subarray(totalLength);\n\n this.context.logger.raw('[companion-link]', `Handle frame, ${this.#buffer.byteLength} bytes left...`);\n\n if (this.isEncrypted) {\n frame = this.#decrypt(frame);\n }\n\n const payload = frame.subarray(HEADER_SIZE, totalLength);\n this.#handle(header, payload);\n }\n } catch (err) {\n this.context.logger.error('[companion-link]', '#onData()', err);\n this.emit('error', err);\n }\n }\n\n #onError(err: Error): void {\n for (const [, reject] of this.#queue.values()) {\n reject(err);\n }\n\n this.#queue.clear();\n }\n\n #decrypt(data: Buffer): Buffer {\n const header = data.subarray(0, 4);\n const payloadLength = header.readUintBE(1, 3);\n\n const payload = data.subarray(4, 4 + payloadLength);\n const authTag = payload.subarray(payload.byteLength - 16);\n const ciphertext = payload.subarray(0, payload.byteLength - 16);\n\n const nonce = Buffer.alloc(12);\n nonce.writeBigUint64LE(BigInt(this.#encryptionState.readCount++), 0);\n\n const decrypted = Chacha20.decrypt(this.#encryptionState.readKey, nonce, header, ciphertext, authTag);\n\n return Buffer.concat([header, decrypted, authTag]);\n }\n\n #handle(header: Buffer, payload: Buffer): void {\n const type = header.readInt8();\n\n if (!OPackFrameTypes.includes(type)) {\n this.context.logger.warn('[companion-link]', 'Packet not handled, no opack frame.');\n return;\n }\n\n payload = OPack.decode(payload);\n\n this.context.logger.raw('[companion-link]', 'Decoded OPACK', {header, payload});\n\n if ('_x' in payload) {\n const _x = Number(payload['_x']);\n\n if (this.#queue.has(_x)) {\n const [resolve] = this.#queue.get(_x);\n resolve([header, payload]);\n\n this.#queue.delete(_x);\n } else if ('_i' in payload) {\n this.emit(payload['_i'] as string, payload['_c']);\n } else {\n // probably an event\n const content = payload['_c'];\n const keys = Object.keys(content).map(k => k.slice(0, -3));\n\n for (const key of keys) {\n this.emit(key, content[key]);\n }\n }\n } else if (this.#queue.has(PAIRING_QUEUE_IDENTIFIER)) {\n const [resolve] = this.#queue.get(PAIRING_QUEUE_IDENTIFIER);\n resolve([header, payload]);\n\n this.#queue.delete(PAIRING_QUEUE_IDENTIFIER);\n } else {\n this.context.logger.warn('[companion-link]', 'No handler for message', [header, payload]);\n }\n }\n}\n","import { randomInt } from 'node:crypto';\nimport { Context, type DiscoveryResult, waitFor } from '@basmilius/apple-common';\nimport { OPack, Plist } from '@basmilius/apple-encoding';\nimport { HidCommand, type HidCommandKey, MediaControlCommand, type MediaControlCommandKey } from './const';\nimport { FrameType, MessageType } from './frame';\nimport { Pairing, Verify } from './pairing';\nimport type { AttentionState, ButtonPressType, LaunchableApp, UserAccount } from './types';\nimport { convertAttentionState } from './utils';\nimport Stream from './stream';\n\nexport default class Protocol {\n get context(): Context {\n return this.#context;\n }\n\n get discoveryResult(): DiscoveryResult {\n return this.#discoveryResult;\n }\n\n get pairing(): Pairing {\n return this.#pairing;\n }\n\n get stream(): Stream {\n return this.#stream;\n }\n\n get verify(): Verify {\n return this.#verify;\n }\n\n readonly #context: Context;\n readonly #discoveryResult: DiscoveryResult;\n readonly #pairing: Pairing;\n readonly #stream: Stream;\n readonly #verify: Verify;\n\n constructor(discoveryResult: DiscoveryResult) {\n this.#context = new Context(discoveryResult.id);\n this.#discoveryResult = discoveryResult;\n this.#stream = new Stream(this.#context, discoveryResult.address, discoveryResult.service.port);\n this.#pairing = new Pairing(this);\n this.#verify = new Verify(this);\n }\n\n async connect(): Promise<void> {\n await this.#stream.connect();\n }\n\n destroy(): void {\n this.#stream.destroy();\n }\n\n async disconnect(): Promise<void> {\n await this.#stream.disconnect();\n }\n\n async fetchMediaControlStatus(): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchMediaControlStatus',\n _t: MessageType.Request,\n _c: {}\n });\n }\n\n async fetchNowPlayingInfo(): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchCurrentNowPlayingInfoEvent',\n _t: MessageType.Request,\n _c: {}\n });\n }\n\n async fetchSupportedActions(): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchSupportedActionsEvent',\n _t: MessageType.Request,\n _c: {}\n });\n }\n\n async getAttentionState(): Promise<AttentionState> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchAttentionState',\n _t: MessageType.Request,\n _c: {}\n });\n\n const {_c} = objectOrFail<AttentionStateResponse>(payload);\n\n return convertAttentionState(_c.state);\n }\n\n async getLaunchableApps(): Promise<LaunchableApp[]> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchLaunchableApplicationsEvent',\n _t: MessageType.Request,\n _c: {}\n });\n\n const {_c} = objectOrFail<LaunchableAppsResponse>(payload);\n\n return Object.entries(_c).map(([bundleId, name]) => ({\n bundleId,\n name\n }));\n }\n\n async getSiriRemoteInfo(): Promise<any> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchSiriRemoteInfo',\n _t: MessageType.Request,\n _c: {}\n });\n\n return Plist.parse(Buffer.from(payload['_c']['SiriRemoteInfoKey']).buffer);\n }\n\n async getUserAccounts(): Promise<UserAccount[]> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'FetchUserAccountsEvent',\n _t: MessageType.Request,\n _c: {}\n });\n\n const {_c} = objectOrFail<UserAccountsResponse>(payload);\n\n return Object.entries(_c).map(([accountId, name]) => ({\n accountId,\n name\n }));\n }\n\n async hidCommand(command: HidCommandKey, down = false): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_hidC',\n _t: MessageType.Request,\n _c: {\n _hBtS: down ? 1 : 2,\n _hidC: HidCommand[command]\n }\n });\n }\n\n async launchApp(bundleId: string): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_launchApp',\n _t: MessageType.Request,\n _c: {\n _bundleID: bundleId\n }\n });\n }\n\n async launchUrl(url: string): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_launchApp',\n _t: MessageType.Request,\n _c: {\n _urlS: url\n }\n });\n }\n\n async mediaControlCommand(command: MediaControlCommandKey, content?: object): Promise<object> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_mcc',\n _t: MessageType.Request,\n _c: {\n _mcc: MediaControlCommand[command],\n ...(content || {})\n }\n });\n\n return objectOrFail(payload);\n }\n\n async pressButton(command: HidCommandKey, type: ButtonPressType = 'SingleTap', holdDelayMs = 500): Promise<void> {\n switch (type) {\n case 'DoubleTap':\n await this.hidCommand(command, true);\n await this.hidCommand(command, false);\n\n await this.hidCommand(command, true);\n await this.hidCommand(command, false);\n break;\n\n case 'Hold':\n await this.hidCommand(command, true);\n await waitFor(holdDelayMs);\n await this.hidCommand(command, false);\n break;\n\n case 'SingleTap':\n await this.hidCommand(command, true);\n await this.hidCommand(command, false);\n break;\n }\n }\n\n async switchUserAccount(accountId: string): Promise<void> {\n await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'SwitchUserAccountEvent',\n _t: MessageType.Request,\n _c: {\n SwitchAccountID: accountId\n }\n });\n }\n\n async subscribe(event: string, fn: (data: unknown) => void): Promise<void> {\n this.#stream.on(event, fn);\n\n this.#stream.sendOPack(FrameType.OPackEncrypted, {\n _i: '_interest',\n _t: MessageType.Event,\n _c: {\n _regEvents: [event]\n }\n });\n }\n\n async unsubscribe(event: string, fn?: (data: unknown) => void): Promise<void> {\n if (!this.#stream.isConnected) {\n return;\n }\n\n if (fn) {\n this.#stream.off(event, fn);\n }\n\n this.#stream.sendOPack(FrameType.OPackEncrypted, {\n _i: '_interest',\n _t: MessageType.Event,\n _c: {\n _deregEvents: [event]\n }\n });\n }\n\n async sessionStart(): Promise<object> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_sessionStart',\n _t: MessageType.Request,\n _btHP: false,\n _c: {\n _srvT: 'com.apple.tvremoteservices',\n _sid: randomInt(0, 2 ** 32 - 1),\n _btHP: false\n }\n });\n\n return objectOrFail(payload);\n }\n\n async systemInfo(pairingId: Buffer): Promise<object> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_systemInfo',\n _t: MessageType.Request,\n _btHP: false,\n _c: {\n _bf: 0,\n _cf: 512,\n _clFl: 128,\n _i: 'b561af32aea6',\n _idsID: pairingId.toString(),\n _pubID: 'DA:6D:1E:D8:A0:4F',\n _sf: 1099511628032,\n _sv: '715.2',\n model: 'iPhone16,2',\n name: 'AP Companion Link',\n _lP: 50402,\n _dC: '1',\n _stA: [\n 'com.apple.sharingd.AirDrop',\n 'SymptomNetworkDiagnostics',\n 'com.apple.photosface.network-service',\n 'com.apple.ApplicationService.chrono',\n 'com.apple.DDUI-Picker',\n 'com.apple.biomesyncd.cascade.rapport',\n 'com.apple.SeymourSession',\n 'com.apple.workflow.remotewidgets',\n 'com.apple.ApplicationService.chrono',\n 'SCD.MessageCenter.remoteIntelligence',\n 'DeviceSharingDaemonApplicationService',\n 'com.apple.biomesyncd.rapport',\n 'com.apple.devicediscoveryui.rapportwake',\n 'com.apple.healthd.rapport',\n 'com.apple.dropin.setup',\n 'com.apple.coreduet.sync',\n 'com.apple.siri.wakeup',\n 'com.apple.wifivelocityd.rapportWake',\n 'com.apple.Seymour',\n 'CPSRemoteLLM',\n 'com.apple.networkrelay.on-demand-setup',\n 'com.apple.home.messaging',\n 'com.apple.accessibility.axremoted.rapportWake',\n 'com.apple.continuitycapture.sideband',\n 'com.apple.announce',\n 'com.apple.coreidv.coreidvd.handoff'\n ]\n }\n });\n\n return objectOrFail(payload);\n }\n\n async tiStart(): Promise<object> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_tiStart',\n _t: MessageType.Request,\n _btHP: false,\n _c: {}\n });\n\n return objectOrFail(payload);\n }\n\n async touchStart(): Promise<object> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: '_touchStart',\n _t: MessageType.Request,\n _btHP: false,\n _c: {\n _height: OPack.float(1000.0),\n _tFl: 0,\n _width: OPack.float(1000.0)\n }\n });\n\n return objectOrFail(payload);\n }\n\n async tvrcSessionStart(): Promise<object> {\n const [, payload] = await this.#stream.exchange(FrameType.OPackEncrypted, {\n _i: 'TVRCSessionStart',\n _t: MessageType.Request,\n _btHP: false,\n _inUseProc: 'tvremoted',\n _c: {}\n });\n\n return objectOrFail(payload);\n }\n\n noOp(): void {\n this.#context.logger.debug('Sending no-op operation.');\n\n this.#stream.send(FrameType.NoOp, Buffer.allocUnsafe(0));\n }\n}\n\nfunction objectOrFail<T = object>(obj: unknown): T {\n if (obj !== null && typeof obj === 'object') {\n return obj as T;\n }\n\n throw new TypeError('Expected an object.');\n}\n\ntype AttentionStateResponse = {\n readonly _c: {\n readonly state: number;\n };\n};\n\ntype LaunchableAppsResponse = {\n readonly _c: Record<string, string>;\n};\n\ntype UserAccountsResponse = {\n readonly _c: Record<string, string>;\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basmilius/apple-companion-link",
|
|
3
3
|
"description": "Implementation of Apple's Companion Link in Node.js.",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": {
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@basmilius/apple-common": "0.8.
|
|
45
|
-
"@basmilius/apple-encoding": "0.8.
|
|
46
|
-
"@basmilius/apple-encryption": "0.8.
|
|
44
|
+
"@basmilius/apple-common": "0.8.2",
|
|
45
|
+
"@basmilius/apple-encoding": "0.8.2",
|
|
46
|
+
"@basmilius/apple-encryption": "0.8.2"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/bun": "^1.3.9",
|