Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

UPNP

Успадковує: RefCounted < Object

Універсальні функції плагіна та Play (UPnP) для відкриття мережевого пристрою, запиту та переадресації портів.

Опис

Цей клас можна використовувати для виявлення сумісних пристроїв UPNPDevice у локальній мережі та виконання команд на них, таких як управління відповідностями портів (для переадресації портів/обходу NAT) та запит IP-адреси локальної та віддаленої мережі. Зверніть увагу, що методи цього класу є синхронними та блокують потік, що їх викликає.

Щоб переадресувати конкретний порт (тут 7777, зверніть увагу, що як discover(), так і add_port_mapping() можуть повертати помилки, які слід перевіряти):

var upnp = UPNP.new()
upnp.discover()
upnp.add_port_mapping(7777)

Щоб закрити конкретний порт (наприклад, після того, як ви закінчили його використовувати):

upnp.delete_port_mapping(port)

Примітка: Виявлення UPnP блокує поточний потік. Щоб виконати виявлення без блокування головного потоку, використовуйте Threads таким чином:

# Видається після завершення налаштування відображення портів UPnP (незалежно від успіху чи невдачі).
signal upnp_completed(error)

# Замініть це на номер порту вашого сервера в діапазоні від 1024 до 65535.
const SERVER_PORT = 3928
var thread = null

func _upnp_setup(server_port):
 # Запити UPNP займають деякий час.
 var upnp = UPNP.new()
 var err = upnp.discover()

 if err != UPNP.UPNP_RESULT_SUCCESS:
 push_error(str(err))
        upnp_completed.emit(err)
 return

 if upnp.get_gateway() and upnp.get_gateway().is_valid_gateway():
 upnp.add_port_mapping(server_port, server_port, ProjectSettings.get_setting("application/config/name"), "UDP")
        upnp.add_port_mapping(server_port, server_port, ProjectSettings.get_setting("application/config/name"), "TCP")
 upnp_completed.emit(UPNP.UPNP_RESULT_SUCCESS)

func _ready():
 thread = Thread.new()
 thread.start(_upnp_setup.bind(SERVER_PORT))

func _exit_tree():
 # Очікуємо завершення роботи потоку, щоб обробити вихід з гри під час його виконання.
 thread.wait_to_finish()

Термінологія: У контексті мереж UPnP «шлюз» (або «пристрій інтернет-шлюзу», скорочено IGD) означає мережеві пристрої, які дозволяють комп’ютерам у локальній мережі отримати доступ до Інтернету («глобальна мережа», WAN). Ці шлюзи часто також називають «маршрутизаторами».

Підводні камені:

  • Як пояснено вище, ці виклики є блокуючими і не повинні виконуватися в головному потоці, особливо з огляду на те, що вони можуть блокувати роботу на кілька секунд за раз. Використовуйте багатопотоковість!

  • Мережеві технології є фізичними та хаотичними. Пакети губляться під час передачі або фільтруються, адреси, вільні порти та призначені відповідності змінюються, а пристрої можуть виходити з мережі або приєднуватися до неї в будь-який момент. Майте це на увазі, будьте пильними під час перевірки та обробки помилок і, якщо можливо, обробляйте їх коректно: додайте зрозумілий інтерфейс помилок, тайм-аути та обробку повторних спроб.

  • Прив'язки портів можуть змінюватися (і видалятися) в будь-який момент, і віддалена/зовнішня IP-адреса шлюзу може змінюватися аналогічно. Вам слід розглянути можливість повторного запиту зовнішньої IP-адреси та спробувати періодично оновлювати/перезавантажувати прив'язку портів (наприклад, кожні 5 хвилин та під час мережевих збоїв).

  • Не всі пристрої підтримують UPnP, а деякі користувачі вимикають підтримку UPnP. Вам потрібно вирішити цю проблему (наприклад, проінформувати користувача та попросити його вручну переадресувати порти, або додати альтернативні методи обходу NAT, такі як релейний/дзеркальний сервер, пробивання дірок у NAT, STUN/TURN тощо).

  • Подумайте, що станеться у разі конфлікту прив’язок. Можливо, кілька користувачів у одній мережі захочуть грати у вашу гру одночасно, або інша програма використовує той самий порт. Зробіть порт настроюваним і оптимально вибирайте порт автоматично (при невдачі повторюйте спробу з іншим портом).

Додаткова інформація: Якщо ви хочете дізнатися більше про UPnP (а конкретно про пристрій інтернет-шлюзу (IGD) та протокол керування портами (PCP)), ` Вікіпедія <https://en.wikipedia.org/wiki/Universal_Plug_and_Play>`__ — це гарне місце для початку, специфікацію можна знайти на сайті Open Connectivity Foundation, а реалізація Godot базується на клієнті MiniUPnP.

Властивості

bool

discover_ipv6

false

int

discover_local_port

0

String

discover_multicast_if

""

Методи

void

add_device(device: UPNPDevice)

int

