Commit 45ebad99 authored by shajiaiming's avatar shajiaiming

Merge branch 'feature/ws_ticker' into 'master'

Feature/ws ticker See merge request !118
parents a5694867 95db9035
......@@ -8,6 +8,7 @@
namespace api\controllers;
use common\service\exchange\ExchangeBuilderFactory;
use Yii;
use api\base\BaseController;
use common\models\pwallet\Notice;
......@@ -29,10 +30,10 @@ class NoticeController extends BaseController
*/
public function actionList()
{
$request = Yii::$app->request;
$page = $request->post('page', 1);
$limit = $request->post('limit', 10);
$post = $request->post();
$request = Yii::$app->request;
$page = $request->post('page', 1);
$limit = $request->post('limit', 10);
$post = $request->post();
$condition = [];
$post = array_filter($post, function ($value, $key) {
......@@ -65,4 +66,32 @@ class NoticeController extends BaseController
$data = Notice::getList($page, $limit, $condition);
return $data;
}
public function actionIndex()
{
$id = Yii::$app->request->get('id', '');
$page = Yii::$app->request->get('page', 1);
$size = Yii::$app->request->get('size', 10);
$exchange = Yii::$app->request->get('exchange', 'zhaobi');
$exchange_arr = ['huobi', 'binance', 'okex', 'zhaobi'];
if (!in_array($exchange, $exchange_arr)) {
$msg = '不存在的交易平台';
$code = -1;
$data = [];
goto doEnd;
}
$params = [
'id' => $id,
'page' => $page,
'size' => $size
];
$builder = ExchangeBuilderFactory::create($exchange);
$result = $builder->getNotice($params);
$code = $result['code'];
$data = $result['notice'];
$msg = isset($result['msg']) ? $result['msg'] : 'success';
doEnd :
return ['code' => $code, 'msg' => $msg, 'data' => $data];
}
}
\ No newline at end of file
<?php
namespace api\controllers;
use linslin\yii2\curl\Curl;
use Yii;
use api\base\BaseController;
use common\models\psources\CoinOptional;
use common\service\exchange\ExchangeFactory;
use common\service\exchange\ExchangeBuilderFactory;
use yii\helpers\ArrayHelper;
class TickerController extends BaseController
{
protected $basic_coin = ['ETH', 'BTC', 'USDT', 'BTY'];
protected $basic_price = [];
public function init()
{
$curl = new Curl();
$data = [
"names" => [
"eth,ethereum",
"btc,btc",
"usdt,ethereum",
"bty,bty",
]
];
$params = json_encode($data);
$curl->setHeader('Content-Type', 'application/json');
$curl->setRawPostData($params);
$res = $curl->post('https://b.biqianbao.net/interface/coin/coin-index', true);
$res = json_decode($res, true);
foreach ($res['data'] as $val) {
$this->basic_price[$val['name']] = $val['rmb'];
}
}
public function actionIndex()
{
$device_code = Yii::$app->request->get('device_code', '');
$exchange = Yii::$app->request->get('exchange', 'zhaobi');
$exchange_arr = ['huobi', 'binance', 'okex', 'zhaobi'];
if (!in_array($exchange, $exchange_arr)) {
$msg = '不存在的交易平台';
$code = -1;
$data = [];
goto doEnd;
}
$builder = ExchangeBuilderFactory::create($exchange);
$result = $builder->getTickerFromCache();
$code = $result['code'];
$data = $result['ticker'];
if (false != $device_code) {
$coin_optional = CoinOptional::find()->select('symbol')->where(['platform' => $exchange, 'device_code' => $device_code])->asArray()->all();
$coin_optional = ArrayHelper::getColumn($coin_optional, 'symbol');
foreach ($data as &$val) {
if (in_array($val['symbol'], $coin_optional)) {
$val['optional'] = true;
}
}
}
$msg = 'success';
doEnd :
return ['code' => $code, 'msg' => $msg, 'data' => $data];
}
public function actionOptional()
{
$code = -1;
$msg = 'fail';
$data = null;
$request = Yii::$app->request;
if ($request->isPost) {
$symbol = $request->post('symbol', '');
$platform = $request->post('platform', '');
$device_code = $request->post('device_code', '');
if (empty($symbol) || empty($platform) || empty($device_code)) {
$msg = '参数错误';
goto doEnd;
}
$model = CoinOptional::find()->where(['device_code' => $device_code, 'symbol' => $symbol])->one();
if ($model) {
$msg = '数据已存在!';
goto doEnd;
}
$model = new CoinOptional();
$model->setScenario(CoinOptional::SCENARIOS_CREATE);
if ($model->load(Yii::$app->request->post(), '') && $model->save()) {
$msg = 'success';
$code = 0;
} else {
$msg = current($model->firstErrors);
}
goto doEnd;
}
if ($request->isGet) {
$device_code = $request->get('device_code', '');
if (empty($device_code)) {
$msg = '参数错误';
goto doEnd;
}
$data = $temp = [];
$model = CoinOptional::find()->select('symbol, platform')->where(['device_code' => $device_code])->asArray()->all();
foreach ($model as $val) {
if ('huobi' == $val['platform']) {
$exchange = 'HuoBi';
} else if ('binance' == $val['platform']) {
$exchange = 'Binance';
} else if ('zhaobi' == $val['platform']) {
$exchange = 'Zhaobi';
} else {
}
$symbol = explode('/', $val['symbol']);
$tag_first = $symbol[0];
$tag_second = $symbol[1];
$exchange = ExchangeFactory::createExchange($exchange);
$quotation = $exchange->getTicker(strtolower($tag_first), strtolower($tag_second));
$temp['symbol'] = $val['symbol'];
$temp['currency'] = strtoupper($tag_first);
$temp['base_currency'] = strtoupper($tag_second);
$temp['close'] = (float)sprintf("%0.6f", $quotation['last']);
$temp['close_usd'] = (float)sprintf("%0.6f", $quotation['last'] * $this->basic_price[$tag_second]['usd']);
$temp['close_rmb'] = (float)sprintf("%0.4f", $quotation['last'] * $this->basic_price[$tag_second]['rmb']);
$temp['change'] = (float)sprintf("%0.4f", ($quotation['last'] - $quotation['open']) / $quotation['open'] * 100);
$temp['high_usd'] = (float)sprintf("%0.4f", $quotation['high'] * $this->basic_price[$tag_second]['usd']);
$temp['low_usd'] = (float)sprintf("%0.4f", $quotation['low'] * $this->basic_price[$tag_second]['usd']);
$temp['high_rmb'] = (float)sprintf("%0.4f", $quotation['high'] * $this->basic_price[$tag_second]['rmb']);
$temp['low_rmb'] = (float)sprintf("%0.4f", $quotation['low'] * $this->basic_price[$tag_second]['rmb']);
$temp['platform_us'] = $val['platform'];
if ('ZHAOBI' == strtoupper($val['platform'])) {
$temp['platform_zh'] = '找币';
}
if ('HUOBI' == strtoupper($val['platform'])) {
$temp['platform_zh'] = '火币';
}
if ('BINANCE' == strtoupper($val['platform'])) {
$temp['platform_zh'] = '币安';
}
array_push($data, $temp);
}
$msg = 'success';
$code = 0;
}
doEnd :
return ['code' => $code, 'msg' => $msg, 'data' => $data];
}
public function actionRemoveOptional()
{
$code = -1;
$msg = 'fail';
$data = null;
$request = Yii::$app->request;
if (!$request->isPost) {
$msg = '请求错误!';
goto doEnd;
}
$symbol = $request->post('symbol', '');
$platform = $request->post('platform', '');
$device_code = $request->post('device_code', '');
if (empty($symbol) || empty($device_code) || empty($platform)) {
$msg = '请求参数错误!';
goto doEnd;
}
$model = CoinOptional::find()->where(['symbol' => $symbol, 'platform' => $platform, 'device_code' => $device_code])->one();
if (empty($model)) {
$msg = '数据不存在!';
goto doEnd;
}
if (!$model->delete()) {
$msg = '删除失败!';
goto doEnd;
}
$code = 0;
$msg = 'success';
doEnd :
return ['code' => $code, 'msg' => $msg, 'data' => $data];
}
public function actionHotTicker()
{
$builder = ExchangeBuilderFactory::create('huobi');
$result = $builder->getHotTicker();
$code = $result['code'];
$data = $result['ticker'];
$msg = 'success';
doEnd :
return ['code' => $code, 'msg' => $msg, 'data' => $data];
}
}
\ No newline at end of file
<?php
namespace common\models\psources;
use Yii;
use common\core\BaseActiveRecord;
class CoinOptional extends BaseActiveRecord
{
public static function getDb()
{
return Yii::$app->get('p_sources');
}
public static function tableName()
{
return '{{%coin_optional}}';
}
//定义场景
const SCENARIOS_CREATE = 'create';
public function rules() {
return [
[['symbol','platform', 'device_code'], 'required'],
];
}
public function scenarios() {
$scenarios = [
self:: SCENARIOS_CREATE => ['symbol','platform', 'device_code'],
];
return array_merge( parent:: scenarios(), $scenarios);
}
}
<?php
namespace common\service\exchange;
/**
* Created by PhpStorm.
* User: jiaming
* Date: 2019/8/15
* Time: 10:10
*/
class ExchangeBuilderFactory
{
private static $cached = [];
public static function create($type)
{
if (empty(static::$cached[$type])) {
$type = str_replace(' ', '', ucwords($type));
$class = __NAMESPACE__ . "\\factory\\{$type}Builder";
static::$cached[$type] = new $class;
}
return static::$cached[$type];
}
}
<?php
/**
* Created by PhpStorm.
* User: jiaming
* Date: 2019/8/15
* Time: 10:10
*/
namespace common\service\exchange\factory;
use linslin\yii2\curl\Curl;
class BinanceBuilder extends FactoryService
{
protected $base_url = 'https://api.binance.com';
public function getTicker()
{
$curl = new Curl();
$api = $this->base_url . '/api/v1/ticker/24hr';
$res = $curl->get($api, false);
$ticker = [];
if (is_array($res)) {
$this->code = 0;
foreach ($res as $val) {
foreach ($this->basic_coin as $k => $coin) {
$explode_arr = explode($coin, $val['symbol']);
if (2 == count($explode_arr) && empty($explode_arr[1])) {
$temp = [];
$temp['symbol'] = $explode_arr[0] . '/' . $coin;
$temp['currency'] = strtoupper($explode_arr[0]);
$temp['base_currency'] = strtoupper($coin);
$temp['close'] = number_format($val['lastPrice'], 6, '.', '');
$temp['close_usd'] = (float)sprintf("%0.6f", $val['lastPrice'] * $this->basic_price[$coin]['usd']);
$temp['close_rmb'] = (float)sprintf("%0.4f", $val['lastPrice'] * $this->basic_price[$coin]['rmb']);
$temp['change'] = (float)sprintf("%0.4f", $val['priceChangePercent']);
$temp['high_usd'] = (float)sprintf("%0.4f", $val['highPrice'] * $this->basic_price[$coin]['usd']);
$temp['low_usd'] = (float)sprintf("%0.4f", $val['lowPrice'] * $this->basic_price[$coin]['usd']);
$temp['high_rmb'] = (float)sprintf("%0.4f", $val['highPrice'] * $this->basic_price[$coin]['rmb']);
$temp['low_rmb'] = (float)sprintf("%0.4f", $val['lowPrice'] * $this->basic_price[$coin]['rmb']);
$temp['vol'] = (float)sprintf("%0.4f", $val['volume']);
$temp['optional'] = false;
$temp['platform_zh'] = '币安';
$temp['platform_us'] = 'binance';
array_push($ticker, $temp);
break;
}
}
}
}
return ['code' => $this->code, 'ticker' => $ticker];
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: jiaming
* Date: 2019/8/20
* Time: 10:10
*/
namespace common\service\exchange\factory;
use linslin\yii2\curl\Curl;
abstract class FactoryService
{
protected $code = -1;
protected $basic_coin = ['ETH', 'BTC', 'USDT', 'BTY'];
protected $basic_price = [];
public function __construct()
{
$curl = new Curl();
$data = [
"names" => [
"eth,ethereum",
"btc,btc",
"usdt,ethereum",
"bty,bty",
]
];
$params = json_encode($data);
$curl->setHeader('Content-Type', 'application/json');
$curl->setRawPostData($params);
$res = $curl->post('https://b.biqianbao.net/interface/coin/coin-index', true);
$res = json_decode($res, true);
foreach ($res['data'] as $val) {
$this->basic_price[$val['name']]['rmb'] = $val['rmb'];
$this->basic_price[$val['name']]['usd'] = $val['usd'];
}
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: jiaming
* Date: 2019/8/15
* Time: 10:10
*/
namespace common\service\exchange\factory;
use linslin\yii2\curl\Curl;
class HuobiBuilder extends FactoryService
{
protected $base_url = 'https://api.huobi.pro';
protected $supported_symbol = 'supported_symbol_huobi';
protected $quotation_prefix = 'quotation_huobi_';
public function getTicker()
{
$curl = new Curl();
$api = $this->base_url . '/market/tickers';
$res = $curl->get($api, false);
$ticker = [];
if (isset($res['status']) && 'ok' == $res['status']) {
$this->code = 0;
foreach ($res['data'] as $val) {
foreach ($this->basic_coin as $k => $coin) {
$explode_arr = explode(strtolower($coin), $val['symbol']);
if (2 == count($explode_arr) && empty($explode_arr[1])) {
$temp = [];
$temp['symbol'] = strtoupper($explode_arr[0]) . '/' . $coin;
$temp['currency'] = strtoupper($explode_arr[0]);
$temp['base_currency'] = strtoupper($coin);
$temp['close'] = number_format($val['close'], 6, '.', '');
$temp['close_usd'] = (float)sprintf("%0.6f", $val['close'] * $this->basic_price[$coin]['usd']);
$temp['close_rmb'] = (float)sprintf("%0.4f", $val['close'] * $this->basic_price[$coin]['rmb']);
$temp['change'] = (float)sprintf("%0.4f", ($val['close'] - $val['open']) / $val['open'] * 100);
$temp['high_usd'] = (float)sprintf("%0.4f", $val['high'] * $this->basic_price[$coin]['usd']);
$temp['low_usd'] = (float)sprintf("%0.4f", $val['low'] * $this->basic_price[$coin]['usd']);
$temp['high_rmb'] = (float)sprintf("%0.4f", $val['high'] * $this->basic_price[$coin]['rmb']);
$temp['low_rmb'] = (float)sprintf("%0.4f", $val['low'] * $this->basic_price[$coin]['rmb']);
$temp['vol'] = (float)sprintf("%0.4f", $val['vol']);
$temp['optional'] = false;
$temp['platform_zh'] = '火币';
$temp['platform_us'] = 'huoBi';
array_push($ticker, $temp);
break;
}
}
}
}
return ['code' => $this->code, 'ticker' => $ticker];
}
public function getTickerFromCache()
{
$redis = \Yii::$app->redis;
$keys = $redis->smembers($this->supported_symbol);
$ticker = [];
foreach ($keys as $val) {
foreach ($this->basic_coin as $k => $coin) {
$explode_arr = explode(strtolower($coin), $val);
if (2 == count($explode_arr) && empty($explode_arr[1])) {
list($low, $high, $close, $open, $vol) = $redis->hmget($this->quotation_prefix.strtolower($val), 'low', 'high', 'last', 'open', 'vol');
$temp = [];
$temp['symbol'] = strtoupper($explode_arr[0]) . '/' . $coin;
$temp['currency'] = strtoupper($explode_arr[0]);
$temp['base_currency'] = strtoupper($coin);
$temp['close'] = number_format($close, 6, '.', '');
$temp['close_usd'] = (float)sprintf("%0.6f", $close * $this->basic_price[$coin]['usd']);
$temp['close_rmb'] = (float)sprintf("%0.4f", $close * $this->basic_price[$coin]['rmb']);
$temp['change'] = (false == $open) ? 0 : (float)sprintf("%0.4f", ($close - $open) / $open * 100);
$temp['high_usd'] = (float)sprintf("%0.4f", $high * $this->basic_price[$coin]['usd']);
$temp['low_usd'] = (float)sprintf("%0.4f", $low * $this->basic_price[$coin]['usd']);
$temp['high_rmb'] = (float)sprintf("%0.4f", $high * $this->basic_price[$coin]['rmb']);
$temp['low_rmb'] = (float)sprintf("%0.4f", $low * $this->basic_price[$coin]['rmb']);
$temp['vol'] = (float)sprintf("%0.4f", $vol);
$temp['optional'] = false;
$temp['platform_zh'] = '火币';
$temp['platform_us'] = 'huoBi';
array_push($ticker, $temp);
}
}
}
echo json_encode($ticker);exit;
}
public function getHotTicker()
{
$curl = new Curl();
$api = $this->base_url . '/market/detail';
$symbol = [
'btcusdt',
'ethusdt',
'eosusdt'
];
$ticker = [];
$this->code = 0;
foreach ($symbol as $key => $val) {
$url = $api . '?symbol=' . $val;
$res = $curl->get($url, false);
if (isset($res['status']) && 'ok' == $res['status']) {
$explode_arr = explode('usdt', $val);
$temp = [];
$temp['symbol'] = strtoupper($explode_arr[0]) . '/USDT';
$temp['currency'] = strtoupper($explode_arr[0]);
$temp['base_currency'] = 'USDT';
$temp['close'] = (float)sprintf("%0.6f", $res['tick']['close']);
$temp['close_usd'] = (float)sprintf("%0.6f", $res['tick']['close'] * $this->basic_price['USDT']['usd']);
$temp['close_rmb'] = (float)sprintf("%0.4f", $res['tick']['close'] * $this->basic_price['USDT']['rmb']);
$temp['change'] = (float)sprintf("%0.4f", ($res['tick']['close'] - $res['tick']['open']) / $res['tick']['open'] * 100);
$temp['high_usd'] = (float)sprintf("%0.4f", $res['tick']['high'] * $this->basic_price['USDT']['usd']);
$temp['low_usd'] = (float)sprintf("%0.4f", $res['tick']['low'] * $this->basic_price['USDT']['usd']);
$temp['high_rmb'] = (float)sprintf("%0.4f", $res['tick']['high'] * $this->basic_price['USDT']['rmb']);
$temp['low_rmb'] = (float)sprintf("%0.4f", $res['tick']['low'] * $this->basic_price['USDT']['rmb']);
$temp['vol'] = (float)sprintf("%0.4f", $res['tick']['amount']);
array_push($ticker, $temp);
}
}
return ['code' => $this->code, 'ticker' => $ticker];
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: jiaming
* Date: 2019/8/15
* Time: 10:10
*/
namespace common\service\exchange\factory;
use Yii;
use linslin\yii2\curl\Curl;
class OkexBuilder
{
protected $base_url = 'https://www.okex.com';
protected $base_coin = ['ETH', 'BTC', 'USDT', 'BTC'];
protected $redis;
protected $supported_symbol = 'supported_symbol_bitfinex_v2';
public function __construct()
{
$this->redis = Yii::$app->redis;
}
public function getSymbol()
{
$curl = new Curl();
$api = $this->base_url . '/v2/spot/markets/products';
$res = $curl->get($api, false);
if (isset($res['code']) && 0 == $res['code']) {
foreach ($res['data'] as $val) {
if ($this->redis->sismember($this->supported_symbol, $val['symbol'])) continue;
$this->redis->sadd($this->supported_symbol, $val['symbol']);
}
}
}
public function getTicker()
{
$symbols = $this->redis->smembers($this->supported_symbol);
if (empty($symbols)) $this->getSymbol();
$symbols = $this->redis->smembers($this->supported_symbol);
$curl = new Curl();
$code = -1;
$ticker = [];
foreach ($symbols as $symbol) {
$api = $this->base_url . '/api/v1/ticker.do?symbol=' . $symbol;
$res = $curl->get($api, false);
if (isset($res['ticker'])) {
$code = 0;
$symbol = strtoupper(str_replace('_', '/', $symbol));
$ticker[$symbol]['symbol'] = $symbol;
$ticker[$symbol]['close'] = (float)sprintf("%0.4f", $res['ticker']['last']);
//$ticker[$symbol]['change'] = (float)sprintf(($val['close'] - $val['open']) / $val['open'] * 100);
$ticker[$symbol]['high'] = (float)sprintf("%0.4f", $res['ticker']['high']);
$ticker[$symbol]['low'] = (float)sprintf("%0.4f", $res['ticker']['low']);
$ticker[$symbol]['vol'] = (float)sprintf("%0.4f", $res['ticker']['last']);
}
}
return ['code' => $code, 'ticker' => $ticker];
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: jiaming
* Date: 2019/8/15
* Time: 10:10
*/
namespace common\service\exchange\factory;
use linslin\yii2\curl\Curl;
class ZhaobiBuilder extends FactoryService
{
protected $base_url = 'https://api.biqianbao.top';
public function getTicker()
{
$curl = new Curl();
$api = $this->base_url . '/api/data/Ticker?sort=cname';
$res = $curl->get($api, false);
$ticker = [];
if (isset($res['message']) && 'OK' == $res['message']) {
$this->code = 0;
$ticker_temp = [];
foreach ($res['data'] as $val) {
$ticker_temp = array_merge($ticker_temp, $val);
}
foreach ($ticker_temp as $val) {
foreach ($this->basic_coin as $k => $coin) {
$explode_arr = explode($coin, $val['symbol']);
if (2 == count($explode_arr) && empty($explode_arr[1])) {
$temp = [];
$temp['symbol'] = strtoupper($explode_arr[0]) . '/' . $coin;
$temp['currency'] = strtoupper($explode_arr[0]);
$temp['base_currency'] = strtoupper($coin);
$temp['close'] = (float)sprintf("%0.6f", $val['last']);
$temp['close_usd'] = (float)sprintf("%0.6f", $val['last'] * $this->basic_price[$coin]['usd']);
$temp['close_rmb'] = (float)sprintf("%0.4f", $val['last'] * $this->basic_price[$coin]['rmb']);
$temp['change'] = (float)sprintf("%0.4f", ($val['last'] - $val['open']) / $val['open'] * 100);
$temp['high_usd'] = (float)sprintf("%0.4f", $val['high'] * $this->basic_price[$coin]['usd']);
$temp['low_usd'] = (float)sprintf("%0.4f", $val['low'] * $this->basic_price[$coin]['usd']);
$temp['high_rmb'] = (float)sprintf("%0.4f", $val['high'] * $this->basic_price[$coin]['rmb']);
$temp['low_rmb'] = (float)sprintf("%0.4f", $val['low'] * $this->basic_price[$coin]['rmb']);
$temp['vol'] = (float)sprintf("%0.4f", $val['vol']);
$temp['optional'] = false;
$temp['platform_zh'] = '找币';
$temp['platform_us'] = 'zhaobi';
array_push($ticker, $temp);
break;
}
}
}
}
return ['code' => $this->code, 'ticker' => $ticker];
}
public function getNotice($params = [])
{
$curl = new Curl();
if (isset($params['id']) && !empty($params['id'])) {
$api = $this->base_url . '/api/data/noticedetail?id=' . $params['id'];
$res = $curl->get($api, false);
if (isset($res['message']) && 'OK' == $res['message']) {
$this->code = 0;
$res['data']['abstract'] = str_replace(' ', '', str_replace('&nbsp;', '', $res['data']['abstract']));
$res['data']['content'] = str_replace(' ', '', str_replace('&nbsp;', '', $res['data']['content']));
return ['code' => $this->code, 'notice' => $res['data']];
} else {
return ['code' => $this->code, 'notice' => $res['data'], 'msg' => $res['message']];
}
}
$api = $this->base_url . '/api/data/noticelist?page=' . $params['page'] . '&size=' . $params['size'];
$res = $curl->get($api, false);
if (isset($res['message']) && 'OK' == $res['message']) {
$this->code = 0;
$notices = $res['data']['rows'];
foreach ($notices as &$notice) {
$notice['abstract'] = str_replace(' ', '', str_replace('&nbsp;', '', $notice['abstract']));
}
$data = [
'list' => $notices,
'count' => $res['data']['count']
];
}
return ['code' => $this->code, 'notice' => $data];
}
}
\ No newline at end of file
......@@ -22,7 +22,8 @@
"yiisoft/yii2-redis": "~2.0.0",
"yiisoft/yii2-queue": "~2.0",
"linslin/yii2-curl": "*",
"voku/simple_html_dom": "^4.5"
"voku/simple_html_dom": "^4.5",
"workerman/workerman": "^3.5"
},
"require-dev": {
"yiisoft/yii2-debug": "~2.0.0",
......
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "5ba1a32b2897f378910c9c125cb6e133",
"content-hash": "81ec58b7ecb4528b2f48761c31829869",
"packages": [
{
"name": "bower-asset/bootstrap",
......@@ -1974,6 +1974,52 @@
"time": "2019-05-20T07:56:13+00:00"
},
{
"name": "workerman/workerman",
"version": "v3.5.20",
"source": {
"type": "git",
"url": "https://github.com/walkor/Workerman.git",
"reference": "4d590130310a8d7632f807120c3ca1c0f55ed0d7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/Workerman/zipball/4d590130310a8d7632f807120c3ca1c0f55ed0d7",
"reference": "4d590130310a8d7632f807120c3ca1c0f55ed0d7",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"suggest": {
"ext-event": "For better performance. "
},
"type": "library",
"autoload": {
"psr-4": {
"Workerman\\": "./"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "walkor",
"role": "Developer",
"email": "walkor@workerman.net",
"homepage": "http://www.workerman.net"
}
],
"description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.",
"homepage": "http://www.workerman.net",
"keywords": [
"asynchronous",
"event-loop"
],
"time": "2019-07-02T10:23:18+00:00"
},
{
"name": "yiisoft/yii2",
"version": "2.0.15.1",
"source": {
......
This diff is collapsed.
......@@ -54,6 +54,7 @@ return array(
'kartik\\affix\\' => array($vendorDir . '/kartik-v/yii2-widget-affix'),
'e282486518\\migration\\' => array($vendorDir . '/e282486518/yii2-console-migration'),
'cebe\\markdown\\' => array($vendorDir . '/cebe/markdown'),
'Workerman\\' => array($vendorDir . '/workerman/workerman'),
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
......
......@@ -88,6 +88,7 @@ class ComposerStaticInit33057934f3e7eaaa1ce2d53797277936
),
'W' =>
array (
'Workerman\\' => 10,
'Webmozart\\Assert\\' => 17,
),
'S' =>
......@@ -327,6 +328,10 @@ class ComposerStaticInit33057934f3e7eaaa1ce2d53797277936
array (
0 => __DIR__ . '/..' . '/cebe/markdown',
),
'Workerman\\' =>
array (
0 => __DIR__ . '/..' . '/workerman/workerman',
),
'Webmozart\\Assert\\' =>
array (
0 => __DIR__ . '/..' . '/webmozart/assert/src',
......
......@@ -4547,6 +4547,54 @@
]
},
{
"name": "workerman/workerman",
"version": "v3.5.20",
"version_normalized": "3.5.20.0",
"source": {
"type": "git",
"url": "https://github.com/walkor/Workerman.git",
"reference": "4d590130310a8d7632f807120c3ca1c0f55ed0d7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/Workerman/zipball/4d590130310a8d7632f807120c3ca1c0f55ed0d7",
"reference": "4d590130310a8d7632f807120c3ca1c0f55ed0d7",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"suggest": {
"ext-event": "For better performance. "
},
"time": "2019-07-02T10:23:18+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Workerman\\": "./"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "walkor",
"role": "Developer",
"email": "walkor@workerman.net",
"homepage": "http://www.workerman.net"
}
],
"description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.",
"homepage": "http://www.workerman.net",
"keywords": [
"asynchronous",
"event-loop"
]
},
{
"name": "yiisoft/yii2",
"version": "2.0.15.1",
"version_normalized": "2.0.15.1",
......
logs
.buildpath
.project
.settings
.idea
.DS_Store
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman;
/**
* Autoload.
*/
class Autoloader
{
/**
* Autoload root path.
*
* @var string
*/
protected static $_autoloadRootPath = '';
/**
* Set autoload root path.
*
* @param string $root_path
* @return void
*/
public static function setRootPath($root_path)
{
self::$_autoloadRootPath = $root_path;
}
/**
* Load files by namespace.
*
* @param string $name
* @return boolean
*/
public static function loadByNamespace($name)
{
$class_path = str_replace('\\', DIRECTORY_SEPARATOR, $name);
if (strpos($name, 'Workerman\\') === 0) {
$class_file = __DIR__ . substr($class_path, strlen('Workerman')) . '.php';
} else {
if (self::$_autoloadRootPath) {
$class_file = self::$_autoloadRootPath . DIRECTORY_SEPARATOR . $class_path . '.php';
}
if (empty($class_file) || !is_file($class_file)) {
$class_file = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . "$class_path.php";
}
}
if (is_file($class_file)) {
require_once($class_file);
if (class_exists($name, false)) {
return true;
}
}
return false;
}
}
spl_autoload_register('\Workerman\Autoloader::loadByNamespace');
\ No newline at end of file
This diff is collapsed.
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Connection;
use Workerman\Events\EventInterface;
use Workerman\Worker;
use Exception;
/**
* AsyncTcpConnection.
*/
class AsyncUdpConnection extends UdpConnection
{
/**
* Emitted when socket connection is successfully established.
*
* @var callback
*/
public $onConnect = null;
/**
* Emitted when socket connection closed.
*
* @var callback
*/
public $onClose = null;
/**
* Connected or not.
*
* @var bool
*/
protected $connected = false;
/**
* Context option.
*
* @var array
*/
protected $_contextOption = null;
/**
* Construct.
*
* @param string $remote_address
* @throws Exception
*/
public function __construct($remote_address, $context_option = null)
{
// Get the application layer communication protocol and listening address.
list($scheme, $address) = explode(':', $remote_address, 2);
// Check application layer protocol class.
if ($scheme !== 'udp') {
$scheme = ucfirst($scheme);
$this->protocol = '\\Protocols\\' . $scheme;
if (!class_exists($this->protocol)) {
$this->protocol = "\\Workerman\\Protocols\\$scheme";
if (!class_exists($this->protocol)) {
throw new Exception("class \\Protocols\\$scheme not exist");
}
}
}
$this->_remoteAddress = substr($address, 2);
$this->_contextOption = $context_option;
}
/**
* For udp package.
*
* @param resource $socket
* @return bool
*/
public function baseRead($socket)
{
$recv_buffer = stream_socket_recvfrom($socket, Worker::MAX_UDP_PACKAGE_SIZE, 0, $remote_address);
if (false === $recv_buffer || empty($remote_address)) {
return false;
}
if ($this->onMessage) {
if ($this->protocol) {
$parser = $this->protocol;
$recv_buffer = $parser::decode($recv_buffer, $this);
}
ConnectionInterface::$statistics['total_request']++;
try {
call_user_func($this->onMessage, $this, $recv_buffer);
} catch (\Exception $e) {
Worker::log($e);
exit(250);
} catch (\Error $e) {
Worker::log($e);
exit(250);
}
}
return true;
}
/**
* Sends data on the connection.
*
* @param string $send_buffer
* @param bool $raw
* @return void|boolean
*/
public function send($send_buffer, $raw = false)
{
if (false === $raw && $this->protocol) {
$parser = $this->protocol;
$send_buffer = $parser::encode($send_buffer, $this);
if ($send_buffer === '') {
return null;
}
}
if ($this->connected === false) {
$this->connect();
}
return strlen($send_buffer) === stream_socket_sendto($this->_socket, $send_buffer, 0);
}
/**
* Close connection.
*
* @param mixed $data
* @param bool $raw
*
* @return bool
*/
public function close($data = null, $raw = false)
{
if ($data !== null) {
$this->send($data, $raw);
}
Worker::$globalEvent->del($this->_socket, EventInterface::EV_READ);
fclose($this->_socket);
$this->connected = false;
// Try to emit onClose callback.
if ($this->onClose) {
try {
call_user_func($this->onClose, $this);
} catch (\Exception $e) {
Worker::log($e);
exit(250);
} catch (\Error $e) {
Worker::log($e);
exit(250);
}
}
$this->onConnect = $this->onMessage = $this->onClose = null;
return true;
}
/**
* Connect.
*
* @return void
*/
public function connect()
{
if ($this->connected === true) {
return;
}
if ($this->_contextOption) {
$context = stream_context_create($this->_contextOption);
$this->_socket = stream_socket_client("udp://{$this->_remoteAddress}", $errno, $errmsg,
30, STREAM_CLIENT_CONNECT, $context);
} else {
$this->_socket = stream_socket_client("udp://{$this->_remoteAddress}", $errno, $errmsg);
}
if (!$this->_socket) {
Worker::safeEcho(new \Exception($errmsg));
return;
}
stream_set_blocking($this->_socket, false);
if ($this->onMessage) {
Worker::$globalEvent->add($this->_socket, EventInterface::EV_READ, array($this, 'baseRead'));
}
$this->connected = true;
// Try to emit onConnect callback.
if ($this->onConnect) {
try {
call_user_func($this->onConnect, $this);
} catch (\Exception $e) {
Worker::log($e);
exit(250);
} catch (\Error $e) {
Worker::log($e);
exit(250);
}
}
}
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Connection;
/**
* ConnectionInterface.
*/
abstract class ConnectionInterface
{
/**
* Statistics for status command.
*
* @var array
*/
public static $statistics = array(
'connection_count' => 0,
'total_request' => 0,
'throw_exception' => 0,
'send_fail' => 0,
);
/**
* Emitted when data is received.
*
* @var callback
*/
public $onMessage = null;
/**
* Emitted when the other end of the socket sends a FIN packet.
*
* @var callback
*/
public $onClose = null;
/**
* Emitted when an error occurs with connection.
*
* @var callback
*/
public $onError = null;
/**
* Sends data on the connection.
*
* @param string $send_buffer
* @return void|boolean
*/
abstract public function send($send_buffer);
/**
* Get remote IP.
*
* @return string
*/
abstract public function getRemoteIp();
/**
* Get remote port.
*
* @return int
*/
abstract public function getRemotePort();
/**
* Get remote address.
*
* @return string
*/
abstract public function getRemoteAddress();
/**
* Get local IP.
*
* @return string
*/
abstract public function getLocalIp();
/**
* Get local port.
*
* @return int
*/
abstract public function getLocalPort();
/**
* Get local address.
*
* @return string
*/
abstract public function getLocalAddress();
/**
* Is ipv4.
*
* @return bool
*/
abstract public function isIPv4();
/**
* Is ipv6.
*
* @return bool
*/
abstract public function isIPv6();
/**
* Close connection.
*
* @param $data
* @return void
*/
abstract public function close($data = null);
}
This diff is collapsed.
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Connection;
/**
* UdpConnection.
*/
class UdpConnection extends ConnectionInterface
{
/**
* Application layer protocol.
* The format is like this Workerman\\Protocols\\Http.
*
* @var \Workerman\Protocols\ProtocolInterface
*/
public $protocol = null;
/**
* Udp socket.
*
* @var resource
*/
protected $_socket = null;
/**
* Remote address.
*
* @var string
*/
protected $_remoteAddress = '';
/**
* Construct.
*
* @param resource $socket
* @param string $remote_address
*/
public function __construct($socket, $remote_address)
{
$this->_socket = $socket;
$this->_remoteAddress = $remote_address;
}
/**
* Sends data on the connection.
*
* @param string $send_buffer
* @param bool $raw
* @return void|boolean
*/
public function send($send_buffer, $raw = false)
{
if (false === $raw && $this->protocol) {
$parser = $this->protocol;
$send_buffer = $parser::encode($send_buffer, $this);
if ($send_buffer === '') {
return null;
}
}
return strlen($send_buffer) === stream_socket_sendto($this->_socket, $send_buffer, 0, $this->_remoteAddress);
}
/**
* Get remote IP.
*
* @return string
*/
public function getRemoteIp()
{
$pos = strrpos($this->_remoteAddress, ':');
if ($pos) {
return trim(substr($this->_remoteAddress, 0, $pos), '[]');
}
return '';
}
/**
* Get remote port.
*
* @return int
*/
public function getRemotePort()
{
if ($this->_remoteAddress) {
return (int)substr(strrchr($this->_remoteAddress, ':'), 1);
}
return 0;
}
/**
* Get remote address.
*
* @return string
*/
public function getRemoteAddress()
{
return $this->_remoteAddress;
}
/**
* Get local IP.
*
* @return string
*/
public function getLocalIp()
{
$address = $this->getLocalAddress();
$pos = strrpos($address, ':');
if (!$pos) {
return '';
}
return substr($address, 0, $pos);
}
/**
* Get local port.
*
* @return int
*/
public function getLocalPort()
{
$address = $this->getLocalAddress();
$pos = strrpos($address, ':');
if (!$pos) {
return 0;
}
return (int)substr(strrchr($address, ':'), 1);
}
/**
* Get local address.
*
* @return string
*/
public function getLocalAddress()
{
return (string)@stream_socket_get_name($this->_socket, false);
}
/**
* Is ipv4.
*
* return bool.
*/
public function isIpV4()
{
if ($this->transport === 'unix') {
return false;
}
return strpos($this->getRemoteIp(), ':') === false;
}
/**
* Is ipv6.
*
* return bool.
*/
public function isIpV6()
{
if ($this->transport === 'unix') {
return false;
}
return strpos($this->getRemoteIp(), ':') !== false;
}
/**
* Close connection.
*
* @param mixed $data
* @param bool $raw
* @return bool
*/
public function close($data = null, $raw = false)
{
if ($data !== null) {
$this->send($data, $raw);
}
return true;
}
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author 有个鬼<42765633@qq.com>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Events;
use Workerman\Worker;
/**
* ev eventloop
*/
class Ev implements EventInterface
{
/**
* All listeners for read/write event.
*
* @var array
*/
protected $_allEvents = array();
/**
* Event listeners of signal.
*
* @var array
*/
protected $_eventSignal = array();
/**
* All timer event listeners.
* [func, args, event, flag, time_interval]
*
* @var array
*/
protected $_eventTimer = array();
/**
* Timer id.
*
* @var int
*/
protected static $_timerId = 1;
/**
* Add a timer.
* {@inheritdoc}
*/
public function add($fd, $flag, $func, $args = null)
{
$callback = function ($event, $socket) use ($fd, $func) {
try {
call_user_func($func, $fd);
} catch (\Exception $e) {
Worker::log($e);
exit(250);
} catch (\Error $e) {
Worker::log($e);
exit(250);
}
};
switch ($flag) {
case self::EV_SIGNAL:
$event = new \EvSignal($fd, $callback);
$this->_eventSignal[$fd] = $event;
return true;
case self::EV_TIMER:
case self::EV_TIMER_ONCE:
$repeat = $flag == self::EV_TIMER_ONCE ? 0 : $fd;
$param = array($func, (array)$args, $flag, $fd, self::$_timerId);
$event = new \EvTimer($fd, $repeat, array($this, 'timerCallback'), $param);
$this->_eventTimer[self::$_timerId] = $event;
return self::$_timerId++;
default :
$fd_key = (int)$fd;
$real_flag = $flag === self::EV_READ ? \Ev::READ : \Ev::WRITE;
$event = new \EvIo($fd, $real_flag, $callback);
$this->_allEvents[$fd_key][$flag] = $event;
return true;
}
}
/**
* Remove a timer.
* {@inheritdoc}
*/
public function del($fd, $flag)
{
switch ($flag) {
case self::EV_READ:
case self::EV_WRITE:
$fd_key = (int)$fd;
if (isset($this->_allEvents[$fd_key][$flag])) {
$this->_allEvents[$fd_key][$flag]->stop();
unset($this->_allEvents[$fd_key][$flag]);
}
if (empty($this->_allEvents[$fd_key])) {
unset($this->_allEvents[$fd_key]);
}
break;
case self::EV_SIGNAL:
$fd_key = (int)$fd;
if (isset($this->_eventSignal[$fd_key])) {
$this->_eventSignal[$fd_key]->stop();
unset($this->_eventSignal[$fd_key]);
}
break;
case self::EV_TIMER:
case self::EV_TIMER_ONCE:
if (isset($this->_eventTimer[$fd])) {
$this->_eventTimer[$fd]->stop();
unset($this->_eventTimer[$fd]);
}
break;
}
return true;
}
/**
* Timer callback.
*
* @param \EvWatcher $event
*/
public function timerCallback($event)
{
$param = $event->data;
$timer_id = $param[4];
if ($param[2] === self::EV_TIMER_ONCE) {
$this->_eventTimer[$timer_id]->stop();
unset($this->_eventTimer[$timer_id]);
}
try {
call_user_func_array($param[0], $param[1]);
} catch (\Exception $e) {
Worker::log($e);
exit(250);
} catch (\Error $e) {
Worker::log($e);
exit(250);
}
}
/**
* Remove all timers.
*
* @return void
*/
public function clearAllTimer()
{
foreach ($this->_eventTimer as $event) {
$event->stop();
}
$this->_eventTimer = array();
}
/**
* Main loop.
*
* @see EventInterface::loop()
*/
public function loop()
{
\Ev::run();
}
/**
* Destroy loop.
*
* @return void
*/
public function destroy()
{
foreach ($this->_allEvents as $event) {
$event->stop();
}
}
/**
* Get timer count.
*
* @return integer
*/
public function getTimerCount()
{
return count($this->_eventTimer);
}
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author 有个鬼<42765633@qq.com>
* @copyright 有个鬼<42765633@qq.com>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Events;
use Workerman\Worker;
/**
* libevent eventloop
*/
class Event implements EventInterface
{
/**
* Event base.
* @var object
*/
protected $_eventBase = null;
/**
* All listeners for read/write event.
* @var array
*/
protected $_allEvents = array();
/**
* Event listeners of signal.
* @var array
*/
protected $_eventSignal = array();
/**
* All timer event listeners.
* [func, args, event, flag, time_interval]
* @var array
*/
protected $_eventTimer = array();
/**
* Timer id.
* @var int
*/
protected static $_timerId = 1;
/**
* construct
* @return void
*/
public function __construct()
{
if (class_exists('\\\\EventBase', false)) {
$class_name = '\\\\EventBase';
} else {
$class_name = '\EventBase';
}
$this->_eventBase = new $class_name();
}
/**
* @see EventInterface::add()
*/
public function add($fd, $flag, $func, $args=array())
{
if (class_exists('\\\\Event', false)) {
$class_name = '\\\\Event';
} else {
$class_name = '\Event';
}
switch ($flag) {
case self::EV_SIGNAL:
$fd_key = (int)$fd;
$event = $class_name::signal($this->_eventBase, $fd, $func);
if (!$event||!$event->add()) {
return false;
}
$this->_eventSignal[$fd_key] = $event;
return true;
case self::EV_TIMER:
case self::EV_TIMER_ONCE:
$param = array($func, (array)$args, $flag, $fd, self::$_timerId);
$event = new $class_name($this->_eventBase, -1, $class_name::TIMEOUT|$class_name::PERSIST, array($this, "timerCallback"), $param);
if (!$event||!$event->addTimer($fd)) {
return false;
}
$this->_eventTimer[self::$_timerId] = $event;
return self::$_timerId++;
default :
$fd_key = (int)$fd;
$real_flag = $flag === self::EV_READ ? $class_name::READ | $class_name::PERSIST : $class_name::WRITE | $class_name::PERSIST;
$event = new $class_name($this->_eventBase, $fd, $real_flag, $func, $fd);
if (!$event||!$event->add()) {
return false;
}
$this->_allEvents[$fd_key][$flag] = $event;
return true;
}
}
/**
* @see Events\EventInterface::del()
*/
public function del($fd, $flag)
{
switch ($flag) {
case self::EV_READ:
case self::EV_WRITE:
$fd_key = (int)$fd;
if (isset($this->_allEvents[$fd_key][$flag])) {
$this->_allEvents[$fd_key][$flag]->del();
unset($this->_allEvents[$fd_key][$flag]);
}
if (empty($this->_allEvents[$fd_key])) {
unset($this->_allEvents[$fd_key]);
}
break;
case self::EV_SIGNAL:
$fd_key = (int)$fd;
if (isset($this->_eventSignal[$fd_key])) {
$this->_eventSignal[$fd_key]->del();
unset($this->_eventSignal[$fd_key]);
}
break;
case self::EV_TIMER:
case self::EV_TIMER_ONCE:
if (isset($this->_eventTimer[$fd])) {
$this->_eventTimer[$fd]->del();
unset($this->_eventTimer[$fd]);
}
break;
}
return true;
}
/**
* Timer callback.
* @param null $fd
* @param int $what
* @param int $timer_id
*/
public function timerCallback($fd, $what, $param)
{
$timer_id = $param[4];
if ($param[2] === self::EV_TIMER_ONCE) {
$this->_eventTimer[$timer_id]->del();
unset($this->_eventTimer[$timer_id]);
}
try {
call_user_func_array($param[0], $param[1]);
} catch (\Exception $e) {
Worker::log($e);
exit(250);
} catch (\Error $e) {
Worker::log($e);
exit(250);
}
}
/**
* @see Events\EventInterface::clearAllTimer()
* @return void
*/
public function clearAllTimer()
{
foreach ($this->_eventTimer as $event) {
$event->del();
}
$this->_eventTimer = array();
}
/**
* @see EventInterface::loop()
*/
public function loop()
{
$this->_eventBase->loop();
}
/**
* Destroy loop.
*
* @return void
*/
public function destroy()
{
foreach ($this->_eventSignal as $event) {
$event->del();
}
}
/**
* Get timer count.
*
* @return integer
*/
public function getTimerCount()
{
return count($this->_eventTimer);
}
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Events;
interface EventInterface
{
/**
* Read event.
*
* @var int
*/
const EV_READ = 1;
/**
* Write event.
*
* @var int
*/
const EV_WRITE = 2;
/**
* Except event
*
* @var int
*/
const EV_EXCEPT = 3;
/**
* Signal event.
*
* @var int
*/
const EV_SIGNAL = 4;
/**
* Timer event.
*
* @var int
*/
const EV_TIMER = 8;
/**
* Timer once event.
*
* @var int
*/
const EV_TIMER_ONCE = 16;
/**
* Add event listener to event loop.
*
* @param mixed $fd
* @param int $flag
* @param callable $func
* @param mixed $args
* @return bool
*/
public function add($fd, $flag, $func, $args = null);
/**
* Remove event listener from event loop.
*
* @param mixed $fd
* @param int $flag
* @return bool
*/
public function del($fd, $flag);
/**
* Remove all timers.
*
* @return void
*/
public function clearAllTimer();
/**
* Main loop.
*
* @return void
*/
public function loop();
/**
* Destroy loop.
*
* @return mixed
*/
public function destroy();
/**
* Get Timer count.
*
* @return mixed
*/
public function getTimerCount();
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Events;
use Workerman\Worker;
/**
* libevent eventloop
*/
class Libevent implements EventInterface
{
/**
* Event base.
*
* @var resource
*/
protected $_eventBase = null;
/**
* All listeners for read/write event.
*
* @var array
*/
protected $_allEvents = array();
/**
* Event listeners of signal.
*
* @var array
*/
protected $_eventSignal = array();
/**
* All timer event listeners.
* [func, args, event, flag, time_interval]
*
* @var array
*/
protected $_eventTimer = array();
/**
* construct
*/
public function __construct()
{
$this->_eventBase = event_base_new();
}
/**
* {@inheritdoc}
*/
public function add($fd, $flag, $func, $args = array())
{
switch ($flag) {
case self::EV_SIGNAL:
$fd_key = (int)$fd;
$real_flag = EV_SIGNAL | EV_PERSIST;
$this->_eventSignal[$fd_key] = event_new();
if (!event_set($this->_eventSignal[$fd_key], $fd, $real_flag, $func, null)) {
return false;
}
if (!event_base_set($this->_eventSignal[$fd_key], $this->_eventBase)) {
return false;
}
if (!event_add($this->_eventSignal[$fd_key])) {
return false;
}
return true;
case self::EV_TIMER:
case self::EV_TIMER_ONCE:
$event = event_new();
$timer_id = (int)$event;
if (!event_set($event, 0, EV_TIMEOUT, array($this, 'timerCallback'), $timer_id)) {
return false;
}
if (!event_base_set($event, $this->_eventBase)) {
return false;
}
$time_interval = $fd * 1000000;
if (!event_add($event, $time_interval)) {
return false;
}
$this->_eventTimer[$timer_id] = array($func, (array)$args, $event, $flag, $time_interval);
return $timer_id;
default :
$fd_key = (int)$fd;
$real_flag = $flag === self::EV_READ ? EV_READ | EV_PERSIST : EV_WRITE | EV_PERSIST;
$event = event_new();
if (!event_set($event, $fd, $real_flag, $func, null)) {
return false;
}
if (!event_base_set($event, $this->_eventBase)) {
return false;
}
if (!event_add($event)) {
return false;
}
$this->_allEvents[$fd_key][$flag] = $event;
return true;
}
}
/**
* {@inheritdoc}
*/
public function del($fd, $flag)
{
switch ($flag) {
case self::EV_READ:
case self::EV_WRITE:
$fd_key = (int)$fd;
if (isset($this->_allEvents[$fd_key][$flag])) {
event_del($this->_allEvents[$fd_key][$flag]);
unset($this->_allEvents[$fd_key][$flag]);
}
if (empty($this->_allEvents[$fd_key])) {
unset($this->_allEvents[$fd_key]);
}
break;
case self::EV_SIGNAL:
$fd_key = (int)$fd;
if (isset($this->_eventSignal[$fd_key])) {
event_del($this->_eventSignal[$fd_key]);
unset($this->_eventSignal[$fd_key]);
}
break;
case self::EV_TIMER:
case self::EV_TIMER_ONCE:
// 这里 fd 为timerid
if (isset($this->_eventTimer[$fd])) {
event_del($this->_eventTimer[$fd][2]);
unset($this->_eventTimer[$fd]);
}
break;
}
return true;
}
/**
* Timer callback.
*
* @param mixed $_null1
* @param int $_null2
* @param mixed $timer_id
*/
protected function timerCallback($_null1, $_null2, $timer_id)
{
if ($this->_eventTimer[$timer_id][3] === self::EV_TIMER) {
event_add($this->_eventTimer[$timer_id][2], $this->_eventTimer[$timer_id][4]);
}
try {
call_user_func_array($this->_eventTimer[$timer_id][0], $this->_eventTimer[$timer_id][1]);
} catch (\Exception $e) {
Worker::log($e);
exit(250);
} catch (\Error $e) {
Worker::log($e);
exit(250);
}
if (isset($this->_eventTimer[$timer_id]) && $this->_eventTimer[$timer_id][3] === self::EV_TIMER_ONCE) {
$this->del($timer_id, self::EV_TIMER_ONCE);
}
}
/**
* {@inheritdoc}
*/
public function clearAllTimer()
{
foreach ($this->_eventTimer as $task_data) {
event_del($task_data[2]);
}
$this->_eventTimer = array();
}
/**
* {@inheritdoc}
*/
public function loop()
{
event_base_loop($this->_eventBase);
}
/**
* Destroy loop.
*
* @return void
*/
public function destroy()
{
foreach ($this->_eventSignal as $event) {
event_del($event);
}
}
/**
* Get timer count.
*
* @return integer
*/
public function getTimerCount()
{
return count($this->_eventTimer);
}
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Events\React;
use Workerman\Events\EventInterface;
use React\EventLoop\TimerInterface;
/**
* Class StreamSelectLoop
* @package Workerman\Events\React
*/
class Base implements \React\EventLoop\LoopInterface
{
/**
* @var array
*/
protected $_timerIdMap = array();
/**
* @var int
*/
protected $_timerIdIndex = 0;
/**
* @var array
*/
protected $_signalHandlerMap = array();
/**
* @var \React\EventLoop\LoopInterface
*/
protected $_eventLoop = null;
/**
* Base constructor.
*/
public function __construct()
{
$this->_eventLoop = new \React\EventLoop\StreamSelectLoop();
}
/**
* Add event listener to event loop.
*
* @param $fd
* @param $flag
* @param $func
* @param array $args
* @return bool
*/
public function add($fd, $flag, $func, $args = array())
{
$args = (array)$args;
switch ($flag) {
case EventInterface::EV_READ:
return $this->addReadStream($fd, $func);
case EventInterface::EV_WRITE:
return $this->addWriteStream($fd, $func);
case EventInterface::EV_SIGNAL:
if (isset($this->_signalHandlerMap[$fd])) {
$this->removeSignal($fd, $this->_signalHandlerMap[$fd]);
}
$this->_signalHandlerMap[$fd] = $func;
return $this->addSignal($fd, $func);
case EventInterface::EV_TIMER:
$timer_obj = $this->addPeriodicTimer($fd, function() use ($func, $args) {
call_user_func_array($func, $args);
});
$this->_timerIdMap[++$this->_timerIdIndex] = $timer_obj;
return $this->_timerIdIndex;
case EventInterface::EV_TIMER_ONCE:
$index = ++$this->_timerIdIndex;
$timer_obj = $this->addTimer($fd, function() use ($func, $args, $index) {
$this->del($index,EventInterface::EV_TIMER_ONCE);
call_user_func_array($func, $args);
});
$this->_timerIdMap[$index] = $timer_obj;
return $this->_timerIdIndex;
}
return false;
}
/**
* Remove event listener from event loop.
*
* @param mixed $fd
* @param int $flag
* @return bool
*/
public function del($fd, $flag)
{
switch ($flag) {
case EventInterface::EV_READ:
return $this->removeReadStream($fd);
case EventInterface::EV_WRITE:
return $this->removeWriteStream($fd);
case EventInterface::EV_SIGNAL:
if (!isset($this->_eventLoop[$fd])) {
return false;
}
$func = $this->_eventLoop[$fd];
unset($this->_eventLoop[$fd]);
return $this->removeSignal($fd, $func);
case EventInterface::EV_TIMER:
case EventInterface::EV_TIMER_ONCE:
if (isset($this->_timerIdMap[$fd])){
$timer_obj = $this->_timerIdMap[$fd];
unset($this->_timerIdMap[$fd]);
$this->cancelTimer($timer_obj);
return true;
}
}
return false;
}
/**
* Main loop.
*
* @return void
*/
public function loop()
{
$this->run();
}
/**
* Destroy loop.
*
* @return void
*/
public function destroy()
{
}
/**
* Get timer count.
*
* @return integer
*/
public function getTimerCount()
{
return count($this->_timerIdMap);
}
/**
* @param resource $stream
* @param callable $listener
*/
public function addReadStream($stream, $listener)
{
return $this->_eventLoop->addReadStream($stream, $listener);
}
/**
* @param resource $stream
* @param callable $listener
*/
public function addWriteStream($stream, $listener)
{
return $this->_eventLoop->addWriteStream($stream, $listener);
}
/**
* @param resource $stream
*/
public function removeReadStream($stream)
{
return $this->_eventLoop->removeReadStream($stream);
}
/**
* @param resource $stream
*/
public function removeWriteStream($stream)
{
return $this->_eventLoop->removeWriteStream($stream);
}
/**
* @param float|int $interval
* @param callable $callback
* @return \React\EventLoop\Timer\Timer|TimerInterface
*/
public function addTimer($interval, $callback)
{
return $this->_eventLoop->addTimer($interval, $callback);
}
/**
* @param float|int $interval
* @param callable $callback
* @return \React\EventLoop\Timer\Timer|TimerInterface
*/
public function addPeriodicTimer($interval, $callback)
{
return $this->_eventLoop->addPeriodicTimer($interval, $callback);
}
/**
* @param TimerInterface $timer
*/
public function cancelTimer(TimerInterface $timer)
{
return $this->_eventLoop->cancelTimer($timer);
}
/**
* @param callable $listener
*/
public function futureTick($listener)
{
return $this->_eventLoop->futureTick($listener);
}
/**
* @param int $signal
* @param callable $listener
*/
public function addSignal($signal, $listener)
{
return $this->_eventLoop->addSignal($signal, $listener);
}
/**
* @param int $signal
* @param callable $listener
*/
public function removeSignal($signal, $listener)
{
return $this->_eventLoop->removeSignal($signal, $listener);
}
/**
* Run.
*/
public function run()
{
return $this->_eventLoop->run();
}
/**
* Stop.
*/
public function stop()
{
return $this->_eventLoop->stop();
}
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Events\React;
/**
* Class ExtEventLoop
* @package Workerman\Events\React
*/
class ExtEventLoop extends Base
{
public function __construct()
{
$this->_eventLoop = new \React\EventLoop\ExtEventLoop();
}
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Events\React;
use Workerman\Events\EventInterface;
/**
* Class ExtLibEventLoop
* @package Workerman\Events\React
*/
class ExtLibEventLoop extends Base
{
public function __construct()
{
$this->_eventLoop = new \React\EventLoop\ExtLibeventLoop();
}
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Events\React;
/**
* Class StreamSelectLoop
* @package Workerman\Events\React
*/
class StreamSelectLoop extends Base
{
public function __construct()
{
$this->_eventLoop = new \React\EventLoop\StreamSelectLoop();
}
}
This diff is collapsed.
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author Ares<aresrr#qq.com>
* @link http://www.workerman.net/
* @link https://github.com/ares333/Workerman
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Events;
use Swoole\Event;
use Swoole\Timer;
class Swoole implements EventInterface
{
protected $_timer = array();
protected $_timerOnceMap = array();
protected $mapId = 0;
protected $_fd = array();
// milisecond
public static $signalDispatchInterval = 200;
protected $_hasSignal = false;
/**
*
* {@inheritdoc}
*
* @see \Workerman\Events\EventInterface::add()
*/
public function add($fd, $flag, $func, $args = null)
{
if (! isset($args)) {
$args = array();
}
switch ($flag) {
case self::EV_SIGNAL:
$res = pcntl_signal($fd, $func, false);
if (! $this->_hasSignal && $res) {
Timer::tick(static::$signalDispatchInterval,
function () {
pcntl_signal_dispatch();
});
$this->_hasSignal = true;
}
return $res;
case self::EV_TIMER:
case self::EV_TIMER_ONCE:
$method = self::EV_TIMER == $flag ? 'tick' : 'after';
if ($this->mapId > PHP_INT_MAX) {
$this->mapId = 0;
}
$mapId = $this->mapId++;
$timer_id = Timer::$method($fd * 1000,
function ($timer_id = null) use ($func, $args, $mapId) {
call_user_func_array($func, $args);
// EV_TIMER_ONCE
if (! isset($timer_id)) {
// may be deleted in $func
if (array_key_exists($mapId, $this->_timerOnceMap)) {
$timer_id = $this->_timerOnceMap[$mapId];
unset($this->_timer[$timer_id],
$this->_timerOnceMap[$mapId]);
}
}
});
if ($flag == self::EV_TIMER_ONCE) {
$this->_timerOnceMap[$mapId] = $timer_id;
$this->_timer[$timer_id] = $mapId;
} else {
$this->_timer[$timer_id] = null;
}
return $timer_id;
case self::EV_READ:
case self::EV_WRITE:
$fd_key = (int) $fd;
if (! isset($this->_fd[$fd_key])) {
if ($flag == self::EV_READ) {
$res = Event::add($fd, $func, null, SWOOLE_EVENT_READ);
$fd_type = SWOOLE_EVENT_READ;
} else {
$res = Event::add($fd, null, $func, SWOOLE_EVENT_WRITE);
$fd_type = SWOOLE_EVENT_WRITE;
}
if ($res) {
$this->_fd[$fd_key] = $fd_type;
}
} else {
$fd_val = $this->_fd[$fd_key];
$res = true;
if ($flag == self::EV_READ) {
if (($fd_val & SWOOLE_EVENT_READ) != SWOOLE_EVENT_READ) {
$res = Event::set($fd, $func, null,
SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE);
$this->_fd[$fd_key] |= SWOOLE_EVENT_READ;
}
} else {
if (($fd_val & SWOOLE_EVENT_WRITE) != SWOOLE_EVENT_WRITE) {
$res = Event::set($fd, null, $func,
SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE);
$this->_fd[$fd_key] |= SWOOLE_EVENT_WRITE;
}
}
}
return $res;
}
}
/**
*
* {@inheritdoc}
*
* @see \Workerman\Events\EventInterface::del()
*/
public function del($fd, $flag)
{
switch ($flag) {
case self::EV_SIGNAL:
return pcntl_signal($fd, SIG_IGN, false);
case self::EV_TIMER:
case self::EV_TIMER_ONCE:
// already remove in EV_TIMER_ONCE callback.
if (! array_key_exists($fd, $this->_timer)) {
return true;
}
$res = Timer::clear($fd);
if ($res) {
$mapId = $this->_timer[$fd];
if (isset($mapId)) {
unset($this->_timerOnceMap[$mapId]);
}
unset($this->_timer[$fd]);
}
return $res;
case self::EV_READ:
case self::EV_WRITE:
$fd_key = (int) $fd;
if (isset($this->_fd[$fd_key])) {
$fd_val = $this->_fd[$fd_key];
if ($flag == self::EV_READ) {
$flag_remove = ~ SWOOLE_EVENT_READ;
} else {
$flag_remove = ~ SWOOLE_EVENT_WRITE;
}
$fd_val &= $flag_remove;
if (0 === $fd_val) {
$res = Event::del($fd);
if ($res) {
unset($this->_fd[$fd_key]);
}
} else {
$res = Event::set($fd, null, null, $fd_val);
if ($res) {
$this->_fd[$fd_key] = $fd_val;
}
}
} else {
$res = true;
}
return $res;
}
}
/**
*
* {@inheritdoc}
*
* @see \Workerman\Events\EventInterface::clearAllTimer()
*/
public function clearAllTimer()
{
foreach (array_keys($this->_timer) as $v) {
Timer::clear($v);
}
$this->_timer = array();
$this->_timerOnceMap = array();
}
/**
*
* {@inheritdoc}
*
* @see \Workerman\Events\EventInterface::loop()
*/
public function loop()
{
Event::wait();
}
/**
*
* {@inheritdoc}
*
* @see \Workerman\Events\EventInterface::destroy()
*/
public function destroy()
{
//Event::exit();
}
/**
*
* {@inheritdoc}
*
* @see \Workerman\Events\EventInterface::getTimerCount()
*/
public function getTimerCount()
{
return count($this->_timer);
}
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
// Display errors.
ini_set('display_errors', 'on');
// Reporting all.
error_reporting(E_ALL);
// Reset opcache.
if (function_exists('opcache_reset')) {
opcache_reset();
}
// For onError callback.
define('WORKERMAN_CONNECT_FAIL', 1);
// For onError callback.
define('WORKERMAN_SEND_FAIL', 2);
// Define OS Type
define('OS_TYPE_LINUX', 'linux');
define('OS_TYPE_WINDOWS', 'windows');
// Compatible with php7
if(!class_exists('Error'))
{
class Error extends Exception
{
}
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Lib;
use Workerman\Events\EventInterface;
use Workerman\Worker;
use Exception;
/**
* Timer.
*
* example:
* Workerman\Lib\Timer::add($time_interval, callback, array($arg1, $arg2..));
*/
class Timer
{
/**
* Tasks that based on ALARM signal.
* [
* run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]],
* run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]],
* ..
* ]
*
* @var array
*/
protected static $_tasks = array();
/**
* event
*
* @var \Workerman\Events\EventInterface
*/
protected static $_event = null;
/**
* Init.
*
* @param \Workerman\Events\EventInterface $event
* @return void
*/
public static function init($event = null)
{
if ($event) {
self::$_event = $event;
} else {
if (function_exists('pcntl_signal')) {
pcntl_signal(SIGALRM, array('\Workerman\Lib\Timer', 'signalHandle'), false);
}
}
}
/**
* ALARM signal handler.
*
* @return void
*/
public static function signalHandle()
{
if (!self::$_event) {
pcntl_alarm(1);
self::tick();
}
}
/**
* Add a timer.
*
* @param float $time_interval
* @param callable $func
* @param mixed $args
* @param bool $persistent
* @return int/false
*/
public static function add($time_interval, $func, $args = array(), $persistent = true)
{
if ($time_interval <= 0) {
Worker::safeEcho(new Exception("bad time_interval"));
return false;
}
if (self::$_event) {
return self::$_event->add($time_interval,
$persistent ? EventInterface::EV_TIMER : EventInterface::EV_TIMER_ONCE, $func, $args);
}
if (!is_callable($func)) {
Worker::safeEcho(new Exception("not callable"));
return false;
}
if (empty(self::$_tasks)) {
pcntl_alarm(1);
}
$time_now = time();
$run_time = $time_now + $time_interval;
if (!isset(self::$_tasks[$run_time])) {
self::$_tasks[$run_time] = array();
}
self::$_tasks[$run_time][] = array($func, (array)$args, $persistent, $time_interval);
return 1;
}
/**
* Tick.
*
* @return void
*/
public static function tick()
{
if (empty(self::$_tasks)) {
pcntl_alarm(0);
return;
}
$time_now = time();
foreach (self::$_tasks as $run_time => $task_data) {
if ($time_now >= $run_time) {
foreach ($task_data as $index => $one_task) {
$task_func = $one_task[0];
$task_args = $one_task[1];
$persistent = $one_task[2];
$time_interval = $one_task[3];
try {
call_user_func_array($task_func, $task_args);
} catch (\Exception $e) {
Worker::safeEcho($e);
}
if ($persistent) {
self::add($time_interval, $task_func, $task_args);
}
}
unset(self::$_tasks[$run_time]);
}
}
}
/**
* Remove a timer.
*
* @param mixed $timer_id
* @return bool
*/
public static function del($timer_id)
{
if (self::$_event) {
return self::$_event->del($timer_id, EventInterface::EV_TIMER);
}
return false;
}
/**
* Remove all timers.
*
* @return void
*/
public static function delAll()
{
self::$_tasks = array();
pcntl_alarm(0);
if (self::$_event) {
self::$_event->clearAllTimer();
}
}
}
The MIT License
Copyright (c) 2009-2015 walkor<walkor@workerman.net> and contributors (see https://github.com/walkor/workerman/contributors)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Protocols;
use Workerman\Connection\TcpConnection;
/**
* Frame Protocol.
*/
class Frame
{
/**
* Check the integrity of the package.
*
* @param string $buffer
* @param TcpConnection $connection
* @return int
*/
public static function input($buffer, TcpConnection $connection)
{
if (strlen($buffer) < 4) {
return 0;
}
$unpack_data = unpack('Ntotal_length', $buffer);
return $unpack_data['total_length'];
}
/**
* Decode.
*
* @param string $buffer
* @return string
*/
public static function decode($buffer)
{
return substr($buffer, 4);
}
/**
* Encode.
*
* @param string $buffer
* @return string
*/
public static function encode($buffer)
{
$total_length = 4 + strlen($buffer);
return pack('N', $total_length) . $buffer;
}
}
This diff is collapsed.
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/x-javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
image/png png;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
image/svg+xml svg svgz;
image/webp webp;
application/java-archive jar war ear;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.ms-excel xls;
application/vnd.ms-powerpoint ppt;
application/vnd.wap.wmlc wmlc;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/zip zip;
application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream eot;
application/octet-stream iso img;
application/octet-stream msi msp msm;
audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Protocols;
use Workerman\Connection\ConnectionInterface;
/**
* Protocol interface
*/
interface ProtocolInterface
{
/**
* Check the integrity of the package.
* Please return the length of package.
* If length is unknow please return 0 that mean wating more data.
* If the package has something wrong please return false the connection will be closed.
*
* @param ConnectionInterface $connection
* @param string $recv_buffer
* @return int|false
*/
public static function input($recv_buffer, ConnectionInterface $connection);
/**
* Decode package and emit onMessage($message) callback, $message is the result that decode returned.
*
* @param ConnectionInterface $connection
* @param string $recv_buffer
* @return mixed
*/
public static function decode($recv_buffer, ConnectionInterface $connection);
/**
* Encode package brefore sending to client.
*
* @param ConnectionInterface $connection
* @param mixed $data
* @return string
*/
public static function encode($data, ConnectionInterface $connection);
}
<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Protocols;
use Workerman\Connection\TcpConnection;
/**
* Text Protocol.
*/
class Text
{
/**
* Check the integrity of the package.
*
* @param string $buffer
* @param TcpConnection $connection
* @return int
*/
public static function input($buffer, TcpConnection $connection)
{
// Judge whether the package length exceeds the limit.
if (strlen($buffer) >= $connection->maxPackageSize) {
$connection->close();
return 0;
}
// Find the position of "\n".
$pos = strpos($buffer, "\n");
// No "\n", packet length is unknown, continue to wait for the data so return 0.
if ($pos === false) {
return 0;
}
// Return the current package length.
return $pos + 1;
}
/**
* Encode.
*
* @param string $buffer
* @return string
*/
public static function encode($buffer)
{
// Add "\n"
return $buffer . "\n";
}
/**
* Decode.
*
* @param string $buffer
* @return string
*/
public static function decode($buffer)
{
// Remove "\n"
return rtrim($buffer, "\r\n");
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
{
"name": "workerman/workerman",
"type": "library",
"keywords": [
"event-loop",
"asynchronous"
],
"homepage": "http://www.workerman.net",
"license": "MIT",
"description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.",
"authors": [
{
"name": "walkor",
"email": "walkor@workerman.net",
"homepage": "http://www.workerman.net",
"role": "Developer"
}
],
"support": {
"email": "walkor@workerman.net",
"issues": "https://github.com/walkor/workerman/issues",
"forum": "http://wenda.workerman.net/",
"wiki": "http://doc.workerman.net/",
"source": "https://github.com/walkor/workerman"
},
"require": {
"php": ">=5.3"
},
"suggest": {
"ext-event": "For better performance. "
},
"autoload": {
"psr-4": {
"Workerman\\": "./"
}
},
"minimum-stability": "dev"
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment