delete_port_mapping: Condition "i != (0)" is true

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Rodrigo Matos

Could anyone explain how the UPNP (Universal Plug and Play) class works? I’ve read UPNP — Godot Engine (3.2) documentation in English and Add UPnP support (port forwarding, querying external IP) by mhilbrunner · Pull Request #18780 · godotengine/godot · GitHub, but I’m still having problems.

After pressing a button, I create a UPNP object by using (upnp is declared in a singleton script)

gamestate.upnp = UPNP.new()

Then I execute discover and add_port_mapping methods while checking for errors, and if there are any, I stop the execution of my function:

if gamestate.upnp.discover() or \
gamestate.upnp.add_port_mapping(gamestate.DEFAULT_PORT):
    ErrorLabel.text = "UPNP error"
    return

And, when I press another button, I delete the port mapping. I check if the number of devices is greater or equal than 1, since I don’t know if there is any way to check if a port was added:

if gamestate.upnp.get_device_count() >= 1:            
    print(gamestate.upnp.delete_port_mapping(gamestate.DEFAULT_PORT))

But, when I try both buttons in the correct order, I get an error:

  E 0:00:05.248   delete_port_mapping: Condition "i != (0)" is true. Returned: UPNP::upnp_result(i)
  <C++ Source>  modules/upnp/upnp_device.cpp:90 @ delete_port_mapping()
  <Stack Trace> main_menu.gd:38 @ _on_host_pressed()

I don’t understand this error. At first, I thought the condition “i != (0)” meant that, in any method I used, I got a return code different from 0. But i’ve tried to print the return codes of discover, add_port_mapping and delete_port_mapping methods, and all of them return 0.

The error is thrown after pressing the first button, not the second. But the error mentions the method “delete_port_mapping”, which is in the second button, so I don’t know really. Any thoughts?

Please create an issue on GitHub. Make sure to state which router model you’re using in the issue.

Also, the error condition refers to something in Godot’s source code, not your script. Many error messages don’t have a human-readable explanation yet, so the condition that caused the assertion to fail is displayed instead.

Calinou | 2020-03-27 08:24

Thanks for sharing your Github issue! I don’t know if it’s a bug though, it seems like the way the function works.

Rodrigo Matos | 2020-04-27 17:14

:bust_in_silhouette: Reply From: Rodrigo Matos

I’ve discovered the reason for the error. Here is the Godot’s source code for add_port_mapping function:

int UPNP::add_port_mapping(int port, int port_internal, String desc, String proto, int duration) const {
	Ref<UPNPDevice> dev = get_gateway();

	if (dev == NULL) {
		return UPNP_RESULT_NO_GATEWAY;
	}

	dev->delete_port_mapping(port, proto);

	return dev->add_port_mapping(port, port_internal, desc, proto, duration);
}

Every time the UPNP’s add_port_mapping is called, it calls UPNPDevice’s delete_port_mapping before calling UPNPDevice’s add_port_mapping. So UPNP’s add_port_mapping will give an error if there isn’t a previous port mapping to delete.

So there’s no problem with my code, it’s the way this function was designed.