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

HttpProxyServer

این node میانی لایهٔ ۴، درخواست‌های پراکسی HTTP/1.0 و HTTP/1.1 و تونل CONNECT را از مسیر خروجی انتخاب‌شده عبور می‌دهد:

TcpListener -> HttpProxyServer -> configured outbound chain

آدرس و port مربوط به listener در TcpListener تنظیم می‌شوند. درخواست عادی باید URI مطلق با scheme برابر http:// داشته باشد. همین URI برای مسیریابی و ساخت Host استفاده می‌شود؛ Host ورودی حتی در صورت متفاوت بودن، مقصد را عوض نمی‌کند. HTTPS از CONNECT با پورت صریح ۱ تا ۶۵۵۳۵ استفاده می‌کند. پاسخ موفق CONNECT فقط بعد از برقراری واقعی خروجی و پیش از دادهٔ مقصد ارسال می‌شود. پس از آن داده‌ها بدون تفسیر HTTP عبور می‌کنند.

HttpClient و HttpServer برای انتقال دادهٔ WaterWall در قالب HTTP هستند. این node از پورت مشترک SOCKS/HTTP، پراکسی خروجی HTTP، TLS interception، Upgrade/WebSocket یا رابط پراکسی HTTP/2 و HTTP/3 پشتیبانی نمی‌کند. متدهای افزوده مثل PROPFIND عبور می‌کنند؛ TRACE با 405 رد می‌شود. OPTIONS با مقصد ستاره یا Max-Forwards صفر، پس از احراز هویت پاسخ محلی خالی می‌گیرد و اتصال بسته می‌شود. در OPTIONS خروجی، Max-Forwards یک واحد کم می‌شود.

پذیرش از cache محلی​

پس از نخستین همگام‌سازی معتبر جدول و مبنای ساعت، authenticationclientCanAuthenticate() در قطع شبکه و احراز هویت دوباره از آخرین cache حافظه استفاده می‌کند؛ cache مهلت کهنگی ندارد. enabled، انقضا، سهمیه ترافیک و reservation محلی اتصال/IP همچنان اعمال می‌شوند. نبود cache، توقف، خطای نهایی continuity یا رد صریح اعتبارنامه خود کلاینت، پذیرش جدید را می‌بندد. فقط پاسخ موفق و معتبر Session رد صریح را پاک می‌کند؛ timeout، قطع اتصال، پاسخ خراب و authentication-required چنین اثری ندارند. اتصال‌های قبلاً مجاز به ثبت مصرف و اجرای محدودیت‌های محلی ادامه می‌دهند. هر درخواست HTTP روی اتصال reused پذیرش تازه است؛ exchange جاری و CONNECT ادامه می‌یابند. ویرایش مدیر پس از refresh معتبر می‌رسد. دو کلاینت قطع‌شده با مصرف شناخته‌شده ۸۰ از سهمیه ۱۰۰ گیگابایت می‌توانند هر کدام ۲۰ مصرف کنند و مجموع نهایی ۱۲۰ شود؛ سهمیه و reservation محلی، تضمین سراسری نیستند.

تنظیمات​

کلیدپیش‌فرض و محدوده
no-authfalse؛ برای دسترسی بدون احراز هویت true باشد و دو انتخاب دیگر حذف شوند
usersآرایهٔ غیرخالی از object‌هایی با فیلدهای username و password؛ دسترسی نامحدود و بدون ثبت مصرف، مطابق هشدار زیر
auth-client-node-nameنام AuthenticationClient برای حساب‌های قابل پیگیری؛ با users و no-auth=true ناسازگار است
fallback-node-nameنام شاخهٔ مستقل لایهٔ ۴؛ فقط شکست احراز هویت اولین درخواست؛ شامل ارسال بایت‌های اطلاعات ورود اصلی
sweep-interval-ms1000؛ فاصلهٔ بررسی سیاست توسط UserController داخلی
max-header-bytes32768؛ بین 1024 و 65536 برای هر بلوک header
max-pending-bytes262144؛ بین 65536 و 1048576 و حداقل برابر محدودیت header
header-timeout-ms15000؛ مهلت header ناقص از اولین بایت، بدون تمدید با ورودی قطره‌ای
connect-timeout-ms30000؛ از Init child تا Est واقعی، شامل DNS و مسیریابی
idle-timeout-ms300000؛ مهلت نبود پیشرفت در درخواست، پاسخ، بدنه، اتصال بیکار و تونل
verbosefalse؛ رمزها و header کامل ورودی ثبت نمی‌شوند

