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 блокує поточний потік. Щоб виконати відкриття без блокування основного потоку, використовуйте Thread таким чином:

# Видається після завершення налаштування відображення порту UPnP (незалежно від успіху чи невдачі).
сигнал 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 error!= ОК:
        push_error(str(err))
        upnp_completed.emit(err)
        return

    if upnp.get_gateway() і 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(ОК)

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), Вікіпедія є хорошою першою зупинкою, специфікацію можна знайти на Реалізація 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.