diff --git a/application/core/Files/AsynchronousFileReader.php b/application/core/Files/AsynchronousFileReader.php index b57847aa..a72e7f75 100644 --- a/application/core/Files/AsynchronousFileReader.php +++ b/application/core/Files/AsynchronousFileReader.php @@ -4,6 +4,11 @@ namespace ManiaControl\Files; use ManiaControl\Callbacks\TimerListener; use ManiaControl\ManiaControl; +/** + * Asynchronous File Reader + * + * @author kremsy & steeffeen + */ class AsynchronousFileReader implements TimerListener { /** * Private Properties @@ -18,33 +23,37 @@ class AsynchronousFileReader implements TimerListener { */ public function __construct(ManiaControl $maniaControl) { $this->maniaControl = $maniaControl; - $this->maniaControl->timerManager->registerTimerListening($this, 'appendData', 1); } public function appendData() { - foreach($this->sockets as &$socket) { + foreach($this->sockets as $key => &$socket) { /** @var SocketStructure $socket */ $socket->streamBuffer .= fread($socket->socket, 512); $info = stream_get_meta_data($socket->socket); - if (feof($socket->socket || $info['timed_out'])) { //TODO special error threadment on timeout + if (feof($socket->socket) || $info['timed_out']) { fclose($socket->socket); + unset($this->sockets[$key]); - $error = 0; //TODO error constants - if ($info['timed_out'] || !$socket->streamBuffer) { - $error = 1; - } else if (substr($socket->streamBuffer, 9, 3) != "200") { - $error = 2; + if ($info['timed_out']) { + throw new \Exception("Timed out while reading data from " . $socket->url); + } + + if (substr($socket->streamBuffer, 9, 3) != "200") { + throw new \Exception("Connection or response error on " . $socket->url); + } + + if ($socket->streamBuffer == '') { + throw new \Exception("No data returned from " . $socket->url); } $result = explode("\r\n\r\n", $socket->streamBuffer, 2); if (count($result) < 2) { - $error = 3; + throw new \Exception("Invalid Result"); } - //TODO call inner function - + call_user_func($socket->function, $result[1]); } } } @@ -53,21 +62,30 @@ class AsynchronousFileReader implements TimerListener { * Load a remote file * * @param string $url + * @param $function * @param string $contentType - * @return string || null + * @return bool */ - public function loadFile($url, $contentType = 'UTF-8', $function) { + public function loadFile($url, $function, $contentType = 'UTF-8') { + if (!is_callable($function)) { + $this->maniaControl->log("Function is not callable"); + return false; + } + if (!$url) { return null; } - $urlData = parse_url($url); - $port = (isset($urlData['port']) ? $urlData['port'] : 80); + $urlData = parse_url($url); + $port = (isset($urlData['port']) ? $urlData['port'] : 80); + $urlQuery = isset($urlData['query']) ? "?" . $urlData['query'] : ""; - $socket = fsockopen($urlData['host'], $port); - stream_set_timeout($socket, 5); + $socket = @fsockopen($urlData['host'], $port, $errno, $errstr, 4); + if (!$socket) { + return false; + } + stream_set_timeout($socket, 10); - - $query = 'GET ' . $urlData['path'] . ' HTTP/1.0' . PHP_EOL; + $query = 'GET ' . $urlData['path'] . $urlQuery . ' HTTP/1.0' . PHP_EOL; $query .= 'Host: ' . $urlData['host'] . PHP_EOL; $query .= 'Content-Type: ' . $contentType . PHP_EOL; $query .= 'User-Agent: ManiaControl v' . ManiaControl::VERSION . PHP_EOL; @@ -75,10 +93,14 @@ class AsynchronousFileReader implements TimerListener { fwrite($socket, $query); - //TODO check error - stream_set_blocking($this->sockets, 0); + $success = stream_set_blocking($socket, 0); + if (!$success) { + return false; + } - $socketStructure = new SocketStructure($socket, $function); + $socketStructure = new SocketStructure($url, $socket, $function); array_push($this->sockets, $socketStructure); + + return true; } } \ No newline at end of file diff --git a/application/core/Files/FileUtil.php b/application/core/Files/FileUtil.php index a130ac8c..a2056929 100644 --- a/application/core/Files/FileUtil.php +++ b/application/core/Files/FileUtil.php @@ -22,13 +22,14 @@ abstract class FileUtil { if (!$url) { return null; } - $urlData = parse_url($url); - $port = (isset($urlData['port']) ? $urlData['port'] : 80); + $urlData = parse_url($url); + $port = (isset($urlData['port']) ? $urlData['port'] : 80); + $urlQuery = isset($urlData['query']) ? "?" . $urlData['query'] : ""; $fsock = fsockopen($urlData['host'], $port); stream_set_timeout($fsock, 3); - $query = 'GET ' . $urlData['path'] . ' HTTP/1.0' . PHP_EOL; + $query = 'GET ' . $urlData['path'] . $urlQuery . ' HTTP/1.0' . PHP_EOL; $query .= 'Host: ' . $urlData['host'] . PHP_EOL; $query .= 'Content-Type: ' . $contentType . PHP_EOL; $query .= 'User-Agent: ManiaControl v' . ManiaControl::VERSION . PHP_EOL; diff --git a/application/core/Files/SocketStructure.php b/application/core/Files/SocketStructure.php index 3a0813bf..0f57cca5 100644 --- a/application/core/Files/SocketStructure.php +++ b/application/core/Files/SocketStructure.php @@ -1,11 +1,9 @@ url = $url; $this->socket = $socket; $this->function = $function; $this->streamBuffer = ''; diff --git a/application/core/ManiaControl.php b/application/core/ManiaControl.php index 02b02fb2..71436d05 100644 --- a/application/core/ManiaControl.php +++ b/application/core/ManiaControl.php @@ -10,6 +10,7 @@ use ManiaControl\Callbacks\TimerManager; use ManiaControl\Commands\CommandListener; use ManiaControl\Commands\CommandManager; use ManiaControl\Configurators\Configurator; +use ManiaControl\Files\AsynchronousFileReader; use ManiaControl\Files\FileUtil; use ManiaControl\Manialinks\ManialinkManager; use ManiaControl\Maps\MapManager; @@ -66,7 +67,7 @@ class ManiaControl implements CommandListener { public $updateManager = null; public $errorHandler = null; public $timerManager = null; - + public $fileReader = null; /** * Private properties */ @@ -88,6 +89,7 @@ class ManiaControl implements CommandListener { $this->database = new Database($this); $this->callbackManager = new CallbackManager($this); $this->timerManager = new TimerManager($this); + $this->fileReader = new AsynchronousFileReader($this); $this->settingManager = new SettingManager($this); $this->statisticManager = new StatisticManager($this); $this->manialinkManager = new ManialinkManager($this); @@ -288,6 +290,9 @@ class ManiaControl implements CommandListener { // Manager callbacks $this->callbackManager->manageCallbacks(); + // Manage FileReader + $this->fileReader->appendData(); + // Yield for next tick $loopEnd = microtime(true); diff --git a/application/core/ManiaExchange/ManiaExchangeManager.php b/application/core/ManiaExchange/ManiaExchangeManager.php index 5fae0846..575734d3 100644 --- a/application/core/ManiaExchange/ManiaExchangeManager.php +++ b/application/core/ManiaExchange/ManiaExchangeManager.php @@ -2,6 +2,7 @@ namespace ManiaControl\ManiaExchange; +use ManiaControl\Files\FileUtil; use ManiaControl\ManiaControl; use ManiaControl\Maps\Map; use ManiaControl\Maps\MapManager; @@ -156,8 +157,7 @@ class ManiaExchangeManager { //If Max Maplimit is reached, or string gets too long send the request if ($id % self::MAPS_PER_MX_FETCH == 0) { $mapIdString = substr($mapIdString, 0, -1); - $maps = $this->getMaplistByMixedUidIdString($mapIdString); - $this->updateMapObjectsWithManiaExchangeIds($maps); + $this->getMaplistByMixedUidIdString($mapIdString); $mapIdString = ''; } @@ -166,8 +166,7 @@ class ManiaExchangeManager { if ($mapIdString != '') { $mapIdString = substr($mapIdString, 0, -1); - $maps = $this->getMaplistByMixedUidIdString($mapIdString); - $this->updateMapObjectsWithManiaExchangeIds($maps); + $this->getMaplistByMixedUidIdString($mapIdString); } $fetchMapStatement->close(); @@ -187,36 +186,36 @@ class ManiaExchangeManager { // compile search URL $url = 'http://api.mania-exchange.com/' . $titlePrefix . '/maps/?ids=' . $string; - // $mapInfo = FileUtil::loadFile($url, "application/json"); //TODO use mc fileutil - $mapInfo = $this->get_file($url); + try { //FIXME exceptions get not caught here? + $success = $this->maniaControl->fileReader->loadFile($url, function ($mapInfo) { - if ($mapInfo === false) { - $this->error = 'Connection or response error on ' . $url; - return array(); - } elseif ($mapInfo === -1) { - $this->error = 'Timed out while reading data from ' . $url; - return array(); - } elseif ($mapInfo == '') { - if (empty($maps)) { - $this->error = 'No data returned from ' . $url; - return array(); - } + // Get Title Id + $titleId = $this->maniaControl->server->titleId; + $titlePrefix = strtolower(substr($titleId, 0, 2)); + + $mxMapList = json_decode($mapInfo); + if ($mxMapList === null) { + trigger_error('Cannot decode searched JSON data'); + return null; + } + + $maps = array(); + foreach($mxMapList as $map) { + if (!empty($map)) { + array_push($maps, new MXMapInfo($titlePrefix, $map)); + } + } + + $this->updateMapObjectsWithManiaExchangeIds($maps); + return true; + }, "application/json"); + } catch(\Exception $e) { + $this->maniaControl->log("Error while fetching Map Infos" . $e->getTraceAsString()); + return false; } - $mxMapList = json_decode($mapInfo); - if ($mxMapList === null) { - trigger_error('Cannot decode searched JSON data from ' . $url); - return null; - } - - $maps = array(); - foreach($mxMapList as $map) { - if (!empty($map)) { - array_push($maps, new MXMapInfo($titlePrefix, $map)); - } - } - return $maps; + return $success; } /** @@ -256,8 +255,7 @@ class ManiaExchangeManager { $url .= '&limit=' . $maxMapsReturned; $url .= '&mtype=' . $mapTypes; - // $mapInfo = FileUtil::loadFile($url, "application/json"); //TODO use mc fileutil - $mapInfo = $this->get_file($url); + $mapInfo = FileUtil::loadFile($url, "application/json"); if ($mapInfo === false) { $this->error = 'Connection or response error on ' . $url; @@ -287,43 +285,6 @@ class ManiaExchangeManager { return $maps; } - /** - * Loads an file - * - * @param $url - * @return bool|int|string - */ - private function get_file($url) { - $url = parse_url($url); - $port = isset($url['port']) ? $url['port'] : 80; - $query = isset($url['query']) ? "?" . $url['query'] : ""; - - $fp = @fsockopen($url['host'], $port, $errno, $errstr, 4); - if (!$fp) { - return false; - } - - fwrite($fp, 'GET ' . $url['path'] . $query . " HTTP/1.0\r\n" . 'Host: ' . $url['host'] . "\r\n" . 'Content-Type: application/json' . "\r\n" . 'User-Agent: ManiaControl v' . ManiaControl::VERSION . "\r\n\r\n"); - stream_set_timeout($fp, 2); - $res = ''; - $info['timed_out'] = false; - while(!feof($fp) && !$info['timed_out']) { - $res .= fread($fp, 512); - $info = stream_get_meta_data($fp); - } - fclose($fp); - - if ($info['timed_out']) { - return -1; - } else { - if (substr($res, 9, 3) != '200') { - return false; - } - $page = explode("\r\n\r\n", $res, 2); - return trim($page[1]); - } - } // get_file - /** * Gets the Current Environemnt by String *