هشدار کاربران محلی: users فقط دسترسی با نام کاربری و رمز می‌دهد. مصرف کاربران با این اطلاعات ورود در سامانهٔ حساب کاربری WaterWall پیگیری نمی‌شود و سهمیهٔ ترافیک، محدودیت اتصال/IP، پهنای باند یا انقضای حساب برای هر کاربر اعمال نمی‌شود. مجوزهای هر کاربر نامحدود است و امکان سوءاستفاده از دسترسی یا تمام‌کردن منابع سرور وجود دارد. برای حساب‌های قابل پیگیری و محدودیت‌های پشتیبانی‌شده از auth-client-node-name استفاده کنید. محدودیت buffer پراکسی، مهلت‌ها، سیاست مسیریابی و کنترل‌های جداگانه همچنان اعمال می‌شوند.

مهلت‌ها و فاصلهٔ sweep عدد صحیح بین ۱ و 2147483647 میلی‌ثانیه هستند. تنظیمات ناشناخته، تکراری، ناسازگار یا با نوع اشتباه، و نبود مسیر بعدی موجب خطای راه‌اندازی می‌شوند. توپولوژی به همسایهٔ لایهٔ ۴ در هر دو سمت نیاز دارد.

حدود ثابت: start line برابر 8192 بایت، 128 فیلد header، خط chunk-size و extension آن برابر 1024 بایت، بخش trailer برابر 16384 بایت و 64 فیلد، و حداکثر 32 پاسخ اطلاعاتی برای هر تبادل. مجموع داده‌های pending در هر دو جهت، همراه با header‌های خروجی محاسبه می‌شود. بودجهٔ کاری چهار buffer تجمیع‌شده را پوشش می‌دهد و هزینهٔ تخصیص آن‌ها از چهار برابر max-pending-bytes بیشتر نمی‌شود. حافظهٔ موقت parse کردن header و اطلاعات ورود جداگانه محدود است. body به‌صورت streaming پردازش می‌شود؛ محدودیت buffer، محدودیت اندازهٔ بدنه نیست. Pause تولید را متوقف می‌کند و Resume پس از کاهش صف اعمال می‌شود.

احراز هویت و حسابداری​

در بدنهٔ chunked حداکثر دو بلوک header با حد مستقل max-header-bytes برای بررسی trailer نگه‌داری می‌شود تا فیلدهای hop-by-hop نام‌برده در Connection نیز رد شوند. این بلوک‌ها با تکمیل بدنه یا بستن session آزاد می‌شوند.

دقیقاً یک حالت انتخاب کنید: no-auth: true، فهرست محلی users یا auth-client-node-name. در دو حالت دارای احراز هویت، no-auth می‌تواند غایب یا false باشد. انتخاب‌های متعارض حتی با مقدار null یا نامعتبر رد می‌شوند؛ آرایهٔ خالی دسترسی بدون احراز هویت ایجاد نمی‌کند.

هر عضو users دقیقاً دو فیلد اجباری username و password از نوع string دارد. هرکدام پس از parse شدن باید ۱ تا ۲۵۵ بایت داشته باشند و شامل بایت کنترلی یا DEL نباشند. نام کاربری نمی‌تواند دونقطه داشته باشد؛ رمز می‌تواند. تطبیق دقیق و حساس به بزرگی و کوچکی حروف است؛ فاصله حذف نمی‌شود و Unicode یا encoding تبدیل نمی‌شود. بایت‌های UTF-8 تنظیم‌شده و ارسالی باید یکسان باشند. NUL داخلی پشتیبانی نمی‌شود و در دادهٔ شبکه رد می‌شود؛ از نمایش فعلی string در cJSON استفاده می‌شود. زوج کاملاً تکراری، فیلد تکراری و فیلد ناشناخته مانند limit، enabled یا expire-at-ms خطای راه‌اندازی است. یک نام با رمزهای متفاوت یا نام‌های متفاوت با رمز مشترک مجاز است؛ هر دو جزء باید با یک عضو فهرست منطبق باشند.

فهرست محلی هنگام راه‌اندازی کپی و تا پایان اجرا ثابت نگه‌داری می‌شود. تغییر آن نیاز به اجرای مجدد WaterWall با تنظیمات جدید دارد؛ ویرایش زنده، لغو دسترسی در زمان اجرا و hot reload ارائه نمی‌شود. رمزها در تنظیمات ذخیره می‌شوند و HTTP Basic به‌خودی‌خود آن‌ها را رمزنگاری نمی‌کند.

Proxy-Authorization از نوع Basic در هر درخواست، حتی هنگام استفادهٔ مجدد از اتصال، بررسی می‌شود. اگر اطلاعات ورود وجود نداشته باشد، نامعتبر باشد یا رد شود، پاسخ 407 با Proxy-Authenticate: Basic realm="WaterWall"، بدنهٔ خالی و Connection close برمی‌گردد. فقط در حالت حساب قابل پیگیری، نبود دسترسی به cache مجاز سرویس احراز هویت پاسخ 503 می‌دهد؛ حالت محلی به این سرویس مراجعه نمی‌کند. OPTIONS محلی هم احراز هویت می‌شود و CONNECT پیش از ایجاد child احراز هویت می‌شود. فیلد تکراری اطلاعات ورود خطای قالب درخواست است.

Base64 باید معتبر و canonical باشد. نام کاربری و رمز هر کدام ۱ تا ۲۵۵ بایت‌اند و نباید NUL یا نویسهٔ کنترلی داشته باشند. اولین دونقطه جداکننده است. بایت‌های اطلاعات ورود ذخیره‌شده و ارسالی باید دقیقاً برابر باشند، از جمله UTF-8؛ تبدیل charset یا نرمال‌سازی Unicode انجام نمی‌شود. فیلد password کاربر در AuthenticationServer مقدار کامل username:password را نگه می‌دارد؛ name فقط metadata است. Proxy-Authorization در حالت no-auth نیز حذف می‌شود؛ Authorization مقصد تغییر نمی‌کند.

فقط در حالت حساب قابل پیگیری، UserController داخلی افزوده می‌شود؛ برای همین لایه کنترلر دیگری دستی اضافه نکنید. child خروجی، marker‌های کاربر را از line اصلی به ارث می‌برد و handle معتبر، اطلاعات ورود، آدرس مبدأ و port‌های listener و peer را دریافت می‌کند. محدودیت‌های پشتیبانی‌شدهٔ اتصال، ترافیک و لغو دسترسی در زمان اجرا با کنترلر موجود اعمال می‌شوند. CONNECT یک بار احراز هویت می‌شود ولی کنترل سیاست حساب در طول تونل ادامه دارد. حالت محلی مستقیماً وارد chainِ خروجی می‌شود و فقط یک marker اطلاعات ورود بدون handle حساب به هر child جدید اضافه می‌کند؛ رکورد حساب، گزارش مصرف، رزرو اتصال/IP یا timer سیاست کاربر ایجاد نمی‌کند. هویت به‌ارث‌رسیده و کنترل‌های مستقل حفظ می‌شوند. marker‌ها روی line کلاینت از نوع borrowed یا child استفاده‌شدهٔ مجدد انباشته نمی‌شوند.

جریان داده، استفادهٔ مجدد و مسیریابی​

