appium-ios-remotexpc 0.0.3 → 0.0.5

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.
Files changed (213) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/src/base-plist-service.d.ts +51 -0
  3. package/build/src/base-plist-service.d.ts.map +1 -0
  4. package/build/src/base-plist-service.js +61 -0
  5. package/build/src/base-socket-service.d.ts +15 -0
  6. package/build/src/base-socket-service.d.ts.map +1 -0
  7. package/build/src/base-socket-service.js +46 -0
  8. package/build/src/index.d.ts +9 -0
  9. package/build/src/index.d.ts.map +1 -0
  10. package/build/src/index.js +7 -0
  11. package/build/src/lib/apple-tv/constants.d.ts +77 -0
  12. package/build/src/lib/apple-tv/constants.d.ts.map +1 -0
  13. package/build/src/lib/apple-tv/constants.js +106 -0
  14. package/build/src/lib/apple-tv/encryption/chacha20-poly1305.d.ts +22 -0
  15. package/build/src/lib/apple-tv/encryption/chacha20-poly1305.d.ts.map +1 -0
  16. package/build/src/lib/apple-tv/encryption/chacha20-poly1305.js +97 -0
  17. package/build/src/lib/apple-tv/encryption/ed25519.d.ts +16 -0
  18. package/build/src/lib/apple-tv/encryption/ed25519.d.ts.map +1 -0
  19. package/build/src/lib/apple-tv/encryption/ed25519.js +93 -0
  20. package/build/src/lib/apple-tv/encryption/hkdf.d.ts +18 -0
  21. package/build/src/lib/apple-tv/encryption/hkdf.d.ts.map +1 -0
  22. package/build/src/lib/apple-tv/encryption/hkdf.js +73 -0
  23. package/build/src/lib/apple-tv/encryption/index.d.ts +5 -0
  24. package/build/src/lib/apple-tv/encryption/index.d.ts.map +1 -0
  25. package/build/src/lib/apple-tv/encryption/index.js +4 -0
  26. package/build/src/lib/apple-tv/encryption/opack2.d.ts +57 -0
  27. package/build/src/lib/apple-tv/encryption/opack2.d.ts.map +1 -0
  28. package/build/src/lib/apple-tv/encryption/opack2.js +203 -0
  29. package/build/src/lib/apple-tv/errors.d.ts +17 -0
  30. package/build/src/lib/apple-tv/errors.d.ts.map +1 -0
  31. package/build/src/lib/apple-tv/errors.js +30 -0
  32. package/build/src/lib/apple-tv/tlv/decoder.d.ts +19 -0
  33. package/build/src/lib/apple-tv/tlv/decoder.d.ts.map +1 -0
  34. package/build/src/lib/apple-tv/tlv/decoder.js +49 -0
  35. package/build/src/lib/apple-tv/tlv/encoder.d.ts +10 -0
  36. package/build/src/lib/apple-tv/tlv/encoder.d.ts.map +1 -0
  37. package/build/src/lib/apple-tv/tlv/encoder.js +20 -0
  38. package/build/src/lib/apple-tv/tlv/index.d.ts +4 -0
  39. package/build/src/lib/apple-tv/tlv/index.d.ts.map +1 -0
  40. package/build/src/lib/apple-tv/tlv/index.js +3 -0
  41. package/build/src/lib/apple-tv/tlv/pairing-tlv.d.ts +14 -0
  42. package/build/src/lib/apple-tv/tlv/pairing-tlv.d.ts.map +1 -0
  43. package/build/src/lib/apple-tv/tlv/pairing-tlv.js +27 -0
  44. package/build/src/lib/apple-tv/types.d.ts +36 -0
  45. package/build/src/lib/apple-tv/types.d.ts.map +1 -0
  46. package/build/src/lib/apple-tv/types.js +1 -0
  47. package/build/src/lib/apple-tv/utils/buffer-utils.d.ts +40 -0
  48. package/build/src/lib/apple-tv/utils/buffer-utils.d.ts.map +1 -0
  49. package/build/src/lib/apple-tv/utils/buffer-utils.js +76 -0
  50. package/build/src/lib/apple-tv/utils/index.d.ts +3 -0
  51. package/build/src/lib/apple-tv/utils/index.d.ts.map +1 -0
  52. package/build/src/lib/apple-tv/utils/index.js +2 -0
  53. package/build/src/lib/apple-tv/utils/uuid-generator.d.ts +9 -0
  54. package/build/src/lib/apple-tv/utils/uuid-generator.d.ts.map +1 -0
  55. package/build/src/lib/apple-tv/utils/uuid-generator.js +36 -0
  56. package/build/src/lib/lockdown/index.d.ts +87 -0
  57. package/build/src/lib/lockdown/index.d.ts.map +1 -0
  58. package/build/src/lib/lockdown/index.js +324 -0
  59. package/build/src/lib/pair-record/index.d.ts +3 -0
  60. package/build/src/lib/pair-record/index.d.ts.map +1 -0
  61. package/build/src/lib/pair-record/index.js +2 -0
  62. package/build/src/lib/pair-record/pair-record.d.ts +48 -0
  63. package/build/src/lib/pair-record/pair-record.d.ts.map +1 -0
  64. package/build/src/lib/pair-record/pair-record.js +85 -0
  65. package/build/src/lib/plist/binary-plist-creator.d.ts +14 -0
  66. package/build/src/lib/plist/binary-plist-creator.d.ts.map +1 -0
  67. package/build/src/lib/plist/binary-plist-creator.js +475 -0
  68. package/build/src/lib/plist/binary-plist-parser.d.ts +14 -0
  69. package/build/src/lib/plist/binary-plist-parser.d.ts.map +1 -0
  70. package/build/src/lib/plist/binary-plist-parser.js +449 -0
  71. package/build/src/lib/plist/constants.d.ts +36 -0
  72. package/build/src/lib/plist/constants.d.ts.map +1 -0
  73. package/build/src/lib/plist/constants.js +43 -0
  74. package/build/src/lib/plist/index.d.ts +14 -0
  75. package/build/src/lib/plist/index.d.ts.map +1 -0
  76. package/build/src/lib/plist/index.js +16 -0
  77. package/build/src/lib/plist/length-based-splitter.d.ts +43 -0
  78. package/build/src/lib/plist/length-based-splitter.d.ts.map +1 -0
  79. package/build/src/lib/plist/length-based-splitter.js +228 -0
  80. package/build/src/lib/plist/plist-creator.d.ts +8 -0
  81. package/build/src/lib/plist/plist-creator.d.ts.map +1 -0
  82. package/build/src/lib/plist/plist-creator.js +33 -0
  83. package/build/src/lib/plist/plist-decoder.d.ts +25 -0
  84. package/build/src/lib/plist/plist-decoder.d.ts.map +1 -0
  85. package/build/src/lib/plist/plist-decoder.js +103 -0
  86. package/build/src/lib/plist/plist-encoder.d.ts +10 -0
  87. package/build/src/lib/plist/plist-encoder.d.ts.map +1 -0
  88. package/build/src/lib/plist/plist-encoder.js +27 -0
  89. package/build/src/lib/plist/plist-parser.d.ts +9 -0
  90. package/build/src/lib/plist/plist-parser.d.ts.map +1 -0
  91. package/build/src/lib/plist/plist-parser.js +109 -0
  92. package/build/src/lib/plist/plist-service.d.ts +86 -0
  93. package/build/src/lib/plist/plist-service.d.ts.map +1 -0
  94. package/build/src/lib/plist/plist-service.js +180 -0
  95. package/build/src/lib/plist/unified-plist-creator.d.ts +9 -0
  96. package/build/src/lib/plist/unified-plist-creator.d.ts.map +1 -0
  97. package/build/src/lib/plist/unified-plist-creator.js +14 -0
  98. package/build/src/lib/plist/unified-plist-parser.d.ts +8 -0
  99. package/build/src/lib/plist/unified-plist-parser.d.ts.map +1 -0
  100. package/build/src/lib/plist/unified-plist-parser.js +23 -0
  101. package/build/src/lib/plist/utils.d.ts +97 -0
  102. package/build/src/lib/plist/utils.d.ts.map +1 -0
  103. package/build/src/lib/plist/utils.js +287 -0
  104. package/build/src/lib/remote-xpc/constants.d.ts +20 -0
  105. package/build/src/lib/remote-xpc/constants.d.ts.map +1 -0
  106. package/build/src/lib/remote-xpc/constants.js +21 -0
  107. package/build/src/lib/remote-xpc/handshake-frames.d.ts +74 -0
  108. package/build/src/lib/remote-xpc/handshake-frames.d.ts.map +1 -0
  109. package/build/src/lib/remote-xpc/handshake-frames.js +285 -0
  110. package/build/src/lib/remote-xpc/handshake.d.ts +14 -0
  111. package/build/src/lib/remote-xpc/handshake.d.ts.map +1 -0
  112. package/build/src/lib/remote-xpc/handshake.js +95 -0
  113. package/build/src/lib/remote-xpc/remote-xpc-connection.d.ts +55 -0
  114. package/build/src/lib/remote-xpc/remote-xpc-connection.d.ts.map +1 -0
  115. package/build/src/lib/remote-xpc/remote-xpc-connection.js +365 -0
  116. package/build/src/lib/remote-xpc/xpc-protocol.d.ts +22 -0
  117. package/build/src/lib/remote-xpc/xpc-protocol.d.ts.map +1 -0
  118. package/build/src/lib/remote-xpc/xpc-protocol.js +368 -0
  119. package/build/src/lib/tunnel/index.d.ts +69 -0
  120. package/build/src/lib/tunnel/index.d.ts.map +1 -0
  121. package/build/src/lib/tunnel/index.js +205 -0
  122. package/build/src/lib/tunnel/packet-stream-client.d.ts +46 -0
  123. package/build/src/lib/tunnel/packet-stream-client.d.ts.map +1 -0
  124. package/build/src/lib/tunnel/packet-stream-client.js +152 -0
  125. package/build/src/lib/tunnel/packet-stream-server.d.ts +37 -0
  126. package/build/src/lib/tunnel/packet-stream-server.d.ts.map +1 -0
  127. package/build/src/lib/tunnel/packet-stream-server.js +109 -0
  128. package/build/src/lib/tunnel/tunnel-api-client.d.ts +85 -0
  129. package/build/src/lib/tunnel/tunnel-api-client.d.ts.map +1 -0
  130. package/build/src/lib/tunnel/tunnel-api-client.js +207 -0
  131. package/build/src/lib/tunnel/tunnel-registry-server.d.ts +68 -0
  132. package/build/src/lib/tunnel/tunnel-registry-server.d.ts.map +1 -0
  133. package/build/src/lib/tunnel/tunnel-registry-server.js +351 -0
  134. package/build/src/lib/types.d.ts +238 -0
  135. package/build/src/lib/types.d.ts.map +1 -0
  136. package/build/src/lib/types.js +4 -0
  137. package/build/src/lib/usbmux/index.d.ts +177 -0
  138. package/build/src/lib/usbmux/index.d.ts.map +1 -0
  139. package/build/src/lib/usbmux/index.js +490 -0
  140. package/build/src/lib/usbmux/usbmux-decoder.d.ts +19 -0
  141. package/build/src/lib/usbmux/usbmux-decoder.d.ts.map +1 -0
  142. package/build/src/lib/usbmux/usbmux-decoder.js +38 -0
  143. package/build/src/lib/usbmux/usbmux-encoder.d.ts +12 -0
  144. package/build/src/lib/usbmux/usbmux-encoder.d.ts.map +1 -0
  145. package/build/src/lib/usbmux/usbmux-encoder.js +32 -0
  146. package/build/src/service-connection.d.ts +34 -0
  147. package/build/src/service-connection.d.ts.map +1 -0
  148. package/build/src/service-connection.js +51 -0
  149. package/build/src/services/index.d.ts +6 -0
  150. package/build/src/services/index.d.ts.map +1 -0
  151. package/build/src/services/index.js +5 -0
  152. package/build/src/services/ios/base-service.d.ts +35 -0
  153. package/build/src/services/ios/base-service.d.ts.map +1 -0
  154. package/build/src/services/ios/base-service.js +55 -0
  155. package/build/src/services/ios/diagnostic-service/index.d.ts +46 -0
  156. package/build/src/services/ios/diagnostic-service/index.d.ts.map +1 -0
  157. package/build/src/services/ios/diagnostic-service/index.js +169 -0
  158. package/build/src/services/ios/diagnostic-service/keys.d.ts +5 -0
  159. package/build/src/services/ios/diagnostic-service/keys.d.ts.map +1 -0
  160. package/build/src/services/ios/diagnostic-service/keys.js +770 -0
  161. package/build/src/services/ios/syslog-service/index.d.ts +91 -0
  162. package/build/src/services/ios/syslog-service/index.d.ts.map +1 -0
  163. package/build/src/services/ios/syslog-service/index.js +323 -0
  164. package/build/src/services/ios/tunnel-service/index.d.ts +17 -0
  165. package/build/src/services/ios/tunnel-service/index.d.ts.map +1 -0
  166. package/build/src/services/ios/tunnel-service/index.js +57 -0
  167. package/build/src/services.d.ts +14 -0
  168. package/build/src/services.d.ts.map +1 -0
  169. package/build/src/services.js +48 -0
  170. package/package.json +12 -3
  171. package/src/lib/apple-tv/constants.ts +42 -0
  172. package/src/lib/apple-tv/encryption/chacha20-poly1305.ts +147 -0
  173. package/src/lib/apple-tv/encryption/ed25519.ts +126 -0
  174. package/src/lib/apple-tv/encryption/hkdf.ts +95 -0
  175. package/src/lib/apple-tv/encryption/index.ts +11 -0
  176. package/src/lib/apple-tv/encryption/opack2.ts +257 -0
  177. package/.github/dependabot.yml +0 -38
  178. package/.github/workflows/format-check.yml +0 -43
  179. package/.github/workflows/lint-and-build.yml +0 -40
  180. package/.github/workflows/pr-title.yml +0 -16
  181. package/.github/workflows/publish.js.yml +0 -43
  182. package/.github/workflows/test-validation.yml +0 -40
  183. package/.mocharc.json +0 -8
  184. package/.prettierignore +0 -3
  185. package/.prettierrc +0 -17
  186. package/.releaserc +0 -48
  187. package/assets/images/ios-arch.png +0 -0
  188. package/eslint.config.js +0 -45
  189. package/npm-shrinkwrap.json +0 -2711
  190. package/test/integration/diagnostics-test.ts +0 -44
  191. package/test/integration/read-pair-record-test.ts +0 -39
  192. package/test/integration/tunnel-test.ts +0 -104
  193. package/test/unit/apple-tv/tlv/decoder.spec.ts +0 -144
  194. package/test/unit/apple-tv/tlv/encoder.spec.ts +0 -91
  195. package/test/unit/apple-tv/tlv/pairing-tlv.spec.ts +0 -101
  196. package/test/unit/apple-tv/tlv/tlv-integration.spec.ts +0 -146
  197. package/test/unit/apple-tv/utils/buffer-utils.spec.ts +0 -74
  198. package/test/unit/apple-tv/utils/uuid-generator.spec.ts +0 -39
  199. package/test/unit/fixtures/index.ts +0 -88
  200. package/test/unit/fixtures/usbmuxconnectmessage.bin +0 -0
  201. package/test/unit/fixtures/usbmuxlistdevicemessage.bin +0 -0
  202. package/test/unit/plist/error-handling.spec.ts +0 -101
  203. package/test/unit/plist/fixtures/sample.binary.plist +0 -0
  204. package/test/unit/plist/fixtures/sample.xml.plist +0 -38
  205. package/test/unit/plist/plist-parser.spec.ts +0 -283
  206. package/test/unit/plist/plist.spec.ts +0 -205
  207. package/test/unit/plist/tag-position-handling.spec.ts +0 -90
  208. package/test/unit/plist/unified-plist-parser.spec.ts +0 -227
  209. package/test/unit/plist/utils.spec.ts +0 -249
  210. package/test/unit/plist/xml-cleaning.spec.ts +0 -60
  211. package/test/unit/tunnel/tunnel-registry-server.spec.ts +0 -194
  212. package/test/unit/usbmux/usbmux-specs.ts +0 -71
  213. package/tsconfig.json +0 -36
