Skip to content

Commit 7e34afd

Browse files
committed
address review comments
1 parent 421dfe8 commit 7e34afd

7 files changed

Lines changed: 63 additions & 50 deletions

File tree

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export type {
7171
ProcessControlService,
7272
ProcessLaunchOptions,
7373
OutputReceivedEvent,
74+
SendMessageOptions,
7475
TestmanagerdService,
7576
TestmanagerdServiceWithConnection,
7677
} from './lib/types.js';

src/lib/types.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,6 +1756,16 @@ export interface InstallationProxyServiceWithConnection {
17561756
remoteXPC: RemoteXpcConnection;
17571757
}
17581758

1759+
/**
1760+
* Options for sending a DTX message
1761+
*/
1762+
export interface SendMessageOptions {
1763+
/** Optional message arguments */
1764+
args?: any | null;
1765+
/** Whether a reply is expected (default: true) */
1766+
expectsReply?: boolean;
1767+
}
1768+
17591769
/**
17601770
* Testmanagerd DTX service interface for XCTest session management
17611771
*/
@@ -1776,14 +1786,12 @@ export interface TestmanagerdService extends BaseService {
17761786
* Send a DTX message on a channel
17771787
* @param channel The channel code
17781788
* @param selector The ObjectiveC method selector
1779-
* @param args Optional message arguments
1780-
* @param expectsReply Whether a reply is expected
1789+
* @param options Optional message options
17811790
*/
17821791
sendMessage(
17831792
channel: number,
17841793
selector: string | null,
1785-
args?: any | null,
1786-
expectsReply?: boolean,
1794+
options?: SendMessageOptions,
17871795
): Promise<void>;
17881796

17891797
/**

src/services/ios/base-service.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type net from 'node:net';
2+
13
import { getLogger } from '../../lib/logger.js';
24
import { ServiceConnection } from '../../service-connection.js';
35

@@ -75,15 +77,15 @@ export class BaseService {
7577
throw error;
7678
}
7779
}
80+
}
7881

79-
/**
80-
* Remove any SSL wrapper from the socket so raw binary protocols (DTX)
81-
* can read/write directly. Both DVT and testmanagerd services require this.
82-
*/
83-
protected stripSSL(socket: import('net').Socket): void {
84-
if ('_sslobj' in socket) {
85-
(socket as any)._sslobj = null;
86-
}
82+
/**
83+
* Remove any SSL wrapper from the socket so raw binary protocols (DTX)
84+
* can read/write directly. Both DVT and testmanagerd services require this.
85+
*/
86+
export function stripSSL(socket: net.Socket): void {
87+
if ('_sslobj' in socket) {
88+
(socket as any)._sslobj = null;
8789
}
8890
}
8991

src/services/ios/dvt/channel.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { SendMessageOptions } from '../../../lib/types.js';
12
import type { MessageAux } from './dtx-message.js';
23

34
/**
@@ -9,8 +10,7 @@ export interface DTXServiceProvider {
910
sendMessage(
1011
channel: number,
1112
selector: string | null,
12-
args?: MessageAux | null,
13-
expectsReply?: boolean,
13+
options?: SendMessageOptions,
1414
): Promise<void>;
1515
}
1616

@@ -65,12 +65,10 @@ export class Channel {
6565
call(methodName: string): ChannelMethodCall {
6666
const selector = this.convertToSelector(methodName);
6767
return (async (args, expectsReply = true) => {
68-
await this.service.sendMessage(
69-
this.channelCode,
70-
selector,
68+
await this.service.sendMessage(this.channelCode, selector, {
7169
args,
7270
expectsReply,
73-
);
71+
});
7472
}) as ChannelMethodCall;
7573
}
7674

src/services/ios/dvt/index.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
import net from 'node:net';
1+
import type net from 'node:net';
22

33
import { getLogger } from '../../../lib/logger.js';
44
import {
55
PlistUID,
66
createBinaryPlist,
77
parseBinaryPlist,
88
} from '../../../lib/plist/index.js';
9-
import type { PlistDictionary } from '../../../lib/types.js';
9+
import type {
10+
PlistDictionary,
11+
SendMessageOptions,
12+
} from '../../../lib/types.js';
1013
import { ServiceConnection } from '../../../service-connection.js';
11-
import { BaseService, type Service } from '../base-service.js';
14+
import { BaseService, type Service, stripSSL } from '../base-service.js';
1215
import { ChannelFragmenter } from './channel-fragmenter.js';
1316
import { Channel } from './channel.js';
1417
import { DTXMessage, DTX_CONSTANTS, MessageAux } from './dtx-message.js';
@@ -68,7 +71,7 @@ export class DVTSecureSocketProxyService extends BaseService {
6871
// DVT uses DTX binary protocol, connect without plist-based RSDCheckin
6972
this.connection = await this.startLockdownWithoutCheckin(service);
7073
this.socket = this.connection.getSocket();
71-
this.stripSSL(this.socket);
74+
stripSSL(this.socket);
7275

7376
await this.performHandshake();
7477
}
@@ -101,7 +104,7 @@ export class DVTSecureSocketProxyService extends BaseService {
101104
args.appendInt(channelCode);
102105
args.appendObj(identifier);
103106

104-
await this.sendMessage(0, '_requestChannelWithCode:identifier:', args);
107+
await this.sendMessage(0, '_requestChannelWithCode:identifier:', { args });
105108

106109
const [ret] = await this.recvPlist();
107110

@@ -119,15 +122,14 @@ export class DVTSecureSocketProxyService extends BaseService {
119122
* Send a DTX message on a channel
120123
* @param channel The channel code
121124
* @param selector The ObjectiveC method selector
122-
* @param args Optional message arguments
123-
* @param expectsReply Whether a reply is expected
125+
* @param options Optional message options
124126
*/
125127
async sendMessage(
126128
channel: number,
127129
selector: string | null = null,
128-
args: MessageAux | null = null,
129-
expectsReply: boolean = true,
130+
options: SendMessageOptions = {},
130131
): Promise<void> {
132+
const { args = null, expectsReply = true } = options;
131133
if (!this.socket) {
132134
throw new Error('Not connected to DVT service');
133135
}
@@ -269,8 +271,7 @@ export class DVTSecureSocketProxyService extends BaseService {
269271
await this.sendMessage(
270272
DVTSecureSocketProxyService.BROADCAST_CHANNEL,
271273
'_channelCanceled:',
272-
args,
273-
false,
274+
{ args, expectsReply: false },
274275
);
275276
} catch (error) {
276277
log.debug('Error sending channel canceled message:', error);
@@ -298,7 +299,10 @@ export class DVTSecureSocketProxyService extends BaseService {
298299
'com.apple.private.DTXBlockCompression': 0,
299300
'com.apple.private.DTXConnection': 1,
300301
});
301-
await this.sendMessage(0, '_notifyOfPublishedCapabilities:', args, false);
302+
await this.sendMessage(0, '_notifyOfPublishedCapabilities:', {
303+
args,
304+
expectsReply: false,
305+
});
302306

303307
const [retData, aux] = await this.recvMessage();
304308
const ret = retData ? parseBinaryPlist(retData) : null;

src/services/ios/testmanagerd/index.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import net from 'node:net';
1+
import type net from 'node:net';
22

33
import { getLogger } from '../../../lib/logger.js';
44
import {
55
createBinaryPlist,
66
parseBinaryPlist,
77
} from '../../../lib/plist/index.js';
8-
import type { PlistDictionary } from '../../../lib/types.js';
8+
import type {
9+
PlistDictionary,
10+
SendMessageOptions,
11+
} from '../../../lib/types.js';
912
import { ServiceConnection } from '../../../service-connection.js';
10-
import { BaseService, type Service } from '../base-service.js';
13+
import { BaseService, type Service, stripSSL } from '../base-service.js';
1114
import { ChannelFragmenter } from '../dvt/channel-fragmenter.js';
1215
import { Channel } from '../dvt/channel.js';
1316
import { DTXMessage, DTX_CONSTANTS, MessageAux } from '../dvt/dtx-message.js';
@@ -153,7 +156,7 @@ export class DvtTestmanagedProxyService extends BaseService {
153156
// testmanagerd uses DTX binary protocol, connect without plist-based RSDCheckin
154157
this.connection = await this.startLockdownWithoutCheckin(service);
155158
this.socket = this.connection.getSocket();
156-
this.stripSSL(this.socket);
159+
stripSSL(this.socket);
157160

158161
await this.performHandshake();
159162
}
@@ -186,7 +189,7 @@ export class DvtTestmanagedProxyService extends BaseService {
186189
args.appendInt(channelCode);
187190
args.appendObj(identifier);
188191

189-
await this.sendMessage(0, '_requestChannelWithCode:identifier:', args);
192+
await this.sendMessage(0, '_requestChannelWithCode:identifier:', { args });
190193

191194
const [ret] = await this.recvPlist();
192195

@@ -204,15 +207,14 @@ export class DvtTestmanagedProxyService extends BaseService {
204207
* Send a DTX message on a channel
205208
* @param channel The channel code
206209
* @param selector The ObjectiveC method selector
207-
* @param args Optional message arguments
208-
* @param expectsReply Whether a reply is expected
210+
* @param options Optional message options
209211
*/
210212
async sendMessage(
211213
channel: number,
212214
selector: string | null = null,
213-
args: MessageAux | null = null,
214-
expectsReply: boolean = true,
215+
options: SendMessageOptions = {},
215216
): Promise<void> {
217+
const { args = null, expectsReply = true } = options;
216218
if (!this.socket) {
217219
throw new Error('Not connected to testmanagerd service');
218220
}
@@ -451,8 +453,7 @@ export class DvtTestmanagedProxyService extends BaseService {
451453
await this.sendMessage(
452454
DvtTestmanagedProxyService.BROADCAST_CHANNEL,
453455
'_channelCanceled:',
454-
args,
455-
false,
456+
{ args, expectsReply: false },
456457
);
457458
} catch (error) {
458459
if (this.isExpectedCloseError(error)) {
@@ -485,7 +486,10 @@ export class DvtTestmanagedProxyService extends BaseService {
485486
'com.apple.private.DTXBlockCompression': 0,
486487
'com.apple.private.DTXConnection': 1,
487488
});
488-
await this.sendMessage(0, '_notifyOfPublishedCapabilities:', args, false);
489+
await this.sendMessage(0, '_notifyOfPublishedCapabilities:', {
490+
args,
491+
expectsReply: false,
492+
});
489493

490494
const [retData, aux] = await this.recvMessage();
491495
const ret = retData ? parseBinaryPlist(retData) : null;

test/integration/testmanagerd-test.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,9 @@ const TESTMANAGERD_CHANNEL =
1818
async function safeClose(
1919
...closeables: Array<{ close(): Promise<void> } | null | undefined>
2020
): Promise<void> {
21-
for (const c of closeables) {
22-
try {
23-
await c?.close();
24-
} catch {
25-
// Ignore close errors during cleanup
26-
}
27-
}
21+
await Promise.allSettled(
22+
closeables.map((c) => c?.close() ?? Promise.resolve()),
23+
);
2824
}
2925

3026
/**
@@ -99,7 +95,7 @@ describe('Testmanagerd Service', function () {
9995
await controlConnection!.testmanagerdService.sendMessage(
10096
channelCode,
10197
'_IDE_initiateControlSessionWithProtocolVersion:',
102-
args,
98+
{ args },
10399
);
104100

105101
const [result] =

0 commit comments

Comments
 (0)