UdpListener
UdpListener یک Adapter سرور UDP است. این Node یک آدرس و پورت محلی UDP را Bind
میکند، Datagramهای ورودی را بر اساس Peer راه دور گروهبندی میکند، بهازای هر
Peer یک Line در WaterWall میسازد و Payloadها را در جهت upstream به Node بعدی
میفرستد.
جایگاه معمول:
client -> UdpListener -> ... -> UdpConnector -> remote UDP service
این Node معمولاً ابتدای یک زنجیرهی UDP بهشکل Stream قرار میگیرد.
چه کاری انجام میدهد؟
- روی یک پورت UDP، چند پورت مشخص یا یک بازهی پیوسته از پورتها گوش میدهد.
- Datagramهای UDP ورودی را از طریق Socket Manager در WaterWall دریافت میکند.
- Filterهای اختیاری Listener، مانند
whitelist، blacklistو Balance Groupها را اعمال میکند. - بهازای هر ترکیب آدرس و پورت Peer راه دور، یک Line در WaterWall میسازد.
- Datagramهای ورودی را بهصورت Payload در upstream به Node بعدی میفرستد.
- Payloadهای downstream را به آدرس Peer ذخیرهشده بازمیگرداند.
- Lineهای Peer را با Idle Timeout مربوط به UDP ردیابی میکند.
UDP ذاتاً Connectionless است، اما UdpListener برای بقیهی زنجیره بهازای هر Peer
یک Line پایدار فراهم میکند.
نمونهی پیکربندی
{
"name": "udp-listener",
"type": "UdpListener",
"settings": {
"address": "0.0.0.0",
"port": [
5353,
853,
123
],
"large-send-buffer": true,
"large-recv-buffer": true,
"interface": "eth0",
"fwmark": 10,
"balance-group": "udp-public",
"balance-interval": 30000,
"multiport-backend": "socket",
"whitelist": [
"192.168.1.0/24",
"2001:db8::/64"
],
"blacklist": [
"192.168.1.50/32"
]
},
"next": "next-node-name"
}
فیلدهای الزامی
فیلدهای سطح اول:
| فیلد | نوع | توضیح |
|---|---|---|
name | String | نامی که کاربر برای Node انتخاب میکند و باید در فایل پیکربندی یکتا باشد. |
type | String | باید دقیقاً "UdpListener" باشد. |
next | String | نام Nodeای که Lineها و Payloadهای Peerهای UDP را دریافت میکند. |
فیلدهای الزامی در settings:
| فیلد | نوع | توضیح |
|---|---|---|
address | String | آدرس محلی برای Bind، مانند "0.0.0.0"، "::" یا یک IP محلی مشخص. |
port یا port-range | Number، Array یا Range Array | تعریف پورت Listen؛ وجود دقیقاً یکی از این دو فیلد الزامی است. |
settings باید یک Object غیرخالی باشد.
تنظیم پورت
UdpListener سه حالت برای پورت دارد.
یک پورت
{
"settings": {
"address": "0.0.0.0",
"port": 5353
}
}
فهرست صریح پورتها
{
"settings": {
"address": "0.0.0.0",
"port": [
5353,
853,
123
]
}
}
در این حالت فقط روی پورتهای نوشتهشده گوش داده میشود؛ این Array بهمعنای بازهی
123 تا 5353 نیست.
بازهی پیوستهی پورتها
{
"settings": {
"address": "0.0.0.0",
"port-range": [
20000,
20100
]
}
}
port-range باید Arrayای شامل دقیقاً دو پورت Integer مثبت بهشکل [min, max]
باشد. مقدار کمینه باید کوچکتر یا مساوی مقدار بیشینه باشد.
قواعد:
| قاعده | رفتار |
|---|---|
استفادهی همزمان از port و port-range | راهاندازی متوقف میشود. |
مقدار Number برای port | روی یک پورت UDP گوش میدهد. |
مقدار Array برای port | روی پورتهای صریح موجود در Array گوش میدهد. |
مقدار Array برای port-range | روی همهی پورتهای UDP از مقدار کمینه تا بیشینه گوش میدهد. |
پورت نامعتبر، صفر، منفی یا بیشتر از 65535 | راهاندازی متوقف میشود. |
از بازههای قدیمی با قالب String، مانند "20000-20100"، استفاده نکنید. Parser
فعلی برای port-range یک Array دومقداری انتظار دارد.
تنظیمات اختیاری
| تنظیم | نوع | مقدار پیشفرض | توضیح |
|---|---|---|---|
large-send-buffer | Boolean یا Integer مثبت | true | مقدار SO_SNDBUF را روی Socketهای Listener نوع UDP تنظیم میکند. |
large-recv-buffer | Boolean یا Integer مثبت | true | مقدار SO_RCVBUF را روی Socketهای Listener نوع UDP تنظیم میکند. |
interface | String | تنظیم نشده | Listener را به یک Interface محلی شبکه محدود میکند. |
fwmark | Integer | تنظیم نشده | در صورت پشتیبانی، یک Socket Mark به سبک Linux اعمال میکند. |
balance-group | String | تنظیم نشده | Listenerهای سازگار و همپورت را برای توزیع پایدار Peerها در یک گروه قرار میدهد. |
balance-interval | Integer، بر حسب میلیثانیه | مقدار پیشفرض Socket Manager | مدت حفظ انتخاب قبلی برای Peerهای تکراری در Balance Group. |
multiport-backend | String | مقدار پیشفرض Runtime برای port-range | Backend مربوط به بازهی پیوستهی پورتها: "iptables" یا "socket". |
whitelist | Arrayای از Stringها | تنظیم نشده | IPها یا بازههای CIDR مجاز برای Peer. |
blacklist | Arrayای از Stringها | تنظیم نشده | IPها یا بازههای CIDR مسدود برای Peer. |
گزینههای Socket Buffer
large-send-buffer و large-recv-buffer مقادیر زیر را میپذیرند:
| مقدار | مفهوم |
|---|---|
true | از اندازهی پیشفرض WaterWall برای Socket Buffer بزرگ استفاده میکند که در حال حاضر 4194304 Byte است. |
false | این Socket Buffer را صریحاً تنظیم نمیکند و مقدار پیشفرض Kernel به کار میرود. |
| Integer مثبت | همان تعداد Byte را مستقیماً درخواست میکند. |
هر دو گزینه برای Listenerهای UDP بهصورت پیشفرض از Socket Buffer بزرگ WaterWall استفاده میکنند.
Interface و fwmark
interface، Listener را به یک دستگاه محلی شبکه محدود میکند.
در Linux، WaterWall از SO_BINDTODEVICE استفاده میکند. در Platformهایی که Bind
به Device را پشتیبانی نمیکنند، WaterWall در صورت امکان روی آدرس IPv4 همان
Interface Bind میشود.
fwmark در Platformهای پشتیبانیشده از SO_MARK استفاده میکند. این قابلیت به
Platform وابسته است و در Windows در دسترس نیست.
Filter و توزیع
پیش از آنکه Datagram به UdpListener برسد، Socket Manager مشترک عملیات Filter
و توزیع را انجام میدهد.
| تنظیم | رفتار |
|---|---|
whitelist | در صورت تنظیم، فقط Peerهایی پذیرفته میشوند که IP آنها با فهرست منطبق باشد. |
blacklist | Peerهایی را که IP آنها با فهرست منطبق است رد میکند. |
balance-group | توزیع پایدار Peerها را میان Listenerهای سازگار روی یک پورت فعال میکند. |
balance-interval | مشخص میکند Peer چه مدت به Listener انتخابشده اختصاص داده شود. |
multiport-backend | روش پیادهسازی Listener دارای port-range پیوسته را تعیین میکند. |
اگر هر دو ACL تنظیم شده باشند، Peer باید، در صورت وجود Whitelist، با آن منطبق باشد و نباید با Blacklist تطابق داشته باشد.
نمونه:
{
"settings": {
"address": "0.0.0.0",
"port": 5353,
"whitelist": [
"10.0.0.0/8",
"203.0.113.10/32",
"2001:db8::/64"
],
"blacklist": [
"10.0.0.99/32"
]
}
}
مدل یک Line بهازای هر Peer
UDP اتصال Transport ندارد؛ بنابراین UdpListener برای زنجیره یک مدل
Pseudo-connection میسازد.
برای هر ترکیب یکتای آدرس و پورت Peer راه دور روی یک Socket در حال Listen:
- با نخستین Datagram پذیرفتهشده، یک Line تازه در WaterWall ساخته میشود.
- آدرس Peer در Line State مربوط به Listener ذخیره میشود.
- Datagramهای بعدی همان Peer تا زمان انقضای Line از آن استفاده میکنند.
- Payloadهای downstream روی آن Line به Peer ذخیرهشده بازگردانده میشوند.
به این ترتیب، Nodeهای Stream-style در ادامهی زنجیره میتوانند با Callbackهای عادی Line در WaterWall روی ترافیک UDP کار کنند.
جریان داده
از Peer به زنجیره:
UDP datagram -> UdpListener -> upstream payload -> next node
از زنجیره به Peer:
previous downstream payload -> UdpListener -> UDP send to remembered peer
Source Context مربوط به Line از آدرس Socket سمت Peer پر و بهعنوان UDP علامتگذاری میشود.
معنای Establishment
Line جدید Peer با نخستین Datagram پذیرفتهشده ساخته میشود، اما فقط زمانی
Established خواهد شد که Callback مربوط به est در downstream از Node بعدی به
UdpListener برسد.
رفتار Pause
وقتی Line مربوط به Peer در حالت Pause است، UdpListener، Datagramهای ورودی را در
صف نگه نمیدارد.
اگر Datagramی برای یک Line در حالت Pause برسد:
- Datagram دور ریخته میشود؛
- Line زنده میماند؛
- پس از Resume، Datagramهای تازهی همان Peer دوباره قابل Forward هستند.
این رفتار با Backpressure شبیه TCP متفاوت است. در این Node، Pause یعنی دورریختن داده، نه نگهداشتن آن در Buffer.
Idle Timeout
هر Line مربوط به Peer در یک جدول Idle ردیابی میشود.
Timeoutهای فعلی:
| وضعیت | Timeout |
|---|---|
| Line تازهساختهشده برای Peer | حدود 30 seconds |
| Peer فعال پس از ادامهی ترافیک | حدود 300 seconds |
اگر Line مربوط به Peer منقضی شود، UdpListener یک finish در upstream میفرستد
و Lineای را که خودش ساخته است نابود میکند.
نکات و محدودیتها
UdpListenerیک Chain Head برای UDP است و بهnextنیاز دارد.- Arrayهای
portفهرست صریحاند، نه بازه. - برای بازههای پیوسته از
port-rangeاستفاده کنید. whitelistوblacklist، Stringهای CIDR مربوط به IPv4 و IPv6 را میپذیرند.fwmarkو Bindشدن به Device به Platform وابستهاند.- Lineهای Peer در حالت Pause، Datagramهای ورودی را بهجای Bufferکردن دور میریزند.
- برای رفتار Stateless و در سطح Packet در UDP، شاید
UdpStatelessSocketانتخاب مناسبتری ازUdpListenerباشد.