@@ -0,0 +1,91 @@
1
+ import { EventEmitter } from 'events';
2
+ import type { PacketData } from 'tuntap-bridge';
3
+ import type { PacketSource, SyslogOptions, SyslogService as SyslogServiceInterface } from '../../../lib/types.js';
4
+ import { type Service } from '../base-service.js';
5
+ /**
6
+ * syslog-service provides functionality to capture and process syslog messages
7
+ * from a remote device using Apple's XPC services.
8
+ */
9
+ declare class SyslogService extends EventEmitter implements SyslogServiceInterface {
10
+ private readonly baseService;
11
+ private connection;
12
+ private packetConsumer;
13
+ private packetStreamPromise;
14
+ private isCapturing;
15
+ private enableVerboseLogging;
16
+ /**
17
+ * Creates a new syslog-service instance
18
+ * @param address Tuple containing [host, port]
19
+ */
20
+ constructor(address: [string, number]);
21
+ /**
22
+ * Starts capturing syslog data from the device
23
+ * @param service Service information
24
+ * @param packetSource Source of packet data (can be PacketConsumer or AsyncIterable)
25
+ * @param options Configuration options for syslog capture
26
+ * @returns Promise resolving to the initial response from the service
27
+ */
28
+ start(service: Service, packetSource: PacketSource | AsyncIterable<PacketData>, options?: SyslogOptions): Promise<void>;
29
+ /**
30
+ * Stops capturing syslog data
31
+ * @returns Promise that resolves when capture is stopped
32
+ */
33
+ stop(): Promise<void>;
34
+ /**
35
+ * Restart the device
36
+ * @param service Service information
37
+ * @returns Promise that resolves when the restart request is sent
38
+ */
39
+ restart(service: Service): Promise<void>;
40
+ private attachPacketSource;
41
+ private isPacketSource;
42
+ private processPacketStream;
43
+ private processPacket;
44
+ /**
45
+ * Detaches the packet source
46
+ */
47
+ private detachPacketSource;
48
+ /**
49
+ * Closes the current connection
50
+ */
51
+ private closeConnection;
52
+ /**
53
+ * Processes a TCP packet
54
+ * @param packet TCP packet to process
55
+ */
56
+ private processTcpPacket;
57
+ private processPlistPacket;
58
+ private processTextPacket;
59
+ private emitTextMessage;
60
+ private emitMessage;
61
+ /**
62
+ * Checks if the buffer might be a plist (XML or binary)
63
+ * @param buffer Buffer to check
64
+ * @returns True if the buffer might be a plist
65
+ */
66
+ private mightBePlist;
67
+ /**
68
+ * Processes a UDP packet
69
+ * @param packet UDP packet to process
70
+ */
71
+ private processUdpPacket;
72
+ /**
73
+ * Logs packet details for debugging
74
+ * @param packet Packet to log details for
75
+ */
76
+ private logPacketDetails;
77
+ /**
78
+ * Extracts printable text from a buffer
79
+ * @param buffer Buffer to extract text from
80
+ * @returns Printable text
81
+ */
82
+ private extractPrintableText;
83
+ /**
84
+ * Determines if a buffer contains mostly printable ASCII characters
85
+ * @param buffer Buffer to analyze
86
+ * @returns True if more than 50% of characters are printable ASCII
87
+ */
88
+ private isMostlyPrintable;
89
+ }
90
+ export default SyslogService;
91
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/services/ios/syslog-service/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAkB,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhE,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,aAAa,IAAI,sBAAsB,EACxC,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAe,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAqB/D;;;GAGG;AACH,cAAM,aAAc,SAAQ,YAAa,YAAW,sBAAsB;IACxE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,mBAAmB,CAA8B;IACzD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,oBAAoB,CAAS;IAErC;;;OAGG;gBACS,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;IAKrC;;;;;;OAMG;IACG,KAAK,CACT,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,YAAY,GAAG,aAAa,CAAC,UAAU,CAAC,EACtD,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAgChB;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAc3B;;;;OAIG;IACG,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAY9C,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,cAAc;YASR,mBAAmB;IAejC,OAAO,CAAC,aAAa;IAQrB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAY1B;;OAEG;IACH,OAAO,CAAC,eAAe;IAcvB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,iBAAiB;IAiBzB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,WAAW;IAOnB;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAqCpB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IASxB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;CA2B1B;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,323 @@
1
+ import { logger } from '@appium/support';
2
+ import { EventEmitter } from 'events';
3
+ import { isBinaryPlist } from '../../../lib/plist/binary-plist-parser.js';
4
+ import { parsePlist } from '../../../lib/plist/unified-plist-parser.js';
5
+ import { ServiceConnection } from '../../../service-connection.js';
6
+ import { BaseService } from '../base-service.js';
7
+ const syslogLog = logger.getLogger('SyslogMessages');
8
+ const log = logger.getLogger('Syslog');
9
+ const MIN_PRINTABLE_RATIO = 0.5;
10
+ const ASCII_PRINTABLE_MIN = 32;
11
+ const ASCII_PRINTABLE_MAX = 126;
12
+ const NON_PRINTABLE_ASCII_REGEX = /[^\x20-\x7E]/g;
13
+ const PLIST_XML_MARKERS = ['<?xml', '<plist'];
14
+ const BINARY_PLIST_MARKER = 'bplist';
15
+ const BINARY_PLIST_MARKER_ALT = 'Ibplist00';
16
+ const MIN_PLIST_SIZE = 8;
17
+ const PLIST_HEADER_CHECK_SIZE = 100;
18
+ const DEFAULT_SYSLOG_REQUEST = {
19
+ Request: 'StartActivity',
20
+ MessageFilter: 65535,
21
+ StreamFlags: 60,
22
+ };
23
+ /**
24
+ * syslog-service provides functionality to capture and process syslog messages
25
+ * from a remote device using Apple's XPC services.
26
+ */
27
+ class SyslogService extends EventEmitter {
28
+ baseService;
29
+ connection = null;
30
+ packetConsumer = null;
31
+ packetStreamPromise = null;
32
+ isCapturing = false;
33
+ enableVerboseLogging = false;
34
+ /**
35
+ * Creates a new syslog-service instance
36
+ * @param address Tuple containing [host, port]
37
+ */
38
+ constructor(address) {
39
+ super();
40
+ this.baseService = new BaseService(address);
41
+ }
42
+ /**
43
+ * Starts capturing syslog data from the device
44
+ * @param service Service information
45
+ * @param packetSource Source of packet data (can be PacketConsumer or AsyncIterable)
46
+ * @param options Configuration options for syslog capture
47
+ * @returns Promise resolving to the initial response from the service
48
+ */
49
+ async start(service, packetSource, options = {}) {
50
+ if (this.isCapturing) {
51
+ log.info('Syslog capture already in progress. Stopping previous capture.');
52
+ await this.stop();
53
+ }
54
+ const { pid = -1, enableVerboseLogging = false } = options;
55
+ this.enableVerboseLogging = enableVerboseLogging;
56
+ this.isCapturing = true;
57
+ this.attachPacketSource(packetSource);
58
+ try {
59
+ this.connection = await this.baseService.startLockdownService(service);
60
+ const request = {
61
+ ...DEFAULT_SYSLOG_REQUEST,
62
+ Pid: pid,
63
+ };
64
+ const response = await this.connection.sendPlistRequest(request);
65
+ log.info(`Syslog capture started: ${response}`);
66
+ this.emit('start', response);
67
+ }
68
+ catch (error) {
69
+ this.isCapturing = false;
70
+ this.detachPacketSource();
71
+ throw error;
72
+ }
73
+ }
74
+ /**
75
+ * Stops capturing syslog data
76
+ * @returns Promise that resolves when capture is stopped
77
+ */
78
+ async stop() {
79
+ if (!this.isCapturing) {
80
+ log.info('No syslog capture in progress.');
81
+ return;
82
+ }
83
+ this.detachPacketSource();
84
+ this.closeConnection();
85
+ this.isCapturing = false;
86
+ log.info('Syslog capture stopped');
87
+ this.emit('stop');
88
+ }
89
+ /**
90
+ * Restart the device
91
+ * @param service Service information
92
+ * @returns Promise that resolves when the restart request is sent
93
+ */
94
+ async restart(service) {
95
+ try {
96
+ const conn = await this.baseService.startLockdownService(service);
97
+ const request = { Request: 'Restart' };
98
+ const res = await conn.sendPlistRequest(request);
99
+ log.info(`Restart response: ${res}`);
100
+ }
101
+ catch (error) {
102
+ log.error(`Error during restart: ${error}`);
103
+ throw error;
104
+ }
105
+ }
106
+ attachPacketSource(packetSource) {
107
+ if (this.isPacketSource(packetSource)) {
108
+ this.packetConsumer = {
109
+ onPacket: (packet) => this.processPacket(packet),
110
+ };
111
+ packetSource.addPacketConsumer(this.packetConsumer);
112
+ }
113
+ else {
114
+ // Store the promise so we can handle it properly
115
+ this.packetStreamPromise = this.processPacketStream(packetSource);
116
+ // Handle any errors from the stream processing
117
+ this.packetStreamPromise.catch((error) => {
118
+ log.error(`Packet stream processing failed: ${error}`);
119
+ this.emit('error', error);
120
+ });
121
+ }
122
+ }
123
+ isPacketSource(source) {
124
+ return (typeof source === 'object' &&
125
+ source !== null &&
126
+ 'addPacketConsumer' in source &&
127
+ 'removePacketConsumer' in source);
128
+ }
129
+ async processPacketStream(packetStream) {
130
+ try {
131
+ for await (const packet of packetStream) {
132
+ if (!this.isCapturing) {
133
+ break;
134
+ }
135
+ this.processPacket(packet);
136
+ }
137
+ }
138
+ catch (error) {
139
+ log.error(`Error processing packet stream: ${error}`);
140
+ }
141
+ }
142
+ processPacket(packet) {
143
+ if (packet.protocol === 'TCP') {
144
+ this.processTcpPacket(packet);
145
+ }
146
+ else if (packet.protocol === 'UDP') {
147
+ this.processUdpPacket(packet);
148
+ }
149
+ }
150
+ /**
151
+ * Detaches the packet source
152
+ */
153
+ detachPacketSource() {
154
+ if (this.packetConsumer) {
155
+ this.packetConsumer = null;
156
+ }
157
+ // Cancel the packet stream processing if it's running
158
+ if (this.packetStreamPromise) {
159
+ // Setting isCapturing to false will cause the stream loop to exit
160
+ this.packetStreamPromise = null;
161
+ }
162
+ }
163
+ /**
164
+ * Closes the current connection
165
+ */
166
+ closeConnection() {
167
+ if (!this.connection) {
168
+ return;
169
+ }
170
+ try {
171
+ this.connection.close();
172
+ }
173
+ catch (error) {
174
+ log.debug(`Error closing connection: ${error}`);
175
+ }
176
+ finally {
177
+ this.connection = null;
178
+ }
179
+ }
180
+ /**
181
+ * Processes a TCP packet
182
+ * @param packet TCP packet to process
183
+ */
184
+ processTcpPacket(packet) {
185
+ try {
186
+ if (this.mightBePlist(packet.payload)) {
187
+ this.processPlistPacket(packet);
188
+ }
189
+ else {
190
+ this.processTextPacket(packet);
191
+ }
192
+ }
193
+ catch (error) {
194
+ log.debug(`Error processing packet: ${error}`);
195
+ this.emitTextMessage(packet.payload);
196
+ }
197
+ this.logPacketDetails(packet);
198
+ }
199
+ processPlistPacket(packet) {
200
+ try {
201
+ const plistData = parsePlist(packet.payload);
202
+ log.debug('Successfully parsed packet as plist');
203
+ this.emit('plist', plistData);
204
+ const message = JSON.stringify(plistData);
205
+ this.emitMessage(message);
206
+ }
207
+ catch (error) {
208
+ log.debug(`Failed to parse as plist: ${error}`);
209
+ this.processTextPacket(packet);
210
+ }
211
+ }
212
+ processTextPacket(packet) {
213
+ const message = this.extractPrintableText(packet.payload);
214
+ if (!message.trim()) {
215
+ log.debug('TCP packet contains no printable text, ignoring.');
216
+ return;
217
+ }
218
+ const isMostlyPrintable = this.isMostlyPrintable(packet.payload);
219
+ if (!isMostlyPrintable) {
220
+ log.debug(`TCP packet not mostly printable, but contains text: ${message}`);
221
+ }
222
+ this.emitMessage(message);
223
+ }
224
+ emitTextMessage(buffer) {
225
+ const message = this.extractPrintableText(buffer);
226
+ if (message.trim()) {
227
+ this.emitMessage(message);
228
+ }
229
+ }
230
+ emitMessage(message) {
231
+ if (this.enableVerboseLogging) {
232
+ syslogLog.info(message);
233
+ }
234
+ this.emit('message', message);
235
+ }
236
+ /**
237
+ * Checks if the buffer might be a plist (XML or binary)
238
+ * @param buffer Buffer to check
239
+ * @returns True if the buffer might be a plist
240
+ */
241
+ mightBePlist(buffer) {
242
+ try {
243
+ if (buffer.length < MIN_PLIST_SIZE) {
244
+ return false;
245
+ }
246
+ // Check for XML plist
247
+ const headerStr = buffer.toString('utf8', 0, Math.min(PLIST_HEADER_CHECK_SIZE, buffer.length));
248
+ if (PLIST_XML_MARKERS.every((marker) => headerStr.includes(marker))) {
249
+ return true;
250
+ }
251
+ // Check for binary plist
252
+ if (isBinaryPlist(buffer)) {
253
+ return true;
254
+ }
255
+ // Check alternative binary plist markers
256
+ const firstNineChars = buffer.toString('ascii', 0, Math.min(9, buffer.length));
257
+ return (firstNineChars === BINARY_PLIST_MARKER_ALT ||
258
+ firstNineChars.includes(BINARY_PLIST_MARKER));
259
+ }
260
+ catch (error) {
261
+ log.debug(`Error checking if buffer is plist: ${error}`);
262
+ return false;
263
+ }
264
+ }
265
+ /**
266
+ * Processes a UDP packet
267
+ * @param packet UDP packet to process
268
+ */
269
+ processUdpPacket(packet) {
270
+ log.debug(`Received UDP packet (not filtered here): ${packet}`);
271
+ }
272
+ /**
273
+ * Logs packet details for debugging
274
+ * @param packet Packet to log details for
275
+ */
276
+ logPacketDetails(packet) {
277
+ log.debug('Received syslog-like TCP packet:');
278
+ log.debug(` Source: ${packet.src}`);
279
+ log.debug(` Destination: ${packet.dst}`);
280
+ log.debug(` Source port: ${packet.sourcePort}`);
281
+ log.debug(` Destination port: ${packet.destPort}`);
282
+ log.debug(` Payload length: ${packet.payload.length}`);
283
+ }
284
+ /**
285
+ * Extracts printable text from a buffer
286
+ * @param buffer Buffer to extract text from
287
+ * @returns Printable text
288
+ */
289
+ extractPrintableText(buffer) {
290
+ return buffer.toString().replace(NON_PRINTABLE_ASCII_REGEX, '');
291
+ }
292
+ /**
293
+ * Determines if a buffer contains mostly printable ASCII characters
294
+ * @param buffer Buffer to analyze
295
+ * @returns True if more than 50% of characters are printable ASCII
296
+ */
297
+ isMostlyPrintable(buffer) {
298
+ try {
299
+ const str = buffer.toString('utf8');
300
+ if (!str || str.length === 0) {
301
+ return false;
302
+ }
303
+ const totalLength = str.length;
304
+ const threshold = totalLength * MIN_PRINTABLE_RATIO;
305
+ let printableCount = 0;
306
+ for (let i = 0; i < totalLength; i++) {
307
+ const code = str.charCodeAt(i);
308
+ if (code >= ASCII_PRINTABLE_MIN && code <= ASCII_PRINTABLE_MAX) {
309
+ printableCount++;
310
+ if (printableCount > threshold) {
311
+ return true;
312
+ }
313
+ }
314
+ }
315
+ return printableCount / totalLength > MIN_PRINTABLE_RATIO;
316
+ }
317
+ catch (error) {
318
+ log.debug(error);
319
+ return false;
320
+ }
321
+ }
322
+ }
323
+ export default SyslogService;
@@ -0,0 +1,17 @@
1
+ import { TLSSocket } from 'tls';
2
+ import { LockdownService } from '../../../lib/lockdown/index.js';
3
+ import { PlistService } from '../../../lib/plist/plist-service.js';
4
+ /**
5
+ * Starts a CoreDeviceProxy session over an existing TLS-upgraded lockdown connection.
6
+ *
7
+ * @param lockdownClient - The TLS-upgraded lockdown client used to send the StartService request.
8
+ * @param deviceID - The device identifier to be used in the Connect request.
9
+ * @param udid - The device UDID used to retrieve the pair record.
10
+ * @param tlsOptions - TLS options for upgrading the usbmuxd socket.
11
+ * @returns A promise that resolves with a TLS-upgraded socket and PlistService for communication with CoreDeviceProxy.
12
+ */
13
+ export declare function startCoreDeviceProxy(lockdownClient: LockdownService, deviceID: number | string, udid: string, tlsOptions?: Partial<import('tls').ConnectionOptions>): Promise<{
14
+ socket: TLSSocket;
15
+ plistService: PlistService;
16
+ }>;
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/services/ios/tunnel-service/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EACL,eAAe,EAEhB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAMnE;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,cAAc,EAAE,eAAe,EAC/B,QAAQ,EAAE,MAAM,GAAG,MAAM,EACzB,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,OAAO,CAAC,OAAO,KAAK,EAAE,iBAAiB,CAAM,GACxD,OAAO,CAAC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAE,CAAC,CA4D5D"}
@@ -0,0 +1,57 @@
1
+ import { logger } from '@appium/support';
2
+ import { TLSSocket } from 'tls';
3
+ import { LockdownService, upgradeSocketToTLS, } from '../../../lib/lockdown/index.js';
4
+ import { PlistService } from '../../../lib/plist/plist-service.js';
5
+ import { createUsbmux } from '../../../lib/usbmux/index.js';
6
+ const log = logger.getLogger('TunnelService');
7
+ const LABEL = 'appium-internal';
8
+ /**
9
+ * Starts a CoreDeviceProxy session over an existing TLS-upgraded lockdown connection.
10
+ *
11
+ * @param lockdownClient - The TLS-upgraded lockdown client used to send the StartService request.
12
+ * @param deviceID - The device identifier to be used in the Connect request.
13
+ * @param udid - The device UDID used to retrieve the pair record.
14
+ * @param tlsOptions - TLS options for upgrading the usbmuxd socket.
15
+ * @returns A promise that resolves with a TLS-upgraded socket and PlistService for communication with CoreDeviceProxy.
16
+ */
17
+ export async function startCoreDeviceProxy(lockdownClient, deviceID, udid, tlsOptions = {}) {
18
+ // Wait for TLS upgrade to complete if in progress
19
+ await lockdownClient.waitForTLSUpgrade();
20
+ const response = await lockdownClient.sendAndReceive({
21
+ Label: LABEL,
22
+ Request: 'StartService',
23
+ Service: 'com.apple.internal.devicecompute.CoreDeviceProxy',
24
+ EscrowBag: null,
25
+ });
26
+ lockdownClient.close();
27
+ if (!response.Port) {
28
+ throw new Error('Service didnt return a port');
29
+ }
30
+ log.debug(`Connecting to CoreDeviceProxy service on port: ${response.Port}`);
31
+ const usbmux = await createUsbmux();
32
+ try {
33
+ const pairRecord = await usbmux.readPairRecord(udid);
34
+ if (!pairRecord ||
35
+ !pairRecord.HostCertificate ||
36
+ !pairRecord.HostPrivateKey) {
37
+ throw new Error('Missing required pair record or certificates for TLS upgrade');
38
+ }
39
+ const coreDeviceSocket = await usbmux.connect(Number(deviceID), Number(response.Port));
40
+ log.debug('Socket connected to CoreDeviceProxy, upgrading to TLS...');
41
+ const fullTlsOptions = {
42
+ ...tlsOptions,
43
+ cert: pairRecord.HostCertificate,
44
+ key: pairRecord.HostPrivateKey,
45
+ };
46
+ const tlsSocket = await upgradeSocketToTLS(coreDeviceSocket, fullTlsOptions);
47
+ const plistService = new PlistService(tlsSocket);
48
+ return { socket: tlsSocket, plistService };
49
+ }
50
+ catch (err) {
51
+ // If we haven't connected yet, we can safely close the usbmux
52
+ await usbmux
53
+ .close()
54
+ .catch((closeErr) => log.error(`Error closing usbmux: ${closeErr}`));
55
+ throw err;
56
+ }
57
+ }
@@ -0,0 +1,14 @@
1
+ import RemoteXpcConnection from './lib/remote-xpc/remote-xpc-connection.js';
2
+ import type { DiagnosticsService as DiagnosticsServiceType, SyslogService as SyslogServiceType } from './lib/types.js';
3
+ export declare function startDiagnosticsService(udid: string): Promise<DiagnosticsServiceType>;
4
+ export declare function startSyslogService(udid: string): Promise<SyslogServiceType>;
5
+ export declare function createRemoteXPCConnection(udid: string): Promise<{
6
+ remoteXPC: RemoteXpcConnection;
7
+ tunnelConnection: {
8
+ host: string;
9
+ port: number;
10
+ udid: string;
11
+ packetStreamPort: number;
12
+ };
13
+ }>;
14
+ //# sourceMappingURL=services.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/services.ts"],"names":[],"mappings":"AAEA,OAAO,mBAAmB,MAAM,2CAA2C,CAAC;AAG5E,OAAO,KAAK,EACV,kBAAkB,IAAI,sBAAsB,EAC5C,aAAa,IAAI,iBAAiB,EACnC,MAAM,gBAAgB,CAAC;AAOxB,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,sBAAsB,CAAC,CASjC;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,iBAAiB,CAAC,CAG5B;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,MAAM;;;;;;;;GAO3D"}
@@ -0,0 +1,48 @@
1
+ import { strongbox } from '@appium/strongbox';
2
+ import RemoteXpcConnection from './lib/remote-xpc/remote-xpc-connection.js';
3
+ import { TunnelManager } from './lib/tunnel/index.js';
4
+ import { TunnelApiClient } from './lib/tunnel/tunnel-api-client.js';
5
+ import DiagnosticsService from './services/ios/diagnostic-service/index.js';
6
+ import SyslogService from './services/ios/syslog-service/index.js';
7
+ const APPIUM_XCUITEST_DRIVER_NAME = 'appium-xcuitest-driver';
8
+ const TUNNEL_REGISTRY_PORT = 'tunnelRegistryPort';
9
+ export async function startDiagnosticsService(udid) {
10
+ const { remoteXPC, tunnelConnection } = await createRemoteXPCConnection(udid);
11
+ const diagnosticsService = remoteXPC.findService(DiagnosticsService.RSD_SERVICE_NAME);
12
+ return new DiagnosticsService([
13
+ tunnelConnection.host,
14
+ parseInt(diagnosticsService.port, 10),
15
+ ]);
16
+ }
17
+ export async function startSyslogService(udid) {
18
+ const { tunnelConnection } = await createRemoteXPCConnection(udid);
19
+ return new SyslogService([tunnelConnection.host, tunnelConnection.port]);
20
+ }
21
+ export async function createRemoteXPCConnection(udid) {
22
+ const tunnelConnection = await getTunnelInformation(udid);
23
+ const remoteXPC = await startService(tunnelConnection.host, tunnelConnection.port);
24
+ return { remoteXPC, tunnelConnection };
25
+ }
26
+ // #region Private Functions
27
+ async function getTunnelInformation(udid) {
28
+ const box = strongbox(APPIUM_XCUITEST_DRIVER_NAME);
29
+ const item = await box.createItem(TUNNEL_REGISTRY_PORT);
30
+ const tunnelRegistryPort = await item.read();
31
+ if (tunnelRegistryPort === undefined) {
32
+ throw new Error('Tunnel registry port not found. Please run the tunnel creation script first: sudo appium driver run xcuitest tunnel-creation');
33
+ }
34
+ const tunnelApiClient = new TunnelApiClient(`http://127.0.0.1:${tunnelRegistryPort}/remotexpc/tunnels`);
35
+ const tunnelExists = await tunnelApiClient.hasTunnel(udid);
36
+ if (!tunnelExists) {
37
+ throw new Error(`No tunnel found for device ${udid}. Please run the tunnel creation script first: sudo appium driver run xcuitest tunnel-creation`);
38
+ }
39
+ const tunnelConnection = await tunnelApiClient.getTunnelConnection(udid);
40
+ if (!tunnelConnection) {
41
+ throw new Error(`Failed to get tunnel connection details for device ${udid}`);
42
+ }
43
+ return tunnelConnection;
44
+ }
45
+ async function startService(host, port) {
46
+ return await TunnelManager.createRemoteXPCConnection(host, port);
47
+ }
48
+ // #endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-ios-remotexpc",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "main": "build/src/index.js",
5
5
  "types": "build/src/index.d.ts",
