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

SpeedTestServer

SpeedTestServer همتای chain-end برای SpeedTestClient است. frame‌های speed-test را از upstream می‌گیرد، داده upload را اعتبارسنجی می‌کند، در صورت درخواست داده download را در جهت downstream می‌فرستد و گزارش نهایی sender/receiver را به client برمی‌گرداند.

این یک tunnel معمول connection-oriented است. خودش line نمی‌سازد، مالک از بین بردن line ساخته‌شده توسط listener نیست و packet-line tunnel هم محسوب نمی‌شود.

جایگاه رایج​

SpeedTestServer باید آخرین node chain باشد.

TcpListener -> SpeedTestServer
UdpListener -> SpeedTestServer
TcpListener -> TlsServer -> SpeedTestServer
TcpListener -> EncryptionServer -> SpeedTestServer

سمت client معمولاً با SpeedTestClient متناظر آغاز می‌شود:

SpeedTestClient -> TcpConnector
SpeedTestClient -> UdpConnector
SpeedTestClient -> TlsClient -> TcpConnector
SpeedTestClient -> EncryptionClient -> TcpConnector

نمونه TCP​

[
{
"name": "speedtest-listener",
"type": "TcpListener",
"settings": {
"address": "0.0.0.0",
"port": 9000,
"nodelay": true
},
"next": "speedtest-server"
},
{
"name": "speedtest-server",
"type": "SpeedTestServer",
"settings": {
"report-interval-ms": 1000,
"json-summary": true,
"quiet": false
}
}
]

سمت client matching:

[
{
"name": "speedtest-client",
"type": "SpeedTestClient",
"settings": {
"mode": "tcp",
"direction": "bidirectional",
"duration-ms": 10000,
"warmup-ms": 1000,
"connection-count": 4,
"payload-size": 131072
},
"next": "speedtest-out"
},
{
"name": "speedtest-out",
"type": "TcpConnector",
"settings": {
"address": "198.51.100.10",
"port": 9000,
"nodelay": true
}
}
]

نمونه UDP​

سمت server:

[
{
"name": "speedtest-udp-listener",
"type": "UdpListener",
"settings": {
"address": "0.0.0.0",
"port": 9001
},
"next": "speedtest-server"
},
{
"name": "speedtest-server",
"type": "SpeedTestServer",
"settings": {
"report-interval-ms": 1000
}
}
]

سمت client matching:

[
{
"name": "speedtest-client",
"type": "SpeedTestClient",
"settings": {
"mode": "udp",
"direction": "upload",
"duration-ms": 10000,
"warmup-ms": 1000,
"payload-size": 3800,
"udp-target-bits-per-sec": 10000000
},
"next": "speedtest-udp-out"
},
{
"name": "speedtest-udp-out",
"type": "UdpConnector",
"settings": {
"address": "198.51.100.10",
"port": 9001
}
}
]

فیلدهای لازم​

SpeedTestServer node انتهایی chain است و نباید next داشته باشد.

settings اختیاری است و در صورت حذف شدن، مقدارهای پیش‌فرض به کار می‌روند.

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

فیلدپیش‌فرضتوضیح
report-interval-ms1000فاصله پیش‌فرض گزارش‌ها پیش از دریافت HELLO. پس از آن، interval درخواستی client برای همان line استفاده می‌شود. باید مثبت باشد.
json-summaryfalseمقدار پیش‌فرض برای خلاصه شبیه JSON هر stream. client نیز می‌تواند از طریق HELLO آن را برای هر line درخواست کند.
quietfalselog‌های runtime مانند پذیرفته شدن stream، گزارش دوره‌ای، خلاصه نهایی و خطاهای هر stream را خاموش می‌کند. خطاهای fatal مربوط به setup همچنان ممکن است ثبت شوند.

Init و establishment​

در upstream Init، server:

  1. per-line state را مقداردهی اولیه می‌کند
  2. برای framing در حالت TCP یک receive stream buffer می‌سازد
  3. بلافاصله Est را downstream به سمت node قبلی می‌فرستد

همین downstream Est سیگنال آغاز ارسال HELLO برای SpeedTestClient است.

HELLO و ACK​

نخستین frame دریافتی از client باید HELLO باشد. این frame رفتار server را برای همان line تعیین می‌کند:

  • mode tcp یا udp
  • direction شامل upload، download یا bidirectional
  • duration و warmup
  • report interval
  • payload size
  • target bandwidth
  • total stream count
  • stream id

پس از پذیرفتن HELLO، server یک ACK در جهت downstream می‌فرستد. در حالت UDP، برای HELLOهای تکراری نیز دوباره ACK ارسال می‌شود تا گم شدن پاسخ، client را برای همیشه منتظر نگذارد.

server کاربردی بودن duration-ms، report-interval-ms، payload-size و تعداد کل stream‌ها را اعتبارسنجی می‌کند. payload در حالت UDP حداکثر می‌تواند 64952 بایت باشد.

مسیر upload​

وقتی upload فعال باشد، frame‌های upstream نوع DATA شمارش می‌شوند. با فعال بودن verify-payload، بدنه آن‌ها نیز با الگوی تولیدشده در client بررسی می‌شود.

server این آمار را نگه می‌دارد:

  • تعداد بایت‌ها
  • packets
  • valid packets
  • lost packets
  • duplicate packets
  • out-of-order packets
  • validation errors
  • jitter estimate

با رسیدن frame نوع END برای upload، server آمار receiver را نهایی می‌کند و یک receiver REPORT در جهت downstream می‌فرستد. در حالت UDP، پس از پایان receiver، ENDهای تکراری نادیده گرفته می‌شوند.

مسیر download​

وقتی download فعال باشد، server پس از پذیرفتن HELLO ارسال frame‌های downstream نوع DATA را زمان‌بندی می‌کند. payload size، warmup، duration و target bandwidth همان مقادیری هستند که client درخواست کرده است.

در پایان download، server فریم‌های زیر را می‌فرستد:

  • END برای download
  • REPORT مربوط به sender

در UDP، فریم‌های final END و REPORT سه بار تکرار می‌شوند.

framing​

در حالت TCP، بایت‌های ورودی در splice_stream_t جمع و به frame‌های speed-test decode می‌شوند.

در UDP، هر Waterwall payload buffer باید دقیقاً یک frame کامل speed-test باشد. اولین packet که HELLO با flag UDP داشته باشد، line را وارد UDP-frame handling می‌کند.

header نامعتبر، نوع frame غیرمنتظره، طول ناممکن payload یا ترتیب نادرست protocol باعث شکست line می‌شود. server در صورت امکان پیش از بستن آن، یک frame نوع ERROR می‌فرستد.

رفتار Finish​

اگر upstream پیش از پایان کامل تست بسته شود، server فقط per-line state خودش را از بین می‌برد و lineDestroy() را فراخوانی نمی‌کند؛ زیرا line را listener یا adapter upstream ساخته است.

وقتی server خودش تست را کامل کند یا با خطا پایان دهد، ابتدا بایت‌های نهایی لازم برای protocol را می‌فرستد، سپس state خودش را از بین می‌برد و downstream Finish را می‌فرستد.

اعتبارسنجی payload و splice​

تنظیم verify-payload در SpeedTestClient به‌صورت پیش‌فرض false است و از طریق flag پیام HELLO برای هر دو سمت اعمال می‌شود. مقدار true تولید و بررسی الگوی قطعی داده را فعال می‌کند. در حالت غیرفعال، فرستنده بدنه را با صفر مقداردهی می‌کند و گیرنده فقط تعداد بایت‌ها را حساب می‌کند. بررسی header، طول، stream id، sequence و گزارش نهایی همیشه برقرار است. در این حالت valid_packets و validation_errors مربوط به payload صفر هستند و خلاصه JSON فیلد verification_enabled دارد.

هر دو node در chain مناسب TCP با misc.splice=true از splice پشتیبانی می‌کنند. گیرنده header چهل‌وهشت‌بایتی را می‌خواند و برای frame ناقص فوراً بازمی‌گردد. در Linux بدنه DATA بدون بررسی، از pipe مستقیماً به /dev/null تخلیه می‌شود؛ در صورت نبود پشتیبانی، خواندن معمولی با حافظه موقت محدود استفاده می‌شود. بدنه پیام‌های کنترلی و DATA نیازمند اعتبارسنجی به حافظه معمولی منتقل می‌شوند. UDP همچنان هر datagram را جدا پردازش می‌کند. تولید داده خروجی از حافظه معمولی انجام می‌شود.

حد هزینه ذخیره frame ناقص برای هر line برابر 2 * (16 MiB + 48) است؛ پیش از رد ورودی، فشرده‌سازی bufferها امتحان می‌شود. این عدد حد کل حافظه process یا kernel نیست. هر task حداکثر ۳۲ frame می‌فرستد و به Pause احترام می‌گذارد؛ pacing با زمان‌بندی task انجام می‌شود و worker را به خواب نمی‌برد.

اشتباه‌های رایج​

  • بعد از SpeedTestServer node دیگری نگذارید؛ chain end است.
  • بدون SpeedTestClient متناظر از آن استفاده نکنید.
  • انتظار پردازش application traffic از آن نداشته باشید.
  • آن را packet-line node فرض نکنید؛ با line‌های عادی ساخته‌شده توسط listener یا adapter upstream کار می‌کند.

متادیتای node​

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

ویژگیمقدار
node flagskNodeFlagChainEnd + kNodeFlagSupportsSplice
can_have_prevtrue
can_have_nextfalse
layer_groupkNodeLayer4
layer_group_prev_nodekNodeLayer4
layer_group_next_nodekNodeLayerNone
required_padding_left0 بایت