├── LICENSE.txt ├── config ├── .htaccess ├── extra │ └── workerman.php ├── common.php ├── command.php ├── route.php ├── tags.php ├── database.php └── config.php ├── extend └── .gitignore ├── runtime └── .gitignore ├── public ├── static │ └── .gitignore ├── robots.txt ├── favicon.ico ├── .htaccess ├── router.php └── index.php ├── .gitignore ├── server.bat ├── vendor ├── topthink │ ├── think-installer │ │ ├── .gitignore │ │ ├── composer.json │ │ └── src │ │ │ ├── Plugin.php │ │ │ ├── ThinkFramework.php │ │ │ ├── ThinkTesting.php │ │ │ └── ThinkExtend.php │ └── think-worker │ │ ├── composer.json │ │ ├── README.md │ │ ├── src │ │ └── Server.php │ │ └── LICENSE ├── workerman │ ├── workerman │ │ ├── .gitignore │ │ ├── Lib │ │ │ ├── Constants.php │ │ │ └── Timer.php │ │ ├── composer.json │ │ ├── MIT-LICENSE.txt │ │ ├── Protocols │ │ │ ├── Frame.php │ │ │ ├── ProtocolInterface.php │ │ │ ├── Text.php │ │ │ └── Http │ │ │ │ └── mime.types │ │ ├── Events │ │ │ ├── EventInterface.php │ │ │ ├── Ev.php │ │ │ ├── Event.php │ │ │ ├── Libevent.php │ │ │ └── Select.php │ │ ├── Connection │ │ │ ├── ConnectionInterface.php │ │ │ ├── UdpConnection.php │ │ │ └── AsyncTcpConnection.php │ │ ├── Autoloader.php │ │ └── WebServer.php │ └── workerman-for-win │ │ ├── .gitignore │ │ ├── README.md │ │ ├── Lib │ │ ├── Constants.php │ │ └── Timer.php │ │ ├── composer.json │ │ ├── MIT-LICENSE.txt │ │ ├── Protocols │ │ ├── Frame.php │ │ ├── ProtocolInterface.php │ │ ├── Text.php │ │ └── Http │ │ │ └── mime.types │ │ ├── Events │ │ ├── EventInterface.php │ │ ├── Ev.php │ │ ├── Event.php │ │ ├── Libevent.php │ │ └── Select.php │ │ ├── Connection │ │ ├── ConnectionInterface.php │ │ ├── UdpConnection.php │ │ ├── AsyncUdpConnection.php │ │ └── AsyncTcpConnection.php │ │ ├── Autoloader.php │ │ └── WebServer.php ├── autoload.php └── composer │ ├── autoload_classmap.php │ ├── autoload_namespaces.php │ ├── autoload_psr4.php │ ├── LICENSE │ ├── autoload_static.php │ ├── autoload_real.php │ └── installed.json ├── server.php ├── application ├── index │ ├── view │ │ └── index │ │ │ └── connect.html │ └── controller │ │ └── Index.php └── push │ └── controller │ ├── Push.php │ ├── User.php │ └── Worker.php ├── composer.json ├── think └── README.md /LICENSE.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config/.htaccess: -------------------------------------------------------------------------------- 1 | deny from all -------------------------------------------------------------------------------- /extend/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /runtime/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /public/static/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | composer.lock 3 | *.log 4 | thinkphp 5 | -------------------------------------------------------------------------------- /server.bat: -------------------------------------------------------------------------------- 1 | echo "Do not close this window " 2 | php server.php start 3 | pause -------------------------------------------------------------------------------- /vendor/topthink/think-installer/.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | composer.lock 3 | /vendor -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfang/push-server/master/public/favicon.ico -------------------------------------------------------------------------------- /vendor/workerman/workerman/.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | .buildpath 3 | .project 4 | .settings 5 | .idea -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .buildpath 3 | .settings/org.eclipse.php.core.prefs -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | 2 | Options +FollowSymlinks -Multiviews 3 | RewriteEngine On 4 | 5 | RewriteCond %{REQUEST_FILENAME} !-d 6 | RewriteCond %{REQUEST_FILENAME} !-f 7 | RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] 8 | 9 | -------------------------------------------------------------------------------- /config/extra/workerman.php: -------------------------------------------------------------------------------- 1 | 'websocket://push.pparking.app:2347', 11 | // 内部通讯监听 12 | 'text'=>'Text://push.pparking.app:23478', 13 | ); 14 | -------------------------------------------------------------------------------- /vendor/topthink/think-worker/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "topthink/think-worker", 3 | "description": "workerman extend for thinkphp5", 4 | "license": "Apache-2.0", 5 | "authors": [ 6 | { 7 | "name": "liu21st", 8 | "email": "liu21st@gmail.com" 9 | } 10 | ], 11 | "require": { 12 | "workerman/workerman":"^3.3.0" 13 | }, 14 | "autoload": { 15 | "psr-4": { 16 | "think\\worker\\": "src" 17 | }, 18 | "files": [ 19 | ] 20 | } 21 | } -------------------------------------------------------------------------------- /vendor/composer/autoload_psr4.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/topthink/think-worker/src'), 10 | 'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'), 11 | 'think\\' => array($baseDir . '/thinkphp/library/think'), 12 | 'Workerman\\' => array($vendorDir . '/workerman/workerman-for-win', $vendorDir . '/workerman/workerman'), 13 | ); 14 | -------------------------------------------------------------------------------- /application/index/view/index/connect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 20 | 21 | -------------------------------------------------------------------------------- /config/common.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | // 应用公共文件 13 | -------------------------------------------------------------------------------- /config/command.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | return []; -------------------------------------------------------------------------------- /vendor/topthink/think-installer/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "topthink/think-installer", 3 | "type": "composer-plugin", 4 | "require": { 5 | "composer-plugin-api": "^1.0" 6 | }, 7 | "require-dev": { 8 | "composer/composer": "1.0.*@dev" 9 | }, 10 | "license": "Apache-2.0", 11 | "authors": [ 12 | { 13 | "name": "yunwuxin", 14 | "email": "448901948@qq.com" 15 | } 16 | ], 17 | "autoload": { 18 | "psr-4": { 19 | "think\\composer\\": "src" 20 | } 21 | }, 22 | "extra": { 23 | "class": "think\\composer\\Plugin" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /vendor/topthink/think-installer/src/Plugin.php: -------------------------------------------------------------------------------- 1 | getInstallationManager(); 15 | 16 | //框架核心 17 | $manager->addInstaller(new ThinkFramework($io, $composer)); 18 | 19 | //单元测试 20 | $manager->addInstaller(new ThinkTesting($io, $composer)); 21 | 22 | //扩展 23 | $manager->addInstaller(new ThinkExtend($io, $composer)); 24 | 25 | } 26 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "topthink/think", 3 | "description": "the new thinkphp framework", 4 | "type": "project", 5 | "keywords": [ 6 | "framework", 7 | "thinkphp", 8 | "ORM" 9 | ], 10 | "homepage": "http://thinkphp.cn/", 11 | "license": "Apache-2.0", 12 | "authors": [ 13 | { 14 | "name": "liu21st", 15 | "email": "liu21st@gmail.com" 16 | } 17 | ], 18 | "require": { 19 | "php": ">=5.4.0", 20 | "topthink/framework": "^5.0", 21 | "workerman/workerman-for-win": "^3.3", 22 | "topthink/think-worker": "^1.0" 23 | }, 24 | "extra": { 25 | "think-path": "thinkphp" 26 | }, 27 | "config": { 28 | "preferred-install": "dist" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /public/router.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | // $Id$ 12 | 13 | if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["REQUEST_URI"])) { 14 | return false; 15 | } else { 16 | require __DIR__ . "/index.php"; 17 | } 18 | -------------------------------------------------------------------------------- /think: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 11 | // +---------------------------------------------------------------------- 12 | 13 | // 定义项目路径 14 | define('APP_PATH', __DIR__ . '/application/'); 15 | define('CONF_PATH', __DIR__.'/config/'); 16 | // 加载框架引导文件 17 | require './thinkphp/console.php'; -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/README.md: -------------------------------------------------------------------------------- 1 | # workerman-for-win 2 | workerman-for-win 3 | 4 | ## 环境要求 5 | (php>=5.3.3) 6 | 7 | ## 运行 8 | 运行一个文件 9 | php your_file.php 10 | 11 | 同时运行多个文件 12 | php your_file.php your_file2.php ... 13 | 14 | ## 与Linux多进程版本的区别 15 | 1、单进程,也就是说count属性无效 16 | 2、由于php在win下无法fork进程,Applications/YourApp/start.php被拆成多个子启动项,如start_web.php start_gateway.php等,每个文件自动启动一个进程运行 17 | 3、由于php在win下不支持信号,所以无法使用reload、status、restart、stop命令,也没有start命令 18 | 19 | ## 手册 20 | 开发与Linux版本基本无差别,可以直接参考Linux版本手册 21 | http://doc3.workerman.net/ 22 | 23 | ## 说明 24 | 此版本可用于windows下开发使用,不建议用在生产环境 25 | 26 | ## 移植 27 | ### windows到Linux(需要Linux的Workerman版本3.1.0及以上) 28 | 可以直接将Applications下的应用目录拷贝到Linux版本的Applications下直接运行 29 | 30 | ### Linux到windows 31 | Linux下的应用需要将Applications/YourApp/start.php拆成多个启动项 32 | 33 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | // [ 应用入口文件 ] 13 | 14 | // 定义应用目录 15 | define('APP_PATH', __DIR__ . '/../application/'); 16 | define('CONF_PATH', __DIR__.'/config/'); 17 | // 加载框架引导文件 18 | require __DIR__ . '/../thinkphp/start.php'; 19 | -------------------------------------------------------------------------------- /config/route.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | return [ 13 | '__pattern__' => [ 14 | 'name' => '\w+', 15 | ], 16 | '[hello]' => [ 17 | ':id' => ['index/hello', ['method' => 'get'], ['id' => '\d+']], 18 | ':name' => ['index/hello', ['method' => 'post']], 19 | ], 20 | 21 | ]; 22 | -------------------------------------------------------------------------------- /application/push/controller/Push.php: -------------------------------------------------------------------------------- 1 | close(); 22 | } 23 | /** 24 | * 接受推送 25 | * @param $connection 26 | * @param $strData 27 | */ 28 | public function toUser($connection, $strData) 29 | { 30 | if( isset(User::$uidList[$strData['toUser']]) ){ 31 | User::sendUser(User::$uidList[$strData['toUser']], $strData['sms']); 32 | $connection->send( json_encode(array('errCode'=>0,'errData'=>'OK','data'=>'OK')) ); 33 | }else{ 34 | $connection->send( json_encode(array('errCode'=>4004,'errData'=>'没有用户映射','data'=>'')) ); 35 | } 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /config/tags.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | // 应用行为扩展定义文件 13 | return [ 14 | // 应用初始化 15 | 'app_init' => [], 16 | // 应用开始 17 | 'app_begin' => [], 18 | // 模块初始化 19 | 'module_init' => [], 20 | // 操作开始执行 21 | 'action_begin' => [], 22 | // 视图内容过滤 23 | 'view_filter' => [], 24 | // 日志写入 25 | 'log_write' => [], 26 | // 应用结束 27 | 'app_end' => [], 28 | ]; 29 | -------------------------------------------------------------------------------- /vendor/topthink/think-worker/README.md: -------------------------------------------------------------------------------- 1 | ThinkPHP 5.0 Workerman 扩展 2 | =============== 3 | 4 | ## 安装 5 | composer require topthink/think-worker 6 | 7 | ## 使用方法 8 | 首先创建控制器类并继承 think\worker\Server,然后设置属性和添加回调方法 9 | 10 | ~~~ 11 | namespace app\index\controller; 12 | 13 | use think\worker\Server; 14 | 15 | class Worker extends Server 16 | { 17 | protected $socket = 'http://0.0.0.0:2346'; 18 | 19 | public function onMessage($connection,$data) 20 | { 21 | $connection->send(json_encode($data)); 22 | } 23 | } 24 | ~~~ 25 | 支持workerman所有的回调方法定义(回调方法必须是public类型) 26 | 27 | 28 | 在应用根目录增加入口文件 server.php 29 | 30 | ~~~ 31 | #!/usr/bin/env php 32 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | 15 | // Date.timezone 16 | if (!ini_get('date.timezone')) { 17 | date_default_timezone_set('Asia/Shanghai'); 18 | } 19 | // Display errors. 20 | ini_set('display_errors', 'on'); 21 | // Reporting all. 22 | error_reporting(E_ALL); 23 | 24 | // For onError callback. 25 | define('WORKERMAN_CONNECT_FAIL', 1); 26 | // For onError callback. 27 | define('WORKERMAN_SEND_FAIL', 2); 28 | 29 | // Compatible with php7 30 | if(!class_exists('Error')) 31 | { 32 | class Error extends Exception 33 | { 34 | } 35 | } -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Lib/Constants.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | 15 | // Date.timezone 16 | if (!ini_get('date.timezone')) { 17 | date_default_timezone_set('Asia/Shanghai'); 18 | } 19 | // Display errors. 20 | ini_set('display_errors', 'on'); 21 | // Reporting all. 22 | error_reporting(E_ALL); 23 | 24 | // For onError callback. 25 | define('WORKERMAN_CONNECT_FAIL', 1); 26 | // For onError callback. 27 | define('WORKERMAN_SEND_FAIL', 2); 28 | 29 | // Compatible with php7 30 | if(!class_exists('Error')) 31 | { 32 | class Error extends Exception 33 | { 34 | } 35 | } -------------------------------------------------------------------------------- /application/index/controller/Index.php: -------------------------------------------------------------------------------- 1 | ".json_encode( 10 | array( 11 | 'action' => 'User/bind', 12 | 'data' => array( 13 | 'user' => '123', 14 | ) 15 | ), 16 | JSON_UNESCAPED_UNICODE 17 | ); 18 | echo "
发送推送:
".json_encode( 19 | array( 20 | 'action' => 'Push/toUser', 21 | 'data' => array( 22 | 'toUser' => '123', 23 | 'sms' => '字符串格式', 24 | ), 25 | 'appid' => '应用id', 26 | 'noncestr' => '随机', 27 | 'timestamp' => time(), 28 | 'signature'=>'签名,', 29 | ), 30 | JSON_UNESCAPED_UNICODE 31 | ); 32 | } 33 | public function connect() 34 | { 35 | return view(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "workerman/workerman-for-win", 3 | "type" : "project", 4 | "keywords": ["event-loop", "asynchronous"], 5 | "homepage": "http://www.workerman.net", 6 | "license" : "MIT", 7 | "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.", 8 | "authors" : [ 9 | { 10 | "name" : "walkor", 11 | "email" : "walkor@workerman.net", 12 | "homepage" : "http://www.workerman.net", 13 | "role": "Developer" 14 | } 15 | ], 16 | "support" : { 17 | "email" : "walkor@workerman.net", 18 | "issues": "https://github.com/walkor/workerman/issues", 19 | "forum" : "http://wenda.workerman.net/", 20 | "wiki" : "http://doc3.workerman.net/index.html", 21 | "source": "https://github.com/walkor/workerman" 22 | }, 23 | "require": { 24 | "php": ">=5.3" 25 | }, 26 | "autoload": { 27 | "psr-4": {"Workerman\\": "./"} 28 | }, 29 | "minimum-stability":"dev" 30 | } 31 | -------------------------------------------------------------------------------- /vendor/composer/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2016 Nils Adermann, Jordi Boggiano 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is furnished 9 | to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "workerman/workerman", 3 | "type" : "project", 4 | "keywords": ["event-loop", "asynchronous"], 5 | "homepage": "http://www.workerman.net", 6 | "license" : "MIT", 7 | "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.", 8 | "authors" : [ 9 | { 10 | "name" : "walkor", 11 | "email" : "walkor@workerman.net", 12 | "homepage" : "http://www.workerman.net", 13 | "role": "Developer" 14 | } 15 | ], 16 | "support" : { 17 | "email" : "walkor@workerman.net", 18 | "issues": "https://github.com/walkor/workerman/issues", 19 | "forum" : "http://wenda.workerman.net/", 20 | "wiki" : "http://doc3.workerman.net/index.html", 21 | "source": "https://github.com/walkor/workerman" 22 | }, 23 | "require": { 24 | "php": ">=5.3" 25 | }, 26 | "suggest": { 27 | "ext-libevent": "For better performance." 28 | }, 29 | "autoload": { 30 | "psr-4": {"Workerman\\": "./"} 31 | }, 32 | "minimum-stability":"dev" 33 | } 34 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2009-2015 walkor and contributors (see https://github.com/walkor/workerman/contributors) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2009-2015 walkor and contributors (see https://github.com/walkor/workerman/contributors) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/composer/autoload_static.php: -------------------------------------------------------------------------------- 1 | 11 | array ( 12 | 'think\\worker\\' => 13, 13 | 'think\\composer\\' => 15, 14 | 'think\\' => 6, 15 | ), 16 | 'W' => 17 | array ( 18 | 'Workerman\\' => 10, 19 | ), 20 | ); 21 | 22 | public static $prefixDirsPsr4 = array ( 23 | 'think\\worker\\' => 24 | array ( 25 | 0 => __DIR__ . '/..' . '/topthink/think-worker/src', 26 | ), 27 | 'think\\composer\\' => 28 | array ( 29 | 0 => __DIR__ . '/..' . '/topthink/think-installer/src', 30 | ), 31 | 'think\\' => 32 | array ( 33 | 0 => __DIR__ . '/../..' . '/thinkphp/library/think', 34 | ), 35 | 'Workerman\\' => 36 | array ( 37 | 0 => __DIR__ . '/..' . '/workerman/workerman-for-win', 38 | 1 => __DIR__ . '/..' . '/workerman/workerman', 39 | ), 40 | ); 41 | 42 | public static function getInitializer(ClassLoader $loader) 43 | { 44 | return \Closure::bind(function () use ($loader) { 45 | $loader->prefixLengthsPsr4 = ComposerStaticInit56313defd83f28b1545e500b0456f8b3::$prefixLengthsPsr4; 46 | $loader->prefixDirsPsr4 = ComposerStaticInit56313defd83f28b1545e500b0456f8b3::$prefixDirsPsr4; 47 | 48 | }, null, ClassLoader::class); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Protocols/Frame.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols; 15 | 16 | use Workerman\Connection\TcpConnection; 17 | 18 | /** 19 | * Frame Protocol. 20 | */ 21 | class Frame 22 | { 23 | /** 24 | * Check the integrity of the package. 25 | * 26 | * @param string $buffer 27 | * @param TcpConnection $connection 28 | * @return int 29 | */ 30 | public static function input($buffer, TcpConnection $connection) 31 | { 32 | if (strlen($buffer) < 4) { 33 | return 0; 34 | } 35 | $unpack_data = unpack('Ntotal_length', $buffer); 36 | return $unpack_data['total_length']; 37 | } 38 | 39 | /** 40 | * Decode. 41 | * 42 | * @param string $buffer 43 | * @return string 44 | */ 45 | public static function decode($buffer) 46 | { 47 | return substr($buffer, 4); 48 | } 49 | 50 | /** 51 | * Encode. 52 | * 53 | * @param string $buffer 54 | * @return string 55 | */ 56 | public static function encode($buffer) 57 | { 58 | $total_length = 4 + strlen($buffer); 59 | return pack('N', $total_length) . $buffer; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Protocols/Frame.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols; 15 | 16 | use Workerman\Connection\TcpConnection; 17 | 18 | /** 19 | * Frame Protocol. 20 | */ 21 | class Frame 22 | { 23 | /** 24 | * Check the integrity of the package. 25 | * 26 | * @param string $buffer 27 | * @param TcpConnection $connection 28 | * @return int 29 | */ 30 | public static function input($buffer, TcpConnection $connection) 31 | { 32 | if (strlen($buffer) < 4) { 33 | return 0; 34 | } 35 | $unpack_data = unpack('Ntotal_length', $buffer); 36 | return $unpack_data['total_length']; 37 | } 38 | 39 | /** 40 | * Encode. 41 | * 42 | * @param string $buffer 43 | * @return string 44 | */ 45 | public static function decode($buffer) 46 | { 47 | return substr($buffer, 4); 48 | } 49 | 50 | /** 51 | * Decode. 52 | * 53 | * @param string $buffer 54 | * @return string 55 | */ 56 | public static function encode($buffer) 57 | { 58 | $total_length = 4 + strlen($buffer); 59 | return pack('N', $total_length) . $buffer; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /application/push/controller/User.php: -------------------------------------------------------------------------------- 1 | close(); 25 | } 26 | 27 | public static $uidList = array(); 28 | /** 29 | * 新增用户映射 30 | * @param $connection 31 | * @param $strData 32 | */ 33 | public function bind($connection,$strData) 34 | { 35 | if( $strData['user'] ){ 36 | Timer::del($connection->auth_timer_id);// 验证成功,删除定时器,防止连接被关闭 37 | $connection->user = $strData['user']; 38 | self::$uidList[ $connection->user ] = $connection; 39 | $connection->send( json_encode(array('errCode'=>0,'errData'=>'OK','data'=>'OK')) ); 40 | }else{ 41 | $connection->send( json_encode(array('errCode'=>4004,'errData'=>'user 参数缺失','data'=>'')) ); 42 | } 43 | } 44 | 45 | /** 46 | * 向uid发送信息 47 | * @param $connection 48 | * @param $strData 49 | */ 50 | public static function sendUser($connection,$strData) 51 | { 52 | $connection->send( $strData ); 53 | } 54 | 55 | /** 56 | * 删除映射 57 | * @param $connection 58 | */ 59 | public static function delete($connection) 60 | { 61 | if( isset($connection->user) && isset(self::$uidList[$connection->user]) ){ 62 | unset(self::$uidList[$connection->user]); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /config/database.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | return [ 13 | // 数据库类型 14 | 'type' => 'mysql', 15 | // 服务器地址 16 | 'hostname' => '127.0.0.1', 17 | // 数据库名 18 | 'database' => '', 19 | // 用户名 20 | 'username' => 'root', 21 | // 密码 22 | 'password' => '', 23 | // 端口 24 | 'hostport' => '', 25 | // 连接dsn 26 | 'dsn' => '', 27 | // 数据库连接参数 28 | 'params' => [], 29 | // 数据库编码默认采用utf8 30 | 'charset' => 'utf8', 31 | // 数据库表前缀 32 | 'prefix' => '', 33 | // 数据库调试模式 34 | 'debug' => true, 35 | // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) 36 | 'deploy' => 0, 37 | // 数据库读写是否分离 主从式有效 38 | 'rw_separate' => false, 39 | // 读写分离后 主服务器数量 40 | 'master_num' => 1, 41 | // 指定从服务器序号 42 | 'slave_no' => '', 43 | // 是否严格检查字段是否存在 44 | 'fields_strict' => true, 45 | // 数据集返回类型 array 数组 collection Collection对象 46 | 'resultset_type' => 'array', 47 | // 是否自动写入时间戳字段 48 | 'auto_timestamp' => false, 49 | // 是否需要进行SQL性能分析 50 | 'sql_explain' => false, 51 | ]; 52 | -------------------------------------------------------------------------------- /vendor/topthink/think-worker/src/Server.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | namespace think\worker; 13 | 14 | use Workerman\Worker; 15 | 16 | /** 17 | * Worker控制器扩展类 18 | */ 19 | abstract class Server 20 | { 21 | protected $worker; 22 | protected $socket = ''; 23 | protected $protocol = 'http'; 24 | protected $host = '0.0.0.0'; 25 | protected $port = '2346'; 26 | protected $processes = 4; 27 | 28 | /** 29 | * 架构函数 30 | * @access public 31 | */ 32 | public function __construct() 33 | { 34 | // 实例化 Websocket 服务 35 | $this->worker = new Worker($this->socket ?: $this->protocol . '://' . $this->host . ':' . $this->port); 36 | // 设置进程数 37 | $this->worker->count = $this->processes; 38 | // 初始化 39 | $this->init(); 40 | 41 | // 设置回调 42 | foreach (['onWorkerStart', 'onConnect', 'onMessage', 'onClose', 'onError', 'onBufferFull', 'onBufferDrain', 'onWorkerStop', 'onWorkerReload'] as $event) { 43 | if (method_exists($this, $event)) { 44 | $this->worker->$event = [$this, $event]; 45 | } 46 | } 47 | // Run worker 48 | Worker::runAll(); 49 | } 50 | 51 | protected function init() 52 | { 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Protocols/ProtocolInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols; 15 | 16 | use Workerman\Connection\ConnectionInterface; 17 | 18 | /** 19 | * Protocol interface 20 | */ 21 | interface ProtocolInterface 22 | { 23 | /** 24 | * Check the integrity of the package. 25 | * Please return the length of package. 26 | * If length is unknow please return 0 that mean wating more data. 27 | * If the package has something wrong please return false the connection will be closed. 28 | * 29 | * @param ConnectionInterface $connection 30 | * @param string $recv_buffer 31 | * @return int|false 32 | */ 33 | public static function input($recv_buffer, ConnectionInterface $connection); 34 | 35 | /** 36 | * Decode package and emit onMessage($message) callback, $message is the result that decode returned. 37 | * 38 | * @param ConnectionInterface $connection 39 | * @param string $recv_buffer 40 | * @return mixed 41 | */ 42 | public static function decode($recv_buffer, ConnectionInterface $connection); 43 | 44 | /** 45 | * Encode package brefore sending to client. 46 | * 47 | * @param ConnectionInterface $connection 48 | * @param mixed $data 49 | * @return string 50 | */ 51 | public static function encode($data, ConnectionInterface $connection); 52 | } 53 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Protocols/ProtocolInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols; 15 | 16 | use Workerman\Connection\ConnectionInterface; 17 | 18 | /** 19 | * Protocol interface 20 | */ 21 | interface ProtocolInterface 22 | { 23 | /** 24 | * Check the integrity of the package. 25 | * Please return the length of package. 26 | * If length is unknow please return 0 that mean wating more data. 27 | * If the package has something wrong please return false the connection will be closed. 28 | * 29 | * @param ConnectionInterface $connection 30 | * @param string $recv_buffer 31 | * @return int|false 32 | */ 33 | public static function input($recv_buffer, ConnectionInterface $connection); 34 | 35 | /** 36 | * Decode package and emit onMessage($message) callback, $message is the result that decode returned. 37 | * 38 | * @param ConnectionInterface $connection 39 | * @param string $recv_buffer 40 | * @return mixed 41 | */ 42 | public static function decode($recv_buffer, ConnectionInterface $connection); 43 | 44 | /** 45 | * Encode package brefore sending to client. 46 | * 47 | * @param ConnectionInterface $connection 48 | * @param mixed $data 49 | * @return string 50 | */ 51 | public static function encode($data, ConnectionInterface $connection); 52 | } 53 | -------------------------------------------------------------------------------- /vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | = 50600 && !defined('HHVM_VERSION'); 27 | if ($useStaticLoader) { 28 | require_once __DIR__ . '/autoload_static.php'; 29 | 30 | call_user_func(\Composer\Autoload\ComposerStaticInit56313defd83f28b1545e500b0456f8b3::getInitializer($loader)); 31 | } else { 32 | $map = require __DIR__ . '/autoload_namespaces.php'; 33 | foreach ($map as $namespace => $path) { 34 | $loader->set($namespace, $path); 35 | } 36 | 37 | $map = require __DIR__ . '/autoload_psr4.php'; 38 | foreach ($map as $namespace => $path) { 39 | $loader->setPsr4($namespace, $path); 40 | } 41 | 42 | $classMap = require __DIR__ . '/autoload_classmap.php'; 43 | if ($classMap) { 44 | $loader->addClassMap($classMap); 45 | } 46 | } 47 | 48 | $loader->register(true); 49 | 50 | return $loader; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Events/EventInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Events; 15 | 16 | interface EventInterface 17 | { 18 | /** 19 | * Read event. 20 | * 21 | * @var int 22 | */ 23 | const EV_READ = 1; 24 | 25 | /** 26 | * Write event. 27 | * 28 | * @var int 29 | */ 30 | const EV_WRITE = 2; 31 | 32 | /** 33 | * Signal event. 34 | * 35 | * @var int 36 | */ 37 | const EV_SIGNAL = 4; 38 | 39 | /** 40 | * Timer event. 41 | * 42 | * @var int 43 | */ 44 | const EV_TIMER = 8; 45 | 46 | /** 47 | * Timer once event. 48 | * 49 | * @var int 50 | */ 51 | const EV_TIMER_ONCE = 16; 52 | 53 | /** 54 | * Add event listener to event loop. 55 | * 56 | * @param mixed $fd 57 | * @param int $flag 58 | * @param callable $func 59 | * @param mixed $args 60 | * @return bool 61 | */ 62 | public function add($fd, $flag, $func, $args = null); 63 | 64 | /** 65 | * Remove event listener from event loop. 66 | * 67 | * @param mixed $fd 68 | * @param int $flag 69 | * @return bool 70 | */ 71 | public function del($fd, $flag); 72 | 73 | /** 74 | * Remove all timers. 75 | * 76 | * @return void 77 | */ 78 | public function clearAllTimer(); 79 | 80 | /** 81 | * Main loop. 82 | * 83 | * @return void 84 | */ 85 | public function loop(); 86 | } 87 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Protocols/Text.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols; 15 | 16 | use Workerman\Connection\TcpConnection; 17 | 18 | /** 19 | * Text Protocol. 20 | */ 21 | class Text 22 | { 23 | /** 24 | * Check the integrity of the package. 25 | * 26 | * @param string $buffer 27 | * @param TcpConnection $connection 28 | * @return int 29 | */ 30 | public static function input($buffer, TcpConnection $connection) 31 | { 32 | // Judge whether the package length exceeds the limit. 33 | if (strlen($buffer) >= TcpConnection::$maxPackageSize) { 34 | $connection->close(); 35 | return 0; 36 | } 37 | // Find the position of "\n". 38 | $pos = strpos($buffer, "\n"); 39 | // No "\n", packet length is unknown, continue to wait for the data so return 0. 40 | if ($pos === false) { 41 | return 0; 42 | } 43 | // Return the current package length. 44 | return $pos + 1; 45 | } 46 | 47 | /** 48 | * Encode. 49 | * 50 | * @param string $buffer 51 | * @return string 52 | */ 53 | public static function encode($buffer) 54 | { 55 | // Add "\n" 56 | return $buffer . "\n"; 57 | } 58 | 59 | /** 60 | * Decode. 61 | * 62 | * @param string $buffer 63 | * @return string 64 | */ 65 | public static function decode($buffer) 66 | { 67 | // Remove "\n" 68 | return trim($buffer); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Protocols/Text.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Protocols; 15 | 16 | use Workerman\Connection\TcpConnection; 17 | 18 | /** 19 | * Text Protocol. 20 | */ 21 | class Text 22 | { 23 | /** 24 | * Check the integrity of the package. 25 | * 26 | * @param string $buffer 27 | * @param TcpConnection $connection 28 | * @return int 29 | */ 30 | public static function input($buffer, TcpConnection $connection) 31 | { 32 | // Judge whether the package length exceeds the limit. 33 | if (strlen($buffer) >= TcpConnection::$maxPackageSize) { 34 | $connection->close(); 35 | return 0; 36 | } 37 | // Find the position of "\n". 38 | $pos = strpos($buffer, "\n"); 39 | // No "\n", packet length is unknown, continue to wait for the data so return 0. 40 | if ($pos === false) { 41 | return 0; 42 | } 43 | // Return the current package length. 44 | return $pos + 1; 45 | } 46 | 47 | /** 48 | * Encode. 49 | * 50 | * @param string $buffer 51 | * @return string 52 | */ 53 | public static function encode($buffer) 54 | { 55 | // Add "\n" 56 | return $buffer . "\n"; 57 | } 58 | 59 | /** 60 | * Decode. 61 | * 62 | * @param string $buffer 63 | * @return string 64 | */ 65 | public static function decode($buffer) 66 | { 67 | // Remove "\n" 68 | return trim($buffer); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /vendor/topthink/think-installer/src/ThinkFramework.php: -------------------------------------------------------------------------------- 1 | getPrettyName()) { 17 | throw new \InvalidArgumentException('Unable to install this library!'); 18 | } 19 | 20 | if ($this->composer->getPackage()->getType() !== 'project') { 21 | return parent::getInstallPath($package); 22 | } 23 | 24 | if ($this->composer->getPackage()) { 25 | $extra = $this->composer->getPackage()->getExtra(); 26 | if (!empty($extra['think-path'])) { 27 | return $extra['think-path']; 28 | } 29 | } 30 | 31 | return 'thinkphp'; 32 | } 33 | 34 | public function install(InstalledRepositoryInterface $repo, PackageInterface $package) 35 | { 36 | parent::install($repo, $package); 37 | if ($this->composer->getPackage()->getType() == 'project') { 38 | //remove tests dir 39 | $this->filesystem->removeDirectory($this->getInstallPath($package) . DIRECTORY_SEPARATOR . 'tests'); 40 | } 41 | } 42 | 43 | public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) 44 | { 45 | parent::update($repo, $initial, $target); 46 | if ($this->composer->getPackage()->getType() == 'project') { 47 | //remove tests dir 48 | $this->filesystem->removeDirectory($this->getInstallPath($target) . DIRECTORY_SEPARATOR . 'tests'); 49 | } 50 | } 51 | 52 | /** 53 | * {@inheritDoc} 54 | */ 55 | public function supports($packageType) 56 | { 57 | return 'think-framework' === $packageType; 58 | } 59 | } -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Events/EventInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Events; 15 | 16 | interface EventInterface 17 | { 18 | /** 19 | * Read event. 20 | * 21 | * @var int 22 | */ 23 | const EV_READ = 1; 24 | 25 | /** 26 | * Write event. 27 | * 28 | * @var int 29 | */ 30 | const EV_WRITE = 2; 31 | 32 | /** 33 | * Except event 34 | * 35 | * @var int 36 | */ 37 | const EV_EXCEPT = 3; 38 | 39 | /** 40 | * Signal event. 41 | * 42 | * @var int 43 | */ 44 | const EV_SIGNAL = 4; 45 | 46 | /** 47 | * Timer event. 48 | * 49 | * @var int 50 | */ 51 | const EV_TIMER = 8; 52 | 53 | /** 54 | * Timer once event. 55 | * 56 | * @var int 57 | */ 58 | const EV_TIMER_ONCE = 16; 59 | 60 | /** 61 | * Add event listener to event loop. 62 | * 63 | * @param mixed $fd 64 | * @param int $flag 65 | * @param callable $func 66 | * @param mixed $args 67 | * @return bool 68 | */ 69 | public function add($fd, $flag, $func, $args = null); 70 | 71 | /** 72 | * Remove event listener from event loop. 73 | * 74 | * @param mixed $fd 75 | * @param int $flag 76 | * @return bool 77 | */ 78 | public function del($fd, $flag); 79 | 80 | /** 81 | * Remove all timers. 82 | * 83 | * @return void 84 | */ 85 | public function clearAllTimer(); 86 | 87 | /** 88 | * Main loop. 89 | * 90 | * @return void 91 | */ 92 | public function loop(); 93 | } 94 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Connection/ConnectionInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Connection; 15 | 16 | /** 17 | * ConnectionInterface. 18 | */ 19 | abstract class ConnectionInterface 20 | { 21 | /** 22 | * Statistics for status command. 23 | * 24 | * @var array 25 | */ 26 | public static $statistics = array( 27 | 'connection_count' => 0, 28 | 'total_request' => 0, 29 | 'throw_exception' => 0, 30 | 'send_fail' => 0, 31 | ); 32 | 33 | /** 34 | * Emitted when data is received. 35 | * 36 | * @var callback 37 | */ 38 | public $onMessage = null; 39 | 40 | /** 41 | * Emitted when the other end of the socket sends a FIN packet. 42 | * 43 | * @var callback 44 | */ 45 | public $onClose = null; 46 | 47 | /** 48 | * Emitted when an error occurs with connection. 49 | * 50 | * @var callback 51 | */ 52 | public $onError = null; 53 | 54 | /** 55 | * Sends data on the connection. 56 | * 57 | * @param string $send_buffer 58 | * @return void|boolean 59 | */ 60 | abstract public function send($send_buffer); 61 | 62 | /** 63 | * Get remote IP. 64 | * 65 | * @return string 66 | */ 67 | abstract public function getRemoteIp(); 68 | 69 | /** 70 | * Get remote port. 71 | * 72 | * @return int 73 | */ 74 | abstract public function getRemotePort(); 75 | 76 | /** 77 | * Close connection. 78 | * 79 | * @param $data 80 | * @return void 81 | */ 82 | abstract public function close($data = null); 83 | } 84 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Connection/ConnectionInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Connection; 15 | 16 | /** 17 | * ConnectionInterface. 18 | */ 19 | abstract class ConnectionInterface 20 | { 21 | /** 22 | * Statistics for status command. 23 | * 24 | * @var array 25 | */ 26 | public static $statistics = array( 27 | 'connection_count' => 0, 28 | 'total_request' => 0, 29 | 'throw_exception' => 0, 30 | 'send_fail' => 0, 31 | ); 32 | 33 | /** 34 | * Emitted when data is received. 35 | * 36 | * @var callback 37 | */ 38 | public $onMessage = null; 39 | 40 | /** 41 | * Emitted when the other end of the socket sends a FIN packet. 42 | * 43 | * @var callback 44 | */ 45 | public $onClose = null; 46 | 47 | /** 48 | * Emitted when an error occurs with connection. 49 | * 50 | * @var callback 51 | */ 52 | public $onError = null; 53 | 54 | /** 55 | * Sends data on the connection. 56 | * 57 | * @param string $send_buffer 58 | * @return void|boolean 59 | */ 60 | abstract public function send($send_buffer); 61 | 62 | /** 63 | * Get remote IP. 64 | * 65 | * @return string 66 | */ 67 | abstract public function getRemoteIp(); 68 | 69 | /** 70 | * Get remote port. 71 | * 72 | * @return int 73 | */ 74 | abstract public function getRemotePort(); 75 | 76 | /** 77 | * Close connection. 78 | * 79 | * @param $data 80 | * @return void 81 | */ 82 | abstract public function close($data = null); 83 | } 84 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Autoloader.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman; 15 | 16 | /** 17 | * Autoload. 18 | */ 19 | class Autoloader 20 | { 21 | /** 22 | * Autoload root path. 23 | * 24 | * @var string 25 | */ 26 | protected static $_autoloadRootPath = ''; 27 | 28 | /** 29 | * Set autoload root path. 30 | * 31 | * @param string $root_path 32 | * @return void 33 | */ 34 | public static function setRootPath($root_path) 35 | { 36 | self::$_autoloadRootPath = $root_path; 37 | } 38 | 39 | /** 40 | * Load files by namespace. 41 | * 42 | * @param string $name 43 | * @return boolean 44 | */ 45 | public static function loadByNamespace($name) 46 | { 47 | $class_path = str_replace('\\', DIRECTORY_SEPARATOR, $name); 48 | if (strpos($name, 'Workerman\\') === 0) { 49 | $class_file = __DIR__ . substr($class_path, strlen('Workerman')) . '.php'; 50 | } else { 51 | if (self::$_autoloadRootPath) { 52 | $class_file = self::$_autoloadRootPath . DIRECTORY_SEPARATOR . $class_path . '.php'; 53 | } 54 | if (empty($class_file) || !is_file($class_file)) { 55 | $class_file = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . "$class_path.php"; 56 | } 57 | } 58 | 59 | if (is_file($class_file)) { 60 | require_once($class_file); 61 | if (class_exists($name, false)) { 62 | return true; 63 | } 64 | } 65 | return false; 66 | } 67 | } 68 | 69 | spl_autoload_register('\Workerman\Autoloader::loadByNamespace'); -------------------------------------------------------------------------------- /vendor/topthink/think-installer/src/ThinkTesting.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | namespace think\composer; 13 | 14 | 15 | use Composer\Installer\LibraryInstaller; 16 | use Composer\Package\PackageInterface; 17 | use Composer\Repository\InstalledRepositoryInterface; 18 | 19 | class ThinkTesting extends LibraryInstaller 20 | { 21 | /** 22 | * {@inheritDoc} 23 | */ 24 | public function getInstallPath(PackageInterface $package) 25 | { 26 | if ('topthink/think-testing' !== $package->getPrettyName()) { 27 | throw new \InvalidArgumentException('Unable to install this library!'); 28 | } 29 | 30 | return parent::getInstallPath($package); 31 | } 32 | 33 | public function install(InstalledRepositoryInterface $repo, PackageInterface $package) 34 | { 35 | parent::install($repo, $package); 36 | 37 | $this->copyTestDir($package); 38 | 39 | 40 | } 41 | 42 | public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) 43 | { 44 | parent::update($repo, $initial, $target); 45 | 46 | $this->copyTestDir($target); 47 | 48 | } 49 | 50 | private function copyTestDir(PackageInterface $package) 51 | { 52 | $appDir = dirname($this->vendorDir); 53 | $source = $this->getInstallPath($package) . DIRECTORY_SEPARATOR . 'example'; 54 | if (!is_file($appDir . DIRECTORY_SEPARATOR . 'phpunit.xml')) { 55 | $this->filesystem->copyThenRemove($source, $appDir); 56 | } else { 57 | $this->filesystem->removeDirectoryPhp($source); 58 | } 59 | } 60 | 61 | /** 62 | * {@inheritDoc} 63 | */ 64 | public function supports($packageType) 65 | { 66 | return 'think-testing' === $packageType; 67 | } 68 | } -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Autoloader.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman; 15 | 16 | // 包含常量定义文件 17 | require_once __DIR__.'/Lib/Constants.php'; 18 | 19 | /** 20 | * 自动加载类 21 | * @author walkor 22 | */ 23 | class Autoloader 24 | { 25 | // 应用的初始化目录,作为加载类文件的参考目录 26 | protected static $_appInitPath = ''; 27 | 28 | /** 29 | * 设置应用初始化目录 30 | * @param string $root_path 31 | * @return void 32 | */ 33 | public static function setRootPath($root_path) 34 | { 35 | self::$_appInitPath = $root_path; 36 | } 37 | 38 | /** 39 | * 根据命名空间加载文件 40 | * @param string $name 41 | * @return boolean 42 | */ 43 | public static function loadByNamespace($name) 44 | { 45 | // 相对路径 46 | $class_path = str_replace('\\', DIRECTORY_SEPARATOR ,$name); 47 | // 如果是Workerman命名空间,则在当前目录寻找类文件 48 | if(strpos($name, 'Workerman\\') === 0) 49 | { 50 | $class_file = __DIR__.substr($class_path, strlen('Workerman')).'.php'; 51 | } 52 | else 53 | { 54 | // 先尝试在应用目录寻找文件 55 | if(self::$_appInitPath) 56 | { 57 | $class_file = self::$_appInitPath . DIRECTORY_SEPARATOR . $class_path.'.php'; 58 | } 59 | // 文件不存在,则在上一层目录寻找 60 | if(empty($class_file) || !is_file($class_file)) 61 | { 62 | $class_file = __DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR . "$class_path.php"; 63 | } 64 | } 65 | 66 | // 找到文件 67 | if(is_file($class_file)) 68 | { 69 | // 加载 70 | require_once($class_file); 71 | if(class_exists($name, false)) 72 | { 73 | return true; 74 | } 75 | } 76 | return false; 77 | } 78 | } 79 | // 设置类自动加载回调函数 80 | spl_autoload_register('\Workerman\Autoloader::loadByNamespace'); -------------------------------------------------------------------------------- /vendor/topthink/think-installer/src/ThinkExtend.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | namespace think\composer; 13 | 14 | use Composer\Installer\LibraryInstaller; 15 | use Composer\Package\PackageInterface; 16 | use Composer\Repository\InstalledRepositoryInterface; 17 | 18 | class ThinkExtend extends LibraryInstaller 19 | { 20 | 21 | public function install(InstalledRepositoryInterface $repo, PackageInterface $package) 22 | { 23 | parent::install($repo, $package); 24 | $this->copyExtraFiles($package); 25 | } 26 | 27 | public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) 28 | { 29 | parent::update($repo, $initial, $target); 30 | $this->copyExtraFiles($target); 31 | 32 | } 33 | 34 | protected function copyExtraFiles(PackageInterface $package) 35 | { 36 | $extra = $package->getExtra(); 37 | 38 | if (!empty($extra['think-config'])) { 39 | 40 | $composerExtra = $this->composer->getPackage()->getExtra(); 41 | $extraDir = (!empty($composerExtra['app-path']) ? $composerExtra['app-path'] : 'application') . DIRECTORY_SEPARATOR . 'extra'; 42 | $this->filesystem->ensureDirectoryExists($extraDir); 43 | 44 | //配置文件 45 | foreach ((array) $extra['think-config'] as $name => $config) { 46 | $target = $extraDir . DIRECTORY_SEPARATOR . $name . '.php'; 47 | $source = $this->getInstallPath($package) . DIRECTORY_SEPARATOR . $config; 48 | 49 | if (is_file($target)) { 50 | $this->io->write("File {$target} exist!"); 51 | continue; 52 | } 53 | 54 | if (!is_file($source)) { 55 | $this->io->write("File {$target} not exist!"); 56 | continue; 57 | } 58 | 59 | copy($source, $target); 60 | } 61 | } 62 | } 63 | 64 | public function supports($packageType) 65 | { 66 | return 'think-extend' === $packageType; 67 | } 68 | } -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Connection/UdpConnection.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Connection; 15 | 16 | /** 17 | * UdpConnection. 18 | */ 19 | class UdpConnection extends ConnectionInterface 20 | { 21 | /** 22 | * Application layer protocol. 23 | * The format is like this Workerman\\Protocols\\Http. 24 | * 25 | * @var \Workerman\Protocols\ProtocolInterface 26 | */ 27 | public $protocol = null; 28 | 29 | /** 30 | * Udp socket. 31 | * 32 | * @var resource 33 | */ 34 | protected $_socket = null; 35 | 36 | /** 37 | * Remote address. 38 | * 39 | * @var string 40 | */ 41 | protected $_remoteAddress = ''; 42 | 43 | /** 44 | * Construct. 45 | * 46 | * @param resource $socket 47 | * @param string $remote_address 48 | */ 49 | public function __construct($socket, $remote_address) 50 | { 51 | $this->_socket = $socket; 52 | $this->_remoteAddress = $remote_address; 53 | } 54 | 55 | /** 56 | * Sends data on the connection. 57 | * 58 | * @param string $send_buffer 59 | * @param bool $raw 60 | * @return void|boolean 61 | */ 62 | public function send($send_buffer, $raw = false) 63 | { 64 | if (false === $raw && $this->protocol) { 65 | $parser = $this->protocol; 66 | $send_buffer = $parser::encode($send_buffer, $this); 67 | if ($send_buffer === '') { 68 | return null; 69 | } 70 | } 71 | return strlen($send_buffer) === stream_socket_sendto($this->_socket, $send_buffer, 0, $this->_remoteAddress); 72 | } 73 | 74 | /** 75 | * Get remote IP. 76 | * 77 | * @return string 78 | */ 79 | public function getRemoteIp() 80 | { 81 | $pos = strrpos($this->_remoteAddress, ':'); 82 | if ($pos) { 83 | return trim(substr($this->_remoteAddress, 0, $pos), '[]'); 84 | } 85 | return ''; 86 | } 87 | 88 | /** 89 | * Get remote port. 90 | * 91 | * @return int 92 | */ 93 | public function getRemotePort() 94 | { 95 | if ($this->_remoteAddress) { 96 | return (int)substr(strrchr($this->_remoteAddress, ':'), 1); 97 | } 98 | return 0; 99 | } 100 | 101 | /** 102 | * Close connection. 103 | * 104 | * @param mixed $data 105 | * @return bool 106 | */ 107 | public function close($data = null, $raw = false) 108 | { 109 | if ($data !== null) { 110 | $this->send($data, $raw); 111 | } 112 | return true; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Connection/UdpConnection.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Connection; 15 | 16 | /** 17 | * UdpConnection. 18 | */ 19 | class UdpConnection extends ConnectionInterface 20 | { 21 | /** 22 | * Application layer protocol. 23 | * The format is like this Workerman\\Protocols\\Http. 24 | * 25 | * @var \Workerman\Protocols\ProtocolInterface 26 | */ 27 | public $protocol = null; 28 | 29 | /** 30 | * Udp socket. 31 | * 32 | * @var resource 33 | */ 34 | protected $_socket = null; 35 | 36 | /** 37 | * Remote address. 38 | * 39 | * @var string 40 | */ 41 | protected $_remoteAddress = ''; 42 | 43 | /** 44 | * Construct. 45 | * 46 | * @param resource $socket 47 | * @param string $remote_address 48 | */ 49 | public function __construct($socket, $remote_address) 50 | { 51 | $this->_socket = $socket; 52 | $this->_remoteAddress = $remote_address; 53 | } 54 | 55 | /** 56 | * Sends data on the connection. 57 | * 58 | * @param string $send_buffer 59 | * @param bool $raw 60 | * @return void|boolean 61 | */ 62 | public function send($send_buffer, $raw = false) 63 | { 64 | if (false === $raw && $this->protocol) { 65 | $parser = $this->protocol; 66 | $send_buffer = $parser::encode($send_buffer, $this); 67 | if ($send_buffer === '') { 68 | return null; 69 | } 70 | } 71 | return strlen($send_buffer) === stream_socket_sendto($this->_socket, $send_buffer, 0, $this->_remoteAddress); 72 | } 73 | 74 | /** 75 | * Get remote IP. 76 | * 77 | * @return string 78 | */ 79 | public function getRemoteIp() 80 | { 81 | $pos = strrpos($this->_remoteAddress, ':'); 82 | if ($pos) { 83 | return trim(substr($this->_remoteAddress, 0, $pos), '[]'); 84 | } 85 | return ''; 86 | } 87 | 88 | /** 89 | * Get remote port. 90 | * 91 | * @return int 92 | */ 93 | public function getRemotePort() 94 | { 95 | if ($this->_remoteAddress) { 96 | return (int)substr(strrchr($this->_remoteAddress, ':'), 1); 97 | } 98 | return 0; 99 | } 100 | 101 | /** 102 | * Close connection. 103 | * 104 | * @param mixed $data 105 | * @param bool $raw 106 | * @return bool 107 | */ 108 | public function close($data = null, $raw = false) 109 | { 110 | if ($data !== null) { 111 | $this->send($data, $raw); 112 | } 113 | return true; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Connection/AsyncUdpConnection.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Connection; 15 | 16 | use Workerman\Events\EventInterface; 17 | use Workerman\Worker; 18 | use Exception; 19 | 20 | /** 21 | * AsyncTcpConnection. 22 | */ 23 | class AsyncUdpConnection extends UdpConnection 24 | { 25 | /** 26 | * Construct. 27 | * 28 | * @param string $remote_address 29 | * @throws Exception 30 | */ 31 | public function __construct($remote_address) 32 | { 33 | // Get the application layer communication protocol and listening address. 34 | list($scheme, $address) = explode(':', $remote_address, 2); 35 | // Check application layer protocol class. 36 | if ($scheme !== 'udp') { 37 | $scheme = ucfirst($scheme); 38 | $this->protocol = '\\Protocols\\' . $scheme; 39 | if (!class_exists($this->protocol)) { 40 | $this->protocol = "\\Workerman\\Protocols\\$scheme"; 41 | if (!class_exists($this->protocol)) { 42 | throw new Exception("class \\Protocols\\$scheme not exist"); 43 | } 44 | } 45 | } 46 | 47 | $this->_remoteAddress = substr($address, 2); 48 | $this->_socket = stream_socket_client("udp://{$this->_remoteAddress}"); 49 | Worker::$globalEvent->add($this->_socket, EventInterface::EV_READ, array($this, 'baseRead')); 50 | } 51 | 52 | /** 53 | * For udp package. 54 | * 55 | * @param resource $socket 56 | * @return bool 57 | */ 58 | public function baseRead($socket) 59 | { 60 | $recv_buffer = stream_socket_recvfrom($socket, Worker::MAX_UDP_PACKAGE_SIZE, 0, $remote_address); 61 | if (false === $recv_buffer || empty($remote_address)) { 62 | return false; 63 | } 64 | 65 | if ($this->onMessage) { 66 | if ($this->protocol) { 67 | $parser = $this->protocol; 68 | $recv_buffer = $parser::decode($recv_buffer, $this); 69 | } 70 | ConnectionInterface::$statistics['total_request']++; 71 | try { 72 | call_user_func($this->onMessage, $this, $recv_buffer); 73 | } catch (\Exception $e) { 74 | self::log($e); 75 | exit(250); 76 | } catch (\Error $e) { 77 | self::log($e); 78 | exit(250); 79 | } 80 | } 81 | return true; 82 | } 83 | 84 | 85 | /** 86 | * Close connection. 87 | * 88 | * @param mixed $data 89 | * @return bool 90 | */ 91 | public function close($data = null, $raw = false) 92 | { 93 | if ($data !== null) { 94 | $this->send($data, $raw); 95 | } 96 | Worker::$globalEvent->del($this->_socket, EventInterface::EV_READ); 97 | fclose($this->_socket); 98 | return true; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /application/push/controller/Worker.php: -------------------------------------------------------------------------------- 1 | socket = Config::get('workerman.socket'); 16 | parent::__construct(); 17 | } 18 | 19 | /** 20 | * 收到信息 21 | * @param $connection 22 | * @param $data 23 | */ 24 | public function onMessage($connection, $data) 25 | { 26 | $arrData = json_decode($data, true); 27 | if (!$arrData['action']) { 28 | $connection->send('action 参数不存在'); 29 | } else { 30 | $arrAction = explode('/', $arrData['action']); 31 | $class = 'app\\push\\controller\\' . $arrAction[0]; 32 | $func = $arrAction[1]; 33 | if (class_exists($class)) { 34 | $obj = new $class($connection,$arrData); 35 | if (method_exists($obj, $func)) { 36 | $obj->$func($connection, $arrData['data']); 37 | } else { 38 | $connection->send($func . '类的方法不存在'); 39 | } 40 | } else { 41 | $connection->send($class . '类不存在'); 42 | } 43 | } 44 | } 45 | 46 | /** 47 | * 当连接建立时触发的回调函数 48 | * @param $connection 49 | */ 50 | public function onConnect($connection) 51 | { 52 | // 临时给$connection对象添加一个auth_timer_id属性存储定时器id 53 | // 定时30秒关闭连接,需要客户端30秒内发送验证删除定时器 54 | $connection->auth_timer_id = Timer::add(30, function()use($connection){ 55 | $connection->close(); 56 | }, null, false); 57 | } 58 | 59 | /** 60 | * 当连接断开时触发的回调函数 61 | * @param $connection 62 | */ 63 | public function onClose($connection) 64 | { 65 | User::delete($connection); 66 | } 67 | 68 | /** 69 | * 当客户端的连接上发生错误时触发 70 | * @param $connection 71 | * @param $code 72 | * @param $msg 73 | */ 74 | public function onError($connection, $code, $msg) 75 | { 76 | echo "error $code $msg\n"; 77 | } 78 | 79 | /** 80 | * 每个进程启动 81 | * @param $worker 82 | */ 83 | public function onWorkerStart($worker) 84 | { 85 | // 开启一个内部端口,方便内部系统推送数据,Text协议格式 文本+换行符 86 | $inner_text_worker = new \Workerman\Worker( Config::get('workerman.text') ); 87 | $inner_text_worker->onMessage = function($connection, $data) 88 | { 89 | if( !is_array($data) ){ 90 | $arrData = json_decode($data,true); 91 | } 92 | if( is_array($arrData) && !empty($arrData) ){ 93 | $arrAction = explode('/', $arrData['action']); 94 | $class = 'app\\push\\controller\\' . $arrAction[0]; 95 | $func = $arrAction[1]; 96 | if (class_exists($class)) { 97 | $obj = new $class($connection,$arrData); 98 | if (method_exists($obj, $func)) { 99 | $obj->$func($connection, $arrData['data']); 100 | } else { 101 | $connection->send($func . '类的方法不存在'); 102 | } 103 | } else { 104 | $connection->send($class . '类不存在'); 105 | } 106 | }else{ 107 | $connection->send( json_encode(array('errCode'=>5004,'errData'=>'数据格式错误','data'=>'')) ); 108 | } 109 | }; 110 | $inner_text_worker->listen(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Protocols/Http/mime.types: -------------------------------------------------------------------------------- 1 | 2 | types { 3 | text/html html htm shtml; 4 | text/css css; 5 | text/xml xml; 6 | image/gif gif; 7 | image/jpeg jpeg jpg; 8 | application/x-javascript js; 9 | application/atom+xml atom; 10 | application/rss+xml rss; 11 | 12 | text/mathml mml; 13 | text/plain txt; 14 | text/vnd.sun.j2me.app-descriptor jad; 15 | text/vnd.wap.wml wml; 16 | text/x-component htc; 17 | 18 | image/png png; 19 | image/tiff tif tiff; 20 | image/vnd.wap.wbmp wbmp; 21 | image/x-icon ico; 22 | image/x-jng jng; 23 | image/x-ms-bmp bmp; 24 | image/svg+xml svg svgz; 25 | image/webp webp; 26 | 27 | application/java-archive jar war ear; 28 | application/mac-binhex40 hqx; 29 | application/msword doc; 30 | application/pdf pdf; 31 | application/postscript ps eps ai; 32 | application/rtf rtf; 33 | application/vnd.ms-excel xls; 34 | application/vnd.ms-powerpoint ppt; 35 | application/vnd.wap.wmlc wmlc; 36 | application/vnd.google-earth.kml+xml kml; 37 | application/vnd.google-earth.kmz kmz; 38 | application/x-7z-compressed 7z; 39 | application/x-cocoa cco; 40 | application/x-java-archive-diff jardiff; 41 | application/x-java-jnlp-file jnlp; 42 | application/x-makeself run; 43 | application/x-perl pl pm; 44 | application/x-pilot prc pdb; 45 | application/x-rar-compressed rar; 46 | application/x-redhat-package-manager rpm; 47 | application/x-sea sea; 48 | application/x-shockwave-flash swf; 49 | application/x-stuffit sit; 50 | application/x-tcl tcl tk; 51 | application/x-x509-ca-cert der pem crt; 52 | application/x-xpinstall xpi; 53 | application/xhtml+xml xhtml; 54 | application/zip zip; 55 | 56 | application/octet-stream bin exe dll; 57 | application/octet-stream deb; 58 | application/octet-stream dmg; 59 | application/octet-stream eot; 60 | application/octet-stream iso img; 61 | application/octet-stream msi msp msm; 62 | 63 | audio/midi mid midi kar; 64 | audio/mpeg mp3; 65 | audio/ogg ogg; 66 | audio/x-m4a m4a; 67 | audio/x-realaudio ra; 68 | 69 | video/3gpp 3gpp 3gp; 70 | video/mp4 mp4; 71 | video/mpeg mpeg mpg; 72 | video/quicktime mov; 73 | video/webm webm; 74 | video/x-flv flv; 75 | video/x-m4v m4v; 76 | video/x-mng mng; 77 | video/x-ms-asf asx asf; 78 | video/x-ms-wmv wmv; 79 | video/x-msvideo avi; 80 | } 81 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Protocols/Http/mime.types: -------------------------------------------------------------------------------- 1 | 2 | types { 3 | text/html html htm shtml; 4 | text/css css; 5 | text/xml xml; 6 | image/gif gif; 7 | image/jpeg jpeg jpg; 8 | application/x-javascript js; 9 | application/atom+xml atom; 10 | application/rss+xml rss; 11 | 12 | text/mathml mml; 13 | text/plain txt; 14 | text/vnd.sun.j2me.app-descriptor jad; 15 | text/vnd.wap.wml wml; 16 | text/x-component htc; 17 | 18 | image/png png; 19 | image/tiff tif tiff; 20 | image/vnd.wap.wbmp wbmp; 21 | image/x-icon ico; 22 | image/x-jng jng; 23 | image/x-ms-bmp bmp; 24 | image/svg+xml svg svgz; 25 | image/webp webp; 26 | 27 | application/java-archive jar war ear; 28 | application/mac-binhex40 hqx; 29 | application/msword doc; 30 | application/pdf pdf; 31 | application/postscript ps eps ai; 32 | application/rtf rtf; 33 | application/vnd.ms-excel xls; 34 | application/vnd.ms-powerpoint ppt; 35 | application/vnd.wap.wmlc wmlc; 36 | application/vnd.google-earth.kml+xml kml; 37 | application/vnd.google-earth.kmz kmz; 38 | application/x-7z-compressed 7z; 39 | application/x-cocoa cco; 40 | application/x-java-archive-diff jardiff; 41 | application/x-java-jnlp-file jnlp; 42 | application/x-makeself run; 43 | application/x-perl pl pm; 44 | application/x-pilot prc pdb; 45 | application/x-rar-compressed rar; 46 | application/x-redhat-package-manager rpm; 47 | application/x-sea sea; 48 | application/x-shockwave-flash swf; 49 | application/x-stuffit sit; 50 | application/x-tcl tcl tk; 51 | application/x-x509-ca-cert der pem crt; 52 | application/x-xpinstall xpi; 53 | application/xhtml+xml xhtml; 54 | application/zip zip; 55 | 56 | application/octet-stream bin exe dll; 57 | application/octet-stream deb; 58 | application/octet-stream dmg; 59 | application/octet-stream eot; 60 | application/octet-stream iso img; 61 | application/octet-stream msi msp msm; 62 | 63 | audio/midi mid midi kar; 64 | audio/mpeg mp3; 65 | audio/ogg ogg; 66 | audio/x-m4a m4a; 67 | audio/x-realaudio ra; 68 | 69 | video/3gpp 3gpp 3gp; 70 | video/mp4 mp4; 71 | video/mpeg mpeg mpg; 72 | video/quicktime mov; 73 | video/webm webm; 74 | video/x-flv flv; 75 | video/x-m4v m4v; 76 | video/x-mng mng; 77 | video/x-ms-asf asx asf; 78 | video/x-ms-wmv wmv; 79 | video/x-msvideo avi; 80 | } 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ThinkPHP 5.0 2 | =============== 3 | 4 | [![Total Downloads](https://poser.pugx.org/topthink/think/downloads)](https://packagist.org/packages/topthink/think) 5 | [![Latest Stable Version](https://poser.pugx.org/topthink/think/v/stable)](https://packagist.org/packages/topthink/think) 6 | [![Latest Unstable Version](https://poser.pugx.org/topthink/think/v/unstable)](https://packagist.org/packages/topthink/think) 7 | [![License](https://poser.pugx.org/topthink/think/license)](https://packagist.org/packages/topthink/think) 8 | 9 | ThinkPHP5在保持快速开发和大道至简的核心理念不变的同时,PHP版本要求提升到5.4,对已有的CBD模式做了更深的强化,优化核心,减少依赖,基于全新的架构思想和命名空间实现,是ThinkPHP突破原有框架思路的颠覆之作,其主要特性包括: 10 | 11 | + 基于命名空间和众多PHP新特性 12 | + 核心功能组件化 13 | + 强化路由功能 14 | + 更灵活的控制器 15 | + 重构的模型和数据库类 16 | + 配置文件可分离 17 | + 重写的自动验证和完成 18 | + 简化扩展机制 19 | + API支持完善 20 | + 改进的Log类 21 | + 命令行访问支持 22 | + REST支持 23 | + 引导文件支持 24 | + 方便的自动生成定义 25 | + 真正惰性加载 26 | + 分布式环境支持 27 | + 更多的社交类库 28 | 29 | > ThinkPHP5的运行环境要求PHP5.4以上。 30 | 31 | 详细开发文档参考 [ThinkPHP5完全开发手册](http://www.kancloud.cn/manual/thinkphp5) 32 | 33 | ## 目录结构 34 | 35 | 初始的目录结构如下: 36 | 37 | ~~~ 38 | www WEB部署目录(或者子目录) 39 | ├─application 应用目录 40 | │ ├─common 公共模块目录(可以更改) 41 | │ ├─module_name 模块目录 42 | │ │ ├─config.php 模块配置文件 43 | │ │ ├─common.php 模块函数文件 44 | │ │ ├─controller 控制器目录 45 | │ │ ├─model 模型目录 46 | │ │ ├─view 视图目录 47 | │ │ └─ ... 更多类库目录 48 | │ │ 49 | │ ├─command.php 命令行工具配置文件 50 | │ ├─common.php 公共函数文件 51 | │ ├─config.php 公共配置文件 52 | │ ├─route.php 路由配置文件 53 | │ ├─tags.php 应用行为扩展定义文件 54 | │ └─database.php 数据库配置文件 55 | │ 56 | ├─public WEB目录(对外访问目录) 57 | │ ├─index.php 入口文件 58 | │ ├─router.php 快速测试文件 59 | │ └─.htaccess 用于apache的重写 60 | │ 61 | ├─thinkphp 框架系统目录 62 | │ ├─lang 语言文件目录 63 | │ ├─library 框架类库目录 64 | │ │ ├─think Think类库包目录 65 | │ │ └─traits 系统Trait目录 66 | │ │ 67 | │ ├─tpl 系统模板目录 68 | │ ├─base.php 基础定义文件 69 | │ ├─console.php 控制台入口文件 70 | │ ├─convention.php 框架惯例配置文件 71 | │ ├─helper.php 助手函数文件 72 | │ ├─phpunit.xml phpunit配置文件 73 | │ └─start.php 框架入口文件 74 | │ 75 | ├─extend 扩展类库目录 76 | ├─runtime 应用的运行时目录(可写,可定制) 77 | ├─vendor 第三方类库目录(Composer依赖库) 78 | ├─build.php 自动生成定义文件(参考) 79 | ├─composer.json composer 定义文件 80 | ├─LICENSE.txt 授权说明文件 81 | ├─README.md README 文件 82 | ├─think 命令行入口文件 83 | ~~~ 84 | 85 | > router.php用于php自带webserver支持,可用于快速测试 86 | > 切换到public目录后,启动命令:php -S localhost:8888 router.php 87 | > 上面的目录结构和名称是可以改变的,这取决于你的入口文件和配置参数。 88 | 89 | ## 命名规范 90 | 91 | `ThinkPHP5`遵循PSR-2命名规范和PSR-4自动加载规范,并且注意如下规范: 92 | 93 | ### 目录和文件 94 | 95 | * 目录不强制规范,驼峰和小写+下划线模式均支持; 96 | * 类库、函数文件统一以`.php`为后缀; 97 | * 类的文件名均以命名空间定义,并且命名空间的路径和类库文件所在路径一致; 98 | * 类名和类文件名保持一致,统一采用驼峰法命名(首字母大写); 99 | 100 | ### 函数和类、属性命名 101 | * 类的命名采用驼峰法,并且首字母大写,例如 `User`、`UserType`,默认不需要添加后缀,例如`UserController`应该直接命名为`User`; 102 | * 函数的命名使用小写字母和下划线(小写字母开头)的方式,例如 `get_client_ip`; 103 | * 方法的命名使用驼峰法,并且首字母小写,例如 `getUserName`; 104 | * 属性的命名使用驼峰法,并且首字母小写,例如 `tableName`、`instance`; 105 | * 以双下划线“__”打头的函数或方法作为魔法方法,例如 `__call` 和 `__autoload`; 106 | 107 | ### 常量和配置 108 | * 常量以大写字母和下划线命名,例如 `APP_PATH`和 `THINK_PATH`; 109 | * 配置参数以小写字母和下划线命名,例如 `url_route_on` 和`url_convert`; 110 | 111 | ### 数据表和字段 112 | * 数据表和字段采用小写加下划线方式命名,并注意字段名不要以下划线开头,例如 `think_user` 表和 `user_name`字段,不建议使用驼峰和中文作为数据表字段命名。 113 | 114 | ## 参与开发 115 | 请参阅 [ThinkPHP5 核心框架包](https://github.com/top-think/framework)。 116 | 117 | ## 版权信息 118 | 119 | ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 120 | 121 | 本项目包含的第三方源码和二进制文件之版权信息另行标注。 122 | 123 | 版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn) 124 | 125 | All rights reserved。 126 | 127 | ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 128 | 129 | 更多细节参阅 [LICENSE.txt](LICENSE.txt) 130 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Lib/Timer.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Lib; 15 | 16 | use Workerman\Events\EventInterface; 17 | use Exception; 18 | 19 | /** 20 | * Timer. 21 | * 22 | * example: 23 | * Workerman\Lib\Timer::add($time_interval, callback, array($arg1, $arg2..)); 24 | */ 25 | class Timer 26 | { 27 | /** 28 | * Tasks that based on ALARM signal. 29 | * [ 30 | * run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]], 31 | * run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]], 32 | * .. 33 | * ] 34 | * 35 | * @var array 36 | */ 37 | protected static $_tasks = array(); 38 | 39 | /** 40 | * event 41 | * 42 | * @var \Workerman\Events\EventInterface 43 | */ 44 | protected static $_event = null; 45 | 46 | /** 47 | * Init. 48 | * 49 | * @param \Workerman\Events\EventInterface $event 50 | * @return void 51 | */ 52 | public static function init($event = null) 53 | { 54 | if ($event) { 55 | self::$_event = $event; 56 | } else { 57 | pcntl_signal(SIGALRM, array('\Workerman\Lib\Timer', 'signalHandle'), false); 58 | } 59 | } 60 | 61 | /** 62 | * ALARM signal handler. 63 | * 64 | * @return void 65 | */ 66 | public static function signalHandle() 67 | { 68 | if (!self::$_event) { 69 | pcntl_alarm(1); 70 | self::tick(); 71 | } 72 | } 73 | 74 | /** 75 | * Add a timer. 76 | * 77 | * @param int $time_interval 78 | * @param callback $func 79 | * @param mixed $args 80 | * @param bool $persistent 81 | * @return bool 82 | */ 83 | public static function add($time_interval, $func, $args = array(), $persistent = true) 84 | { 85 | if ($time_interval <= 0) { 86 | echo new Exception("bad time_interval"); 87 | return false; 88 | } 89 | 90 | if (self::$_event) { 91 | return self::$_event->add($time_interval, 92 | $persistent ? EventInterface::EV_TIMER : EventInterface::EV_TIMER_ONCE, $func, $args); 93 | } 94 | 95 | if (!is_callable($func)) { 96 | echo new Exception("not callable"); 97 | return false; 98 | } 99 | 100 | if (empty(self::$_tasks)) { 101 | pcntl_alarm(1); 102 | } 103 | 104 | $time_now = time(); 105 | $run_time = $time_now + $time_interval; 106 | if (!isset(self::$_tasks[$run_time])) { 107 | self::$_tasks[$run_time] = array(); 108 | } 109 | self::$_tasks[$run_time][] = array($func, (array)$args, $persistent, $time_interval); 110 | return true; 111 | } 112 | 113 | 114 | /** 115 | * Tick. 116 | * 117 | * @return void 118 | */ 119 | public static function tick() 120 | { 121 | if (empty(self::$_tasks)) { 122 | pcntl_alarm(0); 123 | return; 124 | } 125 | 126 | $time_now = time(); 127 | foreach (self::$_tasks as $run_time => $task_data) { 128 | if ($time_now >= $run_time) { 129 | foreach ($task_data as $index => $one_task) { 130 | $task_func = $one_task[0]; 131 | $task_args = $one_task[1]; 132 | $persistent = $one_task[2]; 133 | $time_interval = $one_task[3]; 134 | try { 135 | call_user_func_array($task_func, $task_args); 136 | } catch (\Exception $e) { 137 | echo $e; 138 | } 139 | if ($persistent) { 140 | self::add($time_interval, $task_func, $task_args); 141 | } 142 | } 143 | unset(self::$_tasks[$run_time]); 144 | } 145 | } 146 | } 147 | 148 | /** 149 | * Remove a timer. 150 | * 151 | * @param mixed $timer_id 152 | * @return bool 153 | */ 154 | public static function del($timer_id) 155 | { 156 | if (self::$_event) { 157 | return self::$_event->del($timer_id, EventInterface::EV_TIMER); 158 | } 159 | 160 | return false; 161 | } 162 | 163 | /** 164 | * Remove all timers. 165 | * 166 | * @return void 167 | */ 168 | public static function delAll() 169 | { 170 | self::$_tasks = array(); 171 | pcntl_alarm(0); 172 | if (self::$_event) { 173 | self::$_event->clearAllTimer(); 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Lib/Timer.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Lib; 15 | 16 | use Workerman\Events\EventInterface; 17 | use Exception; 18 | 19 | /** 20 | * Timer. 21 | * 22 | * example: 23 | * Workerman\Lib\Timer::add($time_interval, callback, array($arg1, $arg2..)); 24 | */ 25 | class Timer 26 | { 27 | /** 28 | * Tasks that based on ALARM signal. 29 | * [ 30 | * run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]], 31 | * run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]], 32 | * .. 33 | * ] 34 | * 35 | * @var array 36 | */ 37 | protected static $_tasks = array(); 38 | 39 | /** 40 | * event 41 | * 42 | * @var \Workerman\Events\EventInterface 43 | */ 44 | protected static $_event = null; 45 | 46 | /** 47 | * Init. 48 | * 49 | * @param \Workerman\Events\EventInterface $event 50 | * @return void 51 | */ 52 | public static function init($event = null) 53 | { 54 | if ($event) { 55 | self::$_event = $event; 56 | } else { 57 | pcntl_signal(SIGALRM, array('\Workerman\Lib\Timer', 'signalHandle'), false); 58 | } 59 | } 60 | 61 | /** 62 | * ALARM signal handler. 63 | * 64 | * @return void 65 | */ 66 | public static function signalHandle() 67 | { 68 | if (!self::$_event) { 69 | pcntl_alarm(1); 70 | self::tick(); 71 | } 72 | } 73 | 74 | /** 75 | * Add a timer. 76 | * 77 | * @param int $time_interval 78 | * @param callback $func 79 | * @param mixed $args 80 | * @param bool $persistent 81 | * @return bool 82 | */ 83 | public static function add($time_interval, $func, $args = array(), $persistent = true) 84 | { 85 | if ($time_interval <= 0) { 86 | echo new Exception("bad time_interval"); 87 | return false; 88 | } 89 | 90 | if (self::$_event) { 91 | return self::$_event->add($time_interval, 92 | $persistent ? EventInterface::EV_TIMER : EventInterface::EV_TIMER_ONCE, $func, $args); 93 | } 94 | 95 | if (!is_callable($func)) { 96 | echo new Exception("not callable"); 97 | return false; 98 | } 99 | 100 | if (empty(self::$_tasks)) { 101 | pcntl_alarm(1); 102 | } 103 | 104 | $time_now = time(); 105 | $run_time = $time_now + $time_interval; 106 | if (!isset(self::$_tasks[$run_time])) { 107 | self::$_tasks[$run_time] = array(); 108 | } 109 | self::$_tasks[$run_time][] = array($func, (array)$args, $persistent, $time_interval); 110 | return true; 111 | } 112 | 113 | 114 | /** 115 | * Tick. 116 | * 117 | * @return void 118 | */ 119 | public static function tick() 120 | { 121 | if (empty(self::$_tasks)) { 122 | pcntl_alarm(0); 123 | return; 124 | } 125 | 126 | $time_now = time(); 127 | foreach (self::$_tasks as $run_time => $task_data) { 128 | if ($time_now >= $run_time) { 129 | foreach ($task_data as $index => $one_task) { 130 | $task_func = $one_task[0]; 131 | $task_args = $one_task[1]; 132 | $persistent = $one_task[2]; 133 | $time_interval = $one_task[3]; 134 | try { 135 | call_user_func_array($task_func, $task_args); 136 | } catch (\Exception $e) { 137 | echo $e; 138 | } 139 | if ($persistent) { 140 | self::add($time_interval, $task_func, $task_args); 141 | } 142 | } 143 | unset(self::$_tasks[$run_time]); 144 | } 145 | } 146 | } 147 | 148 | /** 149 | * Remove a timer. 150 | * 151 | * @param mixed $timer_id 152 | * @return bool 153 | */ 154 | public static function del($timer_id) 155 | { 156 | if (self::$_event) { 157 | return self::$_event->del($timer_id, EventInterface::EV_TIMER); 158 | } 159 | 160 | return false; 161 | } 162 | 163 | /** 164 | * Remove all timers. 165 | * 166 | * @return void 167 | */ 168 | public static function delAll() 169 | { 170 | self::$_tasks = array(); 171 | pcntl_alarm(0); 172 | if (self::$_event) { 173 | self::$_event->clearAllTimer(); 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Events/Ev.php: -------------------------------------------------------------------------------- 1 | 10 | * @link http://www.workerman.net/ 11 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 12 | */ 13 | namespace Workerman\Events; 14 | 15 | use Workerman\Worker; 16 | 17 | /** 18 | * ev eventloop 19 | */ 20 | class Ev implements EventInterface 21 | { 22 | /** 23 | * All listeners for read/write event. 24 | * 25 | * @var array 26 | */ 27 | protected $_allEvents = array(); 28 | 29 | /** 30 | * Event listeners of signal. 31 | * 32 | * @var array 33 | */ 34 | protected $_eventSignal = array(); 35 | 36 | /** 37 | * All timer event listeners. 38 | * [func, args, event, flag, time_interval] 39 | * 40 | * @var array 41 | */ 42 | protected $_eventTimer = array(); 43 | 44 | /** 45 | * Timer id. 46 | * 47 | * @var int 48 | */ 49 | protected static $_timerId = 1; 50 | 51 | /** 52 | * Add a timer. 53 | * {@inheritdoc} 54 | */ 55 | public function add($fd, $flag, $func, $args = null) 56 | { 57 | $callback = function ($event, $socket) use ($fd, $func) { 58 | try { 59 | call_user_func($func, $fd); 60 | } catch (\Exception $e) { 61 | Worker::log($e); 62 | exit(250); 63 | } catch (\Error $e) { 64 | Worker::log($e); 65 | exit(250); 66 | } 67 | }; 68 | 69 | switch ($flag) { 70 | case self::EV_SIGNAL: 71 | $event = new \EvSignal($fd, $callback); 72 | $this->_eventSignal[$fd] = $event; 73 | return true; 74 | case self::EV_TIMER: 75 | case self::EV_TIMER_ONCE: 76 | $repeat = $flag == self::EV_TIMER_ONCE ? 0 : $fd; 77 | $param = array($func, (array)$args, $flag, $fd, self::$_timerId); 78 | $event = new \EvTimer($fd, $repeat, array($this, 'timerCallback'), $param); 79 | $this->_eventTimer[self::$_timerId] = $event; 80 | return self::$_timerId++; 81 | default : 82 | $fd_key = (int)$fd; 83 | $real_flag = $flag === self::EV_READ ? \Ev::READ : \Ev::WRITE; 84 | $event = new \EvIo($fd, $real_flag, $callback); 85 | $this->_allEvents[$fd_key][$flag] = $event; 86 | return true; 87 | } 88 | 89 | } 90 | 91 | /** 92 | * Remove a timer. 93 | * {@inheritdoc} 94 | */ 95 | public function del($fd, $flag) 96 | { 97 | switch ($flag) { 98 | case self::EV_READ: 99 | case self::EV_WRITE: 100 | $fd_key = (int)$fd; 101 | if (isset($this->_allEvents[$fd_key][$flag])) { 102 | $this->_allEvents[$fd_key][$flag]->stop(); 103 | unset($this->_allEvents[$fd_key][$flag]); 104 | } 105 | if (empty($this->_allEvents[$fd_key])) { 106 | unset($this->_allEvents[$fd_key]); 107 | } 108 | break; 109 | case self::EV_SIGNAL: 110 | $fd_key = (int)$fd; 111 | if (isset($this->_eventSignal[$fd_key])) { 112 | $this->_allEvents[$fd_key][$flag]->stop(); 113 | unset($this->_eventSignal[$fd_key]); 114 | } 115 | break; 116 | case self::EV_TIMER: 117 | case self::EV_TIMER_ONCE: 118 | if (isset($this->_eventTimer[$fd])) { 119 | $this->_eventTimer[$fd]->stop(); 120 | unset($this->_eventTimer[$fd]); 121 | } 122 | break; 123 | } 124 | return true; 125 | } 126 | 127 | /** 128 | * Timer callback. 129 | * 130 | * @param \EvWatcher $event 131 | */ 132 | public function timerCallback($event) 133 | { 134 | $param = $event->data; 135 | $timer_id = $param[4]; 136 | if ($param[2] === self::EV_TIMER_ONCE) { 137 | $this->_eventTimer[$timer_id]->stop(); 138 | unset($this->_eventTimer[$timer_id]); 139 | } 140 | try { 141 | call_user_func_array($param[0], $param[1]); 142 | } catch (\Exception $e) { 143 | Worker::log($e); 144 | exit(250); 145 | } catch (\Error $e) { 146 | Worker::log($e); 147 | exit(250); 148 | } 149 | } 150 | 151 | /** 152 | * Remove all timers. 153 | * 154 | * @return void 155 | */ 156 | public function clearAllTimer() 157 | { 158 | foreach ($this->_eventTimer as $event) { 159 | $event->stop(); 160 | } 161 | $this->_eventTimer = array(); 162 | } 163 | 164 | /** 165 | * Main loop. 166 | * 167 | * @see EventInterface::loop() 168 | */ 169 | public function loop() 170 | { 171 | \Ev::run(); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Events/Ev.php: -------------------------------------------------------------------------------- 1 | 10 | * @link http://www.workerman.net/ 11 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 12 | */ 13 | namespace Workerman\Events; 14 | 15 | use Workerman\Worker; 16 | 17 | /** 18 | * ev eventloop 19 | */ 20 | class Ev implements EventInterface 21 | { 22 | /** 23 | * All listeners for read/write event. 24 | * 25 | * @var array 26 | */ 27 | protected $_allEvents = array(); 28 | 29 | /** 30 | * Event listeners of signal. 31 | * 32 | * @var array 33 | */ 34 | protected $_eventSignal = array(); 35 | 36 | /** 37 | * All timer event listeners. 38 | * [func, args, event, flag, time_interval] 39 | * 40 | * @var array 41 | */ 42 | protected $_eventTimer = array(); 43 | 44 | /** 45 | * Timer id. 46 | * 47 | * @var int 48 | */ 49 | protected static $_timerId = 1; 50 | 51 | /** 52 | * Add a timer. 53 | * {@inheritdoc} 54 | */ 55 | public function add($fd, $flag, $func, $args = null) 56 | { 57 | $callback = function ($event, $socket) use ($fd, $func) { 58 | try { 59 | call_user_func($func, $fd); 60 | } catch (\Exception $e) { 61 | Worker::log($e); 62 | exit(250); 63 | } catch (\Error $e) { 64 | Worker::log($e); 65 | exit(250); 66 | } 67 | }; 68 | 69 | switch ($flag) { 70 | case self::EV_SIGNAL: 71 | $event = new \EvSignal($fd, $callback); 72 | $this->_eventSignal[$fd] = $event; 73 | return true; 74 | case self::EV_TIMER: 75 | case self::EV_TIMER_ONCE: 76 | $repeat = $flag == self::EV_TIMER_ONCE ? 0 : $fd; 77 | $param = array($func, (array)$args, $flag, $fd, self::$_timerId); 78 | $event = new \EvTimer($fd, $repeat, array($this, 'timerCallback'), $param); 79 | $this->_eventTimer[self::$_timerId] = $event; 80 | return self::$_timerId++; 81 | default : 82 | $fd_key = (int)$fd; 83 | $real_flag = $flag === self::EV_READ ? \Ev::READ : \Ev::WRITE; 84 | $event = new \EvIo($fd, $real_flag, $callback); 85 | $this->_allEvents[$fd_key][$flag] = $event; 86 | return true; 87 | } 88 | 89 | } 90 | 91 | /** 92 | * Remove a timer. 93 | * {@inheritdoc} 94 | */ 95 | public function del($fd, $flag) 96 | { 97 | switch ($flag) { 98 | case self::EV_READ: 99 | case self::EV_WRITE: 100 | $fd_key = (int)$fd; 101 | if (isset($this->_allEvents[$fd_key][$flag])) { 102 | $this->_allEvents[$fd_key][$flag]->stop(); 103 | unset($this->_allEvents[$fd_key][$flag]); 104 | } 105 | if (empty($this->_allEvents[$fd_key])) { 106 | unset($this->_allEvents[$fd_key]); 107 | } 108 | break; 109 | case self::EV_SIGNAL: 110 | $fd_key = (int)$fd; 111 | if (isset($this->_eventSignal[$fd_key])) { 112 | $this->_allEvents[$fd_key][$flag]->stop(); 113 | unset($this->_eventSignal[$fd_key]); 114 | } 115 | break; 116 | case self::EV_TIMER: 117 | case self::EV_TIMER_ONCE: 118 | if (isset($this->_eventTimer[$fd])) { 119 | $this->_eventTimer[$fd]->stop(); 120 | unset($this->_eventTimer[$fd]); 121 | } 122 | break; 123 | } 124 | return true; 125 | } 126 | 127 | /** 128 | * Timer callback. 129 | * 130 | * @param \EvWatcher $event 131 | */ 132 | public function timerCallback($event) 133 | { 134 | $param = $event->data; 135 | $timer_id = $param[4]; 136 | if ($param[2] === self::EV_TIMER_ONCE) { 137 | $this->_eventTimer[$timer_id]->stop(); 138 | unset($this->_eventTimer[$timer_id]); 139 | } 140 | try { 141 | call_user_func_array($param[0], $param[1]); 142 | } catch (\Exception $e) { 143 | Worker::log($e); 144 | exit(250); 145 | } catch (\Error $e) { 146 | Worker::log($e); 147 | exit(250); 148 | } 149 | } 150 | 151 | /** 152 | * Remove all timers. 153 | * 154 | * @return void 155 | */ 156 | public function clearAllTimer() 157 | { 158 | foreach ($this->_eventTimer as $event) { 159 | $event->stop(); 160 | } 161 | $this->_eventTimer = array(); 162 | } 163 | 164 | /** 165 | * Main loop. 166 | * 167 | * @see EventInterface::loop() 168 | */ 169 | public function loop() 170 | { 171 | \Ev::run(); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Events/Event.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 有个鬼<42765633@qq.com> 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Events; 15 | 16 | use Workerman\Worker; 17 | 18 | /** 19 | * libevent eventloop 20 | */ 21 | class Event implements EventInterface 22 | { 23 | /** 24 | * Event base. 25 | * @var object 26 | */ 27 | protected $_eventBase = null; 28 | 29 | /** 30 | * All listeners for read/write event. 31 | * @var array 32 | */ 33 | protected $_allEvents = array(); 34 | 35 | /** 36 | * Event listeners of signal. 37 | * @var array 38 | */ 39 | protected $_eventSignal = array(); 40 | 41 | /** 42 | * All timer event listeners. 43 | * [func, args, event, flag, time_interval] 44 | * @var array 45 | */ 46 | protected $_eventTimer = array(); 47 | 48 | /** 49 | * Timer id. 50 | * @var int 51 | */ 52 | protected static $_timerId = 1; 53 | 54 | /** 55 | * construct 56 | * @return void 57 | */ 58 | public function __construct() 59 | { 60 | $this->_eventBase = new \EventBase(); 61 | } 62 | 63 | /** 64 | * @see EventInterface::add() 65 | */ 66 | public function add($fd, $flag, $func, $args=array()) 67 | { 68 | switch ($flag) { 69 | case self::EV_SIGNAL: 70 | 71 | $fd_key = (int)$fd; 72 | $event = \Event::signal($this->_eventBase, $fd, $func); 73 | if (!$event||!$event->add()) { 74 | return false; 75 | } 76 | $this->_eventSignal[$fd_key] = $event; 77 | return true; 78 | 79 | case self::EV_TIMER: 80 | case self::EV_TIMER_ONCE: 81 | 82 | $param = array($func, (array)$args, $flag, $fd, self::$_timerId); 83 | $event = new \Event($this->_eventBase, -1, \Event::TIMEOUT|\Event::PERSIST, array($this, "timerCallback"), $param); 84 | if (!$event||!$event->addTimer($fd)) { 85 | return false; 86 | } 87 | $this->_eventTimer[self::$_timerId] = $event; 88 | return self::$_timerId++; 89 | 90 | default : 91 | $fd_key = (int)$fd; 92 | $real_flag = $flag === self::EV_READ ? \Event::READ | \Event::PERSIST : \Event::WRITE | \Event::PERSIST; 93 | $event = new \Event($this->_eventBase, $fd, $real_flag, $func, $fd); 94 | if (!$event||!$event->add()) { 95 | return false; 96 | } 97 | $this->_allEvents[$fd_key][$flag] = $event; 98 | return true; 99 | } 100 | } 101 | 102 | /** 103 | * @see Events\EventInterface::del() 104 | */ 105 | public function del($fd, $flag) 106 | { 107 | switch ($flag) { 108 | 109 | case self::EV_READ: 110 | case self::EV_WRITE: 111 | 112 | $fd_key = (int)$fd; 113 | if (isset($this->_allEvents[$fd_key][$flag])) { 114 | $this->_allEvents[$fd_key][$flag]->del(); 115 | unset($this->_allEvents[$fd_key][$flag]); 116 | } 117 | if (empty($this->_allEvents[$fd_key])) { 118 | unset($this->_allEvents[$fd_key]); 119 | } 120 | break; 121 | 122 | case self::EV_SIGNAL: 123 | 124 | $fd_key = (int)$fd; 125 | if (isset($this->_eventSignal[$fd_key])) { 126 | $this->_allEvents[$fd_key][$flag]->del(); 127 | unset($this->_eventSignal[$fd_key]); 128 | } 129 | break; 130 | 131 | case self::EV_TIMER: 132 | case self::EV_TIMER_ONCE: 133 | if (isset($this->_eventTimer[$fd])) { 134 | $this->_eventTimer[$fd]->del(); 135 | unset($this->_eventTimer[$fd]); 136 | } 137 | break; 138 | } 139 | return true; 140 | } 141 | 142 | /** 143 | * Timer callback. 144 | * @param null $fd 145 | * @param int $what 146 | * @param int $timer_id 147 | */ 148 | public function timerCallback($fd, $what, $param) 149 | { 150 | $timer_id = $param[4]; 151 | 152 | if ($param[2] === self::EV_TIMER_ONCE) { 153 | $this->_eventTimer[$timer_id]->del(); 154 | unset($this->_eventTimer[$timer_id]); 155 | } 156 | 157 | try { 158 | call_user_func_array($param[0], $param[1]); 159 | } catch (\Exception $e) { 160 | Worker::log($e); 161 | exit(250); 162 | } catch (\Error $e) { 163 | Worker::log($e); 164 | exit(250); 165 | } 166 | } 167 | 168 | /** 169 | * @see Events\EventInterface::clearAllTimer() 170 | * @return void 171 | */ 172 | public function clearAllTimer() 173 | { 174 | foreach ($this->_eventTimer as $event) { 175 | $event->del(); 176 | } 177 | $this->_eventTimer = array(); 178 | } 179 | 180 | 181 | /** 182 | * @see EventInterface::loop() 183 | */ 184 | public function loop() 185 | { 186 | $this->_eventBase->loop(); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Events/Event.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 有个鬼<42765633@qq.com> 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Events; 15 | 16 | use Workerman\Worker; 17 | 18 | /** 19 | * libevent eventloop 20 | */ 21 | class Event implements EventInterface 22 | { 23 | /** 24 | * Event base. 25 | * @var object 26 | */ 27 | protected $_eventBase = null; 28 | 29 | /** 30 | * All listeners for read/write event. 31 | * @var array 32 | */ 33 | protected $_allEvents = array(); 34 | 35 | /** 36 | * Event listeners of signal. 37 | * @var array 38 | */ 39 | protected $_eventSignal = array(); 40 | 41 | /** 42 | * All timer event listeners. 43 | * [func, args, event, flag, time_interval] 44 | * @var array 45 | */ 46 | protected $_eventTimer = array(); 47 | 48 | /** 49 | * Timer id. 50 | * @var int 51 | */ 52 | protected static $_timerId = 1; 53 | 54 | /** 55 | * construct 56 | * @return void 57 | */ 58 | public function __construct() 59 | { 60 | $this->_eventBase = new \EventBase(); 61 | } 62 | 63 | /** 64 | * @see EventInterface::add() 65 | */ 66 | public function add($fd, $flag, $func, $args=array()) 67 | { 68 | switch ($flag) { 69 | case self::EV_SIGNAL: 70 | 71 | $fd_key = (int)$fd; 72 | $event = \Event::signal($this->_eventBase, $fd, $func); 73 | if (!$event||!$event->add()) { 74 | return false; 75 | } 76 | $this->_eventSignal[$fd_key] = $event; 77 | return true; 78 | 79 | case self::EV_TIMER: 80 | case self::EV_TIMER_ONCE: 81 | 82 | $param = array($func, (array)$args, $flag, $fd, self::$_timerId); 83 | $event = new \Event($this->_eventBase, -1, \Event::TIMEOUT|\Event::PERSIST, array($this, "timerCallback"), $param); 84 | if (!$event||!$event->addTimer($fd)) { 85 | return false; 86 | } 87 | $this->_eventTimer[self::$_timerId] = $event; 88 | return self::$_timerId++; 89 | 90 | default : 91 | $fd_key = (int)$fd; 92 | $real_flag = $flag === self::EV_READ ? \Event::READ | \Event::PERSIST : \Event::WRITE | \Event::PERSIST; 93 | $event = new \Event($this->_eventBase, $fd, $real_flag, $func, $fd); 94 | if (!$event||!$event->add()) { 95 | return false; 96 | } 97 | $this->_allEvents[$fd_key][$flag] = $event; 98 | return true; 99 | } 100 | } 101 | 102 | /** 103 | * @see Events\EventInterface::del() 104 | */ 105 | public function del($fd, $flag) 106 | { 107 | switch ($flag) { 108 | 109 | case self::EV_READ: 110 | case self::EV_WRITE: 111 | 112 | $fd_key = (int)$fd; 113 | if (isset($this->_allEvents[$fd_key][$flag])) { 114 | $this->_allEvents[$fd_key][$flag]->del(); 115 | unset($this->_allEvents[$fd_key][$flag]); 116 | } 117 | if (empty($this->_allEvents[$fd_key])) { 118 | unset($this->_allEvents[$fd_key]); 119 | } 120 | break; 121 | 122 | case self::EV_SIGNAL: 123 | 124 | $fd_key = (int)$fd; 125 | if (isset($this->_eventSignal[$fd_key])) { 126 | $this->_allEvents[$fd_key][$flag]->del(); 127 | unset($this->_eventSignal[$fd_key]); 128 | } 129 | break; 130 | 131 | case self::EV_TIMER: 132 | case self::EV_TIMER_ONCE: 133 | if (isset($this->_eventTimer[$fd])) { 134 | $this->_eventTimer[$fd]->del(); 135 | unset($this->_eventTimer[$fd]); 136 | } 137 | break; 138 | } 139 | return true; 140 | } 141 | 142 | /** 143 | * Timer callback. 144 | * @param null $fd 145 | * @param int $what 146 | * @param int $timer_id 147 | */ 148 | public function timerCallback($fd, $what, $param) 149 | { 150 | $timer_id = $param[4]; 151 | 152 | if ($param[2] === self::EV_TIMER_ONCE) { 153 | $this->_eventTimer[$timer_id]->del(); 154 | unset($this->_eventTimer[$timer_id]); 155 | } 156 | 157 | try { 158 | call_user_func_array($param[0], $param[1]); 159 | } catch (\Exception $e) { 160 | Worker::log($e); 161 | exit(250); 162 | } catch (\Error $e) { 163 | Worker::log($e); 164 | exit(250); 165 | } 166 | } 167 | 168 | /** 169 | * @see Events\EventInterface::clearAllTimer() 170 | * @return void 171 | */ 172 | public function clearAllTimer() 173 | { 174 | foreach ($this->_eventTimer as $event) { 175 | $event->del(); 176 | } 177 | $this->_eventTimer = array(); 178 | } 179 | 180 | 181 | /** 182 | * @see EventInterface::loop() 183 | */ 184 | public function loop() 185 | { 186 | $this->_eventBase->loop(); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Events/Libevent.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Events; 15 | 16 | use Workerman\Worker; 17 | 18 | /** 19 | * libevent eventloop 20 | */ 21 | class Libevent implements EventInterface 22 | { 23 | /** 24 | * Event base. 25 | * 26 | * @var resource 27 | */ 28 | protected $_eventBase = null; 29 | 30 | /** 31 | * All listeners for read/write event. 32 | * 33 | * @var array 34 | */ 35 | protected $_allEvents = array(); 36 | 37 | /** 38 | * Event listeners of signal. 39 | * 40 | * @var array 41 | */ 42 | protected $_eventSignal = array(); 43 | 44 | /** 45 | * All timer event listeners. 46 | * [func, args, event, flag, time_interval] 47 | * 48 | * @var array 49 | */ 50 | protected $_eventTimer = array(); 51 | 52 | /** 53 | * construct 54 | */ 55 | public function __construct() 56 | { 57 | $this->_eventBase = event_base_new(); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public function add($fd, $flag, $func, $args = array()) 64 | { 65 | switch ($flag) { 66 | case self::EV_SIGNAL: 67 | $fd_key = (int)$fd; 68 | $real_flag = EV_SIGNAL | EV_PERSIST; 69 | $this->_eventSignal[$fd_key] = event_new(); 70 | if (!event_set($this->_eventSignal[$fd_key], $fd, $real_flag, $func, null)) { 71 | return false; 72 | } 73 | if (!event_base_set($this->_eventSignal[$fd_key], $this->_eventBase)) { 74 | return false; 75 | } 76 | if (!event_add($this->_eventSignal[$fd_key])) { 77 | return false; 78 | } 79 | return true; 80 | case self::EV_TIMER: 81 | case self::EV_TIMER_ONCE: 82 | $event = event_new(); 83 | $timer_id = (int)$event; 84 | if (!event_set($event, 0, EV_TIMEOUT, array($this, 'timerCallback'), $timer_id)) { 85 | return false; 86 | } 87 | 88 | if (!event_base_set($event, $this->_eventBase)) { 89 | return false; 90 | } 91 | 92 | $time_interval = $fd * 1000000; 93 | if (!event_add($event, $time_interval)) { 94 | return false; 95 | } 96 | $this->_eventTimer[$timer_id] = array($func, (array)$args, $event, $flag, $time_interval); 97 | return $timer_id; 98 | 99 | default : 100 | $fd_key = (int)$fd; 101 | $real_flag = $flag === self::EV_READ ? EV_READ | EV_PERSIST : EV_WRITE | EV_PERSIST; 102 | 103 | $event = event_new(); 104 | 105 | if (!event_set($event, $fd, $real_flag, $func, null)) { 106 | return false; 107 | } 108 | 109 | if (!event_base_set($event, $this->_eventBase)) { 110 | return false; 111 | } 112 | 113 | if (!event_add($event)) { 114 | return false; 115 | } 116 | 117 | $this->_allEvents[$fd_key][$flag] = $event; 118 | 119 | return true; 120 | } 121 | 122 | } 123 | 124 | /** 125 | * {@inheritdoc} 126 | */ 127 | public function del($fd, $flag) 128 | { 129 | switch ($flag) { 130 | case self::EV_READ: 131 | case self::EV_WRITE: 132 | $fd_key = (int)$fd; 133 | if (isset($this->_allEvents[$fd_key][$flag])) { 134 | event_del($this->_allEvents[$fd_key][$flag]); 135 | unset($this->_allEvents[$fd_key][$flag]); 136 | } 137 | if (empty($this->_allEvents[$fd_key])) { 138 | unset($this->_allEvents[$fd_key]); 139 | } 140 | break; 141 | case self::EV_SIGNAL: 142 | $fd_key = (int)$fd; 143 | if (isset($this->_eventSignal[$fd_key])) { 144 | event_del($this->_eventSignal[$fd_key]); 145 | unset($this->_eventSignal[$fd_key]); 146 | } 147 | break; 148 | case self::EV_TIMER: 149 | case self::EV_TIMER_ONCE: 150 | // 这里 fd 为timerid 151 | if (isset($this->_eventTimer[$fd])) { 152 | event_del($this->_eventTimer[$fd][2]); 153 | unset($this->_eventTimer[$fd]); 154 | } 155 | break; 156 | } 157 | return true; 158 | } 159 | 160 | /** 161 | * Timer callback. 162 | * 163 | * @param mixed $_null1 164 | * @param int $_null2 165 | * @param mixed $timer_id 166 | */ 167 | protected function timerCallback($_null1, $_null2, $timer_id) 168 | { 169 | if ($this->_eventTimer[$timer_id][3] === self::EV_TIMER) { 170 | event_add($this->_eventTimer[$timer_id][2], $this->_eventTimer[$timer_id][4]); 171 | } 172 | try { 173 | call_user_func_array($this->_eventTimer[$timer_id][0], $this->_eventTimer[$timer_id][1]); 174 | } catch (\Exception $e) { 175 | Worker::log($e); 176 | exit(250); 177 | } catch (\Error $e) { 178 | Worker::log($e); 179 | exit(250); 180 | } 181 | if (isset($this->_eventTimer[$timer_id]) && $this->_eventTimer[$timer_id][3] === self::EV_TIMER_ONCE) { 182 | $this->del($timer_id, self::EV_TIMER_ONCE); 183 | } 184 | } 185 | 186 | /** 187 | * {@inheritdoc} 188 | */ 189 | public function clearAllTimer() 190 | { 191 | foreach ($this->_eventTimer as $task_data) { 192 | event_del($task_data[2]); 193 | } 194 | $this->_eventTimer = array(); 195 | } 196 | 197 | /** 198 | * {@inheritdoc} 199 | */ 200 | public function loop() 201 | { 202 | event_base_loop($this->_eventBase); 203 | } 204 | } 205 | 206 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Events/Libevent.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Events; 15 | 16 | use Workerman\Worker; 17 | 18 | /** 19 | * libevent eventloop 20 | */ 21 | class Libevent implements EventInterface 22 | { 23 | /** 24 | * Event base. 25 | * 26 | * @var resource 27 | */ 28 | protected $_eventBase = null; 29 | 30 | /** 31 | * All listeners for read/write event. 32 | * 33 | * @var array 34 | */ 35 | protected $_allEvents = array(); 36 | 37 | /** 38 | * Event listeners of signal. 39 | * 40 | * @var array 41 | */ 42 | protected $_eventSignal = array(); 43 | 44 | /** 45 | * All timer event listeners. 46 | * [func, args, event, flag, time_interval] 47 | * 48 | * @var array 49 | */ 50 | protected $_eventTimer = array(); 51 | 52 | /** 53 | * construct 54 | */ 55 | public function __construct() 56 | { 57 | $this->_eventBase = event_base_new(); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public function add($fd, $flag, $func, $args = array()) 64 | { 65 | switch ($flag) { 66 | case self::EV_SIGNAL: 67 | $fd_key = (int)$fd; 68 | $real_flag = EV_SIGNAL | EV_PERSIST; 69 | $this->_eventSignal[$fd_key] = event_new(); 70 | if (!event_set($this->_eventSignal[$fd_key], $fd, $real_flag, $func, null)) { 71 | return false; 72 | } 73 | if (!event_base_set($this->_eventSignal[$fd_key], $this->_eventBase)) { 74 | return false; 75 | } 76 | if (!event_add($this->_eventSignal[$fd_key])) { 77 | return false; 78 | } 79 | return true; 80 | case self::EV_TIMER: 81 | case self::EV_TIMER_ONCE: 82 | $event = event_new(); 83 | $timer_id = (int)$event; 84 | if (!event_set($event, 0, EV_TIMEOUT, array($this, 'timerCallback'), $timer_id)) { 85 | return false; 86 | } 87 | 88 | if (!event_base_set($event, $this->_eventBase)) { 89 | return false; 90 | } 91 | 92 | $time_interval = $fd * 1000000; 93 | if (!event_add($event, $time_interval)) { 94 | return false; 95 | } 96 | $this->_eventTimer[$timer_id] = array($func, (array)$args, $event, $flag, $time_interval); 97 | return $timer_id; 98 | 99 | default : 100 | $fd_key = (int)$fd; 101 | $real_flag = $flag === self::EV_READ ? EV_READ | EV_PERSIST : EV_WRITE | EV_PERSIST; 102 | 103 | $event = event_new(); 104 | 105 | if (!event_set($event, $fd, $real_flag, $func, null)) { 106 | return false; 107 | } 108 | 109 | if (!event_base_set($event, $this->_eventBase)) { 110 | return false; 111 | } 112 | 113 | if (!event_add($event)) { 114 | return false; 115 | } 116 | 117 | $this->_allEvents[$fd_key][$flag] = $event; 118 | 119 | return true; 120 | } 121 | 122 | } 123 | 124 | /** 125 | * {@inheritdoc} 126 | */ 127 | public function del($fd, $flag) 128 | { 129 | switch ($flag) { 130 | case self::EV_READ: 131 | case self::EV_WRITE: 132 | $fd_key = (int)$fd; 133 | if (isset($this->_allEvents[$fd_key][$flag])) { 134 | event_del($this->_allEvents[$fd_key][$flag]); 135 | unset($this->_allEvents[$fd_key][$flag]); 136 | } 137 | if (empty($this->_allEvents[$fd_key])) { 138 | unset($this->_allEvents[$fd_key]); 139 | } 140 | break; 141 | case self::EV_SIGNAL: 142 | $fd_key = (int)$fd; 143 | if (isset($this->_eventSignal[$fd_key])) { 144 | event_del($this->_eventSignal[$fd_key]); 145 | unset($this->_eventSignal[$fd_key]); 146 | } 147 | break; 148 | case self::EV_TIMER: 149 | case self::EV_TIMER_ONCE: 150 | // 这里 fd 为timerid 151 | if (isset($this->_eventTimer[$fd])) { 152 | event_del($this->_eventTimer[$fd][2]); 153 | unset($this->_eventTimer[$fd]); 154 | } 155 | break; 156 | } 157 | return true; 158 | } 159 | 160 | /** 161 | * Timer callback. 162 | * 163 | * @param mixed $_null1 164 | * @param int $_null2 165 | * @param mixed $timer_id 166 | */ 167 | protected function timerCallback($_null1, $_null2, $timer_id) 168 | { 169 | if ($this->_eventTimer[$timer_id][3] === self::EV_TIMER) { 170 | event_add($this->_eventTimer[$timer_id][2], $this->_eventTimer[$timer_id][4]); 171 | } 172 | try { 173 | call_user_func_array($this->_eventTimer[$timer_id][0], $this->_eventTimer[$timer_id][1]); 174 | } catch (\Exception $e) { 175 | Worker::log($e); 176 | exit(250); 177 | } catch (\Error $e) { 178 | Worker::log($e); 179 | exit(250); 180 | } 181 | if (isset($this->_eventTimer[$timer_id]) && $this->_eventTimer[$timer_id][3] === self::EV_TIMER_ONCE) { 182 | $this->del($timer_id, self::EV_TIMER_ONCE); 183 | } 184 | } 185 | 186 | /** 187 | * {@inheritdoc} 188 | */ 189 | public function clearAllTimer() 190 | { 191 | foreach ($this->_eventTimer as $task_data) { 192 | event_del($task_data[2]); 193 | } 194 | $this->_eventTimer = array(); 195 | } 196 | 197 | /** 198 | * {@inheritdoc} 199 | */ 200 | public function loop() 201 | { 202 | event_base_loop($this->_eventBase); 203 | } 204 | } 205 | 206 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Connection/AsyncTcpConnection.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Connection; 15 | 16 | use Workerman\Events\EventInterface; 17 | use Workerman\Worker; 18 | use Exception; 19 | 20 | /** 21 | * AsyncTcpConnection. 22 | */ 23 | class AsyncTcpConnection extends TcpConnection 24 | { 25 | /** 26 | * Emitted when socket connection is successfully established. 27 | * 28 | * @var callback 29 | */ 30 | public $onConnect = null; 31 | 32 | /** 33 | * Status. 34 | * 35 | * @var int 36 | */ 37 | protected $_status = self::STATUS_INITIAL; 38 | 39 | /** 40 | * Remote host. 41 | * 42 | * @var string 43 | */ 44 | protected $_remoteHost = ''; 45 | 46 | /** 47 | * Connect start time. 48 | * 49 | * @var string 50 | */ 51 | protected $_connectStartTime = 0; 52 | 53 | /** 54 | * PHP built-in protocols. 55 | * 56 | * @var array 57 | */ 58 | protected static $_builtinTransports = array( 59 | 'tcp' => 'tcp', 60 | 'udp' => 'udp', 61 | 'unix' => 'unix', 62 | 'ssl' => 'ssl', 63 | 'sslv2' => 'sslv2', 64 | 'sslv3' => 'sslv3', 65 | 'tls' => 'tls' 66 | ); 67 | 68 | /** 69 | * Transport layer protocol. 70 | * 71 | * @var string 72 | */ 73 | public $transport = 'tcp'; 74 | 75 | /** 76 | * Construct. 77 | * 78 | * @param string $remote_address 79 | * @throws Exception 80 | */ 81 | public function __construct($remote_address) 82 | { 83 | // Get the application layer communication protocol and listening address. 84 | list($scheme, $address) = explode(':', $remote_address, 2); 85 | // Check application layer protocol class. 86 | if (!isset(self::$_builtinTransports[$scheme])) { 87 | $scheme = ucfirst($scheme); 88 | $this->protocol = '\\Protocols\\' . $scheme; 89 | if (!class_exists($this->protocol)) { 90 | $this->protocol = "\\Workerman\\Protocols\\$scheme"; 91 | if (!class_exists($this->protocol)) { 92 | throw new Exception("class \\Protocols\\$scheme not exist"); 93 | } 94 | } 95 | } else { 96 | $this->transport = self::$_builtinTransports[$scheme]; 97 | } 98 | 99 | $this->_remoteAddress = substr($address, 2); 100 | $this->_remoteHost = substr($this->_remoteAddress, 0, strrpos($this->_remoteAddress, ':')); 101 | $this->id = self::$_idRecorder++; 102 | // For statistics. 103 | self::$statistics['connection_count']++; 104 | $this->maxSendBufferSize = self::$defaultMaxSendBufferSize; 105 | } 106 | 107 | /** 108 | * Do connect 109 | * 110 | * @return void 111 | */ 112 | public function connect() 113 | { 114 | if ($this->_status !== self::STATUS_INITIAL && $this->_status !== self::STATUS_CLOSED && $this->_status !== self::STATUS_CLOSING) { 115 | return; 116 | } 117 | $this->_status = self::STATUS_CONNECTING; 118 | $this->_connectStartTime = microtime(true); 119 | // Open socket connection asynchronously. 120 | $this->_socket = stream_socket_client("{$this->transport}://{$this->_remoteAddress}", $errno, $errstr, 0, 121 | STREAM_CLIENT_ASYNC_CONNECT); 122 | // If failed attempt to emit onError callback. 123 | if (!$this->_socket) { 124 | $this->emitError(WORKERMAN_CONNECT_FAIL, $errstr); 125 | if ($this->_status === self::STATUS_CLOSING) { 126 | $this->destroy(); 127 | } 128 | if ($this->_status === self::STATUS_CLOSED) { 129 | $this->onConnect = null; 130 | } 131 | return; 132 | } 133 | // Add socket to global event loop waiting connection is successfully established or faild. 134 | Worker::$globalEvent->add($this->_socket, EventInterface::EV_WRITE, array($this, 'checkConnection')); 135 | Worker::$globalEvent->add($this->_socket, EventInterface::EV_EXCEPT, array($this, 'checkConnection')); 136 | } 137 | 138 | /** 139 | * Get remote address. 140 | * 141 | * @return string 142 | */ 143 | public function getRemoteHost() 144 | { 145 | return $this->_remoteHost; 146 | } 147 | 148 | /** 149 | * Try to emit onError callback. 150 | * 151 | * @param int $code 152 | * @param string $msg 153 | * @return void 154 | */ 155 | protected function emitError($code, $msg) 156 | { 157 | $this->_status = self::STATUS_CLOSING; 158 | if ($this->onError) { 159 | try { 160 | call_user_func($this->onError, $this, $code, $msg); 161 | } catch (\Exception $e) { 162 | Worker::log($e); 163 | exit(250); 164 | } catch (\Error $e) { 165 | Worker::log($e); 166 | exit(250); 167 | } 168 | } 169 | } 170 | 171 | /** 172 | * Check connection is successfully established or faild. 173 | * 174 | * @param resource $socket 175 | * @return void 176 | */ 177 | public function checkConnection($socket) 178 | { 179 | Worker::$globalEvent->del($socket, EventInterface::EV_EXCEPT); 180 | // Check socket state. 181 | if (stream_socket_get_name($socket, true)) { 182 | // Remove write listener. 183 | Worker::$globalEvent->del($socket, EventInterface::EV_WRITE); 184 | // Nonblocking. 185 | stream_set_blocking($socket, 0); 186 | stream_set_read_buffer($socket, 0); 187 | // Try to open keepalive for tcp and disable Nagle algorithm. 188 | if (function_exists('socket_import_stream') && $this->transport === 'tcp') { 189 | $raw_socket = socket_import_stream($socket); 190 | socket_set_option($raw_socket, SOL_SOCKET, SO_KEEPALIVE, 1); 191 | socket_set_option($raw_socket, SOL_TCP, TCP_NODELAY, 1); 192 | } 193 | // Register a listener waiting read event. 194 | Worker::$globalEvent->add($socket, EventInterface::EV_READ, array($this, 'baseRead')); 195 | // There are some data waiting to send. 196 | if ($this->_sendBuffer) { 197 | Worker::$globalEvent->add($socket, EventInterface::EV_WRITE, array($this, 'baseWrite')); 198 | } 199 | $this->_status = self::STATUS_ESTABLISH; 200 | $this->_remoteAddress = stream_socket_get_name($socket, true); 201 | // Try to emit onConnect callback. 202 | if ($this->onConnect) { 203 | try { 204 | call_user_func($this->onConnect, $this); 205 | } catch (\Exception $e) { 206 | Worker::log($e); 207 | exit(250); 208 | } catch (\Error $e) { 209 | Worker::log($e); 210 | exit(250); 211 | } 212 | } 213 | } else { 214 | // Connection failed. 215 | $this->emitError(WORKERMAN_CONNECT_FAIL, 'connect ' . $this->_remoteAddress . ' fail after ' . round(microtime(true) - $this->_connectStartTime, 4) . ' seconds'); 216 | if ($this->_status === self::STATUS_CLOSING) { 217 | $this->destroy(); 218 | } 219 | if ($this->_status === self::STATUS_CLOSED) { 220 | $this->onConnect = null; 221 | } 222 | } 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /vendor/composer/installed.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "topthink/think-installer", 4 | "version": "v1.0.10", 5 | "version_normalized": "1.0.10.0", 6 | "source": { 7 | "type": "git", 8 | "url": "https://github.com/top-think/think-installer.git", 9 | "reference": "ae50760ebd7c687c7a8573db2cfa94a41e5100e3" 10 | }, 11 | "dist": { 12 | "type": "zip", 13 | "url": "https://packagist.phpcomposer.com/files/top-think/think-installer/ae50760ebd7c687c7a8573db2cfa94a41e5100e3.zip", 14 | "reference": "ae50760ebd7c687c7a8573db2cfa94a41e5100e3", 15 | "shasum": "" 16 | }, 17 | "require": { 18 | "composer-plugin-api": "^1.0" 19 | }, 20 | "require-dev": { 21 | "composer/composer": "1.0.*@dev" 22 | }, 23 | "time": "2016-09-23 04:04:44", 24 | "type": "composer-plugin", 25 | "extra": { 26 | "class": "think\\composer\\Plugin" 27 | }, 28 | "installation-source": "dist", 29 | "autoload": { 30 | "psr-4": { 31 | "think\\composer\\": "src" 32 | } 33 | }, 34 | "notification-url": "https://packagist.org/downloads/", 35 | "license": [ 36 | "Apache-2.0" 37 | ], 38 | "authors": [ 39 | { 40 | "name": "yunwuxin", 41 | "email": "448901948@qq.com" 42 | } 43 | ] 44 | }, 45 | { 46 | "name": "topthink/think-worker", 47 | "version": "v1.0.1", 48 | "version_normalized": "1.0.1.0", 49 | "source": { 50 | "type": "git", 51 | "url": "https://github.com/top-think/think-worker.git", 52 | "reference": "b609ff5e38dbb7194aab027d2b2c6b31a7ed1bd1" 53 | }, 54 | "dist": { 55 | "type": "zip", 56 | "url": "https://packagist.phpcomposer.com/files/top-think/think-worker/b609ff5e38dbb7194aab027d2b2c6b31a7ed1bd1.zip", 57 | "reference": "b609ff5e38dbb7194aab027d2b2c6b31a7ed1bd1", 58 | "shasum": "" 59 | }, 60 | "require": { 61 | "workerman/workerman": "^3.3.0" 62 | }, 63 | "time": "2016-10-08 06:07:03", 64 | "type": "library", 65 | "installation-source": "dist", 66 | "autoload": { 67 | "psr-4": { 68 | "think\\worker\\": "src" 69 | }, 70 | "files": [] 71 | }, 72 | "notification-url": "https://packagist.org/downloads/", 73 | "license": [ 74 | "Apache-2.0" 75 | ], 76 | "authors": [ 77 | { 78 | "name": "liu21st", 79 | "email": "liu21st@gmail.com" 80 | } 81 | ], 82 | "description": "workerman extend for thinkphp5" 83 | }, 84 | { 85 | "name": "workerman/workerman-for-win", 86 | "version": "v3.3.2", 87 | "version_normalized": "3.3.2.0", 88 | "source": { 89 | "type": "git", 90 | "url": "https://github.com/walkor/workerman-for-win.git", 91 | "reference": "40e8d204fa0b3cf845f2ac1cb8d97fa7e11ddf37" 92 | }, 93 | "dist": { 94 | "type": "zip", 95 | "url": "https://packagist.phpcomposer.com/files/walkor/workerman-for-win/40e8d204fa0b3cf845f2ac1cb8d97fa7e11ddf37.zip", 96 | "reference": "40e8d204fa0b3cf845f2ac1cb8d97fa7e11ddf37", 97 | "shasum": "" 98 | }, 99 | "require": { 100 | "php": ">=5.3" 101 | }, 102 | "time": "2016-07-29 04:24:19", 103 | "type": "project", 104 | "installation-source": "dist", 105 | "autoload": { 106 | "psr-4": { 107 | "Workerman\\": "./" 108 | } 109 | }, 110 | "notification-url": "https://packagist.org/downloads/", 111 | "license": [ 112 | "MIT" 113 | ], 114 | "authors": [ 115 | { 116 | "name": "walkor", 117 | "email": "walkor@workerman.net", 118 | "homepage": "http://www.workerman.net", 119 | "role": "Developer" 120 | } 121 | ], 122 | "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.", 123 | "homepage": "http://www.workerman.net", 124 | "keywords": [ 125 | "asynchronous", 126 | "event-loop" 127 | ] 128 | }, 129 | { 130 | "name": "workerman/workerman", 131 | "version": "v3.3.4", 132 | "version_normalized": "3.3.4.0", 133 | "source": { 134 | "type": "git", 135 | "url": "https://github.com/walkor/Workerman.git", 136 | "reference": "d6a7f02c21660e328b7a5aaea82eeb59653b313d" 137 | }, 138 | "dist": { 139 | "type": "zip", 140 | "url": "https://packagist.phpcomposer.com/files/walkor/Workerman/d6a7f02c21660e328b7a5aaea82eeb59653b313d.zip", 141 | "reference": "d6a7f02c21660e328b7a5aaea82eeb59653b313d", 142 | "shasum": "" 143 | }, 144 | "require": { 145 | "php": ">=5.3" 146 | }, 147 | "suggest": { 148 | "ext-libevent": "For better performance." 149 | }, 150 | "time": "2016-09-19 02:15:51", 151 | "type": "project", 152 | "installation-source": "dist", 153 | "autoload": { 154 | "psr-4": { 155 | "Workerman\\": "./" 156 | } 157 | }, 158 | "notification-url": "https://packagist.org/downloads/", 159 | "license": [ 160 | "MIT" 161 | ], 162 | "authors": [ 163 | { 164 | "name": "walkor", 165 | "email": "walkor@workerman.net", 166 | "homepage": "http://www.workerman.net", 167 | "role": "Developer" 168 | } 169 | ], 170 | "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.", 171 | "homepage": "http://www.workerman.net", 172 | "keywords": [ 173 | "asynchronous", 174 | "event-loop" 175 | ] 176 | }, 177 | { 178 | "name": "topthink/framework", 179 | "version": "v5.0.3", 180 | "version_normalized": "5.0.3.0", 181 | "source": { 182 | "type": "git", 183 | "url": "https://github.com/top-think/framework.git", 184 | "reference": "fd30f090e40dc25a758d99029fa07f669f575580" 185 | }, 186 | "dist": { 187 | "type": "zip", 188 | "url": "https://packagist.phpcomposer.com/files/top-think/framework/fd30f090e40dc25a758d99029fa07f669f575580.zip", 189 | "reference": "fd30f090e40dc25a758d99029fa07f669f575580", 190 | "shasum": "" 191 | }, 192 | "require": { 193 | "php": ">=5.4.0", 194 | "topthink/think-installer": "~1.0" 195 | }, 196 | "require-dev": { 197 | "johnkary/phpunit-speedtrap": "^1.0", 198 | "mikey179/vfsstream": "~1.6", 199 | "phpdocumentor/reflection-docblock": "^2.0", 200 | "phploc/phploc": "2.*", 201 | "phpunit/phpunit": "4.8.*", 202 | "sebastian/phpcpd": "2.*", 203 | "squizlabs/php_codesniffer": "2.*" 204 | }, 205 | "time": "2016-11-11 09:22:23", 206 | "type": "think-framework", 207 | "installation-source": "dist", 208 | "autoload": { 209 | "psr-4": { 210 | "think\\": "library/think" 211 | } 212 | }, 213 | "notification-url": "https://packagist.org/downloads/", 214 | "license": [ 215 | "Apache-2.0" 216 | ], 217 | "authors": [ 218 | { 219 | "name": "liu21st", 220 | "email": "liu21st@gmail.com" 221 | } 222 | ], 223 | "description": "the new thinkphp framework", 224 | "homepage": "http://thinkphp.cn/", 225 | "keywords": [ 226 | "framework", 227 | "orm", 228 | "thinkphp" 229 | ] 230 | } 231 | ] 232 | -------------------------------------------------------------------------------- /config/config.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | return [ 13 | // +---------------------------------------------------------------------- 14 | // | 应用设置 15 | // +---------------------------------------------------------------------- 16 | 17 | // 应用命名空间 18 | 'app_namespace' => 'app', 19 | // 应用调试模式 20 | 'app_debug' => true, 21 | // 应用Trace 22 | 'app_trace' => false, 23 | // 应用模式状态 24 | 'app_status' => '', 25 | // 是否支持多模块 26 | 'app_multi_module' => true, 27 | // 入口自动绑定模块 28 | 'auto_bind_module' => false, 29 | // 注册的根命名空间 30 | 'root_namespace' => [], 31 | // 扩展函数文件 32 | 'extra_file_list' => [THINK_PATH . 'helper' . EXT], 33 | // 默认输出类型 34 | 'default_return_type' => 'html', 35 | // 默认AJAX 数据返回格式,可选json xml ... 36 | 'default_ajax_return' => 'json', 37 | // 默认JSONP格式返回的处理方法 38 | 'default_jsonp_handler' => 'jsonpReturn', 39 | // 默认JSONP处理方法 40 | 'var_jsonp_handler' => 'callback', 41 | // 默认时区 42 | 'default_timezone' => 'PRC', 43 | // 是否开启多语言 44 | 'lang_switch_on' => false, 45 | // 默认全局过滤方法 用逗号分隔多个 46 | 'default_filter' => '', 47 | // 默认语言 48 | 'default_lang' => 'zh-cn', 49 | // 应用类库后缀 50 | 'class_suffix' => false, 51 | // 控制器类后缀 52 | 'controller_suffix' => false, 53 | 54 | // +---------------------------------------------------------------------- 55 | // | 模块设置 56 | // +---------------------------------------------------------------------- 57 | 58 | // 默认模块名 59 | 'default_module' => 'index', 60 | // 禁止访问模块 61 | 'deny_module_list' => ['common'], 62 | // 默认控制器名 63 | 'default_controller' => 'Index', 64 | // 默认操作名 65 | 'default_action' => 'index', 66 | // 默认验证器 67 | 'default_validate' => '', 68 | // 默认的空控制器名 69 | 'empty_controller' => 'Error', 70 | // 操作方法后缀 71 | 'action_suffix' => '', 72 | // 自动搜索控制器 73 | 'controller_auto_search' => false, 74 | 75 | // +---------------------------------------------------------------------- 76 | // | URL设置 77 | // +---------------------------------------------------------------------- 78 | 79 | // PATHINFO变量名 用于兼容模式 80 | 'var_pathinfo' => 's', 81 | // 兼容PATH_INFO获取 82 | 'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'], 83 | // pathinfo分隔符 84 | 'pathinfo_depr' => '/', 85 | // URL伪静态后缀 86 | 'url_html_suffix' => 'html', 87 | // URL普通方式参数 用于自动生成 88 | 'url_common_param' => false, 89 | // URL参数方式 0 按名称成对解析 1 按顺序解析 90 | 'url_param_type' => 0, 91 | // 是否开启路由 92 | 'url_route_on' => true, 93 | // 路由使用完整匹配 94 | 'route_complete_match' => false, 95 | // 路由配置文件(支持配置多个) 96 | 'route_config_file' => ['route'], 97 | // 是否强制使用路由 98 | 'url_route_must' => false, 99 | // 域名部署 100 | 'url_domain_deploy' => false, 101 | // 域名根,如thinkphp.cn 102 | 'url_domain_root' => '', 103 | // 是否自动转换URL中的控制器和操作名 104 | 'url_convert' => true, 105 | // 默认的访问控制器层 106 | 'url_controller_layer' => 'controller', 107 | // 表单请求类型伪装变量 108 | 'var_method' => '_method', 109 | // 表单ajax伪装变量 110 | 'var_ajax' => '_ajax', 111 | // 表单pjax伪装变量 112 | 'var_pjax' => '_pjax', 113 | // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则 114 | 'request_cache' => false, 115 | // 请求缓存有效期 116 | 'request_cache_expire' => null, 117 | 118 | // +---------------------------------------------------------------------- 119 | // | 模板设置 120 | // +---------------------------------------------------------------------- 121 | 122 | 'template' => [ 123 | // 模板引擎类型 支持 php think 支持扩展 124 | 'type' => 'Think', 125 | // 模板路径 126 | 'view_path' => '', 127 | // 模板后缀 128 | 'view_suffix' => 'html', 129 | // 模板文件名分隔符 130 | 'view_depr' => DS, 131 | // 模板引擎普通标签开始标记 132 | 'tpl_begin' => '{', 133 | // 模板引擎普通标签结束标记 134 | 'tpl_end' => '}', 135 | // 标签库标签开始标记 136 | 'taglib_begin' => '{', 137 | // 标签库标签结束标记 138 | 'taglib_end' => '}', 139 | ], 140 | 141 | // 视图输出字符串内容替换 142 | 'view_replace_str' => [], 143 | // 默认跳转页面对应的模板文件 144 | 'dispatch_success_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl', 145 | 'dispatch_error_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl', 146 | 147 | // +---------------------------------------------------------------------- 148 | // | 异常及错误设置 149 | // +---------------------------------------------------------------------- 150 | 151 | // 异常页面的模板文件 152 | 'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl', 153 | 154 | // 错误显示信息,非调试模式有效 155 | 'error_message' => '页面错误!请稍后再试~', 156 | // 显示错误信息 157 | 'show_error_msg' => false, 158 | // 异常处理handle类 留空使用 \think\exception\Handle 159 | 'exception_handle' => '', 160 | 161 | // +---------------------------------------------------------------------- 162 | // | 日志设置 163 | // +---------------------------------------------------------------------- 164 | 165 | 'log' => [ 166 | // 日志记录方式,内置 file socket 支持扩展 167 | 'type' => 'File', 168 | // 日志保存目录 169 | 'path' => LOG_PATH, 170 | // 日志记录级别 171 | 'level' => [], 172 | ], 173 | 174 | // +---------------------------------------------------------------------- 175 | // | Trace设置 开启 app_trace 后 有效 176 | // +---------------------------------------------------------------------- 177 | 'trace' => [ 178 | // 内置Html Console 支持扩展 179 | 'type' => 'Html', 180 | ], 181 | 182 | // +---------------------------------------------------------------------- 183 | // | 缓存设置 184 | // +---------------------------------------------------------------------- 185 | 186 | 'cache' => [ 187 | // 驱动方式 188 | 'type' => 'File', 189 | // 缓存保存目录 190 | 'path' => CACHE_PATH, 191 | // 缓存前缀 192 | 'prefix' => '', 193 | // 缓存有效期 0表示永久缓存 194 | 'expire' => 0, 195 | ], 196 | 197 | // +---------------------------------------------------------------------- 198 | // | 会话设置 199 | // +---------------------------------------------------------------------- 200 | 201 | 'session' => [ 202 | 'id' => '', 203 | // SESSION_ID的提交变量,解决flash上传跨域 204 | 'var_session_id' => '', 205 | // SESSION 前缀 206 | 'prefix' => 'think', 207 | // 驱动方式 支持redis memcache memcached 208 | 'type' => '', 209 | // 是否自动开启 SESSION 210 | 'auto_start' => true, 211 | ], 212 | 213 | // +---------------------------------------------------------------------- 214 | // | Cookie设置 215 | // +---------------------------------------------------------------------- 216 | 'cookie' => [ 217 | // cookie 名称前缀 218 | 'prefix' => '', 219 | // cookie 保存时间 220 | 'expire' => 0, 221 | // cookie 保存路径 222 | 'path' => '/', 223 | // cookie 有效域名 224 | 'domain' => '', 225 | // cookie 启用安全传输 226 | 'secure' => false, 227 | // httponly设置 228 | 'httponly' => '', 229 | // 是否使用 setcookie 230 | 'setcookie' => true, 231 | ], 232 | 233 | //分页配置 234 | 'paginate' => [ 235 | 'type' => 'bootstrap', 236 | 'var_page' => 'page', 237 | 'list_rows' => 15, 238 | ], 239 | ]; 240 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Events/Select.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Events; 15 | 16 | /** 17 | * select eventloop 18 | */ 19 | class Select implements EventInterface 20 | { 21 | /** 22 | * All listeners for read/write event. 23 | * 24 | * @var array 25 | */ 26 | public $_allEvents = array(); 27 | 28 | /** 29 | * Event listeners of signal. 30 | * 31 | * @var array 32 | */ 33 | public $_signalEvents = array(); 34 | 35 | /** 36 | * Fds waiting for read event. 37 | * 38 | * @var array 39 | */ 40 | protected $_readFds = array(); 41 | 42 | /** 43 | * Fds waiting for write event. 44 | * 45 | * @var array 46 | */ 47 | protected $_writeFds = array(); 48 | 49 | /** 50 | * Timer scheduler. 51 | * {['data':timer_id, 'priority':run_timestamp], ..} 52 | * 53 | * @var \SplPriorityQueue 54 | */ 55 | protected $_scheduler = null; 56 | 57 | /** 58 | * All timer event listeners. 59 | * [[func, args, flag, timer_interval], ..] 60 | * 61 | * @var array 62 | */ 63 | protected $_task = array(); 64 | 65 | /** 66 | * Timer id. 67 | * 68 | * @var int 69 | */ 70 | protected $_timerId = 1; 71 | 72 | /** 73 | * Select timeout. 74 | * 75 | * @var int 76 | */ 77 | protected $_selectTimeout = 100000000; 78 | 79 | /** 80 | * Paired socket channels 81 | * 82 | * @var array 83 | */ 84 | protected $channel = array(); 85 | 86 | /** 87 | * Construct. 88 | */ 89 | public function __construct() 90 | { 91 | // Create a pipeline and put into the collection of the read to read the descriptor to avoid empty polling. 92 | $this->channel = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP); 93 | if ($this->channel) { 94 | stream_set_blocking($this->channel[0], 0); 95 | $this->_readFds[0] = $this->channel[0]; 96 | } 97 | // Init SplPriorityQueue. 98 | $this->_scheduler = new \SplPriorityQueue(); 99 | $this->_scheduler->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); 100 | } 101 | 102 | /** 103 | * {@inheritdoc} 104 | */ 105 | public function add($fd, $flag, $func, $args = array()) 106 | { 107 | switch ($flag) { 108 | case self::EV_READ: 109 | $fd_key = (int)$fd; 110 | $this->_allEvents[$fd_key][$flag] = array($func, $fd); 111 | $this->_readFds[$fd_key] = $fd; 112 | break; 113 | case self::EV_WRITE: 114 | $fd_key = (int)$fd; 115 | $this->_allEvents[$fd_key][$flag] = array($func, $fd); 116 | $this->_writeFds[$fd_key] = $fd; 117 | break; 118 | case self::EV_SIGNAL: 119 | $fd_key = (int)$fd; 120 | $this->_signalEvents[$fd_key][$flag] = array($func, $fd); 121 | pcntl_signal($fd, array($this, 'signalHandler')); 122 | break; 123 | case self::EV_TIMER: 124 | case self::EV_TIMER_ONCE: 125 | $run_time = microtime(true) + $fd; 126 | $this->_scheduler->insert($this->_timerId, -$run_time); 127 | $this->_task[$this->_timerId] = array($func, (array)$args, $flag, $fd); 128 | $this->tick(); 129 | return $this->_timerId++; 130 | } 131 | 132 | return true; 133 | } 134 | 135 | /** 136 | * Signal handler. 137 | * 138 | * @param int $signal 139 | */ 140 | public function signalHandler($signal) 141 | { 142 | call_user_func_array($this->_signalEvents[$signal][self::EV_SIGNAL][0], array($signal)); 143 | } 144 | 145 | /** 146 | * {@inheritdoc} 147 | */ 148 | public function del($fd, $flag) 149 | { 150 | $fd_key = (int)$fd; 151 | switch ($flag) { 152 | case self::EV_READ: 153 | unset($this->_allEvents[$fd_key][$flag], $this->_readFds[$fd_key]); 154 | if (empty($this->_allEvents[$fd_key])) { 155 | unset($this->_allEvents[$fd_key]); 156 | } 157 | return true; 158 | case self::EV_WRITE: 159 | unset($this->_allEvents[$fd_key][$flag], $this->_writeFds[$fd_key]); 160 | if (empty($this->_allEvents[$fd_key])) { 161 | unset($this->_allEvents[$fd_key]); 162 | } 163 | return true; 164 | case self::EV_SIGNAL: 165 | unset($this->_signalEvents[$fd_key]); 166 | pcntl_signal($fd, SIG_IGN); 167 | break; 168 | case self::EV_TIMER: 169 | case self::EV_TIMER_ONCE; 170 | unset($this->_task[$fd_key]); 171 | return true; 172 | } 173 | return false; 174 | } 175 | 176 | /** 177 | * Tick for timer. 178 | * 179 | * @return void 180 | */ 181 | protected function tick() 182 | { 183 | while (!$this->_scheduler->isEmpty()) { 184 | $scheduler_data = $this->_scheduler->top(); 185 | $timer_id = $scheduler_data['data']; 186 | $next_run_time = -$scheduler_data['priority']; 187 | $time_now = microtime(true); 188 | $this->_selectTimeout = ($next_run_time - $time_now) * 1000000; 189 | if ($this->_selectTimeout <= 0) { 190 | $this->_scheduler->extract(); 191 | 192 | if (!isset($this->_task[$timer_id])) { 193 | continue; 194 | } 195 | 196 | // [func, args, flag, timer_interval] 197 | $task_data = $this->_task[$timer_id]; 198 | if ($task_data[2] === self::EV_TIMER) { 199 | $next_run_time = $time_now + $task_data[3]; 200 | $this->_scheduler->insert($timer_id, -$next_run_time); 201 | } 202 | call_user_func_array($task_data[0], $task_data[1]); 203 | if (isset($this->_task[$timer_id]) && $task_data[2] === self::EV_TIMER_ONCE) { 204 | $this->del($timer_id, self::EV_TIMER_ONCE); 205 | } 206 | continue; 207 | } 208 | return; 209 | } 210 | $this->_selectTimeout = 100000000; 211 | } 212 | 213 | /** 214 | * {@inheritdoc} 215 | */ 216 | public function clearAllTimer() 217 | { 218 | $this->_scheduler = new \SplPriorityQueue(); 219 | $this->_scheduler->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); 220 | $this->_task = array(); 221 | } 222 | 223 | /** 224 | * {@inheritdoc} 225 | */ 226 | public function loop() 227 | { 228 | $e = null; 229 | while (1) { 230 | // Calls signal handlers for pending signals 231 | pcntl_signal_dispatch(); 232 | 233 | $read = $this->_readFds; 234 | $write = $this->_writeFds; 235 | // Waiting read/write/signal/timeout events. 236 | $ret = @stream_select($read, $write, $e, 0, $this->_selectTimeout); 237 | 238 | if (!$this->_scheduler->isEmpty()) { 239 | $this->tick(); 240 | } 241 | 242 | if (!$ret) { 243 | continue; 244 | } 245 | 246 | foreach ($read as $fd) { 247 | $fd_key = (int)$fd; 248 | if (isset($this->_allEvents[$fd_key][self::EV_READ])) { 249 | call_user_func_array($this->_allEvents[$fd_key][self::EV_READ][0], 250 | array($this->_allEvents[$fd_key][self::EV_READ][1])); 251 | } 252 | } 253 | 254 | foreach ($write as $fd) { 255 | $fd_key = (int)$fd; 256 | if (isset($this->_allEvents[$fd_key][self::EV_WRITE])) { 257 | call_user_func_array($this->_allEvents[$fd_key][self::EV_WRITE][0], 258 | array($this->_allEvents[$fd_key][self::EV_WRITE][1])); 259 | } 260 | } 261 | } 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/Connection/AsyncTcpConnection.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Connection; 15 | 16 | use Workerman\Events\EventInterface; 17 | use Workerman\Worker; 18 | use Exception; 19 | 20 | /** 21 | * AsyncTcpConnection. 22 | */ 23 | class AsyncTcpConnection extends TcpConnection 24 | { 25 | /** 26 | * Emitted when socket connection is successfully established. 27 | * 28 | * @var callback 29 | */ 30 | public $onConnect = null; 31 | 32 | /** 33 | * Transport layer protocol. 34 | * 35 | * @var string 36 | */ 37 | public $transport = 'tcp'; 38 | 39 | /** 40 | * Status. 41 | * 42 | * @var int 43 | */ 44 | protected $_status = self::STATUS_INITIAL; 45 | 46 | /** 47 | * Remote host. 48 | * 49 | * @var string 50 | */ 51 | protected $_remoteHost = ''; 52 | 53 | /** 54 | * Connect start time. 55 | * 56 | * @var string 57 | */ 58 | protected $_connectStartTime = 0; 59 | 60 | /** 61 | * Remote URI. 62 | * 63 | * @var string 64 | */ 65 | protected $_remoteURI = ''; 66 | 67 | 68 | /** 69 | * PHP built-in protocols. 70 | * 71 | * @var array 72 | */ 73 | protected static $_builtinTransports = array( 74 | 'tcp' => 'tcp', 75 | 'udp' => 'udp', 76 | 'unix' => 'unix', 77 | 'ssl' => 'ssl', 78 | 'sslv2' => 'sslv2', 79 | 'sslv3' => 'sslv3', 80 | 'tls' => 'tls' 81 | ); 82 | 83 | /** 84 | * Construct. 85 | * 86 | * @param string $remote_address 87 | * @throws Exception 88 | */ 89 | public function __construct($remote_address) 90 | { 91 | $address_info = parse_url($remote_address); 92 | if (!$address_info) { 93 | echo new \Exception('bad remote_address'); 94 | $this->_remoteAddress = $remote_address; 95 | } else { 96 | if (!isset($address_info['port'])) { 97 | $address_info['port'] = 80; 98 | } 99 | if (!isset($address_info['path'])) { 100 | $address_info['path'] = '/'; 101 | } 102 | if (!isset($address_info['query'])) { 103 | $address_info['query'] = ''; 104 | } else { 105 | $address_info['query'] = '?' . $address_info['query']; 106 | } 107 | $this->_remoteAddress = "{$address_info['host']}:{$address_info['port']}"; 108 | $this->_remoteHost = $address_info['host']; 109 | $this->_remoteURI = "{$address_info['path']}{$address_info['query']}"; 110 | $scheme = isset($address_info['scheme']) ? $address_info['scheme'] : 'tcp'; 111 | } 112 | 113 | $this->id = self::$_idRecorder++; 114 | // Check application layer protocol class. 115 | if (!isset(self::$_builtinTransports[$scheme])) { 116 | $scheme = ucfirst($scheme); 117 | $this->protocol = '\\Protocols\\' . $scheme; 118 | if (!class_exists($this->protocol)) { 119 | $this->protocol = "\\Workerman\\Protocols\\$scheme"; 120 | if (!class_exists($this->protocol)) { 121 | throw new Exception("class \\Protocols\\$scheme not exist"); 122 | } 123 | } 124 | } else { 125 | $this->transport = self::$_builtinTransports[$scheme]; 126 | } 127 | 128 | // For statistics. 129 | self::$statistics['connection_count']++; 130 | $this->maxSendBufferSize = self::$defaultMaxSendBufferSize; 131 | } 132 | 133 | /** 134 | * Do connect. 135 | * 136 | * @return void 137 | */ 138 | public function connect() 139 | { 140 | if ($this->_status !== self::STATUS_INITIAL && $this->_status !== self::STATUS_CLOSING && $this->_status !== self::STATUS_CLOSED) { 141 | return; 142 | } 143 | $this->_status = self::STATUS_CONNECTING; 144 | $this->_connectStartTime = microtime(true); 145 | // Open socket connection asynchronously. 146 | $this->_socket = stream_socket_client("{$this->transport}://{$this->_remoteAddress}", $errno, $errstr, 0, 147 | STREAM_CLIENT_ASYNC_CONNECT); 148 | // If failed attempt to emit onError callback. 149 | if (!$this->_socket) { 150 | $this->emitError(WORKERMAN_CONNECT_FAIL, $errstr); 151 | if ($this->_status === self::STATUS_CLOSING) { 152 | $this->destroy(); 153 | } 154 | if ($this->_status === self::STATUS_CLOSED) { 155 | $this->onConnect = null; 156 | } 157 | return; 158 | } 159 | // Add socket to global event loop waiting connection is successfully established or faild. 160 | Worker::$globalEvent->add($this->_socket, EventInterface::EV_WRITE, array($this, 'checkConnection')); 161 | } 162 | 163 | /** 164 | * Get remote address. 165 | * 166 | * @return string 167 | */ 168 | public function getRemoteHost() 169 | { 170 | return $this->_remoteHost; 171 | } 172 | 173 | /** 174 | * Get remote URI. 175 | * 176 | * @return string 177 | */ 178 | public function getRemoteURI() 179 | { 180 | return $this->_remoteURI; 181 | } 182 | 183 | /** 184 | * Try to emit onError callback. 185 | * 186 | * @param int $code 187 | * @param string $msg 188 | * @return void 189 | */ 190 | protected function emitError($code, $msg) 191 | { 192 | $this->_status = self::STATUS_CLOSING; 193 | if ($this->onError) { 194 | try { 195 | call_user_func($this->onError, $this, $code, $msg); 196 | } catch (\Exception $e) { 197 | Worker::log($e); 198 | exit(250); 199 | } catch (\Error $e) { 200 | Worker::log($e); 201 | exit(250); 202 | } 203 | } 204 | } 205 | 206 | /** 207 | * Check connection is successfully established or faild. 208 | * 209 | * @param resource $socket 210 | * @return void 211 | */ 212 | public function checkConnection($socket) 213 | { 214 | // Check socket state. 215 | if ($address = stream_socket_get_name($socket, true)) { 216 | // Remove write listener. 217 | Worker::$globalEvent->del($socket, EventInterface::EV_WRITE); 218 | // Nonblocking. 219 | stream_set_blocking($socket, 0); 220 | // Compatible with hhvm 221 | if (function_exists('stream_set_read_buffer')) { 222 | stream_set_read_buffer($socket, 0); 223 | } 224 | // Try to open keepalive for tcp and disable Nagle algorithm. 225 | if (function_exists('socket_import_stream') && $this->transport === 'tcp') { 226 | $raw_socket = socket_import_stream($socket); 227 | socket_set_option($raw_socket, SOL_SOCKET, SO_KEEPALIVE, 1); 228 | socket_set_option($raw_socket, SOL_TCP, TCP_NODELAY, 1); 229 | } 230 | // Register a listener waiting read event. 231 | Worker::$globalEvent->add($socket, EventInterface::EV_READ, array($this, 'baseRead')); 232 | // There are some data waiting to send. 233 | if ($this->_sendBuffer) { 234 | Worker::$globalEvent->add($socket, EventInterface::EV_WRITE, array($this, 'baseWrite')); 235 | } 236 | $this->_status = self::STATUS_ESTABLISH; 237 | $this->_remoteAddress = $address; 238 | 239 | // Try to emit onConnect callback. 240 | if ($this->onConnect) { 241 | try { 242 | call_user_func($this->onConnect, $this); 243 | } catch (\Exception $e) { 244 | Worker::log($e); 245 | exit(250); 246 | } catch (\Error $e) { 247 | Worker::log($e); 248 | exit(250); 249 | } 250 | } 251 | // Try to emit protocol::onConnect 252 | if (method_exists($this->protocol, 'onConnect')) { 253 | try { 254 | call_user_func(array($this->protocol, 'onConnect'), $this); 255 | } catch (\Exception $e) { 256 | Worker::log($e); 257 | exit(250); 258 | } catch (\Error $e) { 259 | Worker::log($e); 260 | exit(250); 261 | } 262 | } 263 | } else { 264 | // Connection failed. 265 | $this->emitError(WORKERMAN_CONNECT_FAIL, 'connect ' . $this->_remoteAddress . ' fail after ' . round(microtime(true) - $this->_connectStartTime, 4) . ' seconds'); 266 | if ($this->_status === self::STATUS_CLOSING) { 267 | $this->destroy(); 268 | } 269 | if ($this->_status === self::STATUS_CLOSED) { 270 | $this->onConnect = null; 271 | } 272 | } 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/Events/Select.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman\Events; 15 | 16 | class Select implements EventInterface 17 | { 18 | /** 19 | * 所有的事件 20 | * @var array 21 | */ 22 | public $_allEvents = array(); 23 | 24 | /** 25 | * 所有信号事件 26 | * @var array 27 | */ 28 | public $_signalEvents = array(); 29 | 30 | /** 31 | * 监听这些描述符的读事件 32 | * @var array 33 | */ 34 | protected $_readFds = array(); 35 | 36 | /** 37 | * 监听这些描述符的写事件 38 | * @var array 39 | */ 40 | protected $_writeFds = array(); 41 | 42 | /** 43 | * 监听这些描述符的带外事件 44 | * @var array 45 | */ 46 | protected $_exceptFds = array(); 47 | 48 | /** 49 | * 任务调度器,最大堆 50 | * {['data':timer_id, 'priority':run_timestamp], ..} 51 | * @var SplPriorityQueue 52 | */ 53 | protected $_scheduler = null; 54 | 55 | /** 56 | * 定时任务 57 | * [[func, args, flag, timer_interval], ..] 58 | * @var array 59 | */ 60 | protected $_task = array(); 61 | 62 | /** 63 | * 定时器id 64 | * @var int 65 | */ 66 | protected $_timerId = 1; 67 | 68 | /** 69 | * select超时时间,单位:微秒 70 | * @var int 71 | */ 72 | protected $_selectTimeout = 100000000; 73 | 74 | /** 75 | * 构造函数 76 | * @return void 77 | */ 78 | public function __construct() 79 | { 80 | // 创建一个管道,放入监听读的描述符集合中,避免空轮询 81 | $this->channel = stream_socket_pair(STREAM_PF_INET, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP); 82 | if($this->channel) 83 | { 84 | stream_set_blocking($this->channel[0], 0); 85 | $this->_readFds[0] = $this->channel[0]; 86 | } 87 | // 初始化优先队列(最大堆) 88 | $this->_scheduler = new \SplPriorityQueue(); 89 | $this->_scheduler->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); 90 | } 91 | 92 | /** 93 | * 添加事件及处理函数 94 | * @see Events\EventInterface::add() 95 | */ 96 | public function add($fd, $flag, $func, $args = array()) 97 | { 98 | switch ($flag) 99 | { 100 | case self::EV_READ: 101 | $fd_key = (int)$fd; 102 | $this->_allEvents[$fd_key][$flag] = array($func, $fd); 103 | $this->_readFds[$fd_key] = $fd; 104 | break; 105 | case self::EV_WRITE: 106 | $fd_key = (int)$fd; 107 | $this->_allEvents[$fd_key][$flag] = array($func, $fd); 108 | $this->_writeFds[$fd_key] = $fd; 109 | break; 110 | case self::EV_EXCEPT: 111 | $fd_key = (int)$fd; 112 | $this->_allEvents[$fd_key][$flag] = array($func, $fd); 113 | $this->_exceptFds[$fd_key] = $fd; 114 | break; 115 | case self::EV_SIGNAL: 116 | throw new \Exception("not support EV_SIGNAL on Windows"); 117 | break; 118 | case self::EV_TIMER: 119 | case self::EV_TIMER_ONCE: 120 | // $fd 为 定时的时间间隔,单位为秒,支持小数,能精确到0.001秒 121 | $run_time = microtime(true)+$fd; 122 | $this->_scheduler->insert($this->_timerId, -$run_time); 123 | $this->_task[$this->_timerId] = array($func, (array)$args, $flag, $fd); 124 | $this->tick(); 125 | return $this->_timerId++; 126 | } 127 | 128 | return true; 129 | } 130 | 131 | /** 132 | * 信号处理函数 133 | * @param int $signal 134 | */ 135 | public function signalHandler($signal) 136 | { 137 | call_user_func_array($this->_signalEvents[$signal][self::EV_SIGNAL][0], array($signal)); 138 | } 139 | 140 | /** 141 | * 删除某个描述符的某类事件的监听 142 | * @see Events\EventInterface::del() 143 | */ 144 | public function del($fd ,$flag) 145 | { 146 | $fd_key = (int)$fd; 147 | switch ($flag) 148 | { 149 | case self::EV_READ: 150 | unset($this->_allEvents[$fd_key][$flag], $this->_readFds[$fd_key]); 151 | if(empty($this->_allEvents[$fd_key])) 152 | { 153 | unset($this->_allEvents[$fd_key]); 154 | } 155 | return true; 156 | case self::EV_WRITE: 157 | unset($this->_allEvents[$fd_key][$flag], $this->_writeFds[$fd_key]); 158 | if(empty($this->_allEvents[$fd_key])) 159 | { 160 | unset($this->_allEvents[$fd_key]); 161 | } 162 | return true; 163 | case self::EV_EXCEPT: 164 | unset($this->_allEvents[$fd_key][$flag], $this->_exceptFds[$fd_key]); 165 | if(empty($this->_allEvents[$fd_key])) 166 | { 167 | unset($this->_allEvents[$fd_key]); 168 | } 169 | return true; 170 | case self::EV_SIGNAL: 171 | break; 172 | case self::EV_TIMER: 173 | case self::EV_TIMER_ONCE; 174 | // $fd_key为要删除的定时器id,即timerId 175 | unset($this->_task[$fd_key]); 176 | return true; 177 | } 178 | return false;; 179 | } 180 | 181 | /** 182 | * 检查是否有可执行的定时任务,有的话执行 183 | * @return void 184 | */ 185 | protected function tick() 186 | { 187 | while(!$this->_scheduler->isEmpty()) 188 | { 189 | $scheduler_data = $this->_scheduler->top(); 190 | $timer_id = $scheduler_data['data']; 191 | $next_run_time = -$scheduler_data['priority']; 192 | $time_now = microtime(true); 193 | $this->_selectTimeout = ($next_run_time - $time_now) * 1000000; 194 | if ($this->_selectTimeout <= 0) { 195 | $this->_scheduler->extract(); 196 | if (!isset($this->_task[$timer_id])) { 197 | continue; 198 | } 199 | // [func, args, flag, timer_interval] 200 | $task_data = $this->_task[$timer_id]; 201 | if ($task_data[2] === self::EV_TIMER) { 202 | $next_run_time = $time_now + $task_data[3]; 203 | $this->_scheduler->insert($timer_id, -$next_run_time); 204 | } 205 | call_user_func_array($task_data[0], $task_data[1]); 206 | if (isset($this->_task[$timer_id]) && $task_data[2] === self::EV_TIMER_ONCE) { 207 | $this->del($timer_id, self::EV_TIMER_ONCE); 208 | } 209 | continue; 210 | } 211 | return; 212 | } 213 | $this->_selectTimeout = 100000000; 214 | } 215 | 216 | /** 217 | * 删除所有定时器 218 | * @return void 219 | */ 220 | public function clearAllTimer() 221 | { 222 | $this->_scheduler = new \SplPriorityQueue(); 223 | $this->_scheduler->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); 224 | $this->_task = array(); 225 | } 226 | 227 | /** 228 | * 主循环 229 | * @see Events\EventInterface::loop() 230 | */ 231 | public function loop() 232 | { 233 | $e = null; 234 | while (1) 235 | { 236 | $read = $this->_readFds; 237 | $write = $this->_writeFds; 238 | $except = $this->_writeFds; 239 | 240 | // 等待可读或者可写事件 241 | stream_select($read, $write, $except, 0, (int)($this->_selectTimeout.'')); 242 | 243 | // 尝试执行定时任务 244 | if(!$this->_scheduler->isEmpty()) 245 | { 246 | $this->tick(); 247 | } 248 | 249 | // 这些描述符可读,执行对应描述符的读回调函数 250 | if($read) 251 | { 252 | foreach($read as $fd) 253 | { 254 | $fd_key = (int) $fd; 255 | if(isset($this->_allEvents[$fd_key][self::EV_READ])) 256 | { 257 | call_user_func_array($this->_allEvents[$fd_key][self::EV_READ][0], array($this->_allEvents[$fd_key][self::EV_READ][1])); 258 | } 259 | } 260 | } 261 | 262 | // 这些描述符可写,执行对应描述符的写回调函数 263 | if($write) 264 | { 265 | foreach($write as $fd) 266 | { 267 | $fd_key = (int) $fd; 268 | if(isset($this->_allEvents[$fd_key][self::EV_WRITE])) 269 | { 270 | call_user_func_array($this->_allEvents[$fd_key][self::EV_WRITE][0], array($this->_allEvents[$fd_key][self::EV_WRITE][1])); 271 | } 272 | } 273 | } 274 | 275 | // 这些描述符可写,执行对应描述符的写回调函数 276 | if($except) 277 | { 278 | foreach($except as $fd) 279 | { 280 | $fd_key = (int) $fd; 281 | if(isset($this->_allEvents[$fd_key][self::EV_EXCEPT])) 282 | { 283 | call_user_func_array($this->_allEvents[$fd_key][self::EV_EXCEPT][0], array($this->_allEvents[$fd_key][self::EV_EXCEPT][1])); 284 | } 285 | } 286 | } 287 | } 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /vendor/workerman/workerman-for-win/WebServer.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman; 15 | 16 | use Workerman\Protocols\Http; 17 | use Workerman\Protocols\HttpCache; 18 | 19 | /** 20 | * WebServer. 21 | */ 22 | class WebServer extends Worker 23 | { 24 | /** 25 | * Mime. 26 | * 27 | * @var string 28 | */ 29 | protected static $defaultMimeType = 'text/html; charset=utf-8'; 30 | 31 | /** 32 | * Virtual host to path mapping. 33 | * 34 | * @var array ['workerman.net'=>'/home', 'www.workerman.net'=>'home/www'] 35 | */ 36 | protected $serverRoot = array(); 37 | 38 | /** 39 | * Mime mapping. 40 | * 41 | * @var array 42 | */ 43 | protected static $mimeTypeMap = array(); 44 | 45 | 46 | /** 47 | * Used to save user OnWorkerStart callback settings. 48 | * 49 | * @var callback 50 | */ 51 | protected $_onWorkerStart = null; 52 | 53 | /** 54 | * Add virtual host. 55 | * 56 | * @param string $domain 57 | * @param string $root_path 58 | * @return void 59 | */ 60 | public function addRoot($domain, $root_path) 61 | { 62 | $this->serverRoot[$domain] = $root_path; 63 | } 64 | 65 | /** 66 | * Construct. 67 | * 68 | * @param string $socket_name 69 | * @param array $context_option 70 | */ 71 | public function __construct($socket_name, $context_option = array()) 72 | { 73 | list(, $address) = explode(':', $socket_name, 2); 74 | parent::__construct('http:' . $address, $context_option); 75 | $this->name = 'WebServer'; 76 | } 77 | 78 | /** 79 | * Run webserver instance. 80 | * 81 | * @see Workerman.Worker::run() 82 | */ 83 | public function run() 84 | { 85 | $this->_onWorkerStart = $this->onWorkerStart; 86 | $this->onWorkerStart = array($this, 'onWorkerStart'); 87 | $this->onMessage = array($this, 'onMessage'); 88 | parent::run(); 89 | } 90 | 91 | /** 92 | * Emit when process start. 93 | * 94 | * @throws \Exception 95 | */ 96 | public function onWorkerStart() 97 | { 98 | if (empty($this->serverRoot)) { 99 | throw new \Exception('server root not set, please use WebServer::addRoot($domain, $root_path) to set server root path'); 100 | } 101 | // Init HttpCache. 102 | HttpCache::init(); 103 | // Init mimeMap. 104 | $this->initMimeTypeMap(); 105 | 106 | // Try to emit onWorkerStart callback. 107 | if ($this->_onWorkerStart) { 108 | try { 109 | call_user_func($this->_onWorkerStart, $this); 110 | } catch (\Exception $e) { 111 | self::log($e); 112 | exit(250); 113 | } catch (\Error $e) { 114 | self::log($e); 115 | exit(250); 116 | } 117 | } 118 | } 119 | 120 | /** 121 | * Init mime map. 122 | * 123 | * @return void 124 | */ 125 | public function initMimeTypeMap() 126 | { 127 | $mime_file = Http::getMimeTypesFile(); 128 | if (!is_file($mime_file)) { 129 | $this->log("$mime_file mime.type file not fond"); 130 | return; 131 | } 132 | $items = file($mime_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); 133 | if (!is_array($items)) { 134 | $this->log("get $mime_file mime.type content fail"); 135 | return; 136 | } 137 | foreach ($items as $content) { 138 | if (preg_match("/\s*(\S+)\s+(\S.+)/", $content, $match)) { 139 | $mime_type = $match[1]; 140 | $workerman_file_extension_var = $match[2]; 141 | $workerman_file_extension_array = explode(' ', substr($workerman_file_extension_var, 0, -1)); 142 | foreach ($workerman_file_extension_array as $workerman_file_extension) { 143 | self::$mimeTypeMap[$workerman_file_extension] = $mime_type; 144 | } 145 | } 146 | } 147 | } 148 | 149 | /** 150 | * Emit when http message coming. 151 | * 152 | * @param Connection\TcpConnection $connection 153 | * @return void 154 | */ 155 | public function onMessage($connection) 156 | { 157 | // REQUEST_URI. 158 | $workerman_url_info = parse_url($_SERVER['REQUEST_URI']); 159 | if (!$workerman_url_info) { 160 | Http::header('HTTP/1.1 400 Bad Request'); 161 | $connection->close('

