diff --git a/src/Server.php b/src/Server.php index 702739dc5..213beeb12 100644 --- a/src/Server.php +++ b/src/Server.php @@ -64,7 +64,7 @@ use pocketmine\network\Network; use pocketmine\network\query\DedicatedQueryNetworkInterface; use pocketmine\network\query\QueryHandler; use pocketmine\network\query\QueryInfo; -use pocketmine\network\upnp\UPnP; +use pocketmine\network\upnp\UPnPNetworkInterface; use pocketmine\permission\BanList; use pocketmine\permission\DefaultPermissions; use pocketmine\player\GameMode; @@ -1109,7 +1109,7 @@ class Server{ if((bool) $this->configGroup->getProperty("network.upnp-forwarding", false)){ try{ - $this->network->registerInterface(new UPnP($this->logger, Internet::getInternalIP(), $this->getPort())); + $this->network->registerInterface(new UPnPNetworkInterface($this->logger, Internet::getInternalIP(), $this->getPort())); }catch(\RuntimeException $e){ $this->logger->alert("UPnP portforward failed: " . $e->getMessage()); } diff --git a/src/network/upnp/UPnP.php b/src/network/upnp/UPnP.php index fb49dd872..07399e0e4 100644 --- a/src/network/upnp/UPnP.php +++ b/src/network/upnp/UPnP.php @@ -55,7 +55,6 @@ declare(strict_types=1); */ namespace pocketmine\network\upnp; -use pocketmine\network\NetworkInterface; use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\Internet; use function count; @@ -80,7 +79,7 @@ use const SOCKET_ETIMEDOUT; use const SOL_SOCKET; use const SOL_UDP; -class UPnP implements NetworkInterface{ +class UPnP{ private const MAX_DISCOVERY_ATTEMPTS = 3; private static function makePcreError() : \RuntimeException{ @@ -188,36 +187,13 @@ class UPnP implements NetworkInterface{ return $serviceURL; } - /** @var string */ - private $ip; - /** @var int */ - private $port; - - /** @var string|null */ - private $serviceURL = null; - /** @var \Logger */ - private $logger; - - public function __construct(\Logger $logger, string $ip, int $port){ - if(!Internet::$online){ - throw new \RuntimeException("Server is offline"); - } - - $this->ip = $ip; - $this->port = $port; - $this->logger = new \PrefixedLogger($logger, "UPnP Port Forwarder"); - } - - public function start() : void{ - $this->logger->info("Attempting to portforward..."); - $this->serviceURL = self::getServiceUrl(); - + public static function portForward(string $serviceURL, int $port) : void{ $body = '' . '' . - '' . $this->port . '' . + '' . $port . '' . 'UDP' . - '' . $this->port . '' . + '' . $port . '' . '' . Internet::getInternalIP() . '' . '1' . 'PocketMine-MP' . @@ -234,29 +210,16 @@ class UPnP implements NetworkInterface{ 'SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping"' ]; - if(Internet::postURL($this->serviceURL, $contents, 3, $headers, $err) === null){ + if(Internet::postURL($serviceURL, $contents, 3, $headers, $err) === null){ throw new \RuntimeException("Failed to portforward using UPnP: " . $err); } - - $this->logger->info("Forwarded $this->ip:$this->port to external port $this->port"); } - public function setName(string $name) : void{ - - } - - public function tick() : void{ - - } - - public function shutdown() : void{ - if($this->serviceURL === null){ - return; - } + public static function removePortForward(string $serviceURL, int $port) : void{ $body = '' . '' . - '' . $this->port . '' . + '' . $port . '' . 'UDP' . ''; @@ -270,6 +233,6 @@ class UPnP implements NetworkInterface{ 'SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#DeletePortMapping"' ]; - Internet::postURL($this->serviceURL, $contents, 3, $headers); + Internet::postURL($serviceURL, $contents, 3, $headers); } } diff --git a/src/network/upnp/UPnPNetworkInterface.php b/src/network/upnp/UPnPNetworkInterface.php new file mode 100644 index 000000000..f4deafc39 --- /dev/null +++ b/src/network/upnp/UPnPNetworkInterface.php @@ -0,0 +1,75 @@ +ip = $ip; + $this->port = $port; + $this->logger = new \PrefixedLogger($logger, "UPnP Port Forwarder"); + } + + public function start() : void{ + $this->logger->info("Attempting to portforward..."); + $this->serviceURL = UPnP::getServiceUrl(); + + UPnP::portForward($this->serviceURL, $this->port); + + $this->logger->info("Forwarded $this->ip:$this->port to external port $this->port"); + } + + public function setName(string $name) : void{ + + } + + public function tick() : void{ + + } + + public function shutdown() : void{ + if($this->serviceURL === null){ + return; + } + + UPnP::removePortForward($this->serviceURL, $this->port); + } +}