From fda636ac32ce9933785bd2aec9ed4f60ba89a996 Mon Sep 17 00:00:00 2001 From: RyuJongJin <266630912+RyuJongJin@users.noreply.github.com> Date: Tue, 20 Oct 2026 23:51:39 +0900 Subject: [PATCH] =?UTF-8?q?WIP=20=EC=8B=9C=ED=97=98=20=ED=9D=94=EB=93=A4?= =?UTF-8?q?=EB=A6=BC:=20dns=20TC=20=EC=8B=9C=ED=97=98=EC=9D=98=20=EA=B0=80?= =?UTF-8?q?=EC=A7=9C=20DNS=20-=20=EB=A7=89=ED=9E=8C=20=ED=8F=AC=ED=8A=B8?= =?UTF-8?q?=20(Windows=2010013,=20Hyper-V=20=EB=A7=89=EC=95=84=20=EB=91=94?= =?UTF-8?q?=20=EB=B2=94=EC=9C=84)=20=EC=9D=98=20UDP=20=EC=97=B4=EA=B8=B0?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=EA=B0=80=20try=20=EB=B0=96=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20(=EC=9E=A1=ED=9E=88=EC=A7=80=20=EC=95=8A=EC=9D=80?= =?UTF-8?q?=20=EB=B9=84=EB=8F=99=EA=B8=B0=20=EC=98=A4=EB=A5=98)=20?= =?UTF-8?q?=EB=82=98=EC=99=80=20=EC=8B=A4=ED=8C=A8=ED=95=98=EB=8D=98=20?= =?UTF-8?q?=EA=B2=83=20(wt=5Fb3=20=EB=B0=98=EB=B3=B5=203=EB=B2=88=20?= =?UTF-8?q?=EC=A4=91=201=EB=B2=88=20=C2=B7=20=EA=B4=80=EB=A6=AC=EC=9E=90?= =?UTF-8?q?=20=EC=A0=84=EC=B2=B4=20=EC=8B=A4=ED=96=89)=20-=20=EC=97=B4?= =?UTF-8?q?=EA=B8=B0=EB=A5=BC=20=EB=94=B0=EB=A1=9C=20zone=20=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EB=8F=8C=EB=A0=A4=20=EC=96=B4=EB=8A=90=20=EC=AA=BD?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=98=A4=EB=93=A0=20=EB=8B=A4=EB=A5=B8=20?= =?UTF-8?q?=EB=B2=88=ED=98=B8=EB=A1=9C=20=EB=8B=A4=EC=8B=9C=20(=EA=B2=80?= =?UTF-8?q?=ED=86=A0=20=EB=8C=80=EA=B8=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- test/support/fake_dns.dart | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/test/support/fake_dns.dart b/test/support/fake_dns.dart index 83ef0ee..adfc983 100644 --- a/test/support/fake_dns.dart +++ b/test/support/fake_dns.dart @@ -20,6 +20,24 @@ class FakeDns { int get port => _udp.port; + /// 그 번호로 UDP 를 연다 (못 열면 null). 전체 시험 (10/20) 에서 막힌 포트 (10013) 의 오류가 try 밖으로 (잡히지 않은 비동기 오류로) + /// 나와 시험이 실패한 적이 있어, 열기 하나를 따로 영역 (zone) 에서 돌려 어느 쪽으로 오든 "못 열었음" 으로 받는다 + Future _tryUdp(int port) { + final done = Completer(); + runZonedGuarded(() async { + final s = await RawDatagramSocket.bind(InternetAddress.loopbackIPv4, port); + if (done.isCompleted) { + s.close(); + } else { + done.complete(s); + } + }, (e, _) { + events.add('udp bind $port failed: ${e is SocketException ? '${e.osError?.errorCode} ${e.message}' : e}'); + if (!done.isCompleted) done.complete(null); + }); + return done.future; + } + Future start() async { if (!truncateUdp) { _udp = await RawDatagramSocket.bind(InternetAddress.loopbackIPv4, 0); @@ -29,16 +47,15 @@ class FakeDns { // 그 번호의 UDP 가 막혀 있거나 (10013) 쓰는 중이면 다른 번호로 다시 for (var i = 0;; i++) { final tcp = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0); - try { - _udp = await RawDatagramSocket.bind(InternetAddress.loopbackIPv4, tcp.port); + final udp = await _tryUdp(tcp.port); + if (udp != null) { + _udp = udp; _tcp = tcp; events.add('bound tcp+udp ${tcp.port} (try $i)'); break; - } on SocketException catch (e) { - events.add('udp bind ${tcp.port} failed: ${e.osError?.errorCode} ${e.message}'); - await tcp.close(); - if (i > 50) rethrow; } + await tcp.close(); + if (i > 50) throw StateError('UDP 포트를 열지 못함: $events'); } } _udp.listen((e) {