بدنه‌های fixed-length و chunked در هر دو جهت، پاسخ با مرز EOF، HEAD و پاسخ بی‌بدنه، پاسخ‌های اطلاعاتی، Expect: 100-continue و پاسخ نهایی زودهنگام پشتیبانی می‌شوند. پاسخ نهایی زودهنگام آپلود را متوقف می‌کند و اتصال پس از تحویل پاسخ بسته می‌شود. فیلدهای hop-by-hop فیلتر و Via افزوده می‌شود. وضعیت واقعی مقصد، cookie، redirect، چالش احراز هویت و محتوا حفظ می‌شوند؛ redirect به‌صورت خودکار دنبال نمی‌شود.

Content-Length تکراری یا فهرستی، CL همراه Transfer-Encoding، transfer encoding پشتیبانی‌نشده، folded header، مقصد نامعتبر و chunk/trailer خراب رد می‌شوند. header کامل، مقصد و احراز هویت پیش از ایجاد خروجی بررسی می‌شوند. خطای بعدی بدنه باعث بستن تبادل می‌شود؛ دادهٔ قبلاً ارسال‌شده قابل بازگرداندن نیست. پس از ارسال پاسخ نهایی، خطا پاسخ دوم تولید نمی‌کند.

برای هر کلاینت حداکثر یک child خروجی زنده وجود دارد. درخواست‌ها حتی با ورودی pipelined به‌ترتیب اجرا می‌شوند. استفادهٔ مجدد به تکمیل هر دو بدنه، سلامت اتصال، مقصد و حالت احراز هویت یکسان وابسته است. حالت محلی نام کاربری و رمز یکسان می‌خواهد؛ حالت حساب قابل پیگیری علاوه بر اطلاعات ورود، user ID/generation یکسان می‌خواهد. نام domain بدون حساسیت به بزرگی و کوچکی حروف و IP با بایت آدرس مقایسه می‌شود. دامنه‌های متفاوت یا نقطهٔ پایانی DNS ادغام نمی‌شوند. تغییر مقصد یا هویت child تازه ایجاد می‌کند. درخواست مسیر محافظت‌شده خودکار تکرار نمی‌شود.

دامنه به chainِ تنظیم‌شده سپرده می‌شود؛ DNS، انتخاب IPv4/IPv6 و اتصال socket خصوصی در این node وجود ندارد. IPv4 باید dotted-decimal دقیق و IPv6 داخل کروشه باشد. دامنه ASCII/A-label پذیرفته می‌شود. userinfo، fragment، authority کدشده، zone identifier، آدرس عددی مبهم و پورت نامعتبر رد می‌شوند. بایت‌های escaped مسیر و query حفظ می‌شوند.

کنترلر می‌تواند خروجی را با chainِ سازگار مانند Router یا تونل راه‌دور جایگزین کند. authority درخواست‌شده، IP محلی resolve‌شده و peer نهایی transport ممکن است متفاوت باشند. اتصال استفاده‌شدهٔ مجدد مسیر قبلی را حفظ می‌کند؛ child تازه دوباره مسیریابی می‌شود.

کلاینت HTTP/1.0 یک تبادل دارد و بسته می‌شود. یک فیلد Expect: 100-continue در درخواست عادی HTTP/1.0 نادیده گرفته و پیش از ارسال به مقصد حذف می‌شود؛ بدنه بدون انتظار برای پاسخ Continue ارسال می‌شود. پاسخ chunked برای آن به بدنهٔ close-delimited تبدیل و trailer حذف می‌شود. پاسخ Connection close قبل از بستن کامل تحویل داده می‌شود. رفتار فعلی آداپتورهای TCP در POSIX و Windows IOCP، EOF خواندن را به بستن کامل تبدیل می‌کند؛ half-close کامل و دریافت ترافیک برگشتی تازه پس از EOF تضمین نمی‌شود.

