dedicated-server-api update
This commit is contained in:
		
							
								
								
									
										104
									
								
								application/core/Libs/Maniaplanet/DedicatedServer/Connection.php
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										104
									
								
								application/core/Libs/Maniaplanet/DedicatedServer/Connection.php
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -2081,31 +2081,23 @@ class Connection | ||||
| 	/** | ||||
| 	 * Set new server options using the struct passed as parameters. | ||||
| 	 * Mandatory fields: | ||||
| 	 *  Name, Comment, Password, PasswordForSpectator, CallVoteRatio | ||||
| 	 * Optional fields: | ||||
| 	 *  NextMaxPlayers, NextMaxSpectators, IsP2PUpload, IsP2PDownload, NextLadderMode, | ||||
| 	 *	NextVehicleNetQuality, NextCallVoteTimeOut, AllowMapDownload, AutoSaveReplays, | ||||
| 	 *  RefereePassword, RefereeMode, AutoSaveValidationReplays, HideServer, UseChangingValidationSeed, | ||||
| 	 *  ClientInputsMaxLatency, DisableHorns, DisableServiceAnnounces, KeepPlayerSlots. | ||||
| 	 *  Name, Comment, Password, PasswordForSpectator and CallVoteRatio. | ||||
| 	 * Ignored fields: | ||||
| 	 *  LadderServerLimitMin, LadderServerLimitMax and those starting with Current. | ||||
| 	 * All other fields are optional and can be set to null to be ignored. | ||||
| 	 * Only available to Admin. | ||||
| 	 * A change of NextMaxPlayers, NextMaxSpectators, NextLadderMode, NextVehicleNetQuality, | ||||
| 	 *  NextCallVoteTimeOut or UseChangingValidationSeed requires a map restart to be taken into account. | ||||
| 	 * @param struct $options | ||||
| 	 * A change of any field starting with Next requires a map restart to be taken into account. | ||||
| 	 * @param Structures\ServerOptions $options | ||||
| 	 * @param bool $multicall | ||||
| 	 * @return bool | ||||
| 	 * @throws InvalidArgumentException | ||||
| 	 */ | ||||
| 	function setServerOptions($options, $multicall=false) | ||||
| 	{ | ||||
| 		if(!is_array($options) | ||||
| 				|| !(isset($options['Name']) && is_string($options['Name'])) | ||||
| 				|| !(isset($options['Comment']) && is_string($options['Comment'])) | ||||
| 				|| !(isset($options['Password']) && is_string($options['Password'])) | ||||
| 				|| !(isset($options['PasswordForSpectator']) && is_string($options['PasswordForSpectator'])) | ||||
| 				|| !(isset($options['CallVoteRatio']) && Structures\VoteRatio::isRatio($options['CallVoteRatio']))) | ||||
| 		if(!($options instanceof Structures\ServerOptions && $options->isValid())) | ||||
| 			throw new InvalidArgumentException('options = '.print_r($options, true)); | ||||
|  | ||||
| 		return $this->execute(ucfirst(__FUNCTION__), array($options), $multicall); | ||||
| 		return $this->execute(ucfirst(__FUNCTION__), array($options->toSetterArray()), $multicall); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @@ -2573,42 +2565,42 @@ class Connection | ||||
| 	/** | ||||
| 	 * Get the script cloud variables of given object. | ||||
| 	 * Only available to Admin. | ||||
| 	 * @param string $arg1 | ||||
| 	 * @param string $arg2 | ||||
| 	 * @param string $type | ||||
| 	 * @param string $id | ||||
| 	 * @param bool $multicall | ||||
| 	 * @return array | ||||
| 	 * @throws InvalidArgumentException | ||||
| 	 */ | ||||
| 	function getScriptCloudVariables($arg1, $arg2, $multicall=false) | ||||
| 	function getScriptCloudVariables($type, $id, $multicall=false) | ||||
| 	{ | ||||
| 		if(!is_string($arg1)) | ||||
| 			throw new InvalidArgumentException('$arg1 = '.print_r($arg1, true)); | ||||
| 		if(!is_string($arg2)) | ||||
| 			throw new InvalidArgumentException('$arg2 = '.print_r($arg2, true)); | ||||
| 		if(!is_string($type)) | ||||
| 			throw new InvalidArgumentException('type = '.print_r($type, true)); | ||||
| 		if(!is_string($id)) | ||||
| 			throw new InvalidArgumentException('id = '.print_r($id, true)); | ||||
|  | ||||
| 		return $this->execute(ucfirst(__FUNCTION__), array($arg1, $arg2), $multicall); | ||||
| 		return $this->execute(ucfirst(__FUNCTION__), array($type, $id), $multicall); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Set the script cloud variables of given object. | ||||
| 	 * Only available to Admin. | ||||
| 	 * @param string $arg1 | ||||
| 	 * @param string $arg2 | ||||
| 	 * @param struct $arg3 | ||||
| 	 * @param string $type | ||||
| 	 * @param string $id | ||||
| 	 * @param mixed[] $variables {mixed <variable name>, ...} | ||||
| 	 * @param bool $multicall | ||||
| 	 * @return bool | ||||
| 	 * @throws InvalidArgumentException | ||||
| 	 */ | ||||
| 	function setScriptCloudVariables($arg1, $arg2, $arg3, $multicall=false) | ||||
| 	function setScriptCloudVariables($type, $id, $variables, $multicall=false) | ||||
| 	{ | ||||
| 		if(!is_string($arg1)) | ||||
| 			throw new InvalidArgumentException('$arg1 = '.print_r($arg1, true)); | ||||
| 		if(!is_string($arg2)) | ||||
| 			throw new InvalidArgumentException('$arg2 = '.print_r($arg2, true)); | ||||
| 		if(!is_struct($arg3)) | ||||
| 			throw new InvalidArgumentException('$arg3 = '.print_r($arg3, true)); | ||||
| 		if(!is_string($type)) | ||||
| 			throw new InvalidArgumentException('type = '.print_r($type, true)); | ||||
| 		if(!is_string($id)) | ||||
| 			throw new InvalidArgumentException('id = '.print_r($id, true)); | ||||
| 		if(!is_array($variables) || !$variables) | ||||
| 			throw new InvalidArgumentException('variables = '.print_r($variables, true)); | ||||
|  | ||||
| 		return $this->execute(ucfirst(__FUNCTION__), array($arg1, $arg2, $arg3), $multicall); | ||||
| 		return $this->execute(ucfirst(__FUNCTION__), array($type, $id, $variables), $multicall); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @@ -3548,7 +3540,7 @@ class Connection | ||||
| 	/** | ||||
| 	 * Set as next maps the list of maps with the specified filenames, if they are present in the selection. | ||||
| 	 * Only available to Admin. | ||||
| 	 * @param array $filenames Relative to the Maps path | ||||
| 	 * @param string[] $filenames Relative to the Maps path | ||||
| 	 * @param bool $multicall | ||||
| 	 * @return int Number of maps actually chosen | ||||
| 	 * @throws InvalidArgumentException | ||||
| @@ -3942,6 +3934,46 @@ class Connection | ||||
| 		return $this->execute(ucfirst(__FUNCTION__), array(), $multicall); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Join the server on lan. | ||||
| 	 * Only available on client. | ||||
| 	 * Only available to Admin. | ||||
| 	 * @param string $host IPv4 with optionally a port (eg. '192.168.1.42:2350') | ||||
| 	 * @param string $password | ||||
| 	 * @param bool $multicall | ||||
| 	 * @return bool | ||||
| 	 * @throws InvalidArgumentException | ||||
| 	 */ | ||||
| 	function joinServerLan($host, $password='', $multicall=false) | ||||
| 	{ | ||||
| 		if(!is_string($host)) | ||||
| 			throw new InvalidArgumentException('host = '.print_r($host, true)); | ||||
| 		if(!is_string($password)) | ||||
| 			throw new InvalidArgumentException('password = '.print_r($password, true)); | ||||
|  | ||||
| 		return $this->execute(ucfirst(__FUNCTION__), array(array('Server' => $host, 'ServerPassword' => $password)), $multicall); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Join the server on internet. | ||||
| 	 * Only available on client. | ||||
| 	 * Only available to Admin. | ||||
| 	 * @param string $host Server login or IPv4 with optionally a port (eg. '192.168.1.42:2350') | ||||
| 	 * @param string $password | ||||
| 	 * @param bool $multicall | ||||
| 	 * @return bool | ||||
| 	 * @throws InvalidArgumentException | ||||
| 	 */ | ||||
| 	function joinServerInternet($host, $password='', $multicall=false) | ||||
| 	{ | ||||
| 		if(!is_string($host)) | ||||
| 			throw new InvalidArgumentException('host = '.print_r($host, true)); | ||||
| 		if(!is_string($password)) | ||||
| 			throw new InvalidArgumentException('password = '.print_r($password, true)); | ||||
|  | ||||
| 		return $this->execute(ucfirst(__FUNCTION__), array(array('Server' => $host, 'ServerPassword' => $password)), $multicall); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns the login of the given player | ||||
| 	 * @param mixed $player | ||||
|   | ||||
| @@ -71,4 +71,35 @@ class ServerOptions extends AbstractStructure | ||||
| 	public $disableHorns; | ||||
| 	/** @var bool */ | ||||
| 	public $disableServiceAnnounces; | ||||
|  | ||||
| 	/** | ||||
| 	 * @internal | ||||
| 	 * @return bool | ||||
| 	 */ | ||||
| 	function isValid() | ||||
| 	{ | ||||
| 		return is_string($this->name) | ||||
| 			&& is_string($this->comment) | ||||
| 			&& is_string($this->password) | ||||
| 			&& is_string($this->passwordForSpectator) | ||||
| 			&& VoteRatio::isRatio($this->callVoteRatio); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @internal | ||||
| 	 * @return mixed[] | ||||
| 	 */ | ||||
| 	function toSetterArray() | ||||
| 	{ | ||||
| 		$out = array(); | ||||
| 		foreach(get_object_vars($this) as $key => $value) | ||||
| 		{ | ||||
| 			if(substr($key, 0, 7) == 'current' || $value === null) | ||||
| 				continue; | ||||
| 			if($key == 'nextUseChangingValidationSeed') | ||||
| 				$key = 'useChangingValidationSeed'; | ||||
| 			$out[ucfirst($key)] = $value; | ||||
| 		} | ||||
| 		return $out; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -15,6 +15,7 @@ class Status extends AbstractStructure | ||||
| 	const SYNCHRONIZATION = 3; | ||||
| 	const PLAY            = 4; | ||||
| 	const EXITING         = 6; | ||||
| 	const LOCAL           = 7; | ||||
|  | ||||
| 	/** @var int */ | ||||
| 	public $code; | ||||
|   | ||||
| @@ -34,6 +34,7 @@ class Vote extends AbstractStructure | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @internal | ||||
| 	 * @return bool | ||||
| 	 */ | ||||
| 	function isValid() | ||||
|   | ||||
| @@ -37,6 +37,7 @@ class VoteRatio extends AbstractStructure | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @internal | ||||
| 	 * @return bool | ||||
| 	 */ | ||||
| 	function isValid() | ||||
| @@ -47,6 +48,7 @@ class VoteRatio extends AbstractStructure | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @internal | ||||
| 	 * @param float $ratio | ||||
| 	 * @return bool | ||||
| 	 */ | ||||
|   | ||||
							
								
								
									
										67
									
								
								application/core/Libs/Maniaplanet/DedicatedServer/Xmlrpc/GbxRemote.php
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										67
									
								
								application/core/Libs/Maniaplanet/DedicatedServer/Xmlrpc/GbxRemote.php
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -16,10 +16,8 @@ class GbxRemote | ||||
| 	public static $sent; | ||||
|  | ||||
| 	private $socket; | ||||
| 	private $timeouts = array( | ||||
| 		'read' => 8000, | ||||
| 		'write' => 8000 | ||||
| 	); | ||||
| 	private $readTimeout = array('sec' => 5, 'usec' => 0); | ||||
| 	private $writeTimeout = array('sec' => 5, 'usec' => 0); | ||||
| 	private $requestHandle; | ||||
| 	private $callbacksBuffer = array(); | ||||
| 	private $multicallBuffer = array(); | ||||
| @@ -49,9 +47,15 @@ class GbxRemote | ||||
| 	function setTimeouts($read=0, $write=0) | ||||
| 	{ | ||||
| 		if($read) | ||||
| 			$this->timeouts['read'] = $read; | ||||
| 		{ | ||||
| 			$this->readTimeout['sec'] = (int) ($read / 1000); | ||||
| 			$this->readTimeout['usec'] = ($read % 1000) * 1000; | ||||
| 		} | ||||
| 		if($write) | ||||
| 			$this->timeouts['write'] = $write; | ||||
| 		{ | ||||
| 			$this->writeTimeout['sec'] = (int) ($write / 1000); | ||||
| 			$this->writeTimeout['usec'] = ($write % 1000) * 1000; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @@ -75,12 +79,13 @@ class GbxRemote | ||||
| 		if(!$this->socket) | ||||
| 			throw new TransportException('Cannot open socket', TransportException::NOT_INITIALIZED); | ||||
|  | ||||
| 		stream_set_read_buffer($this->socket, 0); | ||||
| 		stream_set_write_buffer($this->socket, 0); | ||||
|  | ||||
| 		// handshake | ||||
| 		$header = $this->read(15); | ||||
| 		if($header === false) | ||||
| 			throw new TransportException('Connection interrupted during handshake', TransportException::INTERRUPTED); | ||||
| 			$this->onIoFailure('during handshake'); | ||||
|  | ||||
| 		extract(unpack('Vsize/a*protocol', $header)); | ||||
| 		/** @var $size int */ | ||||
| @@ -185,10 +190,7 @@ class GbxRemote | ||||
| 	private function flush($waitResponse=false) | ||||
| 	{ | ||||
| 		$r = array($this->socket); | ||||
| 		$w = null; | ||||
| 		$e = null; | ||||
| 		$n = @stream_select($r, $w, $e, 0); | ||||
| 		while($waitResponse || $n > 0) | ||||
| 		while($waitResponse || @stream_select($r, $w, $e, 0) > 0) | ||||
| 		{ | ||||
| 			list($handle, $xml) = $this->readMessage(); | ||||
| 			list($type, $value) = Request::decode($xml); | ||||
| @@ -203,10 +205,7 @@ class GbxRemote | ||||
| 				case 'call': | ||||
| 					$this->callbacksBuffer[] = $value; | ||||
| 			} | ||||
|  | ||||
| 			if(!$waitResponse) | ||||
| 				$n = @stream_select($r, $w, $e, 0); | ||||
| 		}; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @@ -218,8 +217,7 @@ class GbxRemote | ||||
| 	{ | ||||
| 		$header = $this->read(8); | ||||
| 		if($header === false) | ||||
| 			throw new TransportException('Connection interrupted while reading header '.print_r(stream_get_meta_data($this->socket), true), TransportException::INTERRUPTED); | ||||
| 			//throw new TransportException('Connection interrupted while reading header', TransportException::INTERRUPTED); | ||||
| 			$this->onIoFailure('while reading header'); | ||||
|  | ||||
| 		extract(unpack('Vsize/Vhandle', $header)); | ||||
| 		/** @var $size int */ | ||||
| @@ -232,8 +230,7 @@ class GbxRemote | ||||
|  | ||||
| 		$data = $this->read($size); | ||||
| 		if($data === false) | ||||
| 			//throw new TransportException('Connection interrupted while reading data', TransportException::INTERRUPTED); | ||||
| 			throw new TransportException('Connection interrupted while reading data '.print_r(stream_get_meta_data($this->socket), true), TransportException::INTERRUPTED); | ||||
| 			$this->onIoFailure('while reading data'); | ||||
|  | ||||
| 		$this->lastNetworkActivity = time(); | ||||
| 		return array($handle, $data); | ||||
| @@ -245,10 +242,11 @@ class GbxRemote | ||||
| 	 */ | ||||
| 	private function writeMessage($xml) | ||||
| 	{ | ||||
| 		$data = pack('V2a*', strlen($xml), ++$this->requestHandle, $xml); | ||||
| 		if($this->requestHandle == (int) 0xffffffff) | ||||
| 			$this->requestHandle = (int) 0x80000000; | ||||
| 		$data = pack('V2', strlen($xml), ++$this->requestHandle).$xml; | ||||
| 		if(!$this->write($data)) | ||||
| 			throw new TransportException('Connection interrupted while writing '.print_r(stream_get_meta_data($this->socket), true), TransportException::INTERRUPTED); | ||||
| 			//throw new TransportException('Connection interrupted while writing', TransportException::INTERRUPTED); | ||||
| 			$this->onIoFailure('while writing'); | ||||
| 		$this->lastNetworkActivity = time(); | ||||
| 	} | ||||
|  | ||||
| @@ -258,7 +256,7 @@ class GbxRemote | ||||
| 	 */ | ||||
| 	private function read($size) | ||||
| 	{ | ||||
| 		@stream_set_timeout($this->socket, 0, $this->timeouts['read'] * 1000); | ||||
| 		@stream_set_timeout($this->socket, $this->readTimeout['sec'], $this->readTimeout['usec']); | ||||
|  | ||||
| 		$data = ''; | ||||
| 		while(strlen($data) < $size) | ||||
| @@ -279,7 +277,8 @@ class GbxRemote | ||||
| 	 */ | ||||
| 	private function write($data) | ||||
| 	{ | ||||
| 		@stream_set_timeout($this->socket, 0, $this->timeouts['write'] * 1000); | ||||
| 		@stream_set_timeout($this->socket, $this->writeTimeout['sec'], $this->writeTimeout['usec']); | ||||
| 		self::$sent += strlen($data); | ||||
|  | ||||
| 		while(strlen($data) > 0) | ||||
| 		{ | ||||
| @@ -287,22 +286,32 @@ class GbxRemote | ||||
| 			if($written === 0 || $written === false) | ||||
| 				return false; | ||||
|  | ||||
| 			fflush($this->socket); | ||||
|  | ||||
| 			$data = substr($data, $written); | ||||
| 		} | ||||
|  | ||||
| 		self::$sent += strlen($data); | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param string $when | ||||
| 	 * @throws TransportException | ||||
| 	 */ | ||||
| 	private function onIoFailure($when) | ||||
| 	{ | ||||
| 		$meta = stream_get_meta_data($this->socket); | ||||
| 		if($meta['timed_out']) | ||||
| 			throw new TransportException('Connection timed out '.$when, TransportException::TIMED_OUT); | ||||
| 		throw new TransportException('Connection interrupted '.$when, TransportException::INTERRUPTED); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class TransportException extends Exception | ||||
| { | ||||
| 	const NOT_INITIALIZED = 1; | ||||
| 	const INTERRUPTED     = 2; | ||||
| 	const WRONG_PROTOCOL  = 3; | ||||
| 	const PROTOCOL_ERROR  = 4; | ||||
| 	const TIMED_OUT       = 3; | ||||
| 	const WRONG_PROTOCOL  = 4; | ||||
| 	const PROTOCOL_ERROR  = 5; | ||||
| } | ||||
|  | ||||
| class MessageException extends Exception | ||||
|   | ||||
		Reference in New Issue
	
	Block a user