400 Bad Request

'); 162 | return; 163 | } 164 | 165 | $workerman_path = isset($workerman_url_info['path']) ? $workerman_url_info['path'] : '/'; 166 | 167 | $workerman_path_info = pathinfo($workerman_path); 168 | $workerman_file_extension = isset($workerman_path_info['extension']) ? $workerman_path_info['extension'] : ''; 169 | if ($workerman_file_extension === '') { 170 | $workerman_path = ($len = strlen($workerman_path)) && $workerman_path[$len - 1] === '/' ? $workerman_path . 'index.php' : $workerman_path . '/index.php'; 171 | $workerman_file_extension = 'php'; 172 | } 173 | 174 | $workerman_root_dir = isset($this->serverRoot[$_SERVER['SERVER_NAME']]) ? $this->serverRoot[$_SERVER['SERVER_NAME']] : current($this->serverRoot); 175 | 176 | $workerman_file = "$workerman_root_dir/$workerman_path"; 177 | 178 | if ($workerman_file_extension === 'php' && !is_file($workerman_file)) { 179 | $workerman_file = "$workerman_root_dir/index.php"; 180 | if (!is_file($workerman_file)) { 181 | $workerman_file = "$workerman_root_dir/index.html"; 182 | $workerman_file_extension = 'html'; 183 | } 184 | } 185 | 186 | // File exsits. 187 | if (is_file($workerman_file)) { 188 | // Security check. 189 | if ((!($workerman_request_realpath = realpath($workerman_file)) || !($workerman_root_dir_realpath = realpath($workerman_root_dir))) || 0 !== strpos($workerman_request_realpath, 190 | $workerman_root_dir_realpath) 191 | ) { 192 | Http::header('HTTP/1.1 400 Bad Request'); 193 | $connection->close('

