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. | 	 * Set new server options using the struct passed as parameters. | ||||||
| 	 * Mandatory fields: | 	 * Mandatory fields: | ||||||
| 	 *  Name, Comment, Password, PasswordForSpectator, CallVoteRatio | 	 *  Name, Comment, Password, PasswordForSpectator and CallVoteRatio. | ||||||
| 	 * Optional fields: | 	 * Ignored fields: | ||||||
| 	 *  NextMaxPlayers, NextMaxSpectators, IsP2PUpload, IsP2PDownload, NextLadderMode, | 	 *  LadderServerLimitMin, LadderServerLimitMax and those starting with Current. | ||||||
| 	 *	NextVehicleNetQuality, NextCallVoteTimeOut, AllowMapDownload, AutoSaveReplays, | 	 * All other fields are optional and can be set to null to be ignored. | ||||||
| 	 *  RefereePassword, RefereeMode, AutoSaveValidationReplays, HideServer, UseChangingValidationSeed, |  | ||||||
| 	 *  ClientInputsMaxLatency, DisableHorns, DisableServiceAnnounces, KeepPlayerSlots. |  | ||||||
| 	 * Only available to Admin. | 	 * Only available to Admin. | ||||||
| 	 * A change of NextMaxPlayers, NextMaxSpectators, NextLadderMode, NextVehicleNetQuality, | 	 * A change of any field starting with Next requires a map restart to be taken into account. | ||||||
| 	 *  NextCallVoteTimeOut or UseChangingValidationSeed requires a map restart to be taken into account. | 	 * @param Structures\ServerOptions $options | ||||||
| 	 * @param struct $options |  | ||||||
| 	 * @param bool $multicall | 	 * @param bool $multicall | ||||||
| 	 * @return bool | 	 * @return bool | ||||||
| 	 * @throws InvalidArgumentException | 	 * @throws InvalidArgumentException | ||||||
| 	 */ | 	 */ | ||||||
| 	function setServerOptions($options, $multicall=false) | 	function setServerOptions($options, $multicall=false) | ||||||
| 	{ | 	{ | ||||||
| 		if(!is_array($options) | 		if(!($options instanceof Structures\ServerOptions && $options->isValid())) | ||||||
| 				|| !(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']))) |  | ||||||
| 			throw new InvalidArgumentException('options = '.print_r($options, true)); | 			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. | 	 * Get the script cloud variables of given object. | ||||||
| 	 * Only available to Admin. | 	 * Only available to Admin. | ||||||
| 	 * @param string $arg1 | 	 * @param string $type | ||||||
| 	 * @param string $arg2 | 	 * @param string $id | ||||||
| 	 * @param bool $multicall | 	 * @param bool $multicall | ||||||
| 	 * @return array | 	 * @return array | ||||||
| 	 * @throws InvalidArgumentException | 	 * @throws InvalidArgumentException | ||||||
| 	 */ | 	 */ | ||||||
| 	function getScriptCloudVariables($arg1, $arg2, $multicall=false) | 	function getScriptCloudVariables($type, $id, $multicall=false) | ||||||
| 	{ | 	{ | ||||||
| 		if(!is_string($arg1)) | 		if(!is_string($type)) | ||||||
| 			throw new InvalidArgumentException('$arg1 = '.print_r($arg1, true)); | 			throw new InvalidArgumentException('type = '.print_r($type, true)); | ||||||
| 		if(!is_string($arg2)) | 		if(!is_string($id)) | ||||||
| 			throw new InvalidArgumentException('$arg2 = '.print_r($arg2, true)); | 			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. | 	 * Set the script cloud variables of given object. | ||||||
| 	 * Only available to Admin. | 	 * Only available to Admin. | ||||||
| 	 * @param string $arg1 | 	 * @param string $type | ||||||
| 	 * @param string $arg2 | 	 * @param string $id | ||||||
| 	 * @param struct $arg3 | 	 * @param mixed[] $variables {mixed <variable name>, ...} | ||||||
| 	 * @param bool $multicall | 	 * @param bool $multicall | ||||||
| 	 * @return bool | 	 * @return bool | ||||||
| 	 * @throws InvalidArgumentException | 	 * @throws InvalidArgumentException | ||||||
| 	 */ | 	 */ | ||||||
| 	function setScriptCloudVariables($arg1, $arg2, $arg3, $multicall=false) | 	function setScriptCloudVariables($type, $id, $variables, $multicall=false) | ||||||
| 	{ | 	{ | ||||||
| 		if(!is_string($arg1)) | 		if(!is_string($type)) | ||||||
| 			throw new InvalidArgumentException('$arg1 = '.print_r($arg1, true)); | 			throw new InvalidArgumentException('type = '.print_r($type, true)); | ||||||
| 		if(!is_string($arg2)) | 		if(!is_string($id)) | ||||||
| 			throw new InvalidArgumentException('$arg2 = '.print_r($arg2, true)); | 			throw new InvalidArgumentException('id = '.print_r($id, true)); | ||||||
| 		if(!is_struct($arg3)) | 		if(!is_array($variables) || !$variables) | ||||||
| 			throw new InvalidArgumentException('$arg3 = '.print_r($arg3, true)); | 			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. | 	 * Set as next maps the list of maps with the specified filenames, if they are present in the selection. | ||||||
| 	 * Only available to Admin. | 	 * Only available to Admin. | ||||||
| 	 * @param array $filenames Relative to the Maps path | 	 * @param string[] $filenames Relative to the Maps path | ||||||
| 	 * @param bool $multicall | 	 * @param bool $multicall | ||||||
| 	 * @return int Number of maps actually chosen | 	 * @return int Number of maps actually chosen | ||||||
| 	 * @throws InvalidArgumentException | 	 * @throws InvalidArgumentException | ||||||
| @@ -3942,6 +3934,46 @@ class Connection | |||||||
| 		return $this->execute(ucfirst(__FUNCTION__), array(), $multicall); | 		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 | 	 * Returns the login of the given player | ||||||
| 	 * @param mixed $player | 	 * @param mixed $player | ||||||
|   | |||||||
| @@ -71,4 +71,35 @@ class ServerOptions extends AbstractStructure | |||||||
| 	public $disableHorns; | 	public $disableHorns; | ||||||
| 	/** @var bool */ | 	/** @var bool */ | ||||||
| 	public $disableServiceAnnounces; | 	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 SYNCHRONIZATION = 3; | ||||||
| 	const PLAY            = 4; | 	const PLAY            = 4; | ||||||
| 	const EXITING         = 6; | 	const EXITING         = 6; | ||||||
|  | 	const LOCAL           = 7; | ||||||
|  |  | ||||||
| 	/** @var int */ | 	/** @var int */ | ||||||
| 	public $code; | 	public $code; | ||||||
|   | |||||||
| @@ -34,6 +34,7 @@ class Vote extends AbstractStructure | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
|  | 	 * @internal | ||||||
| 	 * @return bool | 	 * @return bool | ||||||
| 	 */ | 	 */ | ||||||
| 	function isValid() | 	function isValid() | ||||||
|   | |||||||
| @@ -37,6 +37,7 @@ class VoteRatio extends AbstractStructure | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
|  | 	 * @internal | ||||||
| 	 * @return bool | 	 * @return bool | ||||||
| 	 */ | 	 */ | ||||||
| 	function isValid() | 	function isValid() | ||||||
| @@ -47,6 +48,7 @@ class VoteRatio extends AbstractStructure | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
|  | 	 * @internal | ||||||
| 	 * @param float $ratio | 	 * @param float $ratio | ||||||
| 	 * @return bool | 	 * @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; | 	public static $sent; | ||||||
|  |  | ||||||
| 	private $socket; | 	private $socket; | ||||||
| 	private $timeouts = array( | 	private $readTimeout = array('sec' => 5, 'usec' => 0); | ||||||
| 		'read' => 8000, | 	private $writeTimeout = array('sec' => 5, 'usec' => 0); | ||||||
| 		'write' => 8000 |  | ||||||
| 	); |  | ||||||
| 	private $requestHandle; | 	private $requestHandle; | ||||||
| 	private $callbacksBuffer = array(); | 	private $callbacksBuffer = array(); | ||||||
| 	private $multicallBuffer = array(); | 	private $multicallBuffer = array(); | ||||||
| @@ -49,9 +47,15 @@ class GbxRemote | |||||||
| 	function setTimeouts($read=0, $write=0) | 	function setTimeouts($read=0, $write=0) | ||||||
| 	{ | 	{ | ||||||
| 		if($read) | 		if($read) | ||||||
| 			$this->timeouts['read'] = $read; | 		{ | ||||||
|  | 			$this->readTimeout['sec'] = (int) ($read / 1000); | ||||||
|  | 			$this->readTimeout['usec'] = ($read % 1000) * 1000; | ||||||
|  | 		} | ||||||
| 		if($write) | 		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) | 		if(!$this->socket) | ||||||
| 			throw new TransportException('Cannot open socket', TransportException::NOT_INITIALIZED); | 			throw new TransportException('Cannot open socket', TransportException::NOT_INITIALIZED); | ||||||
|  |  | ||||||
|  | 		stream_set_read_buffer($this->socket, 0); | ||||||
| 		stream_set_write_buffer($this->socket, 0); | 		stream_set_write_buffer($this->socket, 0); | ||||||
|  |  | ||||||
| 		// handshake | 		// handshake | ||||||
| 		$header = $this->read(15); | 		$header = $this->read(15); | ||||||
| 		if($header === false) | 		if($header === false) | ||||||
| 			throw new TransportException('Connection interrupted during handshake', TransportException::INTERRUPTED); | 			$this->onIoFailure('during handshake'); | ||||||
|  |  | ||||||
| 		extract(unpack('Vsize/a*protocol', $header)); | 		extract(unpack('Vsize/a*protocol', $header)); | ||||||
| 		/** @var $size int */ | 		/** @var $size int */ | ||||||
| @@ -185,10 +190,7 @@ class GbxRemote | |||||||
| 	private function flush($waitResponse=false) | 	private function flush($waitResponse=false) | ||||||
| 	{ | 	{ | ||||||
| 		$r = array($this->socket); | 		$r = array($this->socket); | ||||||
| 		$w = null; | 		while($waitResponse || @stream_select($r, $w, $e, 0) > 0) | ||||||
| 		$e = null; |  | ||||||
| 		$n = @stream_select($r, $w, $e, 0); |  | ||||||
| 		while($waitResponse || $n > 0) |  | ||||||
| 		{ | 		{ | ||||||
| 			list($handle, $xml) = $this->readMessage(); | 			list($handle, $xml) = $this->readMessage(); | ||||||
| 			list($type, $value) = Request::decode($xml); | 			list($type, $value) = Request::decode($xml); | ||||||
| @@ -203,10 +205,7 @@ class GbxRemote | |||||||
| 				case 'call': | 				case 'call': | ||||||
| 					$this->callbacksBuffer[] = $value; | 					$this->callbacksBuffer[] = $value; | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
| 			if(!$waitResponse) |  | ||||||
| 				$n = @stream_select($r, $w, $e, 0); |  | ||||||
| 		}; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -218,8 +217,7 @@ class GbxRemote | |||||||
| 	{ | 	{ | ||||||
| 		$header = $this->read(8); | 		$header = $this->read(8); | ||||||
| 		if($header === false) | 		if($header === false) | ||||||
| 			throw new TransportException('Connection interrupted while reading header '.print_r(stream_get_meta_data($this->socket), true), TransportException::INTERRUPTED); | 			$this->onIoFailure('while reading header'); | ||||||
| 			//throw new TransportException('Connection interrupted while reading header', TransportException::INTERRUPTED); |  | ||||||
|  |  | ||||||
| 		extract(unpack('Vsize/Vhandle', $header)); | 		extract(unpack('Vsize/Vhandle', $header)); | ||||||
| 		/** @var $size int */ | 		/** @var $size int */ | ||||||
| @@ -232,8 +230,7 @@ class GbxRemote | |||||||
|  |  | ||||||
| 		$data = $this->read($size); | 		$data = $this->read($size); | ||||||
| 		if($data === false) | 		if($data === false) | ||||||
| 			//throw new TransportException('Connection interrupted while reading data', TransportException::INTERRUPTED); | 			$this->onIoFailure('while reading data'); | ||||||
| 			throw new TransportException('Connection interrupted while reading data '.print_r(stream_get_meta_data($this->socket), true), TransportException::INTERRUPTED); |  | ||||||
|  |  | ||||||
| 		$this->lastNetworkActivity = time(); | 		$this->lastNetworkActivity = time(); | ||||||
| 		return array($handle, $data); | 		return array($handle, $data); | ||||||
| @@ -245,10 +242,11 @@ class GbxRemote | |||||||
| 	 */ | 	 */ | ||||||
| 	private function writeMessage($xml) | 	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)) | 		if(!$this->write($data)) | ||||||
| 			throw new TransportException('Connection interrupted while writing '.print_r(stream_get_meta_data($this->socket), true), TransportException::INTERRUPTED); | 			$this->onIoFailure('while writing'); | ||||||
| 			//throw new TransportException('Connection interrupted while writing', TransportException::INTERRUPTED); |  | ||||||
| 		$this->lastNetworkActivity = time(); | 		$this->lastNetworkActivity = time(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -258,7 +256,7 @@ class GbxRemote | |||||||
| 	 */ | 	 */ | ||||||
| 	private function read($size) | 	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 = ''; | 		$data = ''; | ||||||
| 		while(strlen($data) < $size) | 		while(strlen($data) < $size) | ||||||
| @@ -279,7 +277,8 @@ class GbxRemote | |||||||
| 	 */ | 	 */ | ||||||
| 	private function write($data) | 	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) | 		while(strlen($data) > 0) | ||||||
| 		{ | 		{ | ||||||
| @@ -287,22 +286,32 @@ class GbxRemote | |||||||
| 			if($written === 0 || $written === false) | 			if($written === 0 || $written === false) | ||||||
| 				return false; | 				return false; | ||||||
|  |  | ||||||
| 			fflush($this->socket); |  | ||||||
|  |  | ||||||
| 			$data = substr($data, $written); | 			$data = substr($data, $written); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		self::$sent += strlen($data); |  | ||||||
| 		return true; | 		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 | class TransportException extends Exception | ||||||
| { | { | ||||||
| 	const NOT_INITIALIZED = 1; | 	const NOT_INITIALIZED = 1; | ||||||
| 	const INTERRUPTED     = 2; | 	const INTERRUPTED     = 2; | ||||||
| 	const WRONG_PROTOCOL  = 3; | 	const TIMED_OUT       = 3; | ||||||
| 	const PROTOCOL_ERROR  = 4; | 	const WRONG_PROTOCOL  = 4; | ||||||
|  | 	const PROTOCOL_ERROR  = 5; | ||||||
| } | } | ||||||
|  |  | ||||||
| class MessageException extends Exception | class MessageException extends Exception | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user