line ورودی از نوع borrowed است و مالک آن node مبدأ است. HttpProxyServer فقط child خروجی خود را می‌سازد، فهرست می‌کند و از بین می‌برد. این node انتهای line ورودی و ابتدای child است، حتی هنگام relay در CONNECT و fallback؛ بنابراین برای نگاشت payload، فشار و بستن بین دو line فعال می‌ماند. کنترل تولید را حفظ می‌کند و Pause/Resume تکراری را بدون اثر اضافی می‌پذیرد؛ bypass دائمی تونل برای این ارتباط قابل اعمال نیست. در quiescence، timer‌ها جدا و کار تازه متوقف می‌شود؛ drain child مستقل از ترتیب توقف مبدأ است.

نمونه‌های کامل​

در مخزن، core.json و config.json کامل موجود است:

  • tunnels/HttpProxyServer/examples/noauth/: SOCKS روی loopback:1080 و HTTP روی loopback:8080 با connector‌های جدا.
  • tunnels/HttpProxyServer/examples/local-users/: HTTP روی loopback:8080 با دو زوج محلی نمونه و بدون سرویس یا دیتابیس حساب.
  • tunnels/HttpProxyServer/examples/authenticated/: HTTP روی loopback:8080، سرویس احراز هویت و users.json با نمونهٔ user:pass.

از پوشهٔ نمونه اجرا کنید تا مسیرهای نسبی درست باشند:

/path/to/Waterwall --restricted-config --config:core.json

در ویندوز مسیر مطلق Waterwall.exe و همان آرگومان‌ها را استفاده کنید. هویت اجرا باید شرایط elevation لانچر ویندوز را داشته باشد. صلاحیت فایل اجرایی، ترکیب CPU/OS، IOCP، کنسول و recovery جداگانه بررسی می‌شود.

نمونهٔ tests/cases/http_proxy/ مسیر Router را با مقصد sentinel آزمایش می‌کند؛ مقصد انتقال درخواست‌شده در آن آزمون در دسترس نیست، بنابراین موفقیت وابسته به مسیر تنظیم‌شده است.

نمونهٔ مستقل کاربران محلی​

هشدار دسترسی نامحدود و بدون پیگیری: users فقط نام کاربری و رمز را بررسی می‌کند. مصرف در سامانهٔ حساب WaterWall ثبت نمی‌شود؛ سهمیهٔ ترافیک، محدودیت اتصال/IP یا پهنای باند و انقضای حساب برای این کاربران وجود ندارد. امکان سوءاستفاده یا تمام‌کردن منابع سرور وجود دارد. برای حساب قابل پیگیری و محدودیت‌های پشتیبانی‌شده auth-client-node-name را انتخاب کنید. buffer، مهلت، مسیریابی و کنترل‌های مستقل همچنان اعمال می‌شوند.

نمونهٔ کامل local-users chainِ TcpListener -> HttpProxyServer -> TcpConnector و تنظیمات زیر را دارد:

{
"users": [
{ "username": "alice", "password": "replace-alice-password" },
{ "username": "bob", "password": "replace-bob-password" }
]
}

از پوشهٔ tunnels/HttpProxyServer/examples/local-users/ در ویندوز اجرا کنید: ../../../../build/msvc/Release/Waterwall.exe --restricted-config. این نمونه به AuthenticationClient، AuthenticationServer یا users.json نیاز ندارد. رمزهای نمونه را پیش از استفاده عوض کنید؛ Basic رمزنگاری فراهم نمی‌کند. برای مقصد HTTP محلی روی پورت 8000:

curl --noproxy "" --proxy http://127.0.0.1:8080 --proxy-basic --proxy-user alice:replace-alice-password http://127.0.0.1:8000/

بودجهٔ کاری P = max-pending-bytes از فضای ورودیِ قبلاً تحویل‌شده جداست. هر جهت یک باقیمانده با حداکثر D = 2 MiB بایت دارد و مجموع بایت‌های نگه‌داری‌شده از P + 2 * D بیشتر نمی‌شود. این حاشیه برای هر جهت ثابت و مستقل از اندازهٔ pool، پروفایل حافظه و تنظیمات splice است. ظرفیت payload هر باقیمانده حداکثر max(small capacity, 2 * D) به‌اضافهٔ گردکردن cache-line است؛ padding، header buffer و سربار alignment جداگانه حساب می‌شوند. باقیمانده‌ها در Pause و تخلیهٔ FIFO و تمام مسیرهای خطا، timeout و Finish لحاظ می‌شوند؛ هزینهٔ چهار buffer کاری همچنان حداکثر 4 * P است.

