mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-03 08:39:53 +00:00
Implemented IPv6 support (#4554)
This commit is contained in:
parent
eb9012401b
commit
cc4bb91fcb
@ -34,6 +34,7 @@ namespace pocketmine {
|
|||||||
use pocketmine\utils\Timezone;
|
use pocketmine\utils\Timezone;
|
||||||
use pocketmine\wizard\SetupWizard;
|
use pocketmine\wizard\SetupWizard;
|
||||||
use Webmozart\PathUtil\Path;
|
use Webmozart\PathUtil\Path;
|
||||||
|
use function defined;
|
||||||
use function extension_loaded;
|
use function extension_loaded;
|
||||||
use function phpversion;
|
use function phpversion;
|
||||||
use function preg_match;
|
use function preg_match;
|
||||||
@ -145,6 +146,10 @@ namespace pocketmine {
|
|||||||
$messages[] = "The native PocketMine extension is no longer supported.";
|
$messages[] = "The native PocketMine extension is no longer supported.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!defined('AF_INET6')){
|
||||||
|
$messages[] = "IPv6 support is required, but your PHP binary was built without IPv6 support.";
|
||||||
|
}
|
||||||
|
|
||||||
return $messages;
|
return $messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,6 +321,10 @@ class Server{
|
|||||||
return $this->configGroup->getConfigInt("server-port", 19132);
|
return $this->configGroup->getConfigInt("server-port", 19132);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getPortV6() : int{
|
||||||
|
return $this->configGroup->getConfigInt("server-portv6", 19133);
|
||||||
|
}
|
||||||
|
|
||||||
public function getViewDistance() : int{
|
public function getViewDistance() : int{
|
||||||
return max(2, $this->configGroup->getConfigInt("view-distance", 8));
|
return max(2, $this->configGroup->getConfigInt("view-distance", 8));
|
||||||
}
|
}
|
||||||
@ -337,6 +341,11 @@ class Server{
|
|||||||
return $str !== "" ? $str : "0.0.0.0";
|
return $str !== "" ? $str : "0.0.0.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getIpV6() : string{
|
||||||
|
$str = $this->configGroup->getConfigString("server-ipv6");
|
||||||
|
return $str !== "" ? $str : "::";
|
||||||
|
}
|
||||||
|
|
||||||
public function getServerUniqueId() : UuidInterface{
|
public function getServerUniqueId() : UuidInterface{
|
||||||
return $this->serverID;
|
return $this->serverID;
|
||||||
}
|
}
|
||||||
@ -784,6 +793,8 @@ class Server{
|
|||||||
new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES, [
|
new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES, [
|
||||||
"motd" => VersionInfo::NAME . " Server",
|
"motd" => VersionInfo::NAME . " Server",
|
||||||
"server-port" => 19132,
|
"server-port" => 19132,
|
||||||
|
"server-portv6" => 19133,
|
||||||
|
"enable-ipv6" => true,
|
||||||
"white-list" => false,
|
"white-list" => false,
|
||||||
"max-players" => 20,
|
"max-players" => 20,
|
||||||
"gamemode" => 0,
|
"gamemode" => 0,
|
||||||
@ -1114,25 +1125,42 @@ class Server{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function startupPrepareNetworkInterfaces() : bool{
|
private function startupPrepareConnectableNetworkInterfaces(string $ip, int $port, bool $ipV6, bool $useQuery) : bool{
|
||||||
$useQuery = $this->configGroup->getConfigBool("enable-query", true);
|
$prettyIp = $ipV6 ? "[$ip]" : $ip;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
$rakLibRegistered = $this->network->registerInterface(new RakLibInterface($this));
|
$rakLibRegistered = $this->network->registerInterface(new RakLibInterface($this, $ip, $port, $ipV6));
|
||||||
}catch(NetworkInterfaceStartException $e){
|
}catch(NetworkInterfaceStartException $e){
|
||||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_networkStartFailed(
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_networkStartFailed(
|
||||||
$this->getIp(),
|
$ip,
|
||||||
(string) $this->getPort(),
|
(string) $port,
|
||||||
$e->getMessage()
|
$e->getMessage()
|
||||||
)));
|
)));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!$rakLibRegistered && $useQuery){
|
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_networkStart($prettyIp, (string) $port)));
|
||||||
|
if($useQuery){
|
||||||
|
if(!$rakLibRegistered){
|
||||||
//RakLib would normally handle the transport for Query packets
|
//RakLib would normally handle the transport for Query packets
|
||||||
//if it's not registered we need to make sure Query still works
|
//if it's not registered we need to make sure Query still works
|
||||||
$this->network->registerInterface(new DedicatedQueryNetworkInterface($this->getIp(), $this->getPort(), new \PrefixedLogger($this->logger, "Dedicated Query Interface")));
|
$this->network->registerInterface(new DedicatedQueryNetworkInterface($ip, $port, $ipV6, new \PrefixedLogger($this->logger, "Dedicated Query Interface")));
|
||||||
|
}
|
||||||
|
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_query_running($prettyIp, (string) $port)));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function startupPrepareNetworkInterfaces() : bool{
|
||||||
|
$useQuery = $this->configGroup->getConfigBool("enable-query", true);
|
||||||
|
|
||||||
|
if(
|
||||||
|
!$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery) ||
|
||||||
|
(
|
||||||
|
$this->configGroup->getConfigBool("enable-ipv6", true) &&
|
||||||
|
!$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery)
|
||||||
|
)
|
||||||
|
){
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_networkStart($this->getIp(), (string) $this->getPort())));
|
|
||||||
|
|
||||||
if($useQuery){
|
if($useQuery){
|
||||||
$this->network->registerRawPacketHandler(new QueryHandler($this));
|
$this->network->registerRawPacketHandler(new QueryHandler($this));
|
||||||
|
@ -32,7 +32,7 @@ use pocketmine\player\Player;
|
|||||||
use function array_shift;
|
use function array_shift;
|
||||||
use function count;
|
use function count;
|
||||||
use function implode;
|
use function implode;
|
||||||
use function preg_match;
|
use function inet_pton;
|
||||||
|
|
||||||
class BanIpCommand extends VanillaCommand{
|
class BanIpCommand extends VanillaCommand{
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ class BanIpCommand extends VanillaCommand{
|
|||||||
$value = array_shift($args);
|
$value = array_shift($args);
|
||||||
$reason = implode(" ", $args);
|
$reason = implode(" ", $args);
|
||||||
|
|
||||||
if(preg_match("/^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$/", $value)){
|
if(inet_pton($value) !== false){
|
||||||
$this->processIPBan($value, $sender, $reason);
|
$this->processIPBan($value, $sender, $reason);
|
||||||
|
|
||||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_banip_success($value));
|
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_banip_success($value));
|
||||||
|
@ -29,7 +29,7 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
|
|||||||
use pocketmine\lang\KnownTranslationFactory;
|
use pocketmine\lang\KnownTranslationFactory;
|
||||||
use pocketmine\permission\DefaultPermissionNames;
|
use pocketmine\permission\DefaultPermissionNames;
|
||||||
use function count;
|
use function count;
|
||||||
use function preg_match;
|
use function inet_pton;
|
||||||
|
|
||||||
class PardonIpCommand extends VanillaCommand{
|
class PardonIpCommand extends VanillaCommand{
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ class PardonIpCommand extends VanillaCommand{
|
|||||||
throw new InvalidCommandSyntaxException();
|
throw new InvalidCommandSyntaxException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(preg_match("/^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$/", $args[0])){
|
if(inet_pton($args[0]) !== false){
|
||||||
$sender->getServer()->getIPBans()->remove($args[0]);
|
$sender->getServer()->getIPBans()->remove($args[0]);
|
||||||
$sender->getServer()->getNetwork()->unblockAddress($args[0]);
|
$sender->getServer()->getNetwork()->unblockAddress($args[0]);
|
||||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_unbanip_success($args[0]));
|
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_unbanip_success($args[0]));
|
||||||
|
@ -88,7 +88,7 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{
|
|||||||
/** @var PacketBroadcaster */
|
/** @var PacketBroadcaster */
|
||||||
private $broadcaster;
|
private $broadcaster;
|
||||||
|
|
||||||
public function __construct(Server $server){
|
public function __construct(Server $server, string $ip, int $port, bool $ipV6){
|
||||||
$this->server = $server;
|
$this->server = $server;
|
||||||
$this->rakServerId = mt_rand(0, PHP_INT_MAX);
|
$this->rakServerId = mt_rand(0, PHP_INT_MAX);
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{
|
|||||||
$this->server->getLogger(),
|
$this->server->getLogger(),
|
||||||
$mainToThreadBuffer,
|
$mainToThreadBuffer,
|
||||||
$threadToMainBuffer,
|
$threadToMainBuffer,
|
||||||
new InternetAddress($this->server->getIp(), $this->server->getPort(), 4),
|
new InternetAddress($ip, $port, $ipV6 ? 6 : 4),
|
||||||
$this->rakServerId,
|
$this->rakServerId,
|
||||||
$this->server->getConfigGroup()->getPropertyInt("network.max-mtu-size", 1492),
|
$this->server->getConfigGroup()->getPropertyInt("network.max-mtu-size", 1492),
|
||||||
self::MCPE_RAKNET_PROTOCOL_VERSION,
|
self::MCPE_RAKNET_PROTOCOL_VERSION,
|
||||||
|
@ -34,11 +34,14 @@ use function socket_recvfrom;
|
|||||||
use function socket_select;
|
use function socket_select;
|
||||||
use function socket_sendto;
|
use function socket_sendto;
|
||||||
use function socket_set_nonblock;
|
use function socket_set_nonblock;
|
||||||
|
use function socket_set_option;
|
||||||
use function socket_strerror;
|
use function socket_strerror;
|
||||||
use function strlen;
|
use function strlen;
|
||||||
use function time;
|
use function time;
|
||||||
use function trim;
|
use function trim;
|
||||||
use const AF_INET;
|
use const AF_INET;
|
||||||
|
use const IPPROTO_IPV6;
|
||||||
|
use const IPV6_V6ONLY;
|
||||||
use const PHP_INT_MAX;
|
use const PHP_INT_MAX;
|
||||||
use const SOCK_DGRAM;
|
use const SOCK_DGRAM;
|
||||||
use const SOCKET_EADDRINUSE;
|
use const SOCKET_EADDRINUSE;
|
||||||
@ -74,15 +77,18 @@ final class DedicatedQueryNetworkInterface implements AdvancedNetworkInterface{
|
|||||||
/** @var string[] */
|
/** @var string[] */
|
||||||
private $rawPacketPatterns = [];
|
private $rawPacketPatterns = [];
|
||||||
|
|
||||||
public function __construct(string $ip, int $port, \Logger $logger){
|
public function __construct(string $ip, int $port, bool $ipV6, \Logger $logger){
|
||||||
$this->ip = $ip;
|
$this->ip = $ip;
|
||||||
$this->port = $port;
|
$this->port = $port;
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
|
|
||||||
$socket = @socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
$socket = @socket_create($ipV6 ? AF_INET6 : AF_INET, SOCK_DGRAM, SOL_UDP);
|
||||||
if($socket === false){
|
if($socket === false){
|
||||||
throw new \RuntimeException("Failed to create socket");
|
throw new \RuntimeException("Failed to create socket");
|
||||||
}
|
}
|
||||||
|
if($ipV6){
|
||||||
|
socket_set_option($socket, IPPROTO_IPV6, IPV6_V6ONLY, 1); //disable linux's cool but annoying ipv4-over-ipv6 network stack
|
||||||
|
}
|
||||||
$this->socket = $socket;
|
$this->socket = $socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ declare(strict_types=1);
|
|||||||
*/
|
*/
|
||||||
namespace pocketmine\network\query;
|
namespace pocketmine\network\query;
|
||||||
|
|
||||||
use pocketmine\lang\KnownTranslationFactory;
|
|
||||||
use pocketmine\network\AdvancedNetworkInterface;
|
use pocketmine\network\AdvancedNetworkInterface;
|
||||||
use pocketmine\network\RawPacketHandler;
|
use pocketmine\network\RawPacketHandler;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
@ -57,8 +56,6 @@ class QueryHandler implements RawPacketHandler{
|
|||||||
public function __construct(Server $server){
|
public function __construct(Server $server){
|
||||||
$this->server = $server;
|
$this->server = $server;
|
||||||
$this->logger = new \PrefixedLogger($this->server->getLogger(), "Query Handler");
|
$this->logger = new \PrefixedLogger($this->server->getLogger(), "Query Handler");
|
||||||
$addr = $this->server->getIp();
|
|
||||||
$port = $this->server->getPort();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The Query protocol is built on top of the existing Minecraft PE UDP network stack.
|
The Query protocol is built on top of the existing Minecraft PE UDP network stack.
|
||||||
@ -71,7 +68,6 @@ class QueryHandler implements RawPacketHandler{
|
|||||||
|
|
||||||
$this->regenerateToken();
|
$this->regenerateToken();
|
||||||
$this->lastToken = $this->token;
|
$this->lastToken = $this->token;
|
||||||
$this->logger->info($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_query_running($addr, (string) $port)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPattern() : string{
|
public function getPattern() : string{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user