add_port_mapping(port: int, port_internal: int = 0, desc: String = "", proto: String = "UDP", duration: int = 0) const

void

clear_devices()

int

delete_port_mapping(port: int, proto: String = "UDP") const

int

discover(timeout: int = 2000, ttl: int = 2, device_filter: String = "InternetGatewayDevice")

UPNPDevice

get_device(index: int) const

int

get_device_count() const

UPNPDevice

get_gateway() const

String

query_external_address() const

void

remove_device(index: int)

void

set_device(index: int, device: UPNPDevice)


Переліки

enum UPNPResult: 🔗

UPNPResult UPNP_RESULT_SUCCESS = 0

Команда UPNP або відкриття було успішним.

UPNPResult UPNP_RESULT_NOT_AUTHORIZED = 1

Не уповноважено використовувати команду на UPNPDevice. Може бути повернено, коли користувач відключений UPNP на своєму маршрутизаторі.

UPNPResult UPNP_RESULT_PORT_MAPPING_NOT_FOUND = 2

Для даного порту було знайдено зображення протоколу UPNPDevice.

UPNPResult UPNP_RESULT_INCONSISTENT_PARAMETERS = 3

Невідповідні параметри.

UPNPResult UPNP_RESULT_NO_SUCH_ENTRY_IN_ARRAY = 4

Такого запису в масиві немає. Може бути повернуто, якщо задана комбінація порту та протоколу не знайдена на UPNPDevice.

UPNPResult UPNP_RESULT_ACTION_FAILED = 5

Не вдалося.

UPNPResult UPNP_RESULT_SRC_IP_WILDCARD_NOT_PERMITTED = 6

UPNPDevice не дозволяє значенням диких карток для джерела IP-адреси.

UPNPResult UPNP_RESULT_EXT_PORT_WILDCARD_NOT_PERMITTED = 7

UPNPDevice не дозволяє значенням диких карток для зовнішнього порту.

UPNPResult UPNP_RESULT_INT_PORT_WILDCARD_NOT_PERMITTED = 8

UPNPDevice не дозволяє значення диких карток для внутрішнього порту.

UPNPResult UPNP_RESULT_REMOTE_HOST_MUST_BE_WILDCARD = 9

Вартість дистанційного хосту повинна бути дикою карткою.

UPNPResult UPNP_RESULT_EXT_PORT_MUST_BE_WILDCARD = 10

Зовнішня вартість порту повинна бути дикоюкартою.

UPNPResult UPNP_RESULT_NO_PORT_MAPS_AVAILABLE = 11

Доступні карти портів. Може також повернутися, якщо не доступна функція копіювання портів.

UPNPResult UPNP_RESULT_CONFLICT_WITH_OTHER_MECHANISM = 12

Налаштування з іншим механізмом. Повернутися замість UPNP_RESULT_CONFLICT_WITH_OTHER_MAPPING, якщо порт картографування конфліктів з існуючим.

UPNPResult UPNP_RESULT_CONFLICT_WITH_OTHER_MAPPING = 13

Конфлікт з існуючим портовим картуванням.

UPNPResult UPNP_RESULT_SAME_PORT_VALUES_REQUIRED = 14

Зовнішні та внутрішні значення порту повинні бути однаковими.

UPNPResult UPNP_RESULT_ONLY_PERMANENT_LEASE_SUPPORTED = 15

Підтримуються тільки постійні орендні витрати. Не використовуйте параметр duration при додаванні портових карт.

UPNPResult UPNP_RESULT_INVALID_GATEWAY = 16

Інвалідний шлюз.

UPNPResult UPNP_RESULT_INVALID_PORT = 17

Неточний порт.

UPNPResult UPNP_RESULT_INVALID_PROTOCOL = 18

Інвалідний протокол.

UPNPResult UPNP_RESULT_INVALID_DURATION = 19

Термін дії.

UPNPResult UPNP_RESULT_INVALID_ARGS = 20

Неточні аргументи.

UPNPResult UPNP_RESULT_INVALID_RESPONSE = 21

Інвалідна відповідь.

UPNPResult UPNP_RESULT_INVALID_PARAM = 22

Неточний параметр.

UPNPResult UPNP_RESULT_HTTP_ERROR = 23

Помилка HTTP.

UPNPResult UPNP_RESULT_SOCKET_ERROR = 24

Похибка розетки.

UPNPResult UPNP_RESULT_MEM_ALLOC_ERROR = 25

Пам'ять про помилку.

UPNPResult UPNP_RESULT_NO_GATEWAY = 26

Немає доступних воріт. Якщо ви не виявите будь-які дійсні IGDs (InternetGatewayDevices).

UPNPResult UPNP_RESULT_NO_DEVICES = 27

Немає доступних пристроїв. Якщо ви не виявите будь-які дії UPNPDevice.

UPNPResult UPNP_RESULT_UNKNOWN_ERROR = 28

Невідома помилка.


Описи властивостей

