├── workerman-chat-for-win ├── vendor │ ├── workerman │ │ ├── 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 │ │ │ │ ├── React │ │ │ │ │ ├── ExtEventLoop.php │ │ │ │ │ ├── LibEventLoop.php │ │ │ │ │ └── StreamSelectLoop.php │ │ │ │ ├── Ev.php │ │ │ │ ├── Event.php │ │ │ │ ├── Libevent.php │ │ │ │ ├── React.php │ │ │ │ └── Select.php │ │ │ ├── Connection │ │ │ │ ├── ConnectionInterface.php │ │ │ │ ├── UdpConnection.php │ │ │ │ ├── AsyncUdpConnection.php │ │ │ │ └── AsyncTcpConnection.php │ │ │ ├── Autoloader.php │ │ │ └── WebServer.php │ │ └── gateway-worker-for-win │ │ │ ├── composer.json │ │ │ ├── README.md │ │ │ ├── MIT-LICENSE.txt │ │ │ └── src │ │ │ ├── Lib │ │ │ ├── Db.php │ │ │ └── Context.php │ │ │ ├── Protocols │ │ │ └── GatewayProtocol.php │ │ │ └── Register.php │ ├── autoload.php │ └── composer │ │ ├── autoload_classmap.php │ │ ├── autoload_namespaces.php │ │ ├── autoload_psr4.php │ │ ├── LICENSE │ │ ├── autoload_static.php │ │ ├── autoload_real.php │ │ ├── installed.json │ │ └── ClassLoader.php ├── .gitignore ├── Applications │ └── Chat │ │ ├── Web │ │ ├── swf │ │ │ └── WebSocketMain.swf │ │ ├── img │ │ │ └── workerman-todpole.png │ │ ├── css │ │ │ ├── style.css │ │ │ └── bootstrap-theme.min.css │ │ ├── index.php │ │ └── js │ │ │ ├── swfobject.js │ │ │ └── web_socket.js │ │ ├── start_register.php │ │ ├── start_businessworker.php │ │ ├── start_web.php │ │ ├── start_gateway.php │ │ └── Events.php ├── start_for_win.bat ├── composer.json ├── README.md └── MIT-LICENSE.txt ├── .project └── test └── index.html /workerman-chat-for-win/vendor/workerman/workerman-for-win/.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .buildpath 3 | .settings/org.eclipse.php.core.prefs -------------------------------------------------------------------------------- /workerman-chat-for-win/.gitignore: -------------------------------------------------------------------------------- 1 | .buildpath 2 | .settings/org.eclipse.php.core.prefs 3 | Workerman/.settings/org.eclipse.php.core.prefs 4 | .project -------------------------------------------------------------------------------- /workerman-chat-for-win/Applications/Chat/Web/swf/WebSocketMain.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wscats/workerman/master/workerman-chat-for-win/Applications/Chat/Web/swf/WebSocketMain.swf -------------------------------------------------------------------------------- /workerman-chat-for-win/Applications/Chat/Web/img/workerman-todpole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wscats/workerman/master/workerman-chat-for-win/Applications/Chat/Web/img/workerman-todpole.png -------------------------------------------------------------------------------- /workerman-chat-for-win/start_for_win.bat: -------------------------------------------------------------------------------- 1 | php Applications\Chat\start_register.php Applications\Chat\start_web.php Applications\Chat\start_gateway.php Applications\Chat\start_businessworker.php 2 | pause -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/autoload.php: -------------------------------------------------------------------------------- 1 | =3.0.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/composer/autoload_psr4.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/workerman/workerman-for-win'), 10 | 'GatewayWorker\\' => array($vendorDir . '/workerman/gateway-worker-for-win/src'), 11 | ); 12 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/workerman/gateway-worker-for-win/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "workerman/gateway-worker-for-win", 3 | "keywords": ["distributed","communication"], 4 | "homepage": "http://www.workerman.net", 5 | "license" : "MIT", 6 | "require": { 7 | "workerman/workerman-for-win" : ">=3.1.8" 8 | }, 9 | "autoload": { 10 | "psr-4": {"GatewayWorker\\": "./src"} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | workerman 4 | 5 | 6 | 7 | 8 | 9 | com.aptana.ide.core.unifiedBuilder 10 | 11 | 12 | 13 | 14 | 15 | com.aptana.projects.webnature 16 | 17 | 18 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/Applications/Chat/start_register.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 | use \Workerman\Worker; 15 | use \GatewayWorker\Register; 16 | 17 | // 自动加载类 18 | require_once __DIR__ . '/../../vendor/autoload.php'; 19 | 20 | // register 服务必须是text协议 21 | $register = new Register('text://0.0.0.0:1236'); 22 | 23 | // 如果不是在根目录启动,则运行runAll方法 24 | if(!defined('GLOBAL_START')) 25 | { 26 | Worker::runAll(); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /workerman-chat-for-win/README.md: -------------------------------------------------------------------------------- 1 | workerman-chat 2 | ======= 3 | 基于workerman的GatewayWorker框架开发的一款高性能支持分布式部署的聊天室系统。 4 | 5 | GatewayWorker框架文档:http://www.workerman.net/gatewaydoc/ 6 | 7 | 特性 8 | ====== 9 | * 使用websocket协议 10 | * 多浏览器支持(浏览器支持html5或者flash任意一种即可) 11 | * 多房间支持 12 | * 私聊支持 13 | * 掉线自动重连 14 | * 支持多服务器部署 15 | * 业务逻辑全部在一个文件中,快速入门可以参考这个文件[Applications/Chat/Event.php](https://github.com/walkor/workerman-chat-for-win/blob/master/Applications/Chat/Event.php) 16 | 17 | 安装 18 | ===== 19 | 20 | 下载 或者 clone 代码到本地 21 | 22 | 进入到代码目录,运行 ```composer install``` 安装 23 | 24 | 要求 php>=5.3.3 并且配置好了php环境变量 25 | 26 | windows系统php环境配置参考 http://www.workerman.net/windows 27 | 28 | 启动停止 29 | ===== 30 | 启动 31 | 32 | 双击start_for_win.bat 33 | 34 | 停止 35 | 36 | ctrl+c 停止 37 | 38 | 注意: 39 | ======= 40 | windows系统下无法使用 stop reload status 等命令 41 | 42 | 测试 43 | ======= 44 | 浏览器访问 http://服务器ip或域:55151,例如http://127.0.0.1:55151 45 | 46 | [更多请访问www.workerman.net](http://www.workerman.net/workerman-chat) 47 | -------------------------------------------------------------------------------- /workerman-chat-for-win/Applications/Chat/start_businessworker.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 | use \Workerman\Worker; 15 | use \GatewayWorker\BusinessWorker; 16 | use \Workerman\Autoloader; 17 | 18 | // 自动加载类 19 | require_once __DIR__ . '/../../vendor/autoload.php'; 20 | 21 | // bussinessWorker 进程 22 | $worker = new BusinessWorker(); 23 | // worker名称 24 | $worker->name = 'ChatBusinessWorker'; 25 | // bussinessWorker进程数量 26 | $worker->count = 4; 27 | // 服务注册地址 28 | $worker->registerAddress = '127.0.0.1:1236'; 29 | 30 | // 如果不是在根目录启动,则运行runAll方法 31 | if(!defined('GLOBAL_START')) 32 | { 33 | Worker::runAll(); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | } -------------------------------------------------------------------------------- /workerman-chat-for-win/Applications/Chat/start_web.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 | use \Workerman\Worker; 15 | use \Workerman\WebServer; 16 | use \GatewayWorker\Gateway; 17 | use \GatewayWorker\BusinessWorker; 18 | use \Workerman\Autoloader; 19 | 20 | 21 | // 自动加载类 22 | require_once __DIR__ . '/../../vendor/autoload.php'; 23 | 24 | // WebServer 25 | $web = new WebServer("http://0.0.0.0:55151"); 26 | // WebServer数量 27 | $web->count = 2; 28 | // 设置站点根目录 29 | $web->addRoot('www.your_domain.com', __DIR__.'/Web'); 30 | 31 | // 如果不是在根目录启动,则运行runAll方法 32 | if(!defined('GLOBAL_START')) 33 | { 34 | Worker::runAll(); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/workerman/gateway-worker-for-win/README.md: -------------------------------------------------------------------------------- 1 | GatewayWorker windows 版本 2 | ================= 3 | 4 | GatewayWorker基于[Workerman](https://github.com/walkor/Workerman)开发的一个项目框架,用于快速开发长连接应用,例如app推送服务端、即时IM服务端、游戏服务端、物联网、智能家居等等。 5 | 6 | GatewayWorker使用经典的Gateway和Worker进程模型。Gateway进程负责维持客户端连接,并转发客户端的数据给Worker进程处理;Worker进程负责处理实际的业务逻辑,并将结果推送给对应的客户端。Gateway服务和Worker服务可以分开部署在不同的服务器上,实现分布式集群。 7 | 8 | GatewayWorker提供非常方便的API,可以全局广播数据、可以向某个群体广播数据、也可以向某个特定客户端推送数据。配合Workerman的定时器,也可以定时推送数据。 9 | 10 | 下载安装 11 | ===== 12 | 本仓库只是GatewayWorker的核心仓库, 13 | 完整的版本[点击这里下载](http://www.workerman.net/download/GatewayWorker-for-win.zip) 14 | 15 | 16 | 手册 17 | ======= 18 | http://www.workerman.net/gatewaydoc/ 19 | 20 | 使用GatewayWorker-for-win开发的项目 21 | ======= 22 | ## [tadpole](http://kedou.workerman.net/) 23 | [Live demo](http://kedou.workerman.net/) 24 | [Source code](https://github.com/walkor/workerman) 25 | ![workerman-todpole](http://www.workerman.net/img/workerman-todpole.png) 26 | 27 | ## [chat room](http://chat.workerman.net/) 28 | [Live demo](http://chat.workerman.net/) 29 | [Source code](https://github.com/walkor/workerman-chat) 30 | ![workerman-chat](http://www.workerman.net/img/workerman-chat.png) 31 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/composer/autoload_static.php: -------------------------------------------------------------------------------- 1 | 11 | array ( 12 | 'Workerman\\' => 10, 13 | ), 14 | 'G' => 15 | array ( 16 | 'GatewayWorker\\' => 14, 17 | ), 18 | ); 19 | 20 | public static $prefixDirsPsr4 = array ( 21 | 'Workerman\\' => 22 | array ( 23 | 0 => __DIR__ . '/..' . '/workerman/workerman-for-win', 24 | ), 25 | 'GatewayWorker\\' => 26 | array ( 27 | 0 => __DIR__ . '/..' . '/workerman/gateway-worker-for-win/src', 28 | ), 29 | ); 30 | 31 | public static function getInitializer(ClassLoader $loader) 32 | { 33 | return \Closure::bind(function () use ($loader) { 34 | $loader->prefixLengthsPsr4 = ComposerStaticInit7b551a701099075b5cc25b17c80e6f82::$prefixLengthsPsr4; 35 | $loader->prefixDirsPsr4 = ComposerStaticInit7b551a701099075b5cc25b17c80e6f82::$prefixDirsPsr4; 36 | 37 | }, null, ClassLoader::class); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /workerman-chat-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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/workerman/gateway-worker-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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | * 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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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\ComposerStaticInit7b551a701099075b5cc25b17c80e6f82::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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/Applications/Chat/start_gateway.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 | use \Workerman\Worker; 15 | use \GatewayWorker\Gateway; 16 | use \Workerman\Autoloader; 17 | 18 | // 自动加载类 19 | require_once __DIR__ . '/../../vendor/autoload.php'; 20 | 21 | // gateway 进程 22 | $gateway = new Gateway("Websocket://0.0.0.0:7272"); 23 | // 设置名称,方便status时查看 24 | $gateway->name = 'ChatGateway'; 25 | // 设置进程数,gateway进程数建议与cpu核数相同 26 | $gateway->count = 4; 27 | // 分布式部署时请设置成内网ip(非127.0.0.1) 28 | $gateway->lanIp = '127.0.0.1'; 29 | // 内部通讯起始端口,假如$gateway->count=4,起始端口为4000 30 | // 则一般会使用4000 4001 4002 4003 4个端口作为内部通讯端口 31 | $gateway->startPort = 2300; 32 | // 心跳间隔 33 | $gateway->pingInterval = 10; 34 | // 心跳数据 35 | $gateway->pingData = '{"type":"ping"}'; 36 | // 服务注册地址 37 | $gateway->registerAddress = '127.0.0.1:1236'; 38 | 39 | /* 40 | // 当客户端连接上来时,设置连接的onWebSocketConnect,即在websocket握手时的回调 41 | $gateway->onConnect = function($connection) 42 | { 43 | $connection->onWebSocketConnect = function($connection , $http_header) 44 | { 45 | // 可以在这里判断连接来源是否合法,不合法就关掉连接 46 | // $_SERVER['HTTP_ORIGIN']标识来自哪个站点的页面发起的websocket链接 47 | if($_SERVER['HTTP_ORIGIN'] != 'http://chat.workerman.net') 48 | { 49 | $connection->close(); 50 | } 51 | // onWebSocketConnect 里面$_GET $_SERVER是可用的 52 | // var_dump($_GET, $_SERVER); 53 | }; 54 | }; 55 | */ 56 | 57 | // 如果不是在根目录启动,则运行runAll方法 58 | if(!defined('GLOBAL_START')) 59 | { 60 | Worker::runAll(); 61 | } 62 | 63 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/workerman/workerman-for-win/Events/React/ExtEventLoop.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\React; 15 | 16 | /** 17 | * Class ExtEventLoop 18 | * @package Workerman\Events\React 19 | */ 20 | class ExtEventLoop extends \React\EventLoop\ExtEventLoop 21 | { 22 | /** 23 | * Event base. 24 | * 25 | * @var EventBase 26 | */ 27 | protected $_eventBase = null; 28 | 29 | /** 30 | * All signal Event instances. 31 | * 32 | * @var array 33 | */ 34 | protected $_signalEvents = array(); 35 | 36 | /** 37 | * Construct 38 | */ 39 | public function __construct() 40 | { 41 | parent::__construct(); 42 | $class = new \ReflectionClass('\React\EventLoop\ExtEventLoop'); 43 | $property = $class->getProperty('eventBase'); 44 | $property->setAccessible(true); 45 | $this->_eventBase = $property->getValue($this); 46 | } 47 | 48 | /** 49 | * Add signal handler. 50 | * 51 | * @param $signal 52 | * @param $callback 53 | * @return bool 54 | */ 55 | public function addSignal($signal, $callback) 56 | { 57 | $event = \Event::signal($this->_eventBase, $signal, $callback); 58 | if (!$event||!$event->add()) { 59 | return false; 60 | } 61 | $this->_signalEvents[$signal] = $event; 62 | } 63 | 64 | /** 65 | * Remove signal handler. 66 | * 67 | * @param $signal 68 | */ 69 | public function removeSignal($signal) 70 | { 71 | if (isset($this->_signalEvents[$signal])) { 72 | $this->_signalEvents[$signal]->del(); 73 | unset($this->_signalEvents[$signal]); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/workerman/workerman-for-win/Events/React/LibEventLoop.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\React; 15 | 16 | /** 17 | * Class LibEventLoop 18 | * @package Workerman\Events\React 19 | */ 20 | class LibEventLoop extends \React\EventLoop\LibEventLoop 21 | { 22 | /** 23 | * Event base. 24 | * 25 | * @var event_base resource 26 | */ 27 | protected $_eventBase = null; 28 | 29 | /** 30 | * All signal Event instances. 31 | * 32 | * @var array 33 | */ 34 | protected $_signalEvents = array(); 35 | 36 | /** 37 | * Construct. 38 | */ 39 | public function __construct() 40 | { 41 | parent::__construct(); 42 | $class = new \ReflectionClass('\React\EventLoop\LibEventLoop'); 43 | $property = $class->getProperty('eventBase'); 44 | $property->setAccessible(true); 45 | $this->_eventBase = $property->getValue($this); 46 | } 47 | 48 | /** 49 | * Add signal handler. 50 | * 51 | * @param $signal 52 | * @param $callback 53 | * @return bool 54 | */ 55 | public function addSignal($signal, $callback) 56 | { 57 | $event = event_new(); 58 | $this->_signalEvents[$signal] = $event; 59 | event_set($event, $signal, EV_SIGNAL | EV_PERSIST, $callback); 60 | event_base_set($event, $this->_eventBase); 61 | event_add($event); 62 | } 63 | 64 | /** 65 | * Remove signal handler. 66 | * 67 | * @param $signal 68 | */ 69 | public function removeSignal($signal) 70 | { 71 | if (isset($this->_signalEvents[$signal])) { 72 | $event = $this->_signalEvents[$signal]; 73 | event_del($event); 74 | unset($this->_signalEvents[$signal]); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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'); -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/workerman/gateway-worker-for-win/src/Lib/Db.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 GatewayWorker\Lib; 15 | 16 | use Config\Db as DbConfig; 17 | use Exception; 18 | 19 | /** 20 | * 数据库类 21 | */ 22 | class Db 23 | { 24 | /** 25 | * 实例数组 26 | * 27 | * @var array 28 | */ 29 | protected static $instance = array(); 30 | 31 | /** 32 | * 获取实例 33 | * 34 | * @param string $config_name 35 | * @return DbConnection 36 | * @throws Exception 37 | */ 38 | public static function instance($config_name) 39 | { 40 | echo "GatewayWorker/Lib/DbConnection has been deprecated. Plese use Workerman/MySQL. 41 | See http://doc3.workerman.net/component/workerman-mysql.html for detail\n"; 42 | if (!isset(DbConfig::$$config_name)) { 43 | echo "\\Config\\Db::$config_name not set\n"; 44 | throw new Exception("\\Config\\Db::$config_name not set\n"); 45 | } 46 | 47 | if (empty(self::$instance[$config_name])) { 48 | $config = DbConfig::$$config_name; 49 | self::$instance[$config_name] = new DbConnection($config['host'], $config['port'], 50 | $config['user'], $config['password'], $config['dbname']); 51 | } 52 | return self::$instance[$config_name]; 53 | } 54 | 55 | /** 56 | * 关闭数据库实例 57 | * 58 | * @param string $config_name 59 | */ 60 | public static function close($config_name) 61 | { 62 | if (isset(self::$instance[$config_name])) { 63 | self::$instance[$config_name]->closeConnection(); 64 | self::$instance[$config_name] = null; 65 | } 66 | } 67 | 68 | /** 69 | * 关闭所有数据库实例 70 | */ 71 | public static function closeAll() 72 | { 73 | foreach (self::$instance as $connection) { 74 | $connection->closeConnection(); 75 | } 76 | self::$instance = array(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/workerman/workerman-for-win/Events/React/StreamSelectLoop.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\React; 15 | 16 | /** 17 | * Class StreamSelectLoop 18 | * @package Workerman\Events\React 19 | */ 20 | class StreamSelectLoop extends \React\EventLoop\StreamSelectLoop 21 | { 22 | /** 23 | * Add signal handler. 24 | * 25 | * @param $signal 26 | * @param $callback 27 | * @return bool 28 | */ 29 | public function addSignal($signal, $callback) 30 | { 31 | if(PHP_EOL !== "\r\n") { 32 | pcntl_signal($signal, $callback); 33 | } 34 | } 35 | 36 | /** 37 | * Remove signal handler. 38 | * 39 | * @param $signal 40 | */ 41 | public function removeSignal($signal) 42 | { 43 | if(PHP_EOL !== "\r\n") { 44 | pcntl_signal($signal, SIG_IGN); 45 | } 46 | } 47 | 48 | /** 49 | * Emulate a stream_select() implementation that does not break when passed 50 | * empty stream arrays. 51 | * 52 | * @param array &$read An array of read streams to select upon. 53 | * @param array &$write An array of write streams to select upon. 54 | * @param integer|null $timeout Activity timeout in microseconds, or null to wait forever. 55 | * 56 | * @return integer|false The total number of streams that are ready for read/write. 57 | * Can return false if stream_select() is interrupted by a signal. 58 | */ 59 | protected function streamSelect(array &$read, array &$write, $timeout) 60 | { 61 | if ($read || $write) { 62 | $except = null; 63 | // Calls signal handlers for pending signals 64 | pcntl_signal_dispatch(); 65 | // suppress warnings that occur, when stream_select is interrupted by a signal 66 | return @stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout); 67 | } 68 | 69 | // Calls signal handlers for pending signals 70 | if(PHP_EOL !== "\r\n") { 71 | pcntl_signal_dispatch(); 72 | } 73 | $timeout && usleep($timeout); 74 | 75 | return 0; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /workerman-chat-for-win/Applications/Chat/Web/css/style.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | background:#FCFCFC; 4 | } 5 | .say-btn 6 | { 7 | text-align:right; 8 | margin-top:12px; 9 | } 10 | 11 | #dialog 12 | { 13 | min-height:600px; 14 | background:#EEEEEE; 15 | } 16 | 17 | .textarea 18 | { 19 | height:6em; 20 | width:100%; 21 | } 22 | 23 | #userlist 24 | { 25 | min-height:600px; 26 | background:#EEEEEE; 27 | } 28 | 29 | #userlist > li 30 | { 31 | color:#1372A2; 32 | list-style:none; 33 | margin-left:12px; 34 | } 35 | 36 | #userlist > h4 37 | { 38 | text-align:center; 39 | font-size:14px; 40 | font-weight:nold; 41 | } 42 | 43 | .words 44 | { 45 | margin:8px; 46 | } 47 | 48 | 49 | .triangle-isosceles { 50 | position:relative; 51 | padding:10px; 52 | margin:10px 0 15px; 53 | color:#000; 54 | background:#D3FF93; /* default background for browsers without gradient support */ 55 | background:-webkit-gradient(linear, 0 0, 0 100%, from(#EFFFD7), to(#D3FF93)); 56 | background:-moz-linear-gradient(#EFFFD7, #D3FF93); 57 | background:-o-linear-gradient(#EFFFD7, #D3FF93); 58 | background:linear-gradient(#EFFFD7, #D3FF93); 59 | -webkit-border-radius:10px; 60 | -moz-border-radius:10px; 61 | border-radius:10px; 62 | -moz-box-shadow:1px 1px 2px hsla(0, 0%, 0%, 0.3); 63 | -webkit-box-shadow:1px 1px 2px hsla(0, 0%, 0%, 0.3); 64 | box-shadow:1px 1px 2px hsla(0, 0%, 0%, 0.3); 65 | } 66 | 67 | .triangle-isosceles:hover{ 68 | top:-2px; 69 | left:-2px; 70 | -moz-box-shadow:3px 3px 2px hsla(0, 0%, 0%, 0.3); 71 | -webkit-box-shadow:3px 3px 2px hsla(0, 0%, 0%, 0.3); 72 | box-shadow:3px 3px 2x hsla(0, 0%, 0%, 0.3); 73 | } 74 | 75 | .triangle-isosceles.top { 76 | background:-webkit-gradient(linear, 0 0, 0 100%, from(#D3FF93), to(#EFFFD7)); 77 | background:-moz-linear-gradient(#D3FF93, #EFFFD7); 78 | background:-o-linear-gradient(#D3FF93, #EFFFD7); 79 | background:linear-gradient(#D3FF93, #EFFFD7); 80 | } 81 | 82 | .triangle-isosceles:after { 83 | content:""; 84 | position:absolute; 85 | bottom:-9px; 86 | left:15px; 87 | border-width:9px 21px 0; 88 | border-style:solid; 89 | border-color:#D3FF93 transparent; 90 | display:block; 91 | width:0; 92 | } 93 | .triangle-isosceles.top:after { 94 | top:-9px; 95 | left:15px; 96 | bottom:auto; 97 | border-width:0 9px 9px; 98 | border-color:#D3FF93 transparent; 99 | } 100 | 101 | .user_icon 102 | { 103 | float:left;border:1px solid #DDDDDD;padding:2px;margin:0 5px 0 5px; 104 | } 105 | 106 | .cp 107 | { 108 | color:#888888; 109 | text-align:center; 110 | font-size:11px; 111 | } 112 | 113 | .thumbnail 114 | { 115 | border:1px solid #CCCCCC; 116 | } -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/composer/installed.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "workerman/workerman-for-win", 4 | "version": "v3.3.90", 5 | "version_normalized": "3.3.90.0", 6 | "source": { 7 | "type": "git", 8 | "url": "https://github.com/walkor/workerman-for-win.git", 9 | "reference": "64994323f7ba50ff34f2eabaa0a4fd39a9845d81" 10 | }, 11 | "dist": { 12 | "type": "zip", 13 | "url": "https://api.github.com/repos/walkor/workerman-for-win/zipball/64994323f7ba50ff34f2eabaa0a4fd39a9845d81", 14 | "reference": "64994323f7ba50ff34f2eabaa0a4fd39a9845d81", 15 | "shasum": "" 16 | }, 17 | "require": { 18 | "php": ">=5.3" 19 | }, 20 | "time": "2017-02-27 13:17:20", 21 | "type": "project", 22 | "installation-source": "dist", 23 | "autoload": { 24 | "psr-4": { 25 | "Workerman\\": "./" 26 | } 27 | }, 28 | "notification-url": "https://packagist.org/downloads/", 29 | "license": [ 30 | "MIT" 31 | ], 32 | "authors": [ 33 | { 34 | "name": "walkor", 35 | "email": "walkor@workerman.net", 36 | "homepage": "http://www.workerman.net", 37 | "role": "Developer" 38 | } 39 | ], 40 | "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.", 41 | "homepage": "http://www.workerman.net", 42 | "keywords": [ 43 | "asynchronous", 44 | "event-loop" 45 | ] 46 | }, 47 | { 48 | "name": "workerman/gateway-worker-for-win", 49 | "version": "v3.0.2", 50 | "version_normalized": "3.0.2.0", 51 | "source": { 52 | "type": "git", 53 | "url": "https://github.com/walkor/GatewayWorker-for-win.git", 54 | "reference": "d97bfb58adee8a2de200ac5bd142a2c252793d0c" 55 | }, 56 | "dist": { 57 | "type": "zip", 58 | "url": "https://api.github.com/repos/walkor/GatewayWorker-for-win/zipball/d97bfb58adee8a2de200ac5bd142a2c252793d0c", 59 | "reference": "d97bfb58adee8a2de200ac5bd142a2c252793d0c", 60 | "shasum": "" 61 | }, 62 | "require": { 63 | "workerman/workerman-for-win": ">=3.1.8" 64 | }, 65 | "time": "2017-03-04 10:24:56", 66 | "type": "library", 67 | "installation-source": "dist", 68 | "autoload": { 69 | "psr-4": { 70 | "GatewayWorker\\": "./src" 71 | } 72 | }, 73 | "notification-url": "https://packagist.org/downloads/", 74 | "license": [ 75 | "MIT" 76 | ], 77 | "homepage": "http://www.workerman.net", 78 | "keywords": [ 79 | "communication", 80 | "distributed" 81 | ] 82 | } 83 | ] 84 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | * @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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/workerman/gateway-worker-for-win/src/Lib/Context.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 GatewayWorker\Lib; 15 | 16 | use Exception; 17 | 18 | /** 19 | * 上下文 包含当前用户 uid, 内部通信 local_ip local_port socket_id,以及客户端 client_ip client_port 20 | */ 21 | class Context 22 | { 23 | /** 24 | * 内部通讯 id 25 | * 26 | * @var string 27 | */ 28 | public static $local_ip; 29 | 30 | /** 31 | * 内部通讯端口 32 | * 33 | * @var int 34 | */ 35 | public static $local_port; 36 | 37 | /** 38 | * 客户端 ip 39 | * 40 | * @var string 41 | */ 42 | public static $client_ip; 43 | 44 | /** 45 | * 客户端端口 46 | * 47 | * @var int 48 | */ 49 | public static $client_port; 50 | 51 | /** 52 | * client_id 53 | * 54 | * @var string 55 | */ 56 | public static $client_id; 57 | 58 | /** 59 | * 连接 connection->id 60 | * 61 | * @var int 62 | */ 63 | public static $connection_id; 64 | 65 | /** 66 | * 旧的session 67 | * 68 | * @var string 69 | */ 70 | public static $old_session; 71 | 72 | /** 73 | * 编码 session 74 | * 75 | * @param mixed $session_data 76 | * @return string 77 | */ 78 | public static function sessionEncode($session_data = '') 79 | { 80 | if ($session_data !== '') { 81 | return serialize($session_data); 82 | } 83 | return ''; 84 | } 85 | 86 | /** 87 | * 解码 session 88 | * 89 | * @param string $session_buffer 90 | * @return mixed 91 | */ 92 | public static function sessionDecode($session_buffer) 93 | { 94 | return unserialize($session_buffer); 95 | } 96 | 97 | /** 98 | * 清除上下文 99 | * 100 | * @return void 101 | */ 102 | public static function clear() 103 | { 104 | self::$local_ip = self::$local_port = self::$client_ip = self::$client_port = 105 | self::$client_id = self::$connection_id = self::$old_session = null; 106 | } 107 | 108 | /** 109 | * 通讯地址到 client_id 的转换 110 | * 111 | * @param int $local_ip 112 | * @param int $local_port 113 | * @param int $connection_id 114 | * @return string 115 | */ 116 | public static function addressToClientId($local_ip, $local_port, $connection_id) 117 | { 118 | return bin2hex(pack('NnN', $local_ip, $local_port, $connection_id)); 119 | } 120 | 121 | /** 122 | * client_id 到通讯地址的转换 123 | * 124 | * @param string $client_id 125 | * @return array 126 | * @throws Exception 127 | */ 128 | public static function clientIdToAddress($client_id) 129 | { 130 | if (strlen($client_id) !== 20) { 131 | echo new Exception("client_id $client_id is invalid"); 132 | return false; 133 | } 134 | return unpack('Nlocal_ip/nlocal_port/Nconnection_id', pack('H*', $client_id)); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |

{{name}}

12 | 15 | 16 | 17 |
18 |
19 | 20 | 21 | 105 | 106 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/workerman/gateway-worker-for-win/src/Protocols/GatewayProtocol.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 GatewayWorker\Protocols; 15 | 16 | /** 17 | * Gateway 与 Worker 间通讯的二进制协议 18 | * 19 | * struct GatewayProtocol 20 | * { 21 | * unsigned int pack_len, 22 | * unsigned char cmd,//命令字 23 | * unsigned int local_ip, 24 | * unsigned short local_port, 25 | * unsigned int client_ip, 26 | * unsigned short client_port, 27 | * unsigned int connection_id, 28 | * unsigned char flag, 29 | * unsigned short gateway_port, 30 | * unsigned int ext_len, 31 | * char[ext_len] ext_data, 32 | * char[pack_length-HEAD_LEN] body//包体 33 | * } 34 | * NCNnNnNCnN 35 | */ 36 | class GatewayProtocol 37 | { 38 | // 发给worker,gateway有一个新的连接 39 | const CMD_ON_CONNECTION = 1; 40 | 41 | // 发给worker的,客户端有消息 42 | const CMD_ON_MESSAGE = 3; 43 | 44 | // 发给worker上的关闭链接事件 45 | const CMD_ON_CLOSE = 4; 46 | 47 | // 发给gateway的向单个用户发送数据 48 | const CMD_SEND_TO_ONE = 5; 49 | 50 | // 发给gateway的向所有用户发送数据 51 | const CMD_SEND_TO_ALL = 6; 52 | 53 | // 发给gateway的踢出用户 54 | const CMD_KICK = 7; 55 | 56 | // 发给gateway,通知用户session更新 57 | const CMD_UPDATE_SESSION = 9; 58 | 59 | // 获取在线状态 60 | const CMD_GET_ALL_CLIENT_INFO = 10; 61 | 62 | // 判断是否在线 63 | const CMD_IS_ONLINE = 11; 64 | 65 | // client_id绑定到uid 66 | const CMD_BIND_UID = 12; 67 | 68 | // 解绑 69 | const CMD_UNBIND_UID = 13; 70 | 71 | // 向uid发送数据 72 | const CMD_SEND_TO_UID = 14; 73 | 74 | // 根据uid获取绑定的clientid 75 | const CMD_GET_CLIENT_ID_BY_UID = 15; 76 | 77 | // 加入组 78 | const CMD_JOIN_GROUP = 20; 79 | 80 | // 离开组 81 | const CMD_LEAVE_GROUP = 21; 82 | 83 | // 向组成员发消息 84 | const CMD_SEND_TO_GROUP = 22; 85 | 86 | // 获取组成员 87 | const CMD_GET_CLINET_INFO_BY_GROUP = 23; 88 | 89 | // 获取组成员数 90 | const CMD_GET_CLIENT_COUNT_BY_GROUP = 24; 91 | 92 | // worker连接gateway事件 93 | const CMD_WORKER_CONNECT = 200; 94 | 95 | // 心跳 96 | const CMD_PING = 201; 97 | 98 | // GatewayClient连接gateway事件 99 | const CMD_GATEWAY_CLIENT_CONNECT = 202; 100 | 101 | // 根据client_id获取session 102 | const CMD_GET_SESSION_BY_CLIENT_ID = 203; 103 | 104 | // 发给gateway,覆盖session 105 | const CMD_SET_SESSION = 204; 106 | 107 | // 包体是标量 108 | const FLAG_BODY_IS_SCALAR = 0x01; 109 | 110 | // 通知gateway在send时不调用协议encode方法,在广播组播时提升性能 111 | const FLAG_NOT_CALL_ENCODE = 0x02; 112 | 113 | /** 114 | * 包头长度 115 | * 116 | * @var int 117 | */ 118 | const HEAD_LEN = 28; 119 | 120 | public static $empty = array( 121 | 'cmd' => 0, 122 | 'local_ip' => 0, 123 | 'local_port' => 0, 124 | 'client_ip' => 0, 125 | 'client_port' => 0, 126 | 'connection_id' => 0, 127 | 'flag' => 0, 128 | 'gateway_port' => 0, 129 | 'ext_data' => '', 130 | 'body' => '', 131 | ); 132 | 133 | /** 134 | * 返回包长度 135 | * 136 | * @param string $buffer 137 | * @return int return current package length 138 | */ 139 | public static function input($buffer) 140 | { 141 | if (strlen($buffer) < self::HEAD_LEN) { 142 | return 0; 143 | } 144 | 145 | $data = unpack("Npack_len", $buffer); 146 | return $data['pack_len']; 147 | } 148 | 149 | /** 150 | * 获取整个包的 buffer 151 | * 152 | * @param mixed $data 153 | * @return string 154 | */ 155 | public static function encode($data) 156 | { 157 | $flag = (int)is_scalar($data['body']); 158 | if (!$flag) { 159 | $data['body'] = serialize($data['body']); 160 | } 161 | $data['flag'] |= $flag; 162 | $ext_len = strlen($data['ext_data']); 163 | $package_len = self::HEAD_LEN + $ext_len + strlen($data['body']); 164 | return pack("NCNnNnNCnN", $package_len, 165 | $data['cmd'], $data['local_ip'], 166 | $data['local_port'], $data['client_ip'], 167 | $data['client_port'], $data['connection_id'], 168 | $data['flag'], $data['gateway_port'], 169 | $ext_len) . $data['ext_data'] . $data['body']; 170 | } 171 | 172 | /** 173 | * 从二进制数据转换为数组 174 | * 175 | * @param string $buffer 176 | * @return array 177 | */ 178 | public static function decode($buffer) 179 | { 180 | $data = unpack("Npack_len/Ccmd/Nlocal_ip/nlocal_port/Nclient_ip/nclient_port/Nconnection_id/Cflag/ngateway_port/Next_len", 181 | $buffer); 182 | if ($data['ext_len'] > 0) { 183 | $data['ext_data'] = substr($buffer, self::HEAD_LEN, $data['ext_len']); 184 | if ($data['flag'] & self::FLAG_BODY_IS_SCALAR) { 185 | $data['body'] = substr($buffer, self::HEAD_LEN + $data['ext_len']); 186 | } else { 187 | $data['body'] = unserialize(substr($buffer, self::HEAD_LEN + $data['ext_len'])); 188 | } 189 | } else { 190 | $data['ext_data'] = ''; 191 | if ($data['flag'] & self::FLAG_BODY_IS_SCALAR) { 192 | $data['body'] = substr($buffer, self::HEAD_LEN); 193 | } else { 194 | $data['body'] = unserialize(substr($buffer, self::HEAD_LEN)); 195 | } 196 | } 197 | return $data; 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /workerman-chat-for-win/Applications/Chat/Events.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 | /** 16 | * 用于检测业务代码死循环或者长时间阻塞等问题 17 | * 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload 18 | * 然后观察一段时间workerman.log看是否有process_timeout异常 19 | */ 20 | //declare(ticks=1); 21 | 22 | /** 23 | * 聊天主逻辑 24 | * 主要是处理 onMessage onClose 25 | */ 26 | use \GatewayWorker\Lib\Gateway; 27 | 28 | class Events 29 | { 30 | /** 31 | * 有消息时 32 | * @param int $client_id 33 | * @param mixed $message 34 | */ 35 | public static function onMessage($client_id, $message) 36 | { 37 | // debug 38 | echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} client_id:$client_id session:".json_encode($_SESSION)." onMessage:".$message."\n"; 39 | 40 | // 客户端传递的是json数据 41 | $message_data = json_decode($message, true); 42 | if(!$message_data) 43 | { 44 | return ; 45 | } 46 | 47 | // 根据类型执行不同的业务 48 | switch($message_data['type']) 49 | { 50 | // 客户端回应服务端的心跳 51 | case 'pong': 52 | return; 53 | // 客户端登录 message格式: {type:login, name:xx, room_id:1} ,添加到客户端,广播给所有客户端xx进入聊天室 54 | case 'login': 55 | // 判断是否有房间号 56 | if(!isset($message_data['room_id'])) 57 | { 58 | throw new \Exception("\$message_data['room_id'] not set. client_ip:{$_SERVER['REMOTE_ADDR']} \$message:$message"); 59 | } 60 | 61 | // 把房间号昵称放到session中 62 | $room_id = $message_data['room_id']; 63 | $client_name = htmlspecialchars($message_data['client_name']); 64 | $_SESSION['room_id'] = $room_id; 65 | $_SESSION['client_name'] = $client_name; 66 | 67 | // 获取房间内所有用户列表 68 | $clients_list = Gateway::getClientSessionsByGroup($room_id); 69 | foreach($clients_list as $tmp_client_id=>$item) 70 | { 71 | $clients_list[$tmp_client_id] = $item['client_name']; 72 | } 73 | $clients_list[$client_id] = $client_name; 74 | 75 | // 转播给当前房间的所有客户端,xx进入聊天室 message {type:login, client_id:xx, name:xx} 76 | $new_message = array('type'=>$message_data['type'], 'client_id'=>$client_id, 'client_name'=>htmlspecialchars($client_name), 'time'=>date('Y-m-d H:i:s')); 77 | Gateway::sendToGroup($room_id, json_encode($new_message)); 78 | Gateway::joinGroup($client_id, $room_id); 79 | 80 | // 给当前用户发送用户列表 81 | $new_message['client_list'] = $clients_list; 82 | Gateway::sendToCurrentClient(json_encode($new_message)); 83 | return; 84 | 85 | // 客户端发言 message: {type:say, to_client_id:xx, content:xx} 86 | case 'say': 87 | // 非法请求 88 | if(!isset($_SESSION['room_id'])) 89 | { 90 | throw new \Exception("\$_SESSION['room_id'] not set. client_ip:{$_SERVER['REMOTE_ADDR']}"); 91 | } 92 | $room_id = $_SESSION['room_id']; 93 | $client_name = $_SESSION['client_name']; 94 | 95 | // 私聊 96 | if($message_data['to_client_id'] != 'all') 97 | { 98 | $new_message = array( 99 | 'type'=>'say', 100 | 'from_client_id'=>$client_id, 101 | 'from_client_name' =>$client_name, 102 | 'to_client_id'=>$message_data['to_client_id'], 103 | 'content'=>"对你说: ".nl2br(htmlspecialchars($message_data['content'])), 104 | 'time'=>date('Y-m-d H:i:s'), 105 | ); 106 | Gateway::sendToClient($message_data['to_client_id'], json_encode($new_message)); 107 | $new_message['content'] = "你对".htmlspecialchars($message_data['to_client_name'])."说: ".nl2br(htmlspecialchars($message_data['content'])); 108 | return Gateway::sendToCurrentClient(json_encode($new_message)); 109 | } 110 | 111 | $new_message = array( 112 | 'type'=>'say', 113 | 'from_client_id'=>$client_id, 114 | 'from_client_name' =>$client_name, 115 | 'to_client_id'=>'all', 116 | 'content'=>nl2br(htmlspecialchars($message_data['content'])), 117 | 'time'=>date('Y-m-d H:i:s'), 118 | ); 119 | return Gateway::sendToGroup($room_id ,json_encode($new_message)); 120 | } 121 | } 122 | 123 | /** 124 | * 当客户端断开连接时 125 | * @param integer $client_id 客户端id 126 | */ 127 | public static function onClose($client_id) 128 | { 129 | // debug 130 | echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} client_id:$client_id onClose:''\n"; 131 | 132 | // 从房间的客户端列表中删除 133 | if(isset($_SESSION['room_id'])) 134 | { 135 | $room_id = $_SESSION['room_id']; 136 | $new_message = array('type'=>'logout', 'from_client_id'=>$client_id, 'from_client_name'=>$_SESSION['client_name'], 'time'=>date('Y-m-d H:i:s')); 137 | Gateway::sendToGroup($room_id, json_encode($new_message)); 138 | } 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/workerman/gateway-worker-for-win/src/Register.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 GatewayWorker; 15 | 16 | use Workerman\Worker; 17 | use Workerman\Lib\Timer; 18 | 19 | /** 20 | * 21 | * 注册中心,用于注册 Gateway 和 BusinessWorker 22 | * 23 | * @author walkor 24 | * 25 | */ 26 | class Register extends Worker 27 | { 28 | /** 29 | * {@inheritdoc} 30 | */ 31 | public $name = 'Register'; 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | public $reloadable = false; 37 | 38 | /** 39 | * 秘钥 40 | * @var string 41 | */ 42 | public $secretKey = ''; 43 | 44 | /** 45 | * 所有 gateway 的连接 46 | * 47 | * @var array 48 | */ 49 | protected $_gatewayConnections = array(); 50 | 51 | /** 52 | * 所有 worker 的连接 53 | * 54 | * @var array 55 | */ 56 | protected $_workerConnections = array(); 57 | 58 | /** 59 | * 进程启动时间 60 | * 61 | * @var int 62 | */ 63 | protected $_startTime = 0; 64 | 65 | /** 66 | * {@inheritdoc} 67 | */ 68 | public function run() 69 | { 70 | // 设置 onMessage 连接回调 71 | $this->onConnect = array($this, 'onConnect'); 72 | 73 | // 设置 onMessage 回调 74 | $this->onMessage = array($this, 'onMessage'); 75 | 76 | // 设置 onClose 回调 77 | $this->onClose = array($this, 'onClose'); 78 | 79 | // 记录进程启动的时间 80 | $this->_startTime = time(); 81 | 82 | // 强制使用text协议 83 | $this->protocol = '\Workerman\Protocols\Text'; 84 | 85 | // 运行父方法 86 | parent::run(); 87 | } 88 | 89 | /** 90 | * 设置个定时器,将未及时发送验证的连接关闭 91 | * 92 | * @param \Workerman\Connection\ConnectionInterface $connection 93 | * @return void 94 | */ 95 | public function onConnect($connection) 96 | { 97 | $connection->timeout_timerid = Timer::add(10, function () use ($connection) { 98 | self::log("Register auth timeout (".$connection->getRemoteIp()."). See http://wiki.workerman.net/Error4 for detail"); 99 | $connection->close(); 100 | }, null, false); 101 | } 102 | 103 | /** 104 | * 设置消息回调 105 | * 106 | * @param \Workerman\Connection\ConnectionInterface $connection 107 | * @param string $buffer 108 | * @return void 109 | */ 110 | public function onMessage($connection, $buffer) 111 | { 112 | // 删除定时器 113 | Timer::del($connection->timeout_timerid); 114 | $data = @json_decode($buffer, true); 115 | if (empty($data['event'])) { 116 | $error = "Bad request for Register service. Request info(IP:".$connection->getRemoteIp().", Request Buffer:$buffer). See http://wiki.workerman.net/Error4 for detail"; 117 | self::log($error); 118 | return $connection->close($error); 119 | } 120 | $event = $data['event']; 121 | $secret_key = isset($data['secret_key']) ? $data['secret_key'] : ''; 122 | // 开始验证 123 | switch ($event) { 124 | // 是 gateway 连接 125 | case 'gateway_connect': 126 | if (empty($data['address'])) { 127 | echo "address not found\n"; 128 | return $connection->close(); 129 | } 130 | if ($secret_key !== $this->secretKey) { 131 | self::log("Register: Key does not match ".var_export($secret_key, true)." !== ".var_export($this->secretKey, true)); 132 | return $connection->close(); 133 | } 134 | $this->_gatewayConnections[$connection->id] = $data['address']; 135 | $this->broadcastAddresses(); 136 | break; 137 | // 是 worker 连接 138 | case 'worker_connect': 139 | if ($secret_key !== $this->secretKey) { 140 | self::log("Register: Key does not match ".var_export($secret_key, true)." !== ".var_export($this->secretKey, true)); 141 | return $connection->close(); 142 | } 143 | $this->_workerConnections[$connection->id] = $connection; 144 | $this->broadcastAddresses($connection); 145 | break; 146 | case 'ping': 147 | break; 148 | default: 149 | self::log("Register unknown event:$event IP: ".$connection->getRemoteIp()." Buffer:$buffer. See http://wiki.workerman.net/Error4 for detail"); 150 | $connection->close(); 151 | } 152 | } 153 | 154 | /** 155 | * 连接关闭时 156 | * 157 | * @param \Workerman\Connection\ConnectionInterface $connection 158 | */ 159 | public function onClose($connection) 160 | { 161 | if (isset($this->_gatewayConnections[$connection->id])) { 162 | unset($this->_gatewayConnections[$connection->id]); 163 | $this->broadcastAddresses(); 164 | } 165 | if (isset($this->_workerConnections[$connection->id])) { 166 | unset($this->_workerConnections[$connection->id]); 167 | } 168 | } 169 | 170 | /** 171 | * 向 BusinessWorker 广播 gateway 内部通讯地址 172 | * 173 | * @param \Workerman\Connection\ConnectionInterface $connection 174 | */ 175 | public function broadcastAddresses($connection = null) 176 | { 177 | $data = array( 178 | 'event' => 'broadcast_addresses', 179 | 'addresses' => array_unique(array_values($this->_gatewayConnections)), 180 | ); 181 | $buffer = json_encode($data); 182 | if ($connection) { 183 | $connection->send($buffer); 184 | return; 185 | } 186 | foreach ($this->_workerConnections as $con) { 187 | $con->send($buffer); 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/Applications/Chat/Web/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | workerman-chat PHP聊天室 Websocket(HTLM5/Flash)+PHP多进程socket实时推送技术 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 138 | 139 | 140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | 152 | 153 |
154 |
155 |
156 |     房间列表:(当前在 房间0 ? intval($_GET['room_id']):1; ?>)
157 |     房间1    房间2    房间3    房间4 158 |

159 |
160 |

PHP多进程+Websocket(HTML5/Flash)+PHP Socket实时推送技术    Powered by workerman-chat

161 |
162 |
163 |
164 |
165 |
166 | 167 |
168 |
169 |
170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/workerman/workerman-for-win/Events/React.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 | use React\EventLoop\LoopInterface; 16 | use React\EventLoop\Timer\TimerInterface; 17 | 18 | /** 19 | * select eventloop 20 | */ 21 | class React implements LoopInterface 22 | { 23 | /** 24 | * @var React\EventLoop\LoopInterface 25 | */ 26 | protected $_loop = null; 27 | 28 | /** 29 | * @var array 30 | */ 31 | protected $_timerIdMap = array(); 32 | 33 | /** 34 | * @var int 35 | */ 36 | protected $_timerIdIndex = 0; 37 | 38 | /** 39 | * React constructor. 40 | */ 41 | public function __construct() { 42 | if (function_exists('event_base_new')) { 43 | $this->_loop = new \Workerman\Events\React\LibEventLoop(); 44 | } elseif (class_exists('EventBase', false)) { 45 | $this->_loop = new \Workerman\Events\React\ExtEventLoop(); 46 | } else { 47 | $this->_loop = new \Workerman\Events\React\StreamSelectLoop(); 48 | } 49 | } 50 | 51 | /** 52 | * Add event listener to event loop. 53 | * 54 | * @param $fd 55 | * @param $flag 56 | * @param $func 57 | * @param array $args 58 | * @return bool 59 | */ 60 | public function add($fd, $flag, $func, $args = array()) 61 | { 62 | $args = (array)$args; 63 | switch ($flag) { 64 | case EventInterface::EV_READ: 65 | return $this->_loop->addReadStream($fd, $func); 66 | case EventInterface::EV_WRITE: 67 | return $this->_loop->addWriteStream($fd, $func); 68 | case EventInterface::EV_SIGNAL: 69 | return $this->_loop->addSignal($fd, $func); 70 | case EventInterface::EV_TIMER: 71 | $timer_obj = $this->_loop->addPeriodicTimer($fd, function() use ($func, $args) { 72 | call_user_func_array($func, $args); 73 | }); 74 | $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj; 75 | return $this->_timerIdIndex; 76 | case EventInterface::EV_TIMER_ONCE: 77 | $timer_obj = $this->_loop->addTimer($fd, function() use ($func, $args) { 78 | call_user_func_array($func, $args); 79 | }); 80 | $this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj; 81 | return $this->_timerIdIndex; 82 | } 83 | return false; 84 | } 85 | 86 | /** 87 | * Remove event listener from event loop. 88 | * 89 | * @param mixed $fd 90 | * @param int $flag 91 | * @return bool 92 | */ 93 | public function del($fd, $flag) 94 | { 95 | switch ($flag) { 96 | case EventInterface::EV_READ: 97 | return $this->_loop->removeReadStream($fd); 98 | case EventInterface::EV_WRITE: 99 | return $this->_loop->removeWriteStream($fd); 100 | case EventInterface::EV_SIGNAL: 101 | return $this->_loop->removeSignal($fd); 102 | case EventInterface::EV_TIMER: 103 | case EventInterface::EV_TIMER_ONCE; 104 | if (isset($this->_timerIdMap[$fd])){ 105 | $timer_obj = $this->_timerIdMap[$fd]; 106 | unset($this->_timerIdMap[$fd]); 107 | $this->_loop->cancelTimer($timer_obj); 108 | return true; 109 | } 110 | } 111 | return false; 112 | } 113 | 114 | 115 | /** 116 | * Main loop. 117 | * 118 | * @return void 119 | */ 120 | public function loop() 121 | { 122 | $this->_loop->run(); 123 | } 124 | 125 | /** 126 | * Register a listener to be notified when a stream is ready to read. 127 | * 128 | * @param resource $stream The PHP stream resource to check. 129 | * @param callable $listener Invoked when the stream is ready. 130 | */ 131 | public function addReadStream($stream, callable $listener) { 132 | return call_user_func(array($this->_loop, 'addReadStream'), $stream, $listener); 133 | } 134 | 135 | /** 136 | * Register a listener to be notified when a stream is ready to write. 137 | * 138 | * @param resource $stream The PHP stream resource to check. 139 | * @param callable $listener Invoked when the stream is ready. 140 | */ 141 | public function addWriteStream($stream, callable $listener) { 142 | return call_user_func(array($this->_loop, 'addWriteStream'), $stream, $listener); 143 | } 144 | 145 | /** 146 | * Remove the read event listener for the given stream. 147 | * 148 | * @param resource $stream The PHP stream resource. 149 | */ 150 | public function removeReadStream($stream) { 151 | return call_user_func(array($this->_loop, 'removeReadStream'), $stream); 152 | } 153 | 154 | /** 155 | * Remove the write event listener for the given stream. 156 | * 157 | * @param resource $stream The PHP stream resource. 158 | */ 159 | public function removeWriteStream($stream) { 160 | return call_user_func(array($this->_loop, 'removeWriteStream'), $stream); 161 | } 162 | 163 | /** 164 | * Remove all listeners for the given stream. 165 | * 166 | * @param resource $stream The PHP stream resource. 167 | */ 168 | public function removeStream($stream) { 169 | return call_user_func(array($this->_loop, 'removeStream'), $stream); 170 | } 171 | 172 | /** 173 | * Enqueue a callback to be invoked once after the given interval. 174 | * 175 | * The execution order of timers scheduled to execute at the same time is 176 | * not guaranteed. 177 | * 178 | * @param int|float $interval The number of seconds to wait before execution. 179 | * @param callable $callback The callback to invoke. 180 | * 181 | * @return TimerInterface 182 | */ 183 | public function addTimer($interval, callable $callback) { 184 | return call_user_func(array($this->_loop, 'addTimer'), $interval, $callback); 185 | } 186 | 187 | /** 188 | * Enqueue a callback to be invoked repeatedly after the given interval. 189 | * 190 | * The execution order of timers scheduled to execute at the same time is 191 | * not guaranteed. 192 | * 193 | * @param int|float $interval The number of seconds to wait before execution. 194 | * @param callable $callback The callback to invoke. 195 | * 196 | * @return TimerInterface 197 | */ 198 | public function addPeriodicTimer($interval, callable $callback) { 199 | return call_user_func(array($this->_loop, 'addPeriodicTimer'), $interval, $callback); 200 | } 201 | 202 | /** 203 | * Cancel a pending timer. 204 | * 205 | * @param TimerInterface $timer The timer to cancel. 206 | */ 207 | public function cancelTimer(TimerInterface $timer) { 208 | return call_user_func(array($this->_loop, 'cancelTimer'), $timer); 209 | } 210 | 211 | /** 212 | * Check if a given timer is active. 213 | * 214 | * @param TimerInterface $timer The timer to check. 215 | * 216 | * @return boolean True if the timer is still enqueued for execution. 217 | */ 218 | public function isTimerActive(TimerInterface $timer) { 219 | return call_user_func(array($this->_loop, 'isTimerActive'), $timer); 220 | } 221 | 222 | /** 223 | * Schedule a callback to be invoked on the next tick of the event loop. 224 | * 225 | * Callbacks are guaranteed to be executed in the order they are enqueued, 226 | * before any timer or stream events. 227 | * 228 | * @param callable $listener The callback to invoke. 229 | */ 230 | public function nextTick(callable $listener) { 231 | return call_user_func(array($this->_loop, 'nextTick'), $listener); 232 | } 233 | 234 | /** 235 | * Schedule a callback to be invoked on a future tick of the event loop. 236 | * 237 | * Callbacks are guaranteed to be executed in the order they are enqueued. 238 | * 239 | * @param callable $listener The callback to invoke. 240 | */ 241 | public function futureTick(callable $listener) { 242 | return call_user_func(array($this->_loop, 'futureTick'), $listener); 243 | } 244 | 245 | /** 246 | * Perform a single iteration of the event loop. 247 | */ 248 | public function tick() { 249 | return call_user_func(array($this->_loop, 'tick')); 250 | } 251 | 252 | /** 253 | * Run the event loop until there are no more tasks to perform. 254 | */ 255 | public function run() { 256 | return call_user_func(array($this->_loop, 'run')); 257 | } 258 | 259 | /** 260 | * Instruct a running event loop to stop. 261 | */ 262 | public function stop() { 263 | return call_user_func(array($this->_loop, 'stop')); 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /workerman-chat-for-win/Applications/Chat/Web/js/swfobject.js: -------------------------------------------------------------------------------- 1 | /* SWFObject v2.2 2 | is released under the MIT License 3 | */ 4 | var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y0){for(var af=0;af0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad'}}aa.outerHTML='"+af+"";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab 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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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\Lib\Timer; 18 | use Workerman\Worker; 19 | use Exception; 20 | 21 | /** 22 | * AsyncTcpConnection. 23 | */ 24 | class AsyncTcpConnection extends TcpConnection 25 | { 26 | /** 27 | * Emitted when socket connection is successfully established. 28 | * 29 | * @var callback 30 | */ 31 | public $onConnect = null; 32 | 33 | /** 34 | * Transport layer protocol. 35 | * 36 | * @var string 37 | */ 38 | public $transport = 'tcp'; 39 | 40 | /** 41 | * Status. 42 | * 43 | * @var int 44 | */ 45 | protected $_status = self::STATUS_INITIAL; 46 | 47 | /** 48 | * Remote host. 49 | * 50 | * @var string 51 | */ 52 | protected $_remoteHost = ''; 53 | 54 | /** 55 | * Connect start time. 56 | * 57 | * @var string 58 | */ 59 | protected $_connectStartTime = 0; 60 | 61 | /** 62 | * Remote URI. 63 | * 64 | * @var string 65 | */ 66 | protected $_remoteURI = ''; 67 | 68 | /** 69 | * Context option. 70 | * 71 | * @var resource 72 | */ 73 | protected $_contextOption = null; 74 | 75 | /** 76 | * Reconnect timer. 77 | * 78 | * @var int 79 | */ 80 | protected $_reconnectTimer = null; 81 | 82 | 83 | /** 84 | * PHP built-in protocols. 85 | * 86 | * @var array 87 | */ 88 | protected static $_builtinTransports = array( 89 | 'tcp' => 'tcp', 90 | 'udp' => 'udp', 91 | 'unix' => 'unix', 92 | 'ssl' => 'ssl', 93 | 'sslv2' => 'sslv2', 94 | 'sslv3' => 'sslv3', 95 | 'tls' => 'tls' 96 | ); 97 | 98 | /** 99 | * Construct. 100 | * 101 | * @param string $remote_address 102 | * @param array $context_option 103 | * @throws Exception 104 | */ 105 | public function __construct($remote_address, $context_option = null) 106 | { 107 | $address_info = parse_url($remote_address); 108 | if (!$address_info) { 109 | list($scheme, $this->_remoteAddress) = explode(':', $remote_address, 2); 110 | if (!$this->_remoteAddress) { 111 | echo new \Exception('bad remote_address'); 112 | } 113 | } else { 114 | if (!isset($address_info['port'])) { 115 | $address_info['port'] = 80; 116 | } 117 | if (!isset($address_info['path'])) { 118 | $address_info['path'] = '/'; 119 | } 120 | if (!isset($address_info['query'])) { 121 | $address_info['query'] = ''; 122 | } else { 123 | $address_info['query'] = '?' . $address_info['query']; 124 | } 125 | $this->_remoteAddress = "{$address_info['host']}:{$address_info['port']}"; 126 | $this->_remoteHost = $address_info['host']; 127 | $this->_remoteURI = "{$address_info['path']}{$address_info['query']}"; 128 | $scheme = isset($address_info['scheme']) ? $address_info['scheme'] : 'tcp'; 129 | } 130 | 131 | $this->id = self::$_idRecorder++; 132 | // Check application layer protocol class. 133 | if (!isset(self::$_builtinTransports[$scheme])) { 134 | $scheme = ucfirst($scheme); 135 | $this->protocol = '\\Protocols\\' . $scheme; 136 | if (!class_exists($this->protocol)) { 137 | $this->protocol = "\\Workerman\\Protocols\\$scheme"; 138 | if (!class_exists($this->protocol)) { 139 | throw new Exception("class \\Protocols\\$scheme not exist"); 140 | } 141 | } 142 | } else { 143 | $this->transport = self::$_builtinTransports[$scheme]; 144 | } 145 | 146 | // For statistics. 147 | self::$statistics['connection_count']++; 148 | $this->maxSendBufferSize = self::$defaultMaxSendBufferSize; 149 | $this->_contextOption = $context_option; 150 | } 151 | 152 | /** 153 | * Do connect. 154 | * 155 | * @return void 156 | */ 157 | public function connect() 158 | { 159 | if ($this->_status !== self::STATUS_INITIAL && $this->_status !== self::STATUS_CLOSING && 160 | $this->_status !== self::STATUS_CLOSED) { 161 | return; 162 | } 163 | $this->_status = self::STATUS_CONNECTING; 164 | $this->_connectStartTime = microtime(true); 165 | // Open socket connection asynchronously. 166 | if ($this->_contextOption) { 167 | $context = stream_context_create($this->_contextOption); 168 | $this->_socket = stream_socket_client("{$this->transport}://{$this->_remoteAddress}", $errno, $errstr, 0, 169 | STREAM_CLIENT_ASYNC_CONNECT, $context); 170 | } else { 171 | $this->_socket = stream_socket_client("{$this->transport}://{$this->_remoteAddress}", $errno, $errstr, 0, 172 | STREAM_CLIENT_ASYNC_CONNECT); 173 | } 174 | // If failed attempt to emit onError callback. 175 | if (!$this->_socket) { 176 | $this->emitError(WORKERMAN_CONNECT_FAIL, $errstr); 177 | if ($this->_status === self::STATUS_CLOSING) { 178 | $this->destroy(); 179 | } 180 | if ($this->_status === self::STATUS_CLOSED) { 181 | $this->onConnect = null; 182 | } 183 | return; 184 | } 185 | // Add socket to global event loop waiting connection is successfully established or faild. 186 | Worker::$globalEvent->add($this->_socket, EventInterface::EV_WRITE, array($this, 'checkConnection')); 187 | Worker::$globalEvent->add($this->_socket, EventInterface::EV_EXCEPT, array($this, 'checkConnection')); 188 | } 189 | 190 | /** 191 | * Reconnect. 192 | * 193 | * @param int $after 194 | * @return void 195 | */ 196 | public function reConnect($after = 0) { 197 | $this->_status = self::STATUS_INITIAL; 198 | if ($this->_reconnectTimer) { 199 | Timer::del($this->_reconnectTimer); 200 | } 201 | if ($after > 0) { 202 | $this->_reconnectTimer = Timer::add($after, array($this, 'connect'), null, false); 203 | return; 204 | } 205 | return $this->connect(); 206 | } 207 | 208 | /** 209 | * Get remote address. 210 | * 211 | * @return string 212 | */ 213 | public function getRemoteHost() 214 | { 215 | return $this->_remoteHost; 216 | } 217 | 218 | /** 219 | * Get remote URI. 220 | * 221 | * @return string 222 | */ 223 | public function getRemoteURI() 224 | { 225 | return $this->_remoteURI; 226 | } 227 | 228 | /** 229 | * Try to emit onError callback. 230 | * 231 | * @param int $code 232 | * @param string $msg 233 | * @return void 234 | */ 235 | protected function emitError($code, $msg) 236 | { 237 | $this->_status = self::STATUS_CLOSING; 238 | if ($this->onError) { 239 | try { 240 | call_user_func($this->onError, $this, $code, $msg); 241 | } catch (\Exception $e) { 242 | Worker::log($e); 243 | exit(250); 244 | } catch (\Error $e) { 245 | Worker::log($e); 246 | exit(250); 247 | } 248 | } 249 | } 250 | 251 | /** 252 | * Check connection is successfully established or faild. 253 | * 254 | * @param resource $socket 255 | * @return void 256 | */ 257 | public function checkConnection($socket) 258 | { 259 | Worker::$globalEvent->del($socket, EventInterface::EV_EXCEPT); 260 | // Check socket state. 261 | if ($address = stream_socket_get_name($socket, true)) { 262 | // Remove write listener. 263 | Worker::$globalEvent->del($socket, EventInterface::EV_WRITE); 264 | // Nonblocking. 265 | stream_set_blocking($socket, 0); 266 | // Compatible with hhvm 267 | if (function_exists('stream_set_read_buffer')) { 268 | stream_set_read_buffer($socket, 0); 269 | } 270 | // Try to open keepalive for tcp and disable Nagle algorithm. 271 | if (function_exists('socket_import_stream') && $this->transport === 'tcp') { 272 | $raw_socket = socket_import_stream($socket); 273 | socket_set_option($raw_socket, SOL_SOCKET, SO_KEEPALIVE, 1); 274 | socket_set_option($raw_socket, SOL_TCP, TCP_NODELAY, 1); 275 | } 276 | // Register a listener waiting read event. 277 | Worker::$globalEvent->add($socket, EventInterface::EV_READ, array($this, 'baseRead')); 278 | // There are some data waiting to send. 279 | if ($this->_sendBuffer) { 280 | Worker::$globalEvent->add($socket, EventInterface::EV_WRITE, array($this, 'baseWrite')); 281 | } 282 | $this->_status = self::STATUS_ESTABLISH; 283 | $this->_remoteAddress = $address; 284 | 285 | // Try to emit onConnect callback. 286 | if ($this->onConnect) { 287 | try { 288 | call_user_func($this->onConnect, $this); 289 | } catch (\Exception $e) { 290 | Worker::log($e); 291 | exit(250); 292 | } catch (\Error $e) { 293 | Worker::log($e); 294 | exit(250); 295 | } 296 | } 297 | // Try to emit protocol::onConnect 298 | if (method_exists($this->protocol, 'onConnect')) { 299 | try { 300 | call_user_func(array($this->protocol, 'onConnect'), $this); 301 | } catch (\Exception $e) { 302 | Worker::log($e); 303 | exit(250); 304 | } catch (\Error $e) { 305 | Worker::log($e); 306 | exit(250); 307 | } 308 | } 309 | } else { 310 | // Connection failed. 311 | $this->emitError(WORKERMAN_CONNECT_FAIL, 'connect ' . $this->_remoteAddress . ' fail after ' . round(microtime(true) - $this->_connectStartTime, 4) . ' seconds'); 312 | if ($this->_status === self::STATUS_CLOSING) { 313 | $this->destroy(); 314 | } 315 | if ($this->_status === self::STATUS_CLOSED) { 316 | $this->onConnect = null; 317 | } 318 | } 319 | } 320 | } 321 | -------------------------------------------------------------------------------- /workerman-chat-for-win/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 | * 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 | echo new \Exception('server root not set, please use WebServer::addRoot($domain, $root_path) to set server root path'); 93 | exit(250); 94 | } 95 | 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 | -------------------------------------------------------------------------------- /workerman-chat-for-win/vendor/composer/ClassLoader.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer\Autoload; 14 | 15 | /** 16 | * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. 17 | * 18 | * $loader = new \Composer\Autoload\ClassLoader(); 19 | * 20 | * // register classes with namespaces 21 | * $loader->add('Symfony\Component', __DIR__.'/component'); 22 | * $loader->add('Symfony', __DIR__.'/framework'); 23 | * 24 | * // activate the autoloader 25 | * $loader->register(); 26 | * 27 | * // to enable searching the include path (eg. for PEAR packages) 28 | * $loader->setUseIncludePath(true); 29 | * 30 | * In this example, if you try to use a class in the Symfony\Component 31 | * namespace or one of its children (Symfony\Component\Console for instance), 32 | * the autoloader will first look for the class under the component/ 33 | * directory, and it will then fallback to the framework/ directory if not 34 | * found before giving up. 35 | * 36 | * This class is loosely based on the Symfony UniversalClassLoader. 37 | * 38 | * @author Fabien Potencier 39 | * @author Jordi Boggiano 40 | * @see http://www.php-fig.org/psr/psr-0/ 41 | * @see http://www.php-fig.org/psr/psr-4/ 42 | */ 43 | class ClassLoader 44 | { 45 | // PSR-4 46 | private $prefixLengthsPsr4 = array(); 47 | private $prefixDirsPsr4 = array(); 48 | private $fallbackDirsPsr4 = array(); 49 | 50 | // PSR-0 51 | private $prefixesPsr0 = array(); 52 | private $fallbackDirsPsr0 = array(); 53 | 54 | private $useIncludePath = false; 55 | private $classMap = array(); 56 | private $classMapAuthoritative = false; 57 | private $missingClasses = array(); 58 | 59 | public function getPrefixes() 60 | { 61 | if (!empty($this->prefixesPsr0)) { 62 | return call_user_func_array('array_merge', $this->prefixesPsr0); 63 | } 64 | 65 | return array(); 66 | } 67 | 68 | public function getPrefixesPsr4() 69 | { 70 | return $this->prefixDirsPsr4; 71 | } 72 | 73 | public function getFallbackDirs() 74 | { 75 | return $this->fallbackDirsPsr0; 76 | } 77 | 78 | public function getFallbackDirsPsr4() 79 | { 80 | return $this->fallbackDirsPsr4; 81 | } 82 | 83 | public function getClassMap() 84 | { 85 | return $this->classMap; 86 | } 87 | 88 | /** 89 | * @param array $classMap Class to filename map 90 | */ 91 | public function addClassMap(array $classMap) 92 | { 93 | if ($this->classMap) { 94 | $this->classMap = array_merge($this->classMap, $classMap); 95 | } else { 96 | $this->classMap = $classMap; 97 | } 98 | } 99 | 100 | /** 101 | * Registers a set of PSR-0 directories for a given prefix, either 102 | * appending or prepending to the ones previously set for this prefix. 103 | * 104 | * @param string $prefix The prefix 105 | * @param array|string $paths The PSR-0 root directories 106 | * @param bool $prepend Whether to prepend the directories 107 | */ 108 | public function add($prefix, $paths, $prepend = false) 109 | { 110 | if (!$prefix) { 111 | if ($prepend) { 112 | $this->fallbackDirsPsr0 = array_merge( 113 | (array) $paths, 114 | $this->fallbackDirsPsr0 115 | ); 116 | } else { 117 | $this->fallbackDirsPsr0 = array_merge( 118 | $this->fallbackDirsPsr0, 119 | (array) $paths 120 | ); 121 | } 122 | 123 | return; 124 | } 125 | 126 | $first = $prefix[0]; 127 | if (!isset($this->prefixesPsr0[$first][$prefix])) { 128 | $this->prefixesPsr0[$first][$prefix] = (array) $paths; 129 | 130 | return; 131 | } 132 | if ($prepend) { 133 | $this->prefixesPsr0[$first][$prefix] = array_merge( 134 | (array) $paths, 135 | $this->prefixesPsr0[$first][$prefix] 136 | ); 137 | } else { 138 | $this->prefixesPsr0[$first][$prefix] = array_merge( 139 | $this->prefixesPsr0[$first][$prefix], 140 | (array) $paths 141 | ); 142 | } 143 | } 144 | 145 | /** 146 | * Registers a set of PSR-4 directories for a given namespace, either 147 | * appending or prepending to the ones previously set for this namespace. 148 | * 149 | * @param string $prefix The prefix/namespace, with trailing '\\' 150 | * @param array|string $paths The PSR-4 base directories 151 | * @param bool $prepend Whether to prepend the directories 152 | * 153 | * @throws \InvalidArgumentException 154 | */ 155 | public function addPsr4($prefix, $paths, $prepend = false) 156 | { 157 | if (!$prefix) { 158 | // Register directories for the root namespace. 159 | if ($prepend) { 160 | $this->fallbackDirsPsr4 = array_merge( 161 | (array) $paths, 162 | $this->fallbackDirsPsr4 163 | ); 164 | } else { 165 | $this->fallbackDirsPsr4 = array_merge( 166 | $this->fallbackDirsPsr4, 167 | (array) $paths 168 | ); 169 | } 170 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 171 | // Register directories for a new namespace. 172 | $length = strlen($prefix); 173 | if ('\\' !== $prefix[$length - 1]) { 174 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 175 | } 176 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 177 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 178 | } elseif ($prepend) { 179 | // Prepend directories for an already registered namespace. 180 | $this->prefixDirsPsr4[$prefix] = array_merge( 181 | (array) $paths, 182 | $this->prefixDirsPsr4[$prefix] 183 | ); 184 | } else { 185 | // Append directories for an already registered namespace. 186 | $this->prefixDirsPsr4[$prefix] = array_merge( 187 | $this->prefixDirsPsr4[$prefix], 188 | (array) $paths 189 | ); 190 | } 191 | } 192 | 193 | /** 194 | * Registers a set of PSR-0 directories for a given prefix, 195 | * replacing any others previously set for this prefix. 196 | * 197 | * @param string $prefix The prefix 198 | * @param array|string $paths The PSR-0 base directories 199 | */ 200 | public function set($prefix, $paths) 201 | { 202 | if (!$prefix) { 203 | $this->fallbackDirsPsr0 = (array) $paths; 204 | } else { 205 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 206 | } 207 | } 208 | 209 | /** 210 | * Registers a set of PSR-4 directories for a given namespace, 211 | * replacing any others previously set for this namespace. 212 | * 213 | * @param string $prefix The prefix/namespace, with trailing '\\' 214 | * @param array|string $paths The PSR-4 base directories 215 | * 216 | * @throws \InvalidArgumentException 217 | */ 218 | public function setPsr4($prefix, $paths) 219 | { 220 | if (!$prefix) { 221 | $this->fallbackDirsPsr4 = (array) $paths; 222 | } else { 223 | $length = strlen($prefix); 224 | if ('\\' !== $prefix[$length - 1]) { 225 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 226 | } 227 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 228 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 229 | } 230 | } 231 | 232 | /** 233 | * Turns on searching the include path for class files. 234 | * 235 | * @param bool $useIncludePath 236 | */ 237 | public function setUseIncludePath($useIncludePath) 238 | { 239 | $this->useIncludePath = $useIncludePath; 240 | } 241 | 242 | /** 243 | * Can be used to check if the autoloader uses the include path to check 244 | * for classes. 245 | * 246 | * @return bool 247 | */ 248 | public function getUseIncludePath() 249 | { 250 | return $this->useIncludePath; 251 | } 252 | 253 | /** 254 | * Turns off searching the prefix and fallback directories for classes 255 | * that have not been registered with the class map. 256 | * 257 | * @param bool $classMapAuthoritative 258 | */ 259 | public function setClassMapAuthoritative($classMapAuthoritative) 260 | { 261 | $this->classMapAuthoritative = $classMapAuthoritative; 262 | } 263 | 264 | /** 265 | * Should class lookup fail if not found in the current class map? 266 | * 267 | * @return bool 268 | */ 269 | public function isClassMapAuthoritative() 270 | { 271 | return $this->classMapAuthoritative; 272 | } 273 | 274 | /** 275 | * Registers this instance as an autoloader. 276 | * 277 | * @param bool $prepend Whether to prepend the autoloader or not 278 | */ 279 | public function register($prepend = false) 280 | { 281 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 282 | } 283 | 284 | /** 285 | * Unregisters this instance as an autoloader. 286 | */ 287 | public function unregister() 288 | { 289 | spl_autoload_unregister(array($this, 'loadClass')); 290 | } 291 | 292 | /** 293 | * Loads the given class or interface. 294 | * 295 | * @param string $class The name of the class 296 | * @return bool|null True if loaded, null otherwise 297 | */ 298 | public function loadClass($class) 299 | { 300 | if ($file = $this->findFile($class)) { 301 | includeFile($file); 302 | 303 | return true; 304 | } 305 | } 306 | 307 | /** 308 | * Finds the path to the file where the class is defined. 309 | * 310 | * @param string $class The name of the class 311 | * 312 | * @return string|false The path if found, false otherwise 313 | */ 314 | public function findFile($class) 315 | { 316 | // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 317 | if ('\\' == $class[0]) { 318 | $class = substr($class, 1); 319 | } 320 | 321 | // class map lookup 322 | if (isset($this->classMap[$class])) { 323 | return $this->classMap[$class]; 324 | } 325 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { 326 | return false; 327 | } 328 | 329 | $file = $this->findFileWithExtension($class, '.php'); 330 | 331 | // Search for Hack files if we are running on HHVM 332 | if (false === $file && defined('HHVM_VERSION')) { 333 | $file = $this->findFileWithExtension($class, '.hh'); 334 | } 335 | 336 | if (false === $file) { 337 | // Remember that this class does not exist. 338 | $this->missingClasses[$class] = true; 339 | } 340 | 341 | return $file; 342 | } 343 | 344 | private function findFileWithExtension($class, $ext) 345 | { 346 | // PSR-4 lookup 347 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 348 | 349 | $first = $class[0]; 350 | if (isset($this->prefixLengthsPsr4[$first])) { 351 | foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { 352 | if (0 === strpos($class, $prefix)) { 353 | foreach ($this->prefixDirsPsr4[$prefix] as $dir) { 354 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { 355 | return $file; 356 | } 357 | } 358 | } 359 | } 360 | } 361 | 362 | // PSR-4 fallback dirs 363 | foreach ($this->fallbackDirsPsr4 as $dir) { 364 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 365 | return $file; 366 | } 367 | } 368 | 369 | // PSR-0 lookup 370 | if (false !== $pos = strrpos($class, '\\')) { 371 | // namespaced class name 372 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 373 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 374 | } else { 375 | // PEAR-like class name 376 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 377 | } 378 | 379 | if (isset($this->prefixesPsr0[$first])) { 380 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 381 | if (0 === strpos($class, $prefix)) { 382 | foreach ($dirs as $dir) { 383 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 384 | return $file; 385 | } 386 | } 387 | } 388 | } 389 | } 390 | 391 | // PSR-0 fallback dirs 392 | foreach ($this->fallbackDirsPsr0 as $dir) { 393 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 394 | return $file; 395 | } 396 | } 397 | 398 | // PSR-0 include paths. 399 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 400 | return $file; 401 | } 402 | 403 | return false; 404 | } 405 | } 406 | 407 | /** 408 | * Scope isolated include. 409 | * 410 | * Prevents access to $this/self from included files. 411 | */ 412 | function includeFile($file) 413 | { 414 | include $file; 415 | } 416 | -------------------------------------------------------------------------------- /workerman-chat-for-win/Applications/Chat/Web/js/web_socket.js: -------------------------------------------------------------------------------- 1 | // Copyright: Hiroshi Ichikawa 2 | // License: New BSD License 3 | // Reference: http://dev.w3.org/html5/websockets/ 4 | // Reference: http://tools.ietf.org/html/rfc6455 5 | 6 | (function() { 7 | 8 | if (window.WEB_SOCKET_FORCE_FLASH) { 9 | // Keeps going. 10 | } else if (window.WebSocket) { 11 | return; 12 | } else if (window.MozWebSocket) { 13 | // Firefox. 14 | window.WebSocket = MozWebSocket; 15 | return; 16 | } 17 | 18 | var logger; 19 | if (window.WEB_SOCKET_LOGGER) { 20 | logger = WEB_SOCKET_LOGGER; 21 | } else if (window.console && window.console.log && window.console.error) { 22 | // In some environment, console is defined but console.log or console.error is missing. 23 | logger = window.console; 24 | } else { 25 | logger = {log: function(){ }, error: function(){ }}; 26 | } 27 | 28 | // swfobject.hasFlashPlayerVersion("10.0.0") doesn't work with Gnash. 29 | if (swfobject.getFlashPlayerVersion().major < 10) { 30 | logger.error("Flash Player >= 10.0.0 is required."); 31 | return; 32 | } 33 | if (location.protocol == "file:") { 34 | logger.error( 35 | "WARNING: web-socket-js doesn't work in file:///... URL " + 36 | "unless you set Flash Security Settings properly. " + 37 | "Open the page via Web server i.e. http://..."); 38 | } 39 | 40 | /** 41 | * Our own implementation of WebSocket class using Flash. 42 | * @param {string} url 43 | * @param {array or string} protocols 44 | * @param {string} proxyHost 45 | * @param {int} proxyPort 46 | * @param {string} headers 47 | */ 48 | window.WebSocket = function(url, protocols, proxyHost, proxyPort, headers) { 49 | var self = this; 50 | self.__id = WebSocket.__nextId++; 51 | WebSocket.__instances[self.__id] = self; 52 | self.readyState = WebSocket.CONNECTING; 53 | self.bufferedAmount = 0; 54 | self.__events = {}; 55 | if (!protocols) { 56 | protocols = []; 57 | } else if (typeof protocols == "string") { 58 | protocols = [protocols]; 59 | } 60 | // Uses setTimeout() to make sure __createFlash() runs after the caller sets ws.onopen etc. 61 | // Otherwise, when onopen fires immediately, onopen is called before it is set. 62 | self.__createTask = setTimeout(function() { 63 | WebSocket.__addTask(function() { 64 | self.__createTask = null; 65 | WebSocket.__flash.create( 66 | self.__id, url, protocols, proxyHost || null, proxyPort || 0, headers || null); 67 | }); 68 | }, 0); 69 | }; 70 | 71 | /** 72 | * Send data to the web socket. 73 | * @param {string} data The data to send to the socket. 74 | * @return {boolean} True for success, false for failure. 75 | */ 76 | WebSocket.prototype.send = function(data) { 77 | if (this.readyState == WebSocket.CONNECTING) { 78 | throw "INVALID_STATE_ERR: Web Socket connection has not been established"; 79 | } 80 | // We use encodeURIComponent() here, because FABridge doesn't work if 81 | // the argument includes some characters. We don't use escape() here 82 | // because of this: 83 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#escape_and_unescape_Functions 84 | // But it looks decodeURIComponent(encodeURIComponent(s)) doesn't 85 | // preserve all Unicode characters either e.g. "\uffff" in Firefox. 86 | // Note by wtritch: Hopefully this will not be necessary using ExternalInterface. Will require 87 | // additional testing. 88 | var result = WebSocket.__flash.send(this.__id, encodeURIComponent(data)); 89 | if (result < 0) { // success 90 | return true; 91 | } else { 92 | this.bufferedAmount += result; 93 | return false; 94 | } 95 | }; 96 | 97 | /** 98 | * Close this web socket gracefully. 99 | */ 100 | WebSocket.prototype.close = function() { 101 | if (this.__createTask) { 102 | clearTimeout(this.__createTask); 103 | this.__createTask = null; 104 | this.readyState = WebSocket.CLOSED; 105 | return; 106 | } 107 | if (this.readyState == WebSocket.CLOSED || this.readyState == WebSocket.CLOSING) { 108 | return; 109 | } 110 | this.readyState = WebSocket.CLOSING; 111 | WebSocket.__flash.close(this.__id); 112 | }; 113 | 114 | /** 115 | * Implementation of {@link DOM 2 EventTarget Interface} 116 | * 117 | * @param {string} type 118 | * @param {function} listener 119 | * @param {boolean} useCapture 120 | * @return void 121 | */ 122 | WebSocket.prototype.addEventListener = function(type, listener, useCapture) { 123 | if (!(type in this.__events)) { 124 | this.__events[type] = []; 125 | } 126 | this.__events[type].push(listener); 127 | }; 128 | 129 | /** 130 | * Implementation of {@link DOM 2 EventTarget Interface} 131 | * 132 | * @param {string} type 133 | * @param {function} listener 134 | * @param {boolean} useCapture 135 | * @return void 136 | */ 137 | WebSocket.prototype.removeEventListener = function(type, listener, useCapture) { 138 | if (!(type in this.__events)) return; 139 | var events = this.__events[type]; 140 | for (var i = events.length - 1; i >= 0; --i) { 141 | if (events[i] === listener) { 142 | events.splice(i, 1); 143 | break; 144 | } 145 | } 146 | }; 147 | 148 | /** 149 | * Implementation of {@link DOM 2 EventTarget Interface} 150 | * 151 | * @param {Event} event 152 | * @return void 153 | */ 154 | WebSocket.prototype.dispatchEvent = function(event) { 155 | var events = this.__events[event.type] || []; 156 | for (var i = 0; i < events.length; ++i) { 157 | events[i](event); 158 | } 159 | var handler = this["on" + event.type]; 160 | if (handler) handler.apply(this, [event]); 161 | }; 162 | 163 | /** 164 | * Handles an event from Flash. 165 | * @param {Object} flashEvent 166 | */ 167 | WebSocket.prototype.__handleEvent = function(flashEvent) { 168 | 169 | if ("readyState" in flashEvent) { 170 | this.readyState = flashEvent.readyState; 171 | } 172 | if ("protocol" in flashEvent) { 173 | this.protocol = flashEvent.protocol; 174 | } 175 | 176 | var jsEvent; 177 | if (flashEvent.type == "open" || flashEvent.type == "error") { 178 | jsEvent = this.__createSimpleEvent(flashEvent.type); 179 | } else if (flashEvent.type == "close") { 180 | jsEvent = this.__createSimpleEvent("close"); 181 | jsEvent.wasClean = flashEvent.wasClean ? true : false; 182 | jsEvent.code = flashEvent.code; 183 | jsEvent.reason = flashEvent.reason; 184 | } else if (flashEvent.type == "message") { 185 | var data = decodeURIComponent(flashEvent.message); 186 | jsEvent = this.__createMessageEvent("message", data); 187 | } else { 188 | throw "unknown event type: " + flashEvent.type; 189 | } 190 | 191 | this.dispatchEvent(jsEvent); 192 | 193 | }; 194 | 195 | WebSocket.prototype.__createSimpleEvent = function(type) { 196 | if (document.createEvent && window.Event) { 197 | var event = document.createEvent("Event"); 198 | event.initEvent(type, false, false); 199 | return event; 200 | } else { 201 | return {type: type, bubbles: false, cancelable: false}; 202 | } 203 | }; 204 | 205 | WebSocket.prototype.__createMessageEvent = function(type, data) { 206 | if (window.MessageEvent && typeof(MessageEvent) == "function" && !window.opera) { 207 | return new MessageEvent("message", { 208 | "view": window, 209 | "bubbles": false, 210 | "cancelable": false, 211 | "data": data 212 | }); 213 | } else if (document.createEvent && window.MessageEvent && !window.opera) { 214 | var event = document.createEvent("MessageEvent"); 215 | event.initMessageEvent("message", false, false, data, null, null, window, null); 216 | return event; 217 | } else { 218 | // Old IE and Opera, the latter one truncates the data parameter after any 0x00 bytes. 219 | return {type: type, data: data, bubbles: false, cancelable: false}; 220 | } 221 | }; 222 | 223 | /** 224 | * Define the WebSocket readyState enumeration. 225 | */ 226 | WebSocket.CONNECTING = 0; 227 | WebSocket.OPEN = 1; 228 | WebSocket.CLOSING = 2; 229 | WebSocket.CLOSED = 3; 230 | 231 | // Field to check implementation of WebSocket. 232 | WebSocket.__isFlashImplementation = true; 233 | WebSocket.__initialized = false; 234 | WebSocket.__flash = null; 235 | WebSocket.__instances = {}; 236 | WebSocket.__tasks = []; 237 | WebSocket.__nextId = 0; 238 | 239 | /** 240 | * Load a new flash security policy file. 241 | * @param {string} url 242 | */ 243 | WebSocket.loadFlashPolicyFile = function(url){ 244 | WebSocket.__addTask(function() { 245 | WebSocket.__flash.loadManualPolicyFile(url); 246 | }); 247 | }; 248 | 249 | /** 250 | * Loads WebSocketMain.swf and creates WebSocketMain object in Flash. 251 | */ 252 | WebSocket.__initialize = function() { 253 | 254 | if (WebSocket.__initialized) return; 255 | WebSocket.__initialized = true; 256 | 257 | if (WebSocket.__swfLocation) { 258 | // For backword compatibility. 259 | window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation; 260 | } 261 | if (!window.WEB_SOCKET_SWF_LOCATION) { 262 | logger.error("[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf"); 263 | return; 264 | } 265 | if (!window.WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR && 266 | !WEB_SOCKET_SWF_LOCATION.match(/(^|\/)WebSocketMainInsecure\.swf(\?.*)?$/) && 267 | WEB_SOCKET_SWF_LOCATION.match(/^\w+:\/\/([^\/]+)/)) { 268 | var swfHost = RegExp.$1; 269 | if (location.host != swfHost) { 270 | logger.error( 271 | "[WebSocket] You must host HTML and WebSocketMain.swf in the same host " + 272 | "('" + location.host + "' != '" + swfHost + "'). " + 273 | "See also 'How to host HTML file and SWF file in different domains' section " + 274 | "in README.md. If you use WebSocketMainInsecure.swf, you can suppress this message " + 275 | "by WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;"); 276 | } 277 | } 278 | var container = document.createElement("div"); 279 | container.id = "webSocketContainer"; 280 | // Hides Flash box. We cannot use display: none or visibility: hidden because it prevents 281 | // Flash from loading at least in IE. So we move it out of the screen at (-100, -100). 282 | // But this even doesn't work with Flash Lite (e.g. in Droid Incredible). So with Flash 283 | // Lite, we put it at (0, 0). This shows 1x1 box visible at left-top corner but this is 284 | // the best we can do as far as we know now. 285 | container.style.position = "absolute"; 286 | if (WebSocket.__isFlashLite()) { 287 | container.style.left = "0px"; 288 | container.style.top = "0px"; 289 | } else { 290 | container.style.left = "-100px"; 291 | container.style.top = "-100px"; 292 | } 293 | var holder = document.createElement("div"); 294 | holder.id = "webSocketFlash"; 295 | container.appendChild(holder); 296 | document.body.appendChild(container); 297 | // See this article for hasPriority: 298 | // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html 299 | swfobject.embedSWF( 300 | WEB_SOCKET_SWF_LOCATION, 301 | "webSocketFlash", 302 | "1" /* width */, 303 | "1" /* height */, 304 | "10.0.0" /* SWF version */, 305 | null, 306 | null, 307 | {hasPriority: true, swliveconnect : true, allowScriptAccess: "always"}, 308 | null, 309 | function(e) { 310 | if (!e.success) { 311 | logger.error("[WebSocket] swfobject.embedSWF failed"); 312 | } 313 | } 314 | ); 315 | 316 | }; 317 | 318 | /** 319 | * Called by Flash to notify JS that it's fully loaded and ready 320 | * for communication. 321 | */ 322 | WebSocket.__onFlashInitialized = function() { 323 | // We need to set a timeout here to avoid round-trip calls 324 | // to flash during the initialization process. 325 | setTimeout(function() { 326 | WebSocket.__flash = document.getElementById("webSocketFlash"); 327 | WebSocket.__flash.setCallerUrl(location.href); 328 | WebSocket.__flash.setDebug(!!window.WEB_SOCKET_DEBUG); 329 | for (var i = 0; i < WebSocket.__tasks.length; ++i) { 330 | WebSocket.__tasks[i](); 331 | } 332 | WebSocket.__tasks = []; 333 | }, 0); 334 | }; 335 | 336 | /** 337 | * Called by Flash to notify WebSockets events are fired. 338 | */ 339 | WebSocket.__onFlashEvent = function() { 340 | setTimeout(function() { 341 | try { 342 | // Gets events using receiveEvents() instead of getting it from event object 343 | // of Flash event. This is to make sure to keep message order. 344 | // It seems sometimes Flash events don't arrive in the same order as they are sent. 345 | var events = WebSocket.__flash.receiveEvents(); 346 | for (var i = 0; i < events.length; ++i) { 347 | WebSocket.__instances[events[i].webSocketId].__handleEvent(events[i]); 348 | } 349 | } catch (e) { 350 | logger.error(e); 351 | } 352 | }, 0); 353 | return true; 354 | }; 355 | 356 | // Called by Flash. 357 | WebSocket.__log = function(message) { 358 | logger.log(decodeURIComponent(message)); 359 | }; 360 | 361 | // Called by Flash. 362 | WebSocket.__error = function(message) { 363 | logger.error(decodeURIComponent(message)); 364 | }; 365 | 366 | WebSocket.__addTask = function(task) { 367 | if (WebSocket.__flash) { 368 | task(); 369 | } else { 370 | WebSocket.__tasks.push(task); 371 | } 372 | }; 373 | 374 | /** 375 | * Test if the browser is running flash lite. 376 | * @return {boolean} True if flash lite is running, false otherwise. 377 | */ 378 | WebSocket.__isFlashLite = function() { 379 | if (!window.navigator || !window.navigator.mimeTypes) { 380 | return false; 381 | } 382 | var mimeType = window.navigator.mimeTypes["application/x-shockwave-flash"]; 383 | if (!mimeType || !mimeType.enabledPlugin || !mimeType.enabledPlugin.filename) { 384 | return false; 385 | } 386 | return mimeType.enabledPlugin.filename.match(/flashlite/i) ? true : false; 387 | }; 388 | 389 | if (!window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION) { 390 | // NOTE: 391 | // This fires immediately if web_socket.js is dynamically loaded after 392 | // the document is loaded. 393 | swfobject.addDomLoadEvent(function() { 394 | WebSocket.__initialize(); 395 | }); 396 | } 397 | 398 | })(); 399 | -------------------------------------------------------------------------------- /workerman-chat-for-win/Applications/Chat/Web/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.0.1 by @fat and @mdo 3 | * Copyright 2013 Twitter, Inc. 4 | * Licensed under http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Designed and built with all the love in the world by @mdo and @fat. 7 | */ 8 | 9 | .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e0e0e0));background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-moz-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe0e0e0',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#2d6ca2));background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-moz-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);background-repeat:repeat-x;border-color:#2b669a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff2d6ca2',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#419641));background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);background-repeat:repeat-x;border-color:#3e8f3e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff419641',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#eb9316));background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);background-repeat:repeat-x;border-color:#e38d13;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffeb9316',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c12e2a));background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);background-repeat:repeat-x;border-color:#b92c28;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc12e2a',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.btn-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#2aabd2));background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);background-repeat:repeat-x;border-color:#28a4c9;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2aabd2',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar-default{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#f8f8f8));background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-moz-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f3f3f3));background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff3f3f3',GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.075);box-shadow:inset 0 3px 9px rgba(0,0,0,0.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-gradient(linear,left 0,left 100%,from(#3c3c3c),to(#222));background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-moz-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-gradient(linear,left 0,left 100%,from(#222),to(#282828));background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:-moz-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff282828',GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.25);box-shadow:inset 0 3px 9px rgba(0,0,0,0.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#c8e5bc));background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#b9def0));background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#f8efc0));background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#e7c3c3));background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-moz-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3278b3));background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-moz-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#d0e9c6));background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#c4e3f3));background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#faf2cc));background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#ebcccc));background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-moz-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-gradient(linear,left 0,left 100%,from(#e8e8e8),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-moz-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} --------------------------------------------------------------------------------