400 Bad Request

'); 194 | return; 195 | } 196 | 197 | $workerman_file = realpath($workerman_file); 198 | 199 | // Request php file. 200 | if ($workerman_file_extension === 'php') { 201 | $workerman_cwd = getcwd(); 202 | chdir($workerman_root_dir); 203 | ini_set('display_errors', 'off'); 204 | ob_start(); 205 | // Try to include php file. 206 | try { 207 | // $_SERVER. 208 | $_SERVER['REMOTE_ADDR'] = $connection->getRemoteIp(); 209 | $_SERVER['REMOTE_PORT'] = $connection->getRemotePort(); 210 | include $workerman_file; 211 | } catch (\Exception $e) { 212 | // Jump_exit? 213 | if ($e->getMessage() != 'jump_exit') { 214 | echo $e; 215 | } 216 | } 217 | $content = ob_get_clean(); 218 | ini_set('display_errors', 'on'); 219 | $connection->close($content); 220 | chdir($workerman_cwd); 221 | return; 222 | } 223 | 224 | // Send file to client. 225 | return self::sendFile($connection, $workerman_file); 226 | } else { 227 | // 404 228 | Http::header("HTTP/1.1 404 Not Found"); 229 | $connection->close('404 File not found

404 Not Found

'); 230 | return; 231 | } 232 | } 233 | 234 | public static function sendFile($connection, $file_name) 235 | { 236 | // Check 304. 237 | $info = stat($file_name); 238 | $modified_time = $info ? date('D, d M Y H:i:s', $info['mtime']) . ' GMT' : ''; 239 | if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $info) { 240 | // Http 304. 241 | if ($modified_time === $_SERVER['HTTP_IF_MODIFIED_SINCE']) { 242 | // 304 243 | Http::header('HTTP/1.1 304 Not Modified'); 244 | // Send nothing but http headers.. 245 | $connection->close(''); 246 | return; 247 | } 248 | } 249 | 250 | // Http header. 251 | if ($modified_time) { 252 | $modified_time = "Last-Modified: $modified_time\r\n"; 253 | } 254 | $file_size = filesize($file_name); 255 | $extension = pathinfo($file_name, PATHINFO_EXTENSION); 256 | $content_type = isset(self::$mimeTypeMap[$extension]) ? self::$mimeTypeMap[$extension] : self::$defaultMimeType; 257 | $header = "HTTP/1.1 200 OK\r\n"; 258 | $header .= "Content-Type: $content_type\r\n"; 259 | $header .= "Connection: keep-alive\r\n"; 260 | $header .= $modified_time; 261 | $header .= "Content-Length: $file_size\r\n\r\n"; 262 | $trunk_limit_size = 1024*1024; 263 | if ($file_size < $trunk_limit_size) { 264 | return $connection->send($header.file_get_contents($file_name), true); 265 | } 266 | $connection->send($header, true); 267 | 268 | // Read file content from disk piece by piece and send to client. 269 | $connection->fileHandler = fopen($file_name, 'r'); 270 | $do_write = function()use($connection) 271 | { 272 | // Send buffer not full. 273 | while(empty($connection->bufferFull)) 274 | { 275 | // Read from disk. 276 | $buffer = fread($connection->fileHandler, 8192); 277 | // Read eof. 278 | if($buffer === '' || $buffer === false) 279 | { 280 | return; 281 | } 282 | $connection->send($buffer, true); 283 | } 284 | }; 285 | // Send buffer full. 286 | $connection->onBufferFull = function($connection) 287 | { 288 | $connection->bufferFull = true; 289 | }; 290 | // Send buffer drain. 291 | $connection->onBufferDrain = function($connection)use($do_write) 292 | { 293 | $connection->bufferFull = false; 294 | $do_write(); 295 | }; 296 | $do_write(); 297 | } 298 | } 299 | -------------------------------------------------------------------------------- /vendor/workerman/workerman/WebServer.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright walkor 11 | * @link http://www.workerman.net/ 12 | * @license http://www.opensource.org/licenses/mit-license.php MIT License 13 | */ 14 | namespace Workerman; 15 | 16 | use Workerman\Protocols\Http; 17 | use Workerman\Protocols\HttpCache; 18 | 19 | /** 20 | * WebServer. 21 | */ 22 | class WebServer extends Worker 23 | { 24 | /** 25 | * Virtual host to path mapping. 26 | * 27 | * @var array ['workerman.net'=>'/home', 'www.workerman.net'=>'home/www'] 28 | */ 29 | protected $serverRoot = array(); 30 | 31 | /** 32 | * Mime mapping. 33 | * 34 | * @var array 35 | */ 36 | protected static $mimeTypeMap = array(); 37 | 38 | 39 | /** 40 | * Used to save user OnWorkerStart callback settings. 41 | * 42 | * @var callback 43 | */ 44 | protected $_onWorkerStart = null; 45 | 46 | /** 47 | * Add virtual host. 48 | * 49 | * @param string $domain 50 | * @param string $root_path 51 | * @return void 52 | */ 53 | public function addRoot($domain, $root_path) 54 | { 55 | $this->serverRoot[$domain] = $root_path; 56 | } 57 | 58 | /** 59 | * Construct. 60 | * 61 | * @param string $socket_name 62 | * @param array $context_option 63 | */ 64 | public function __construct($socket_name, $context_option = array()) 65 | { 66 | list(, $address) = explode(':', $socket_name, 2); 67 | parent::__construct('http:' . $address, $context_option); 68 | $this->name = 'WebServer'; 69 | } 70 | 71 | /** 72 | * Run webserver instance. 73 | * 74 | * @see Workerman.Worker::run() 75 | */ 76 | public function run() 77 | { 78 | $this->_onWorkerStart = $this->onWorkerStart; 79 | $this->onWorkerStart = array($this, 'onWorkerStart'); 80 | $this->onMessage = array($this, 'onMessage'); 81 | parent::run(); 82 | } 83 | 84 | /** 85 | * Emit when process start. 86 | * 87 | * @throws \Exception 88 | */ 89 | public function onWorkerStart() 90 | { 91 | if (empty($this->serverRoot)) { 92 | throw new \Exception('server root not set, please use WebServer::addRoot($domain, $root_path) to set server root path'); 93 | } 94 | // Init HttpCache. 95 | HttpCache::init(); 96 | // Init mimeMap. 97 | $this->initMimeTypeMap(); 98 | 99 | // Try to emit onWorkerStart callback. 100 | if ($this->_onWorkerStart) { 101 | try { 102 | call_user_func($this->_onWorkerStart, $this); 103 | } catch (\Exception $e) { 104 | self::log($e); 105 | exit(250); 106 | } catch (\Error $e) { 107 | self::log($e); 108 | exit(250); 109 | } 110 | } 111 | } 112 | 113 | /** 114 | * Init mime map. 115 | * 116 | * @return void 117 | */ 118 | public function initMimeTypeMap() 119 | { 120 | $mime_file = Http::getMimeTypesFile(); 121 | if (!is_file($mime_file)) { 122 | $this->log("$mime_file mime.type file not fond"); 123 | return; 124 | } 125 | $items = file($mime_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); 126 | if (!is_array($items)) { 127 | $this->log("get $mime_file mime.type content fail"); 128 | return; 129 | } 130 | foreach ($items as $content) { 131 | if (preg_match("/\s*(\S+)\s+(\S.+)/", $content, $match)) { 132 | $mime_type = $match[1]; 133 | $workerman_file_extension_var = $match[2]; 134 | $workerman_file_extension_array = explode(' ', substr($workerman_file_extension_var, 0, -1)); 135 | foreach ($workerman_file_extension_array as $workerman_file_extension) { 136 | self::$mimeTypeMap[$workerman_file_extension] = $mime_type; 137 | } 138 | } 139 | } 140 | } 141 | 142 | /** 143 | * Emit when http message coming. 144 | * 145 | * @param Connection\TcpConnection $connection 146 | * @return void 147 | */ 148 | public function onMessage($connection) 149 | { 150 | // REQUEST_URI. 151 | $workerman_url_info = parse_url($_SERVER['REQUEST_URI']); 152 | if (!$workerman_url_info) { 153 | Http::header('HTTP/1.1 400 Bad Request'); 154 | $connection->close('