حد هر ورودی یک‌باره P + D است؛ پیشوندی که فوراً قابل تخلیه باشد پیش از نگه‌داری باقیمانده پردازش می‌شود.

مسیر جایگزین احراز هویت​

گزینهٔ اختیاری fallback-node-name نام غیرخالی یک شاخهٔ مستقل لایهٔ ۴ در همان config است. این شاخه فقط برای شکست احراز هویت اولین درخواست اتصال انتخاب می‌شود: نبود اطلاعات ورود، روش پشتیبانی‌نشده یا کدگذاری Basic ردشده، عدم تطابق کاربر محلی، نبود دسترسی به cache مجاز AuthenticationClient یا جدول کاربران، یا رد حساب به دلیل ناشناخته بودن، عدم تطابق، غیرفعال بودن، انقضا، محدودیت حساب یا نبود شناسهٔ لازم. بدون این گزینه رفتار 407/503 قبلی برقرار است؛ در حالت no-auth این گزینه اثری ندارد.

HTTP نامعتبر، header احراز هویت تکراری، مقصد یا framing نامعتبر، قابلیت پشتیبانی‌نشده، محدودیت یا مهلت header و خطاهای داخلی احراز هویت یا ذخیره‌سازی وارد fallback نمی‌شوند. موفقیت اولین احراز هویت، حتی برای OPTIONS محلی یا CONNECT، انتخاب مسیر محافظت‌شده را برای کل اتصال قطعی می‌کند. شکست احراز هویت درخواست‌های بعدی و خطاهای UserController، مسیریابی، DNS یا اتصال مقصد پس از موفقیت احراز هویت fallback را فعال نمی‌کنند.

شاخهٔ جایگزین یک child line متعلق به پراکسی می‌گیرد و UserController خصوصی این پراکسی را دور می‌زند. header، بدنه و دنبالهٔ درخواست دقیقاً با همان بایت‌ها، مقصد اصلی، فاصله‌ها و بایت‌های اطلاعات ورود ردشده در Proxy-Authorization ارسال می‌شوند؛ سرویس انتخابی باید برای دریافت این اطلاعات قابل اعتماد باشد. پراکسی این اطلاعات را لاگ نمی‌کند. از آن پس کل اتصال یک stream خام است؛ اطلاعات ورود معتبر در داده‌های بعدی آن را به مسیر محافظت‌شده برنمی‌گرداند. هیچ پاسخ محلی 407/503، موفقیت CONNECT، Continue یا OPTIONS تولید نمی‌شود و سرویس جایگزین پاسخ را تعیین می‌کند.

مقصد اتصال را شاخهٔ جایگزین تعیین می‌کند، نه authority درخواست ردشده. وجود next محافظت‌شده همچنان الزامی است. ارجاع به خود پراکسی، کنترلر خصوصی، مسیر محافظت‌شده، چرخه یا هدفی با اتصال قبلی متعلق به مالک دیگر رد می‌شود. این قابلیت تبدیل پروتکل یا تلاش مجدد برای مقصد درخواستی نیست. نمونهٔ node‌های پس از TcpListener:

[
{
"name": "proxy", "type": "HttpProxyServer", "next": "protected",
"settings": {
"users": [{ "username": "alice", "password": "replace-me" }],
"fallback-node-name": "fallback-service"
}
},
{
"name": "protected", "type": "TcpConnector",
"settings": { "address": "dest_context->address", "port": "dest_context->port" }
},
{
"name": "fallback-service", "type": "TcpConnector",
"settings": { "address": "127.0.0.1", "port": 8081 }
}
]

