پرش به مطلب اصلی

ConnectionFisherClient

ConnectionFisherClient بخش کلاینت ConnectionFisherServer است. برای هر line ورودی، چند child line را هم‌زمان به سمت next باز می‌کند و probe پنج‌بایتی FISH? را روی هرکدام می‌فرستد. نخستین child line که پاسخ معتبر FISH! بگیرد انتخاب می‌شود و بقیه بسته می‌شوند.

این نود زمانی کاربرد دارد که مسیر خروجی پایدار نیست یا می‌خواهید چند اتصال را هم‌زمان امتحان کنید و اولین مسیری را برگزینید که رسیدن به ConnectionFisherServer متناظر را تأیید می‌کند.

جایگاه رایج

طرح‌بندی ساده TCP:

TcpListener -> ConnectionFisherClient -> TcpConnector
TcpListener -> ConnectionFisherServer -> TcpConnector

همراه با تونل‌های stream دیگر در میانه مسیر:

TesterClient -> ConnectionFisherClient -> MuxClient -> MuxServer -> ConnectionFisherServer -> TesterServer

کلاینت و سرور باید دو سر یک مسیر منطقی stream باشند. هر تونل میانی باید بایت‌های ثابت probe را بدون تغییر عبور دهد.

این نود چه می‌کند؟

  • مقدار settings.simultaneous-tries-perline را می‌خواند.
  • با هر Init در جهت upstream روی main line، به تعداد تنظیم‌شده child line داخلی می‌سازد.
  • upstream Init را روی هر child line به next می‌فرستد.
  • probe ثابت FISH? را روی هر child line می‌فرستد.
  • منتظر پاسخ ثابت FISH! می‌ماند.
  • تا زمان انتخاب یک child، payloadِ upstream روی main line را در صف نگه می‌دارد.
  • اولین child که پاسخ معتبر دریافت کند را انتخاب می‌کند.
  • همه child lineهای انتخاب‌نشده را می‌بندد.
  • payloadهای upstream صف‌شده را به ترتیب برای child انتخاب‌شده می‌فرستد.
  • payloadهای downstream از child انتخاب‌شده را به main line برمی‌گرداند.

ConnectionFisherClient یک تونل میانی stream است. مستقیماً socket یا packet line نمی‌سازد.

نمونه تنظیم

{
"name": "fisher-client",
"type": "ConnectionFisherClient",
"settings": {
"simultaneous-tries-perline": 3
},
"next": "tcp-out"
}

سمت سرور متناظر:

{
"name": "fisher-server",
"type": "ConnectionFisherServer",
"next": "service"
}

فیلدهای اجباری

فیلدهای سطح اصلی:

فیلدنوعتوضیح
namestringنام یکتای نود در پیکربندی.
typestringباید دقیقاً "ConnectionFisherClient" باشد.
nextstringاجباری. نود stream بعدی که child lineهای نامزد را می‌گیرد.

ConnectionFisherClient باید نود قبلی نیز داشته باشد؛ این نود ابتدا یا انتهای chain نیست.

تنظیمات اختیاری

گزینهنوعپیش‌فرضتوضیح
simultaneous-tries-perlineinteger >= 12تعداد child lineهای نامزد که برای هر main line ورودی ساخته می‌شوند.

settings می‌تواند حذف شود. مقادیر کمتر از 1 رد می‌شوند.

تبادل Probe

Probe مقدار ثابتی دارد و secret قابل تنظیمی برای آن وجود ندارد:

جهتBytesمعنی
کلاینت به سرورFISH?بلافاصله پس از Init در upstream، روی هر child line فرستاده می‌شود.
سرور به کلاینتFISH!پاسخ الزامی ConnectionFisherServer.

این markerها فقط نشان می‌دهند که child line به ConnectionFisherServer متناظر رسیده است؛ هیچ احراز هویت، رمزنگاری یا تضمین صحتی برای ترافیک فراهم نمی‌کنند.

مدل Line

ConnectionFisherClient از دو نوع line استفاده می‌کند:

Lineهدف
main lineline ورودی اصلی از نود قبلی که در سمت previous باقی می‌ماند.
child lineslineهای نامزد داخلی که کلاینت می‌سازد و فقط به سمت next می‌روند.

Main line هیچ‌گاه مستقیم به next فرستاده نمی‌شود و child lineها نیز هرگز به سمت prev نمی‌روند. پس از انتخاب یک child، تونل payload و callbackهای Est، Pause، Resume و Finish را به‌صورت دستی میان main line و child منتخب جابه‌جا می‌کند.

جریان انتخاب

برای هر upstream Init روی main line:

  1. state مربوط به main line مقداردهی اولیه می‌شود.
  2. simultaneous-tries-perline child line روی همان worker ساخته می‌شود.
  3. هر child line به سمت next مقداردهی اولیه می‌شود.
  4. هر child، FISH? می‌فرستد.
  5. برای main line یک timeout انتخاب به مدت 5000 ms زمان‌بندی می‌شود.
  6. تا مشخص شدن child برنده، payloadِ upstream روی main line در صف می‌ماند.
  7. اولین child که FISH! دریافت کند، child انتخاب‌شده می‌شود.
  8. child lineهای بازنده بسته می‌شوند.
  9. payloadهای upstream صف‌شده برای child منتخب فرستاده می‌شوند.
  10. بایت‌های اضافه downstream که پس از FISH! از قبل بافر شده‌اند، به‌عنوان payloadِ downstream به نود قبلی فرستاده می‌شوند.

اگر هیچ child پیش از timeout معتبر شناخته نشود، main line بسته می‌شود.

محدودیت‌ها و Buffer

محدودیتمقداررفتار
Selection timeout5000 msاگر child‌ای انتخاب نشود، main line بسته می‌شود.
Pending upstream payload1 MiBاگر payload صف‌شده از این حد بگذرد، main line بسته می‌شود.
Child handshake buffer4096 bytesاگر یک child انتخاب‌نشده بیش از حد داده handshake جمع کند، main line بسته می‌شود.
required_padding_left0نود header پروتکل را به بافرهای موجود اضافه نمی‌کند.

برای probeِ FISH? یک بافر کوچک جداگانه گرفته می‌شود. Payload کاربر در همان بافرهای WaterWall در صف می‌ماند یا ارسال می‌شود.

رفتار Lifecycle

قبل از انتخاب:

  • payload upstream از main line در صف قرار می‌گیرد
  • payload downstream از child به‌عنوان داده handshake در نظر گرفته می‌شود
  • Est در downstream، child را برقرارشده علامت می‌زند؛ اما تنها وقتی به main line فرستاده می‌شود که آن child از قبل انتخاب شده باشد.
  • pause و resume تا زمان انتخاب child، به main line منعکس نمی‌شوند

بعد از انتخاب:

  • payloadِ upstream روی main line با tunnelNextUpStreamPayload به child منتخب فرستاده می‌شود.
  • payloadِ downstream روی child منتخب با tunnelPrevDownStreamPayload به نود قبلی می‌رود.
  • Est در downstream از child منتخب تنها یک بار به نود قبلی فرستاده می‌شود.
  • Pause و resume فقط میان child منتخب و main line جابه‌جا می‌شوند.

اگر child منتخب بسته شود، main line نیز بسته می‌شود. اگر همه childها پیش از انتخاب برنده بسته شوند، main line هم بسته خواهد شد.

نکته‌ها

  • با ConnectionFisherServer متناظر استفاده کنید.
  • برای chainهای stream طراحی شده است، نه packet-line.
  • افزایش simultaneous-tries-perline تعداد و بار اتصال‌ها را نیز بالا می‌برد.
  • Probe ثابت و عمومی است؛ در مسیرهایی که به امنیت نیاز دارند از TLS یا نودهای رمزنگاری، احراز هویت و مسیریابی استفاده کنید.
  • upstream Est و downstream Init برای این نود غیرفعال هستند.