Path: blob/1.0-develop/app/Services/Allocations/FindAssignableAllocationService.php
14042 views
<?php12namespace Pterodactyl\Services\Allocations;34use Webmozart\Assert\Assert;5use Pterodactyl\Models\Server;6use Pterodactyl\Models\Allocation;7use Pterodactyl\Exceptions\Service\Allocation\AutoAllocationNotEnabledException;8use Pterodactyl\Exceptions\Service\Allocation\NoAutoAllocationSpaceAvailableException;910class FindAssignableAllocationService11{12/**13* FindAssignableAllocationService constructor.14*/15public function __construct(private AssignmentService $service)16{17}1819/**20* Finds an existing unassigned allocation and attempts to assign it to the given server. If21* no allocation can be found, a new one will be created with a random port between the defined22* range from the configuration.23*24* @throws \Pterodactyl\Exceptions\DisplayException25* @throws \Pterodactyl\Exceptions\Service\Allocation\CidrOutOfRangeException26* @throws \Pterodactyl\Exceptions\Service\Allocation\InvalidPortMappingException27* @throws \Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException28* @throws \Pterodactyl\Exceptions\Service\Allocation\TooManyPortsInRangeException29*/30public function handle(Server $server): Allocation31{32if (!config('pterodactyl.client_features.allocations.enabled')) {33throw new AutoAllocationNotEnabledException();34}3536// Attempt to find a given available allocation for a server. If one cannot be found37// we will fall back to attempting to create a new allocation that can be used for the38// server.39/** @var Allocation|null $allocation */40$allocation = $server->node->allocations()41->lockForUpdate()42->where('ip', $server->allocation->ip)43->whereNull('server_id')44->inRandomOrder()45->first();4647$allocation = $allocation ?? $this->createNewAllocation($server);4849$allocation->update(['server_id' => $server->id]);5051return $allocation->refresh();52}5354/**55* Create a new allocation on the server's node with a random port from the defined range56* in the settings. If there are no matches in that range, or something is wrong with the57* range information provided an exception will be raised.58*59* @throws \Pterodactyl\Exceptions\DisplayException60* @throws \Pterodactyl\Exceptions\Service\Allocation\CidrOutOfRangeException61* @throws \Pterodactyl\Exceptions\Service\Allocation\InvalidPortMappingException62* @throws \Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException63* @throws \Pterodactyl\Exceptions\Service\Allocation\TooManyPortsInRangeException64*/65protected function createNewAllocation(Server $server): Allocation66{67$start = config('pterodactyl.client_features.allocations.range_start', null);68$end = config('pterodactyl.client_features.allocations.range_end', null);6970if (!$start || !$end) {71throw new NoAutoAllocationSpaceAvailableException();72}7374Assert::integerish($start);75Assert::integerish($end);7677// Get all of the currently allocated ports for the node so that we can figure out78// which port might be available.79$ports = $server->node->allocations()80->where('ip', $server->allocation->ip)81->whereBetween('port', [$start, $end])82->pluck('port');8384// Compute the difference of the range and the currently created ports, finding85// any port that does not already exist in the database. We will then use this86// array of ports to create a new allocation to assign to the server.87$available = array_diff(range($start, $end), $ports->toArray());8889// If we've already allocated all of the ports, just abort.90if (empty($available)) {91throw new NoAutoAllocationSpaceAvailableException();92}9394// Pick a random port out of the remaining available ports.95/** @var int $port */96$port = $available[array_rand($available)];9798$this->service->handle($server->node, [99'allocation_ip' => $server->allocation->ip,100'allocation_ports' => [$port],101]);102103/** @var Allocation $allocation */104$allocation = $server->node->allocations()105->lockForUpdate()106->where('ip', $server->allocation->ip)107->where('port', $port)108->firstOrFail();109110return $allocation;111}112}113114115