400 Bad Request

'); 155 | return; 156 | } 157 | 158 | $workerman_path = isset($workerman_url_info['path']) ? $workerman_url_info['path'] : '/'; 159 | 160 | $workerman_path_info = pathinfo($workerman_path); 161 | $workerman_file_extension = isset($workerman_path_info['extension']) ? $workerman_path_info['extension'] : ''; 162 | if ($workerman_file_extension === '') { 163 | $workerman_path = ($len = strlen($workerman_path)) && $workerman_path[$len - 1] === '/' ? $workerman_path . 'index.php' : $workerman_path . '/index.php'; 164 | $workerman_file_extension = 'php'; 165 | } 166 | 167 | $workerman_root_dir = isset($this->serverRoot[$_SERVER['SERVER_NAME']]) ? $this->serverRoot[$_SERVER['SERVER_NAME']] : current($this->serverRoot); 168 | 169 | $workerman_file = "$workerman_root_dir/$workerman_path"; 170 | 171 | if ($workerman_file_extension === 'php' && !is_file($workerman_file)) { 172 | $workerman_file = "$workerman_root_dir/index.php"; 173 | if (!is_file($workerman_file)) { 174 | $workerman_file = "$workerman_root_dir/index.html"; 175 | $workerman_file_extension = 'html'; 176 | } 177 | } 178 | 179 | // File exsits. 180 | if (is_file($workerman_file)) { 181 | // Security check. 182 | if ((!($workerman_request_realpath = realpath($workerman_file)) || !($workerman_root_dir_realpath = realpath($workerman_root_dir))) || 0 !== strpos($workerman_request_realpath, 183 | $workerman_root_dir_realpath) 184 | ) { 185 | Http::header('HTTP/1.1 400 Bad Request'); 186 | $connection->close('

