@stim-cli/server 1.10.1 → 1.11.0
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/README.md +170 -27
- package/dist/{protocol-B3k9Ykuu.mjs → protocol-CmlG7X7_.mjs} +258 -11
- package/dist/protocol.d.mts +180 -10
- package/dist/protocol.mjs +2 -2
- package/dist/protocol.schema.json +464 -5
- package/dist/stim-frames/EmulatorDiscovery.swift +49 -0
- package/dist/stim-frames/EmulatorInput.swift +141 -0
- package/dist/stim-frames/GrpcFraming.swift +85 -0
- package/dist/stim-frames/InputMessages.swift +73 -0
- package/dist/stim-frames/ScreenshotMessages.swift +129 -0
- package/dist/stim-frames/ScreenshotStream.swift +130 -0
- package/dist/stim-frames/SimulatorDisplay.swift +116 -0
- package/dist/stim-frames/SimulatorHID.swift +101 -0
- package/dist/stim-frames/VideoEncoder.swift +282 -0
- package/dist/stim-frames/main.swift +389 -0
- package/dist/stim-server.mjs +1177 -106
- package/package.json +4 -4
|
@@ -28,7 +28,11 @@
|
|
|
28
28
|
"status-failed",
|
|
29
29
|
"logs-failed",
|
|
30
30
|
"stim-failed",
|
|
31
|
-
"frames-failed"
|
|
31
|
+
"frames-failed",
|
|
32
|
+
"forbidden",
|
|
33
|
+
"unknown-action",
|
|
34
|
+
"action-busy",
|
|
35
|
+
"action-failed"
|
|
32
36
|
]
|
|
33
37
|
},
|
|
34
38
|
"message": {
|
|
@@ -104,6 +108,7 @@
|
|
|
104
108
|
"protocol",
|
|
105
109
|
"server",
|
|
106
110
|
"capabilities",
|
|
111
|
+
"actions",
|
|
107
112
|
"device"
|
|
108
113
|
],
|
|
109
114
|
"additionalProperties": false,
|
|
@@ -116,7 +121,8 @@
|
|
|
116
121
|
"required": [
|
|
117
122
|
"name",
|
|
118
123
|
"version",
|
|
119
|
-
"stim"
|
|
124
|
+
"stim",
|
|
125
|
+
"home"
|
|
120
126
|
],
|
|
121
127
|
"additionalProperties": false,
|
|
122
128
|
"properties": {
|
|
@@ -128,6 +134,9 @@
|
|
|
128
134
|
},
|
|
129
135
|
"stim": {
|
|
130
136
|
"type": "string"
|
|
137
|
+
},
|
|
138
|
+
"home": {
|
|
139
|
+
"type": "string"
|
|
131
140
|
}
|
|
132
141
|
}
|
|
133
142
|
},
|
|
@@ -135,7 +144,17 @@
|
|
|
135
144
|
"type": "array",
|
|
136
145
|
"items": {
|
|
137
146
|
"enum": [
|
|
138
|
-
"read"
|
|
147
|
+
"read",
|
|
148
|
+
"control"
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
"actions": {
|
|
153
|
+
"type": "array",
|
|
154
|
+
"items": {
|
|
155
|
+
"enum": [
|
|
156
|
+
"reload",
|
|
157
|
+
"stop"
|
|
139
158
|
]
|
|
140
159
|
}
|
|
141
160
|
},
|
|
@@ -197,7 +216,8 @@
|
|
|
197
216
|
"metro",
|
|
198
217
|
"client",
|
|
199
218
|
"device",
|
|
200
|
-
"build"
|
|
219
|
+
"build",
|
|
220
|
+
"agent"
|
|
201
221
|
]
|
|
202
222
|
}
|
|
203
223
|
},
|
|
@@ -251,6 +271,120 @@
|
|
|
251
271
|
"type": "string",
|
|
252
272
|
"minLength": 1,
|
|
253
273
|
"default": "default"
|
|
274
|
+
},
|
|
275
|
+
"fps": {
|
|
276
|
+
"type": "integer",
|
|
277
|
+
"minimum": 1,
|
|
278
|
+
"maximum": 60,
|
|
279
|
+
"default": 5,
|
|
280
|
+
"description": "At most 30 unless the result offers video."
|
|
281
|
+
},
|
|
282
|
+
"maxEdge": {
|
|
283
|
+
"type": "integer",
|
|
284
|
+
"minimum": 240,
|
|
285
|
+
"maximum": 2048,
|
|
286
|
+
"default": 1280
|
|
287
|
+
},
|
|
288
|
+
"video": {
|
|
289
|
+
"type": "array",
|
|
290
|
+
"items": {
|
|
291
|
+
"enum": [
|
|
292
|
+
"h264"
|
|
293
|
+
]
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
"ActionParams": {
|
|
299
|
+
"oneOf": [
|
|
300
|
+
{
|
|
301
|
+
"type": "object",
|
|
302
|
+
"required": [
|
|
303
|
+
"action",
|
|
304
|
+
"workspace"
|
|
305
|
+
],
|
|
306
|
+
"additionalProperties": false,
|
|
307
|
+
"properties": {
|
|
308
|
+
"action": {
|
|
309
|
+
"const": "reload"
|
|
310
|
+
},
|
|
311
|
+
"workspace": {
|
|
312
|
+
"type": "string",
|
|
313
|
+
"description": "An environment path from a status payload."
|
|
314
|
+
},
|
|
315
|
+
"platform": {
|
|
316
|
+
"enum": [
|
|
317
|
+
"ios",
|
|
318
|
+
"android"
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"type": "object",
|
|
325
|
+
"required": [
|
|
326
|
+
"action",
|
|
327
|
+
"workspace"
|
|
328
|
+
],
|
|
329
|
+
"additionalProperties": false,
|
|
330
|
+
"properties": {
|
|
331
|
+
"action": {
|
|
332
|
+
"const": "stop"
|
|
333
|
+
},
|
|
334
|
+
"workspace": {
|
|
335
|
+
"type": "string",
|
|
336
|
+
"description": "An environment path from a status payload."
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
]
|
|
341
|
+
},
|
|
342
|
+
"ActionResult": {
|
|
343
|
+
"type": "object",
|
|
344
|
+
"required": [
|
|
345
|
+
"action",
|
|
346
|
+
"workspace",
|
|
347
|
+
"output"
|
|
348
|
+
],
|
|
349
|
+
"additionalProperties": false,
|
|
350
|
+
"properties": {
|
|
351
|
+
"action": {
|
|
352
|
+
"enum": [
|
|
353
|
+
"reload",
|
|
354
|
+
"stop"
|
|
355
|
+
]
|
|
356
|
+
},
|
|
357
|
+
"workspace": {
|
|
358
|
+
"type": "string"
|
|
359
|
+
},
|
|
360
|
+
"output": {
|
|
361
|
+
"type": "object",
|
|
362
|
+
"description": "The JSON the command printed."
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
"BuildPlanParams": {
|
|
367
|
+
"type": "object",
|
|
368
|
+
"required": [
|
|
369
|
+
"workspace",
|
|
370
|
+
"platform"
|
|
371
|
+
],
|
|
372
|
+
"additionalProperties": false,
|
|
373
|
+
"properties": {
|
|
374
|
+
"workspace": {
|
|
375
|
+
"type": "string",
|
|
376
|
+
"description": "An environment path from a status payload."
|
|
377
|
+
},
|
|
378
|
+
"platform": {
|
|
379
|
+
"enum": [
|
|
380
|
+
"ios",
|
|
381
|
+
"android"
|
|
382
|
+
]
|
|
383
|
+
},
|
|
384
|
+
"slot": {
|
|
385
|
+
"type": "string",
|
|
386
|
+
"pattern": "^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$",
|
|
387
|
+
"default": "default"
|
|
254
388
|
}
|
|
255
389
|
}
|
|
256
390
|
},
|
|
@@ -264,6 +398,182 @@
|
|
|
264
398
|
}
|
|
265
399
|
}
|
|
266
400
|
},
|
|
401
|
+
"MachineHistory": {
|
|
402
|
+
"type": "object",
|
|
403
|
+
"required": [
|
|
404
|
+
"intervalMs",
|
|
405
|
+
"samples"
|
|
406
|
+
],
|
|
407
|
+
"additionalProperties": false,
|
|
408
|
+
"properties": {
|
|
409
|
+
"intervalMs": {
|
|
410
|
+
"type": "integer"
|
|
411
|
+
},
|
|
412
|
+
"samples": {
|
|
413
|
+
"type": "array",
|
|
414
|
+
"items": {
|
|
415
|
+
"type": "object",
|
|
416
|
+
"required": [
|
|
417
|
+
"at",
|
|
418
|
+
"cpu",
|
|
419
|
+
"memoryUsedBytes",
|
|
420
|
+
"memoryPressure",
|
|
421
|
+
"diskFreeBytes"
|
|
422
|
+
],
|
|
423
|
+
"additionalProperties": false,
|
|
424
|
+
"properties": {
|
|
425
|
+
"at": {
|
|
426
|
+
"type": "integer"
|
|
427
|
+
},
|
|
428
|
+
"cpu": {
|
|
429
|
+
"type": [
|
|
430
|
+
"number",
|
|
431
|
+
"null"
|
|
432
|
+
]
|
|
433
|
+
},
|
|
434
|
+
"memoryUsedBytes": {
|
|
435
|
+
"type": [
|
|
436
|
+
"number",
|
|
437
|
+
"null"
|
|
438
|
+
]
|
|
439
|
+
},
|
|
440
|
+
"memoryPressure": {
|
|
441
|
+
"enum": [
|
|
442
|
+
0,
|
|
443
|
+
1,
|
|
444
|
+
2,
|
|
445
|
+
null
|
|
446
|
+
]
|
|
447
|
+
},
|
|
448
|
+
"diskFreeBytes": {
|
|
449
|
+
"type": [
|
|
450
|
+
"number",
|
|
451
|
+
"null"
|
|
452
|
+
]
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
"MachineUsage": {
|
|
460
|
+
"type": "object",
|
|
461
|
+
"required": [
|
|
462
|
+
"volumes",
|
|
463
|
+
"memory",
|
|
464
|
+
"load",
|
|
465
|
+
"cpu",
|
|
466
|
+
"sampledAt"
|
|
467
|
+
],
|
|
468
|
+
"additionalProperties": false,
|
|
469
|
+
"properties": {
|
|
470
|
+
"volumes": {
|
|
471
|
+
"type": "array",
|
|
472
|
+
"items": {
|
|
473
|
+
"type": "object",
|
|
474
|
+
"required": [
|
|
475
|
+
"mount",
|
|
476
|
+
"holds",
|
|
477
|
+
"freeBytes",
|
|
478
|
+
"totalBytes"
|
|
479
|
+
],
|
|
480
|
+
"additionalProperties": false,
|
|
481
|
+
"properties": {
|
|
482
|
+
"mount": {
|
|
483
|
+
"type": "string"
|
|
484
|
+
},
|
|
485
|
+
"holds": {
|
|
486
|
+
"type": "array",
|
|
487
|
+
"items": {
|
|
488
|
+
"type": "string"
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
"freeBytes": {
|
|
492
|
+
"type": "number"
|
|
493
|
+
},
|
|
494
|
+
"totalBytes": {
|
|
495
|
+
"type": "number"
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
},
|
|
500
|
+
"memory": {
|
|
501
|
+
"type": "object",
|
|
502
|
+
"required": [
|
|
503
|
+
"totalBytes",
|
|
504
|
+
"usedBytes",
|
|
505
|
+
"pressure"
|
|
506
|
+
],
|
|
507
|
+
"additionalProperties": false,
|
|
508
|
+
"properties": {
|
|
509
|
+
"totalBytes": {
|
|
510
|
+
"type": "number"
|
|
511
|
+
},
|
|
512
|
+
"usedBytes": {
|
|
513
|
+
"type": [
|
|
514
|
+
"number",
|
|
515
|
+
"null"
|
|
516
|
+
]
|
|
517
|
+
},
|
|
518
|
+
"pressure": {
|
|
519
|
+
"enum": [
|
|
520
|
+
"normal",
|
|
521
|
+
"warning",
|
|
522
|
+
"critical",
|
|
523
|
+
null
|
|
524
|
+
]
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
},
|
|
528
|
+
"load": {
|
|
529
|
+
"type": "object",
|
|
530
|
+
"required": [
|
|
531
|
+
"avg1",
|
|
532
|
+
"avg5",
|
|
533
|
+
"avg15",
|
|
534
|
+
"cpus"
|
|
535
|
+
],
|
|
536
|
+
"additionalProperties": false,
|
|
537
|
+
"properties": {
|
|
538
|
+
"avg1": {
|
|
539
|
+
"type": "number"
|
|
540
|
+
},
|
|
541
|
+
"avg5": {
|
|
542
|
+
"type": "number"
|
|
543
|
+
},
|
|
544
|
+
"avg15": {
|
|
545
|
+
"type": "number"
|
|
546
|
+
},
|
|
547
|
+
"cpus": {
|
|
548
|
+
"type": "integer"
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
"cpu": {
|
|
553
|
+
"type": "object",
|
|
554
|
+
"required": [
|
|
555
|
+
"usage",
|
|
556
|
+
"cores"
|
|
557
|
+
],
|
|
558
|
+
"additionalProperties": false,
|
|
559
|
+
"properties": {
|
|
560
|
+
"usage": {
|
|
561
|
+
"type": [
|
|
562
|
+
"number",
|
|
563
|
+
"null"
|
|
564
|
+
]
|
|
565
|
+
},
|
|
566
|
+
"cores": {
|
|
567
|
+
"type": "integer"
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
},
|
|
571
|
+
"sampledAt": {
|
|
572
|
+
"type": "string",
|
|
573
|
+
"format": "date-time"
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
},
|
|
267
577
|
"ClientRequest": {
|
|
268
578
|
"oneOf": [
|
|
269
579
|
{
|
|
@@ -381,6 +691,112 @@
|
|
|
381
691
|
}
|
|
382
692
|
}
|
|
383
693
|
},
|
|
694
|
+
{
|
|
695
|
+
"type": "object",
|
|
696
|
+
"required": [
|
|
697
|
+
"id",
|
|
698
|
+
"method",
|
|
699
|
+
"params"
|
|
700
|
+
],
|
|
701
|
+
"additionalProperties": false,
|
|
702
|
+
"properties": {
|
|
703
|
+
"id": {
|
|
704
|
+
"type": [
|
|
705
|
+
"integer",
|
|
706
|
+
"string"
|
|
707
|
+
]
|
|
708
|
+
},
|
|
709
|
+
"method": {
|
|
710
|
+
"const": "frames.keyframe"
|
|
711
|
+
},
|
|
712
|
+
"params": {
|
|
713
|
+
"type": "object",
|
|
714
|
+
"required": [
|
|
715
|
+
"subscription"
|
|
716
|
+
],
|
|
717
|
+
"additionalProperties": false,
|
|
718
|
+
"properties": {
|
|
719
|
+
"subscription": {
|
|
720
|
+
"type": "string"
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
},
|
|
726
|
+
{
|
|
727
|
+
"type": "object",
|
|
728
|
+
"required": [
|
|
729
|
+
"id",
|
|
730
|
+
"method",
|
|
731
|
+
"params"
|
|
732
|
+
],
|
|
733
|
+
"additionalProperties": false,
|
|
734
|
+
"properties": {
|
|
735
|
+
"id": {
|
|
736
|
+
"type": [
|
|
737
|
+
"integer",
|
|
738
|
+
"string"
|
|
739
|
+
]
|
|
740
|
+
},
|
|
741
|
+
"method": {
|
|
742
|
+
"const": "build.plan"
|
|
743
|
+
},
|
|
744
|
+
"params": {
|
|
745
|
+
"$ref": "#/$defs/BuildPlanParams"
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
},
|
|
749
|
+
{
|
|
750
|
+
"type": "object",
|
|
751
|
+
"required": [
|
|
752
|
+
"id",
|
|
753
|
+
"method"
|
|
754
|
+
],
|
|
755
|
+
"additionalProperties": false,
|
|
756
|
+
"properties": {
|
|
757
|
+
"id": {
|
|
758
|
+
"type": [
|
|
759
|
+
"integer",
|
|
760
|
+
"string"
|
|
761
|
+
]
|
|
762
|
+
},
|
|
763
|
+
"method": {
|
|
764
|
+
"const": "machine.get"
|
|
765
|
+
},
|
|
766
|
+
"params": {
|
|
767
|
+
"type": "object",
|
|
768
|
+
"maxProperties": 0
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
"type": "object",
|
|
774
|
+
"required": [
|
|
775
|
+
"id",
|
|
776
|
+
"method"
|
|
777
|
+
],
|
|
778
|
+
"additionalProperties": false,
|
|
779
|
+
"properties": {
|
|
780
|
+
"id": {
|
|
781
|
+
"type": [
|
|
782
|
+
"integer",
|
|
783
|
+
"string"
|
|
784
|
+
]
|
|
785
|
+
},
|
|
786
|
+
"method": {
|
|
787
|
+
"const": "machine.history"
|
|
788
|
+
},
|
|
789
|
+
"params": {
|
|
790
|
+
"type": "object",
|
|
791
|
+
"additionalProperties": false,
|
|
792
|
+
"properties": {
|
|
793
|
+
"sinceMs": {
|
|
794
|
+
"type": "number"
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
},
|
|
384
800
|
{
|
|
385
801
|
"type": "object",
|
|
386
802
|
"required": [
|
|
@@ -456,6 +872,29 @@
|
|
|
456
872
|
}
|
|
457
873
|
}
|
|
458
874
|
}
|
|
875
|
+
},
|
|
876
|
+
{
|
|
877
|
+
"type": "object",
|
|
878
|
+
"required": [
|
|
879
|
+
"id",
|
|
880
|
+
"method",
|
|
881
|
+
"params"
|
|
882
|
+
],
|
|
883
|
+
"additionalProperties": false,
|
|
884
|
+
"properties": {
|
|
885
|
+
"id": {
|
|
886
|
+
"type": [
|
|
887
|
+
"integer",
|
|
888
|
+
"string"
|
|
889
|
+
]
|
|
890
|
+
},
|
|
891
|
+
"method": {
|
|
892
|
+
"const": "action"
|
|
893
|
+
},
|
|
894
|
+
"params": {
|
|
895
|
+
"$ref": "#/$defs/ActionParams"
|
|
896
|
+
}
|
|
897
|
+
}
|
|
459
898
|
}
|
|
460
899
|
]
|
|
461
900
|
},
|
|
@@ -480,6 +919,15 @@
|
|
|
480
919
|
{
|
|
481
920
|
"$ref": "#/$defs/HelloResult"
|
|
482
921
|
},
|
|
922
|
+
{
|
|
923
|
+
"$ref": "#/$defs/ActionResult"
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
"$ref": "#/$defs/MachineUsage"
|
|
927
|
+
},
|
|
928
|
+
{
|
|
929
|
+
"$ref": "#/$defs/MachineHistory"
|
|
930
|
+
},
|
|
483
931
|
{
|
|
484
932
|
"type": "object",
|
|
485
933
|
"required": [
|
|
@@ -489,6 +937,11 @@
|
|
|
489
937
|
"properties": {
|
|
490
938
|
"subscription": {
|
|
491
939
|
"type": "string"
|
|
940
|
+
},
|
|
941
|
+
"video": {
|
|
942
|
+
"enum": [
|
|
943
|
+
"h264"
|
|
944
|
+
]
|
|
492
945
|
}
|
|
493
946
|
}
|
|
494
947
|
},
|
|
@@ -509,7 +962,7 @@
|
|
|
509
962
|
},
|
|
510
963
|
{
|
|
511
964
|
"type": "object",
|
|
512
|
-
"description": "The payload of `stim stats --json` or `stim
|
|
965
|
+
"description": "The payload of `stim stats --json`, `stim settings --json` or `stim ios|android --plan --json`, or {} for unsubscribe."
|
|
513
966
|
}
|
|
514
967
|
]
|
|
515
968
|
}
|
|
@@ -629,6 +1082,12 @@
|
|
|
629
1082
|
"data": {
|
|
630
1083
|
"type": "string",
|
|
631
1084
|
"contentEncoding": "base64"
|
|
1085
|
+
},
|
|
1086
|
+
"posture": {
|
|
1087
|
+
"enum": [
|
|
1088
|
+
"folded",
|
|
1089
|
+
"unfolded"
|
|
1090
|
+
]
|
|
632
1091
|
}
|
|
633
1092
|
}
|
|
634
1093
|
},
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// The gRPC endpoint a running Android emulator advertises in its discovery file.
|
|
4
|
+
public struct EmulatorEndpoint: Equatable, Sendable {
|
|
5
|
+
public var consolePort: Int
|
|
6
|
+
public var grpcPort: Int
|
|
7
|
+
public var token: String?
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
public enum EmulatorDiscovery {
|
|
11
|
+
// The emulator writes pid_<pid>.ini here on macOS, ignoring XDG_RUNTIME_DIR,
|
|
12
|
+
// and only when it was started with -grpc. `adb emu avd discoverypath`
|
|
13
|
+
// prints the same path.
|
|
14
|
+
static var directory: URL {
|
|
15
|
+
FileManager.default.homeDirectoryForCurrentUser
|
|
16
|
+
.appendingPathComponent("Library/Caches/TemporaryItems/avd/running", isDirectory: true)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public static func parse(_ contents: String) -> EmulatorEndpoint? {
|
|
20
|
+
var values: [Substring: Substring] = [:]
|
|
21
|
+
for line in contents.split(whereSeparator: \.isNewline) {
|
|
22
|
+
guard let separator = line.firstIndex(of: "=") else { continue }
|
|
23
|
+
values[line[..<separator]] = line[line.index(after: separator)...]
|
|
24
|
+
}
|
|
25
|
+
guard let console = values["port.serial"].flatMap({ Int($0) }),
|
|
26
|
+
let grpc = values["grpc.port"].flatMap({ Int($0) })
|
|
27
|
+
else { return nil }
|
|
28
|
+
return EmulatorEndpoint(consolePort: console, grpcPort: grpc, token: values["grpc.token"].map(String.init))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public static func consolePort(serial: String) -> Int? {
|
|
32
|
+
guard serial.hasPrefix("emulator-") else { return nil }
|
|
33
|
+
return Int(serial.dropFirst("emulator-".count))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public static func endpoint(serial: String) -> EmulatorEndpoint? {
|
|
37
|
+
guard let console = consolePort(serial: serial),
|
|
38
|
+
let names = try? FileManager.default.contentsOfDirectory(atPath: directory.path)
|
|
39
|
+
else { return nil }
|
|
40
|
+
for name in names where name.hasPrefix("pid_") && name.hasSuffix(".ini") {
|
|
41
|
+
guard let pid = Int32(name.dropFirst(4).dropLast(4)), kill(pid, 0) == 0,
|
|
42
|
+
let contents = try? String(contentsOf: directory.appendingPathComponent(name), encoding: .utf8),
|
|
43
|
+
let endpoint = parse(contents), endpoint.consolePort == console
|
|
44
|
+
else { continue }
|
|
45
|
+
return endpoint
|
|
46
|
+
}
|
|
47
|
+
return nil
|
|
48
|
+
}
|
|
49
|
+
}
|