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

ConnectionFisherServer

ConnectionFisherServer بخش سرور ConnectionFisherClient است. منتظر probe ثابت کلاینت می‌ماند، با marker ثابت سرور پاسخ می‌دهد و تنها پس از آن اجازه می‌دهد line وارد حالت عادی عبور stream شود.

این node را فقط در مسیری قرار دهید که انتظار دارید ترافیک ConnectionFisherClient را دریافت کند.

جایگاه رایج​

چیدمان سادهٔ TCP:

TcpListener -> ConnectionFisherServer -> TcpConnector

کلاینت متناظر:

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

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

ConnectionFisherClient -> EncryptionClient -> TcpConnector
TcpListener -> EncryptionServer -> ConnectionFisherServer -> TcpConnector

پس از decode شدن داده در هر جفت تونل کلاینت/سرور میانی، سرور باید دقیقاً همان بایت‌های FISH? ارسالی کلاینت را ببیند.

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

  • با دریافت Init در upstream، فقط state محلی line را مقداردهی اولیه می‌کند.
  • upstream Init به next را به تأخیر می‌اندازد.
  • بایت‌های upstream را تا رسیدن دست‌کم ۵ بایت buffer می‌کند.
  • نیاز دارد ۵ بایت اول دقیقاً FISH? باشند.
  • پاسخ ثابت FISH! را downstream به client می‌فرستد.
  • next را تنها پس از رسیدن payload بعد از probe مقداردهی اولیه می‌کند.
  • پس از کامل شدن مرحله probe، payload را به‌صورت عادی عبور می‌دهد.
  • اگر probe نامعتبر باشد یا حجم داده handshake در buffer از حد بگذرد، line را می‌بندد.

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

نمونه تنظیم​

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

در نسخه فعلی settings استفاده نمی‌شود.

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

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

فیلدنوعتوضیح
namestringنام یکتای node در config.
typestringباید دقیقاً "ConnectionFisherServer" باشد.
nextstringاجباری. node stream بعدی که payload بعد از فاز probe را دریافت می‌کند.

ConnectionFisherServer باید node قبلی نیز داشته باشد؛ این node ابتدا یا انتهای chain نیست.

تنظیمات​

در حال حاضر هیچ فیلدی از settings خوانده نمی‌شود.

تبادل Probe​

جهتBytesمعنی
کلاینت به سرورFISH?پنج بایت الزامی ابتدای upstream.
سرور به کلاینتFISH!پس از دریافت probe معتبر ارسال می‌شود.

markerها بایت‌های ثابت ASCII هستند و سازوکار امنیتی محسوب نمی‌شوند.

مرحله‌های سرور​

پیاده‌سازی از سه فاز استفاده می‌کند:

فازرفتار
wait pingبایت‌های upstream تا رسیدن دست‌کم ۵ بایت buffer می‌شوند.
wait payloadprobe معتبر بوده و FISH! فرستاده شده است؛ با این حال next هنوز مقداردهی نشده، مگر اینکه payload اضافه از قبل در buffer باشد.
establishedInit سمت next شروع شده است؛ ورودی نگه‌داشته‌شده پیش از بازنشستگی سرور تخلیه می‌شود.

جریان Handshake​

با دریافت Init در upstream، سرور فقط state محلی line را مقداردهی اولیه می‌کند و هنوز tunnelNextUpStreamInit() را فراخوانی نمی‌کند.

پردازش payloadِ upstream پیش از برقراری کامل:

  1. سرور بایت‌های ورودی را buffer می‌کند.
  2. probe ناقص حداکثر چهار بایت دارد؛ بدنه پس از probe کامل سقف جداگانه 2 MiB دارد.
  3. وقتی حداقل ۵ بایت در دسترس باشد، ۵ بایت اول خوانده می‌شوند.
  4. اگر دقیقاً FISH? نباشند، line بسته می‌شود.
  5. اگر منطبق باشند، FISH! در جهت downstream به سمت previous فرستاده می‌شود.
  6. اگر پس از پنج بایت اول payload‌ی مانده باشد، سرور next را مقداردهی اولیه می‌کند و payload باقی‌مانده را در upstream می‌فرستد.
  7. اگر payload اضافه‌ای نباشد، سرور منتظر payload بعدی upstream می‌ماند؛ سپس next را مقداردهی اولیه و آن payload را ارسال می‌کند.

مسیر ادامه پیش از فراخوانی Init بعدی منتشر می‌شود. همه اعلان‌های Est مربوط به transport، حتی اعلان تکراری از داخل Init، فوری منتقل می‌شوند. payload برای Est منتظر نمی‌ماند.

بدنه همراه FISH? و نخستین payload پس از probe، هنگام پاسخ FISH!، Init بعدی و Est re-entrant جای FIFO خود را حفظ می‌کنند. ترتیب موقت ورودی، شامل بدنه در انتظار بازگشت Init، سقف 2 MiB و 1,024 buffer دارد و در همان dispatch پذیرفته‌شده تکمیل می‌شود. Pause یا Est به‌تنهایی صف داده آماده ایجاد نمی‌کنند. probe ناقص حداکثر چهار بایت دارد و بدنه پس از probe کامل سقف جداگانه 2 MiB دارد. بسته‌شدن در Init یا Est داده محلی قدیمی را آزاد می‌کند.