6
6
  "type": "module",
@@ -18,6 +18,7 @@
18
18
  "build:es": "tsc",
19
19
  "build": "run-s clean:* build:*",
20
20
  "lint": "eslint src --ext .ts --quiet",
21
+ "prepare": "npm run build",
21
22
  "format": "prettier --write \"{src,test}/**/*.{ts,tsx}\"",
22
23
  "format:check": "prettier --check \"{src,test}/**/*.{ts,tsx}\"",
23
24
  "lint:fix": "eslint src --ext .ts --fix",
@@ -35,7 +36,7 @@
35
36
  "license": "Apache-2.0",
36
37
  "repository": {
37
38
  "type": "git",
38
- "url": "https://github.com/appium/appium-ios-remotexpc.git"
39
+ "url": "git+https://github.com/appium/appium-ios-remotexpc.git"
39
40
  },
40
41
  "bugs": {
41
42
  "url": "https://github.com/appium/appium-ios-remotexpc/issues"
@@ -74,5 +75,13 @@
74
75
  "@xmldom/xmldom": "^0.9.8",
75
76
  "npm-run-all2": "^7.0.2",
76
77
  "tuntap-bridge": "^0.x"
77
- }
78
+ },
79
+ "files": [
80
+ "src",
81
+ "scripts",
82
+ "build/src",
83
+ "!.DS_Store",
84
+ "CHANGELOG.md",
85
+ "LICENSE"
86
+ ]
78
87
  }