400 Bad Request

'); 187 | return; 188 | } 189 | 190 | $workerman_file = realpath($workerman_file); 191 | 192 | // Request php file. 193 | if ($workerman_file_extension === 'php') { 194 | $workerman_cwd = getcwd(); 195 | chdir($workerman_root_dir); 196 | ini_set('display_errors', 'off'); 197 | ob_start(); 198 | // Try to include php file. 199 | try { 200 | // $_SERVER. 201 | $_SERVER['REMOTE_ADDR'] = $connection->getRemoteIp(); 202 | $_SERVER['REMOTE_PORT'] = $connection->getRemotePort(); 203 | include $workerman_file; 204 | } catch (\Exception $e) { 205 | // Jump_exit? 206 | if ($e->getMessage() != 'jump_exit') { 207 | echo $e; 208 | } 209 | } 210 | $content = ob_get_clean(); 211 | ini_set('display_errors', 'on'); 212 | if (strtolower($_SERVER['HTTP_CONNECTION']) === "keep-alive") { 213 | $connection->send($content); 214 | } else { 215 | $connection->close($content); 216 | } 217 | chdir($workerman_cwd); 218 | return; 219 | } 220 | 221 | // Send file to client. 222 | return self::sendFile($connection, $workerman_file); 223 | } else { 224 | // 404 225 | Http::header("HTTP/1.1 404 Not Found"); 226 | $connection->close('404 File not found