رفتار Lifecycle​

قبل از establishment:

  • Init در upstream فقط محلی است.
  • upstream payload به‌عنوان probe یا اولین payload بعد از probe در نظر گرفته می‌شود
  • آخرین Pause در upstream برای ارسال پس از Init سمت next نگه داشته می‌شود؛ Resume آن را لغو می‌کند، حتی هنگام ورود مجدد در Init.
  • Est، Pause و Resume در downstream عبور داده نمی‌شوند.
  • payloadِ downstream در این مرحله غیرمنتظره است؛ buffer آن برای استفاده مجدد برمی‌گردد و line بسته می‌شود.

بعد از establishment:

  • payloadِ upstream به next فرستاده می‌شود.
  • payloadِ downstream به node قبلی می‌رود.
  • Pause و Resume در upstream، از جمله اعلان‌های تکراری، به next فرستاده می‌شوند.
  • Est، Pause و Resume در downstream، از جمله اعلان‌های تکراری، به node قبلی می‌روند.

پس از اتمام Init سمت next، ارسال Pause باقی‌مانده و تخلیه همه ورودی پذیرفته‌شده، سرور state خط را آزاد و کاملاً صفر می‌کند و روی همان line برای همیشه bypass می‌شود. این کار برای Est یا Resume منتظر نمی‌ماند. Pause یا Resume تازه هنگام Init، ارسال درخواست قدیمی را لغو می‌کند. callback‌های بعدی مستقیماً میان همسایه‌ها عبور می‌کنند.

پیش از bypass، با دریافت Finish در upstream، سرور state محلی را از بین می‌برد. تنها در صورتی Finish را در upstream منتشر می‌کند که next قبلاً مقداردهی اولیه شده باشد. اگر پیش از ایجاد سمت next خطای پروتکل رخ دهد، فقط سمت previous بسته می‌شود، زیرا هنوز line‌ای در سمت next وجود ندارد.

محدودیت‌ها​

محدودیتمقداررفتار
طول probe5 بایتپنج بایت نخست باید FISH? باشند.
probe ناقص4 بایتprobe کامل پنج‌بایتی بی‌درنگ اعتبارسنجی می‌شود.
داده pending برنامه2 MiB / 1,024 buffersبدنه در انتظار Init نیز شمرده می‌شود؛ marker از سقف کم نمی‌کند.
required_padding_left0سرور چیزی به buffer‌های موجود اضافه نمی‌کند.

برای پاسخ FISH! یک buffer کوچک جداگانه گرفته می‌شود.

نکته‌ها​

  • با ConnectionFisherClient متناظر استفاده کنید.
  • آن را پس از هر تونل سمت سرور قرار دهید که transport میان کلاینت و سرور را decode می‌کند.
  • برای chain‌های stream طراحی شده است، نه packet-line.
  • probe ثابت و عمومی است؛ برای امنیت واقعی از node‌های دیگر WaterWall استفاده کنید.
  • upstream Est و downstream Init برای این node غیرفعال هستند.

پشتیبانی از splice و بازنشستگی state راه‌اندازی​

هر دو node، buffer عادی و payload موجود در pipe خصوصی را می‌پذیرند. هر delivery که وارد parsing handshake یا ترتیب‌دهی هنگام انتخاب child شود، با sbufEnsureOrdinary() کامل به buffer عادی تبدیل می‌شود. FIFO برنامه buffer را بدون خواندن محتوا نگه می‌دارد. marker کامل پنج‌بایتی می‌تواند تا 2 MiB داده برنامه همراه داشته باشد؛ marker از سقف داده برنامه کم نمی‌کند و marker ناقص حداکثر چهار بایت دارد.

پس از راه‌اندازی و تخلیه FIFO، client فضای handshake و صف خالی را آزاد می‌کند، اما نگاشت main به child منتخب و کنترل جریان endpoint برای payload، فشار و Finish باقی می‌ماند. server پس از اتمام Init سمت backend و replay، همه state خط را آزاد و صفر می‌کند و روی همان line برای همیشه bypass می‌شود. payload آماده بدون inspection، materialization یا سقف backlog راه‌اندازی عبور می‌کند. server همچنان backend را با نخستین payload برنامه مقداردهی می‌کند؛ childهای بازنده اتصال backend نمی‌سازند. برای TCP آماده، ترجیح خواندن عادی ثبت نمی‌شود.

متادیتای نود​

metadata برگرفته از کد منبع:

ویژگیمقدار
node flagskNodeFlagSupportsSplice
can_have_prevtrue
can_have_nexttrue
layer_groupkNodeLayer4
layer_group_prev_nodekNodeLayer4
layer_group_next_nodekNodeLayer4
required_padding_left0 bytes