@@ -81,3 +81,45 @@ export const HKDF_HASH_ALGORITHM = 'sha512';
81
81
 
82
82
  // Output length (in bytes) for HKDF key derivation
83
83
  export const HKDF_HASH_LENGTH = 64;
84
+
85
+ // OPACK2 encoding constants
86
+ export const OPACK2_NULL = 0x03;
87
+ export const OPACK2_TRUE = 0x01;
88
+ export const OPACK2_FALSE = 0x02;
89
+ export const OPACK2_SMALL_INT_OFFSET = 8;
90
+ export const OPACK2_SMALL_INT_MAX = 0x27;
91
+ export const OPACK2_SMALL_STRING_MAX = 0x20;
92
+ export const OPACK2_SMALL_BYTES_MAX = 0x20;
93
+ export const OPACK2_SMALL_ARRAY_MAX = 15;
94
+ export const OPACK2_SMALL_DICT_MAX = 15;
95
+
96
+ // OPACK2 number type markers
97
+ export const OPACK2_INT8_MARKER = 0x30;
98
+ export const OPACK2_INT32_MARKER = 0x32;
99
+ export const OPACK2_INT64_MARKER = 0x33;
100
+ export const OPACK2_FLOAT_MARKER = 0x35;
101
+
102
+ // OPACK2 string type markers
103
+ export const OPACK2_SMALL_STRING_BASE = 0x40;
104
+ export const OPACK2_STRING_8BIT_LEN_MARKER = 0x61;
105
+ export const OPACK2_STRING_16BIT_LEN_MARKER = 0x62;
106
+ export const OPACK2_STRING_32BIT_LEN_MARKER = 0x63;
107
+
108
+ // OPACK2 bytes type markers
109
+ export const OPACK2_SMALL_BYTES_BASE = 0x70;
110
+ export const OPACK2_BYTES_8BIT_LEN_MARKER = 0x91;
111
+ export const OPACK2_BYTES_16BIT_LEN_MARKER = 0x92;
112
+ export const OPACK2_BYTES_32BIT_LEN_MARKER = 0x93;
113
+
114
+ // OPACK2 array type markers
115
+ export const OPACK2_SMALL_ARRAY_BASE = 0xd0;
116
+ export const OPACK2_VARIABLE_ARRAY_MARKER = 0xdf;
117
+
118
+ // OPACK2 dictionary type markers
119
+ export const OPACK2_SMALL_DICT_BASE = 0xe0;
120
+ export const OPACK2_VARIABLE_DICT_MARKER = 0xef;
121
+
122
+ // OPACK2 size limits
123
+ export const OPACK2_UINT8_MAX = 0xff;
124
+ export const OPACK2_UINT16_MAX = 0xffff;
125
+ export const OPACK2_UINT32_MAX = 0xffffffff;