404 Not Found

'); 227 | return; 228 | } 229 | } 230 | 231 | public static function sendFile($connection, $file_path) 232 | { 233 | // Check 304. 234 | $info = stat($file_path); 235 | $modified_time = $info ? date('D, d M Y H:i:s', $info['mtime']) . ' GMT' : ''; 236 | if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $info) { 237 | // Http 304. 238 | if ($modified_time === $_SERVER['HTTP_IF_MODIFIED_SINCE']) { 239 | // 304 240 | Http::header('HTTP/1.1 304 Not Modified'); 241 | // Send nothing but http headers.. 242 | $connection->close(''); 243 | return; 244 | } 245 | } 246 | 247 | // Http header. 248 | if ($modified_time) { 249 | $modified_time = "Last-Modified: $modified_time\r\n"; 250 | } 251 | $file_size = filesize($file_path); 252 | $file_info = pathinfo($file_path); 253 | $extension = isset($file_info['extension']) ? $file_info['extension'] : ''; 254 | $file_name = isset($file_info['filename']) ? $file_info['filename'] : ''; 255 | $header = "HTTP/1.1 200 OK\r\n"; 256 | if (isset(self::$mimeTypeMap[$extension])) { 257 | $header .= "Content-Type: " . self::$mimeTypeMap[$extension] . "\r\n"; 258 | } else { 259 | $header .= "Content-Type: application/octet-stream\r\n"; 260 | $header .= "Content-Disposition: attachment; filename=\"$file_name\"\r\n"; 261 | } 262 | $header .= "Connection: keep-alive\r\n"; 263 | $header .= $modified_time; 264 | $header .= "Content-Length: $file_size\r\n\r\n"; 265 | $trunk_limit_size = 1024*1024; 266 | if ($file_size < $trunk_limit_size) { 267 | return $connection->send($header.file_get_contents($file_path), true); 268 | } 269 | $connection->send($header, true); 270 | 271 | // Read file content from disk piece by piece and send to client. 272 | $connection->fileHandler = fopen($file_path, 'r'); 273 | $do_write = function()use($connection) 274 | { 275 | // Send buffer not full. 276 | while(empty($connection->bufferFull)) 277 | { 278 | // Read from disk. 279 | $buffer = fread($connection->fileHandler, 8192); 280 | // Read eof. 281 | if($buffer === '' || $buffer === false) 282 | { 283 | return; 284 | } 285 | $connection->send($buffer, true); 286 | } 287 | }; 288 | // Send buffer full. 289 | $connection->onBufferFull = function($connection) 290 | { 291 | $connection->bufferFull = true; 292 | }; 293 | // Send buffer drain. 294 | $connection->onBufferDrain = function($connection)use($do_write) 295 | { 296 | $connection->bufferFull = false; 297 | $do_write(); 298 | }; 299 | $do_write(); 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /vendor/topthink/think-worker/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------