تأخیر عمدی اضافه نمی‌شود. مهلت اتصال از Init child تا Est و مهلت بیکاری برای stream خام برقرارند؛ مهلت header HTTP هنگام تحویل پایان می‌یابد. پاسخ زودهنگام Est مصنوعی ایجاد نمی‌کند. شکست بعد از انتخاب فقط اتصال را می‌بندد. پاسخ‌های پذیرفته‌شده پیش از Finish child، با رعایت Pause گیرنده تخلیه می‌شوند؛ Finish کلاینت داده‌های محلی را فوراً آزاد می‌کند. shutdown مربوط به worker همان فهرست childان را تخلیه می‌کند.

حدود P = max-pending-bytes و D = 2 MiB تغییر نمی‌کنند: مجموع منطقی P + 2 * D، هر تحویل P + D و هزینهٔ تخصیص چهار buffer کاری حداکثر 4 * P است. فقط نسخهٔ موقت header اصلی با حداکثر max-header-bytes + 1 بایت اضافه می‌شود و هنگام تصمیم پاک می‌شود؛ بایت‌های بازپخش پیش از Init وارد بودجهٔ کاری می‌شوند. بدنه و دنباله نسخهٔ جداگانه ندارند. relay آمادهٔ fallback می‌تواند با همان شرایط CONNECT که در ادامه آمده، bufferهای splice را حفظ کند.

بافرهای splice​

در chainهای واجد شرایط لینوکس، HttpProxyServer ورودی splice را در هر دو جهت می‌پذیرد. درخواست و پاسخ HTTP، از جمله بدنه و trailer، برای parse کردن به‌طور کامل به buffer معمولی تبدیل می‌شوند. دادهٔ گذار CONNECT، بازپخش fallback و ورودی متوقف‌شده یا بازگشتی نیز پیش از ورود به فضای نگه‌داری session به buffer معمولی تبدیل می‌شوند. پس از تحویل پاسخ موفق CONNECT، یا تکمیل Init مربوط به fallback و بازپخش داده‌های قدیمی همان جهت، یک buffer کامل و تازهٔ splice می‌تواند بدون تبدیل به گیرنده‌ای که Pause نیست تحویل شود. انتخاب مقصد به‌تنهایی HTTP عادی را به stream خام تبدیل نمی‌کند.

پس از احراز هویت و انتخاب HTTP عادی، پراکسی برای خواندن upstream روی line ورودی و خواندن downstream روی هر child مربوط به HTTP پیش از Init آن، buffer معمولی درخواست می‌کند. CONNECT و fallback چنین ترجیحی ثبت نمی‌کنند. اگر یک تبادل HTTP قبلی این ترجیح را روی اتصال ورودی ثبت کرده باشد، در CONNECT بعدی همان اتصال نیز باقی می‌ماند. ورودی splice همچنان معتبر است؛ از جمله داده‌ای که قبلاً تحویل شده یا از ارتباط‌های Mux می‌رسد.

هنگام تبدیل، یک ورودی معمولی موقت با حداکثر P + D بایت منطقی تخصیص می‌یابد. حد تخصیص باقیمانده همچنان max(small capacity, 2 * D) به‌اضافهٔ alignment، padding مسیر بعدی و سربار header مربوط به buffer است. حدود پذیرش قبلی، بایت‌های نگه‌داری‌شده را محدود می‌کنند؛ این عدد حد RSS یا تضمین انتقال بدون کپی نیست. تمام bufferهای نگه‌داری‌شدهٔ session معمولی‌اند.

تنظیم misc.splice در core، پشتیبانی پلتفرم و تمام nodeهای chain گسترش‌یافته، شامل UserController، DomainResolver و شاخه‌های fallback، شرایط استفاده را تعیین می‌کنند. chainهای غیرفعال یا فاقد پشتیبانی رفتار معمولی دارند. تنظیم تازه‌ای برای پراکسی لازم نیست؛ HttpClient و HttpServer فقط از buffer معمولی استفاده می‌کنند.

متادیتای node​

متادیتای برگرفته از tunnels/HttpProxyServer/instance/node.c:

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