bool discover_ipv6 = false 🔗

  • void set_discover_ipv6(value: bool)

  • bool is_discover_ipv6()

Якщо true, IPv6 використовується для відкриття UPNPDevice.


int discover_local_port = 0 🔗

  • void set_discover_local_port(value: int)

  • int get_discover_local_port()

Якщо 0, локальний порт використовувати для відкриття автоматично обирається системою. Якщо 1, відкриття буде зроблено з порту джерела 1900 (наприклад, порт призначення). В іншому випадку значення буде використовуватися як порт.


String discover_multicast_if = "" 🔗

  • void set_discover_multicast_if(value: String)

  • String get_discover_multicast_if()

Інтерфейс Multicast для використання для відкриття. Використовуйте інтерфейс за замовчуванням, якщо порожній.


Описи методів

void add_device(device: UPNPDevice) 🔗

Додає задану UPNPDevice до списку відкритих пристроїв.


int add_port_mapping(port: int, port_internal: int = 0, desc: String = "", proto: String = "UDP", duration: int = 0) const 🔗

Додавання картографування на переадресацію зовнішнього port (between 1 і 65535, хоча рекомендується використовувати порт 1024 або вище) на шлюзу за замовчуванням (див. get_gateway()) до port_internal на локальній машині для заданого протоколу proto (надалі "TCP" або "UDP", з UDP будучи за замовчуванням). Якщо портове картування для даного порту і поєднання протоколу вже існує на цьому пристрої для шлюзу, цей метод намагається переписати його. Якщо це не потрібно, ви можете отримати шлюзу вручну за допомогою get_gateway() і виклику add_port_mapping() на ньому, якщо будь-який. Зауважте, що переадресація відомого порту (до 1024) з UPnP може не в залежності від пристрою.

Залежно від пристрою шлюзу, якщо вже існує карта для цього порту, вона буде оновлена або вона відмовляється від цієї команди через цей конфлікт, особливо якщо існуюча карта для цього порту не була створена через UPnP або точки на інший мережевий адрес (або пристрій), ніж це.

Якщо port_internal є 0 (за замовчуванням), той самий номер порту використовується як для зовнішнього, так і внутрішнього порту ( значення port).

Опис (desc) відображається в деяких маршрутизаторах управління UIs і може бути використаний для позначення, яку додаток додано картографування.

Здається в оренду картографування duration може бути обмежена, вказавши тривалість за секундами. За замовчуванням 0 означає, що немає тривалості, тобто постійне орендодавство і неможливі деякі пристрої тільки підтримують ці постійні оренди. Зауважте, чи є постійним або не постійним, це тільки запит, і шлюз все ще може вирішити в будь-якій точці, щоб видалити картографію (що зазвичай відбувається на перезавантаження шлюзу, коли його зовнішні зміни IP-адреси, або на деяких моделях, коли він виявить портову картографію стала неактивним, тобто не було трафіку за кілька хвилин). Якщо не 0 (перманент), допустимий діапазон за специфікацією між 120 (2 хвилини) і 86400 секунд (24 годин).

Див. UPNPResult для можливих значень повернення.


void clear_devices() 🔗

Очистити список відкритих пристроїв.


int delete_port_mapping(port: int, proto: String = "UDP") const 🔗

Видаляє портову картографію для вказаного порту та комбінації протоколів за умовчанням (див. get_gateway()) якщо існує один. port повинен бути дійсним портом між 1 і 65535, proto може бути як "TCP" або "UDP"". Може бути відмовлено в картографуваннях, що вказують на адреси, крім цього, для відомих портів (до 1024), або для картування не додано через UPnP. Див. UPNPResult для можливих значень повернення.


int discover(timeout: int = 2000, ttl: int = 2, device_filter: String = "InternetGatewayDevice") 🔗

Виставки місцевих UPNPDevices. Очистити список раніше відкритих пристроїв.

Фільтри для пристроїв типу IGD (InternetGatewayDevice) за замовчуванням, оскільки переадресація портів керування. timeout – час очікування відповіді на мілісекунди. ttl це часово-живий; тільки доторкнутися до цього, якщо ви знаєте, що ви робите.

Див. UPNPResult для можливих значень повернення.


UPNPDevice get_device(index: int) const 🔗

Повертає UPNPDevice на поданому index.


int get_device_count() const 🔗

Повертає кількість виявлених UPNPDevices.


UPNPDevice get_gateway() const 🔗

Повернення за замовчуванням воріт. Це перший відкритий UPNPDevice, який також є дійсним IGD (InternetGatewayDevice).


String query_external_address() const 🔗

Повертає зовнішній IP адресу за замовчуванням шлюзу (див. get_gateway()) як рядок. Повертає порожній рядок на помилку.


void remove_device(index: int) 🔗

Видаліть пристрій в індексі index з переліку відкритих пристроїв.


void set_device(index: int, device: UPNPDevice) 🔗

Налаштовує пристрій в індексі index з переліку відкритих пристроїв до device.