Browse Source

add to local

stanley-king 4 years ago
parent
commit
912094d724
100 changed files with 3196 additions and 236 deletions
  1. 9 1
      conf/nginx/nginx-debug-http.conf
  2. 11 0
      conf/php/mobile-spwan-start
  3. 2 0
      conf/php/php-debug.ini
  4. 1 1
      conf/php/docker-php-spwan-start
  5. 2 3
      core/framework/core/base.php
  6. 2 2
      core/framework/function/http.php
  7. 2 1
      data/config/dev/refill.ini.php
  8. 36 2
      docker-compose-dev.yml
  9. 0 2
      fooder.php
  10. 0 153
      helper/fcgi_server.php
  11. 92 0
      helper/fcgisrv/BaseServer.php
  12. 128 0
      helper/fcgisrv/MobileServer.php
  13. 57 0
      helper/fcgisrv/RAccServer.php
  14. 2 3
      helper/mtopcard/mtopcard.php
  15. 192 0
      helper/queue/iqueue.php
  16. 42 0
      helper/queue/rdispatcher.php
  17. 20 0
      helper/refill/RefillFactory.php
  18. 1 0
      helper/refill/bjbyd/RefillPhone.php
  19. 1 0
      mobile/control/control.php
  20. 0 5
      mobile/index.php
  21. 49 51
      fcgi_run.php
  22. 146 0
      racc/control/merchant.php
  23. 223 0
      racc/control/refill.php
  24. 8 0
      racc/index.php
  25. 39 0
      rdispatcher/dispatcher.php
  26. 52 0
      rdispatcher/processor.php
  27. 44 0
      rdispatcher/proxy.php
  28. 13 0
      rdispatcher/yzpolicy.php
  29. 94 0
      test/TestDispatcher.php
  30. 0 4
      test/TestRedis.php
  31. 0 8
      test/TestRefill.php
  32. 49 0
      test/TestSwool.php
  33. 117 0
      test/coroutine/TestHttpServ.php
  34. 59 0
      test/coroutine/backtrace.php
  35. 25 0
      test/coroutine/before_server_start.php
  36. 18 0
      test/coroutine/behavior/do-while.php
  37. 27 0
      test/coroutine/behavior/for.php
  38. 14 0
      test/coroutine/behavior/foreach.php
  39. 14 0
      test/coroutine/behavior/goto.php
  40. 24 0
      test/coroutine/behavior/preemptive_timer.php
  41. 32 0
      test/coroutine/behavior/tick.php
  42. 35 0
      test/coroutine/behavior/while.php
  43. 27 0
      test/coroutine/behavior/while2.php
  44. 32 0
      test/coroutine/channel/test.php
  45. 27 0
      test/coroutine/client_send_yield.php
  46. 27 0
      test/coroutine/client_send_yield_server.php
  47. 19 0
      test/coroutine/coro_array_map.php
  48. 19 0
      test/coroutine/coro_call_user.php
  49. 25 0
      test/coroutine/coro_channel.php
  50. 28 0
      test/coroutine/coro_destruct.php
  51. 32 0
      test/coroutine/coro_destuct.php
  52. 7 0
      test/coroutine/coro_empty.php
  53. 11 0
      test/coroutine/coro_gethost.php
  54. 9 0
      test/coroutine/coro_include.php
  55. 22 0
      test/coroutine/coro_invoke.php
  56. 17 0
      test/coroutine/coro_nested.php
  57. 16 0
      test/coroutine/coro_nested_empty.php
  58. 39 0
      test/coroutine/coro_serialize.php
  59. 10 0
      test/coroutine/coro_set_stack_size.php
  60. 11 0
      test/coroutine/coro_sleep.php
  61. 19 0
      test/coroutine/coro_stackless.php
  62. 16 0
      test/coroutine/coro_util.php
  63. 40 0
      test/coroutine/csp.php
  64. 11 0
      test/coroutine/deadlock.php
  65. 27 0
      test/coroutine/defer.php
  66. 79 0
      test/coroutine/defer_client.php
  67. 27 0
      test/coroutine/enable_coroutine.php
  68. 14 0
      test/coroutine/exception/empty.php
  69. 5 0
      test/coroutine/exec.php
  70. 26 0
      test/coroutine/exit_in_coroutine.php
  71. 12 0
      test/coroutine/exit_with_status.php
  72. 20 0
      test/coroutine/fgets.php
  73. 11 0
      test/coroutine/fread.php
  74. 10 0
      test/coroutine/fwrite.php
  75. 7 0
      test/coroutine/gethostbyname.php
  76. 53 0
      test/coroutine/http/server.php
  77. 81 0
      test/coroutine/http2_client.php
  78. 40 0
      test/coroutine/http_backend_serv.php
  79. 12 0
      test/coroutine/http_client.php
  80. 13 0
      test/coroutine/http_download.php
  81. 37 0
      test/coroutine/http_server.php
  82. 162 0
      test/coroutine/httpmulti.php
  83. 40 0
      test/coroutine/library/base.php
  84. 21 0
      test/coroutine/list_coroutines.php
  85. 32 0
      test/coroutine/mysql_chan.php
  86. 16 0
      test/coroutine/mysql_escape.php
  87. 14 0
      test/coroutine/mysql_execute_empty.php
  88. 41 0
      test/coroutine/mysql_prepare.php
  89. 24 0
      test/coroutine/mysql_prepare_2.php
  90. 28 0
      test/coroutine/mysql_procedure_exec.php
  91. 26 0
      test/coroutine/mysql_query.php
  92. 15 0
      test/coroutine/mysql_unixsocket.php
  93. 20 0
      test/coroutine/proc_open.php
  94. 71 0
      test/coroutine/reconnect_test.php
  95. 8 0
      test/coroutine/redis/auth.php
  96. 24 0
      test/coroutine/redis/defer.php
  97. 7 0
      test/coroutine/redis/eval.php
  98. 8 0
      test/coroutine/redis/get.php
  99. 19 0
      test/coroutine/redis/multi.php
  100. 0 0
      test/coroutine/redis/pipeline.php

+ 9 - 1
conf/nginx/nginx-debug-http.conf

@@ -64,7 +64,7 @@ http
 
         location ~ /mobile/[/\w]+\.php$ {
             root           $folder_name;
-            fastcgi_pass   mobilesrv:9100;
+            fastcgi_pass   host.docker.internal:9100;
             fastcgi_index  index.php;
             fastcgi_param  SCRIPT_FILENAME  $folder_name$fastcgi_script_name;
             include fastcgi_params;
@@ -74,6 +74,14 @@ http
             try_files $uri $uri/ /mobile/index.html;
         }
 
+        location ~ /racc/[/\w]+\.php$ {
+            root           $folder_name;
+            fastcgi_pass   host.docker.internal:9101;
+            fastcgi_index  index.php;
+            fastcgi_param  SCRIPT_FILENAME  $folder_name$fastcgi_script_name;
+            include fastcgi_params;
+        }
+
         location ~ \.php$ {
 	        add_header Cache-Control no-store;
             root           $folder_name;

+ 11 - 0
conf/php/mobile-spwan-start

@@ -0,0 +1,11 @@
+#!/bin/sh
+set -e
+spawn-fcgi -a 0.0.0.0 -p 9100 -F 1 -f "php /var/www/html/mobile/mobile_run.php"
+
+time=$(date "+%Y%m%d")
+
+if [ ! -f "/var/www/html/data/log/${time}-mobile.log" ]; then
+    touch "/var/www/html/data/log/${time}-mobile.log"
+fi
+
+tail -f "/var/www/html/data/log/${time}-mobile.log"

+ 2 - 0
conf/php/php-debug.ini

@@ -928,6 +928,8 @@ default_socket_timeout = 60
 ; Module Settings ;
 ;;;;;;;;;;;;;;;;;;;
 
+extension=swoole.so
+
 [CLI Server]
 ; Whether the CLI web server uses ANSI color coding in its terminal output.
 cli_server.color = On

+ 1 - 1
conf/php/docker-php-spwan-start

@@ -1,6 +1,6 @@
 #!/bin/sh
 set -e
-spawn-fcgi -a 0.0.0.0 -p 9100 -F 1 -f "php /var/www/html/fcgi_run.php"
+spawn-fcgi -a 0.0.0.0 -p 9101 -F 1 -f "php /var/www/html/racc/racc.php"
 
 time=$(date "+%Y%m%d")
 

+ 2 - 3
core/framework/core/base.php

@@ -243,7 +243,7 @@ final class Base
 				exit("Class Error: {$class}.isn't exists!");
 			}
 		}
-		elseif (substr($class,0,9) == 'phpexcel_') {
+		elseif(substr($class,0,9) == 'phpexcel_') {
 
         }
 		elseif (!@include_once(BASE_CORE_PATH.'/framework/libraries/'.$class.'.php')){
@@ -293,8 +293,7 @@ final class Base
 				}
 			}
 			return;
-			//header('location: http://abc.abc.com');exit();
-		} 
+		}
 		else
         {
 			$d = strtolower(stristr($_SERVER['HTTP_HOST'],self::CPURL));

+ 2 - 2
core/framework/function/http.php

@@ -18,8 +18,8 @@ function http_request($url, $params = array(), $method = 'GET', $multi = false,
     $method = strtoupper($method);
     $ci = curl_init();
     curl_setopt($ci, CURLOPT_USERAGENT, 'PHP-SDK OAuth2.0');
-    curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 10);
-    curl_setopt($ci, CURLOPT_TIMEOUT, 10);
+//    curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 10);
+//    curl_setopt($ci, CURLOPT_TIMEOUT, 10);
     curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
     curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, false);
     curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, false);

+ 2 - 1
data/config/dev/refill.ini.php

@@ -63,5 +63,6 @@ $jiec_phone = ['name' => 'jiec', 'store_id' => 17, 'card_type' => ['chinaunicom'
 $phone_providers = [
         ['name' => 'beixt', 'cfg' => $beixt_phone, 'opened' => true, 'sort' => 1],
         ['name' => 'bxtwt', 'cfg' => $bxtwt_phone, 'opened' => true, 'sort' => 2],
-    ['name' => 'jiec', 'cfg' => $jiec_phone, 'opened' => true, 'sort' => 1]];
+        ['name' => 'jiec', 'cfg' => $jiec_phone, 'opened' => true, 'sort' => 1]];
+
 $config['phone_providers'] = $phone_providers;

+ 36 - 2
docker-compose-dev.yml

@@ -31,12 +31,14 @@ services:
 
   mobilesrv:
     image: php-zts-debug:7.3.18
+    ports:
+      - "9100:9100"
     volumes:
       - $PWD/conf/etc/localtime:/etc/localtime:ro
       - $PWD:/var/www/html
       - $PWD/conf/php/php-debug.ini:/usr/local/etc/php/php.ini
       - /Volumes/Transcend/upload:/var/www/html/data/upload
-      - $PWD/conf/php/docker-php-spwan-start:/usr/local/bin/docker-spwan-start
+      - $PWD/conf/php/mobile-spwan-start:/usr/local/bin/docker-spwan-start
     links:
       - redisrv
     container_name: "panda-mobile"
@@ -45,6 +47,37 @@ services:
       - "redisrv"
       - "searcher"
 
+  raccsrv:
+    image: php-zts-debug:7.3.18
+    ports:
+      - "9101:9101"
+    volumes:
+      - $PWD/conf/etc/localtime:/etc/localtime:ro
+      - $PWD:/var/www/html
+      - $PWD/conf/php/php-debug.ini:/usr/local/etc/php/php.ini
+      - /Volumes/Transcend/upload:/var/www/html/data/upload
+      - $PWD/conf/php/racc-spwan-start:/usr/local/bin/docker-spwan-start
+    links:
+      - redisrv
+    container_name: "panda-racc"
+    command: [docker-spwan-start]
+    depends_on:
+      - "redisrv"
+
+  rdsrv:
+    image: php-swool:latest
+    volumes:
+      - $PWD/conf/etc/localtime:/etc/localtime:ro
+      - $PWD:/var/www/html
+      - /Volumes/Transcend/upload:/var/www/html/data/upload
+      - $PWD/conf/php/php-debug.ini:/usr/local/etc/php/php.ini
+    links:
+      - redisrv
+    container_name: "panda-dispatcher"
+    command: [php,"/var/www/html/rdispatcher/dispatcher.php","5"]
+    depends_on:
+      - "redisrv"
+
   websrv:
       image: php-fpm:alpine
       volumes:
@@ -115,7 +148,8 @@ services:
       depends_on:
         - "redisrv"
   phpcli:
-    image: php-zts-debug:7.3.18
+    image: php-swool:latest
+#    image: php-zts-debug:7.3.18
     volumes:
       - $PWD/conf/etc/localtime:/etc/localtime:ro
       - $PWD/conf/php/php-debug.ini:/usr/local/etc/php/php.ini

+ 0 - 2
fooder.php

@@ -22,8 +22,6 @@ require_once(BASE_CORE_PATH . '/framework/libraries/resizeimage.php');
 require_once(BASE_CORE_PATH . '/framework/libraries/pinyin.php');
 
 require_once(BASE_ROOT_PATH . '/helper/performance_helper.php');
-require_once(BASE_ROOT_PATH . '/helper/sensitive_word/dfa.php');
-require_once(BASE_ROOT_PATH . '/helper/request_helper.php');
 require_once(BASE_ROOT_PATH . '/helper/configure.php');
 require_once(BASE_ROOT_PATH . '/helper/pay_helper.php');
 require_once(BASE_ROOT_PATH . '/helper/model_helper.php');

+ 0 - 153
helper/fcgi_server.php

@@ -1,153 +0,0 @@
-<?php
-
-/**
- * Created by PhpStorm.
- * User: stanley-king
- * Date: 16/3/10
- * Time: 下午9:08
- */
-
-require_once (BASE_ROOT_PATH . '/mobile/index.php');
-require_once (BASE_ROOT_PATH . '/helper/area_helper.php');
-require_once (BASE_CORE_PATH . '/framework/function/http.php');
-
-class fcgi_server
-{
-    static private $stInstance = NULL;
-    static public function instance()
-    {
-        if(self::$stInstance == NULL) {
-            self::$stInstance = new fcgi_server();
-        }
-        return self::$stInstance;
-    }
-
-    private function is_exclude($file)
-    {
-        static $exfiles = ['web_wxnotify.php',
-            'wxnotify.php','pub_wxnotify.php','alipay_notify_url.php','dispatch_notify.php','kdniao_notify.php',
-            'cmbpay_notify.php','cmbpay_sign.php','wxauthor.php','api/wxLogin/index.php','api/wxLogin/callback.php',
-            'signature.php',
-            'refill_tianjt.php','refill_suhctm.php','refill_suhcpdd.php','refill_gftd.php',
-            'refill_beixt.php','refill_bxtwt.php','refill_bjb.php','refill_xyz.php',
-            'refill_zzx.php','refill_inner.php','refill_jiec.php','refill_yifa.php',
-            'bridge_shr.php','refill_weit.php','refill_tianx.php','refill_afand.php'
-        ];
-        $path = BASE_ROOT_PATH . '/mobile/';
-        $file = str_replace($path,'',$file);
-
-        return in_array($file,$exfiles);
-    }
-
-    private function clear_global()
-    {
-        $_SESSION = [];
-        $_COOKIE = [];
-        $_POST = [];
-        $_GET = [];
-    }
-
-    public function handle_error($level, $message, $file, $line)
-    {
-        if($level == E_NOTICE) return;
-        $trace = "handle_error: level={$level},msg={$message} file={$file},line={$line}\n";
-        $backtrace = debug_backtrace();
-        foreach ($backtrace as $item) {
-            $trace .= "{$item['file']}\t{$item['line']}\t{$item['function']}\n";
-        }
-
-        Log::record($trace,Log::ERR);
-    }
-
-    public function run_looper()
-    {
-        Log::record(__FUNCTION__,Log::DEBUG);
-        DFAFilter::instance();
-        area_helper::instance();
-        set_error_handler([$this, 'handle_error']);
-
-        Log::record('Waiting......',Log::DEBUG);
-        while(($ret = fcgi_accept()) >= 0)
-        {
-            $start = microtime(true);
-
-            ob_start();
-            $this->clear_global();
-            performance_helper::clear();
-            http_header::instance()->start();
-
-            try
-            {
-                Log::start_sql_log();
-                init_request();
-                init_cookie($_SERVER['HTTP_COOKIE']);
-                $file = request_helper::script_file();
-
-                if(file_exists($file))
-                {
-                    if(defined('CROSS_DOAMIN') && CROSS_DOAMIN == true) {
-                        $host = 'http://localhost:3333';
-                        fcgi_header("Content-Type: text/html; charset=UTF-8");
-                        fcgi_header("Access-Control-Allow-Credentials: true");
-                        fcgi_header("Access-Control-Allow-Origin: {$host}");
-                        fcgi_header('Access-Control-Allow-Methods: GET, POST, PUT,DELETE,PATCH');
-                    }
-
-                    if(self::is_exclude($file)) {
-                        Log::record("Call {$file}",Log::DEBUG);
-                        include $file;
-                    }
-                    else
-                    {
-                        if(!isset($_GET['act'])) {
-                            $_GET['act'] = 'index';
-                        }
-                        if(!isset($_GET['op'])) {
-                            $_GET['op'] = 'index';
-                        }
-                        if(!isset($_POST['act'])) {
-                            $_POST['act'] = 'index';
-                        }
-                        if(!isset($_POST['op'])) {
-                            $_POST['op'] = 'index';
-                        }
-
-                        //部分控制器不需要使用session.
-                        $act = $_GET['act'];
-                        if($act != 'refill') {
-                            session::instance()->start();
-                            Log::record("member_id=" . session_helper::memberid(),Log::DEBUG);
-                        }
-
-                        Base::mobile_control();
-                    }
-                }
-                else
-                {
-                    fcgi_header("Content-Type: text/html; charset=UTF-8");
-                    echo "no such file.";
-                }
-            }
-            catch (UnloginException $ex) {
-                mobileControl::outerr(errcode::ErrUnLogin,errcode::msg(errcode::ErrUnLogin),'','android');
-            }
-            catch (Exception $ex) {
-                mobileControl::outerr($ex->getCode(),$ex->getMessage(),'','android');
-                Log::record("run_looper exception catch code={$ex->getCode()} msg={$ex->getMessage()} trace={$ex->getTraceAsString()}",Log::ERR);
-            }
-            session::instance()->end();
-            fcgi_headers_sent();
-            $contents = ob_get_clean();
-            fcgi_echo($contents);
-            Log::end_sql_log();
-//            Log::record("content={$contents}",Log::DEBUG);
-
-            //fcgi_finish();//单线程的情况下不需要调用
-            $msg = sprintf("request time=%.6f\r\n\r\n",microtime(true) - $start);
-            Log::record($msg ,Log::DEBUG);
-        }
-
-        fcgi_fini();
-        Log::record('Waiting quit......',Log::DEBUG);
-    }
-}

+ 92 - 0
helper/fcgisrv/BaseServer.php

@@ -0,0 +1,92 @@
+<?php
+
+namespace fcgisrv;
+
+require_once(BASE_ROOT_PATH . '/helper/http_header.php');
+require_once(BASE_ROOT_PATH . '/helper/performance_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/request_helper.php');
+
+use http_header;
+use Log;
+use performance_helper;
+use request_helper;
+
+
+abstract class BaseServer
+{
+    protected $mSubPath;
+    public function __construct($subPath) {
+        $this->mSubPath = $subPath;
+    }
+
+    protected $mExFiles;
+    protected function setExFiles(array $files)
+    {
+        $this->mExFiles = $files;
+    }
+
+    protected function is_exclude($file)
+    {
+        $path = BASE_ROOT_PATH . '/mobile/';
+        $file = str_replace($path,'',$file);
+        return in_array($file,$this->mExFiles);
+    }
+
+    private function clear_global()
+    {
+        $_SESSION = [];
+        $_COOKIE = [];
+        $_POST = [];
+        $_GET = [];
+    }
+
+    public function handle_error($level, $message, $file, $line)
+    {
+        if($level == E_NOTICE) return;
+        $trace = "handle_error: level={$level},msg={$message} file={$file},line={$line}\n";
+        $backtrace = debug_backtrace();
+        foreach ($backtrace as $item) {
+            $trace .= "{$item['file']}\t{$item['line']}\t{$item['function']}\n";
+        }
+
+        Log::record($trace,Log::ERR);
+    }
+
+    protected function preLooper()
+    {
+        set_error_handler([$this, 'handle_error']);
+    }
+
+    abstract function handle_req($file);
+    public function run_looper()
+    {
+        Log::record(__FUNCTION__,Log::DEBUG);
+        $this->preLooper();
+        Log::record('Waiting......',Log::DEBUG);
+        while(($ret = fcgi_accept()) >= 0)
+        {
+            $start = microtime(true);
+
+            ob_start();
+            $this->clear_global();
+            performance_helper::clear();
+            Log::start_sql_log();
+            init_request();
+            init_cookie($_SERVER['HTTP_COOKIE']);
+            http_header::instance()->start();
+
+            $file = request_helper::script_file();
+            $this->handle_req($file);
+
+            fcgi_headers_sent();
+            $contents = ob_get_clean();
+            fcgi_echo($contents);
+            Log::end_sql_log();
+            $msg = sprintf("request time=%.6f\r\n\r\n",microtime(true) - $start);
+            Log::record($msg ,Log::DEBUG);
+        }
+
+        fcgi_fini();
+        Log::record('Waiting quit......',Log::DEBUG);
+    }
+}

+ 128 - 0
helper/fcgisrv/MobileServer.php

@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * Created by PhpStorm.
+ * User: stanley-king
+ * Date: 16/3/10
+ * Time: 下午9:08
+ */
+
+namespace fcgisrv;
+
+require_once (BASE_HELPER_PATH . '/fcgisrv/BaseServer.php');
+require_once (BASE_ROOT_PATH . '/helper/area_helper.php');
+require_once (BASE_CORE_PATH . '/framework/function/http.php');
+require_once (BASE_ROOT_PATH . '/mobile/index.php');
+require_once (BASE_ROOT_PATH . '/helper/session_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/sensitive_word/dfa.php');
+require_once(BASE_HELPER_PATH . '/session.php');
+require_once (BASE_ROOT_PATH . '/helper/session_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/exceptionex.php');
+require_once(BASE_MOBILE_PATH . '/util/errcode.php');
+
+use DFAFilter;
+use area_helper;
+use Log;
+use session;
+use session_helper;
+use Base;
+use UnloginException;
+use Exception;
+use mobileControl;
+use errcode;
+
+class MobileServer extends BaseServer
+{
+    static private $stInstance = NULL;
+    static public function instance()
+    {
+        if(self::$stInstance == NULL) {
+            self::$stInstance = new MobileServer('mobile');
+
+        }
+        return self::$stInstance;
+    }
+
+    public function __construct($subPath)
+    {
+        parent::__construct($subPath);
+
+        $exfiles = ['web_wxnotify.php',
+            'wxnotify.php','pub_wxnotify.php','alipay_notify_url.php','dispatch_notify.php','kdniao_notify.php',
+            'cmbpay_notify.php','cmbpay_sign.php','wxauthor.php','api/wxLogin/index.php','api/wxLogin/callback.php',
+            'signature.php',
+            'refill_tianjt.php','refill_suhctm.php','refill_suhcpdd.php','refill_gftd.php',
+            'refill_beixt.php','refill_bxtwt.php','refill_bjb.php','refill_xyz.php',
+            'refill_zzx.php','refill_inner.php','refill_jiec.php','refill_yifa.php',
+            'bridge_shr.php','refill_weit.php','refill_tianx.php','refill_afand.php'
+        ];
+
+        $this->setExFiles($exfiles);
+    }
+
+    protected function preLooper()
+    {
+        parent::preLooper();
+        DFAFilter::instance();
+        area_helper::instance();
+    }
+
+    public function handle_req($file)
+    {
+        try
+        {
+            if(file_exists($file))
+            {
+                if(defined('CROSS_DOAMIN') && CROSS_DOAMIN == true) {
+                    $host = 'http://localhost:3333';
+                    fcgi_header("Content-Type: text/html; charset=UTF-8");
+                    fcgi_header("Access-Control-Allow-Credentials: true");
+                    fcgi_header("Access-Control-Allow-Origin: {$host}");
+                    fcgi_header('Access-Control-Allow-Methods: GET, POST, PUT,DELETE,PATCH');
+                }
+
+                if(self::is_exclude($file)) {
+                    Log::record("Call {$file}",Log::DEBUG);
+                    include $file;
+                }
+                else
+                {
+                    if(!isset($_GET['act'])) {
+                        $_GET['act'] = 'index';
+                    }
+                    if(!isset($_GET['op'])) {
+                        $_GET['op'] = 'index';
+                    }
+                    if(!isset($_POST['act'])) {
+                        $_POST['act'] = 'index';
+                    }
+                    if(!isset($_POST['op'])) {
+                        $_POST['op'] = 'index';
+                    }
+
+                    //部分控制器不需要使用session.
+                    $act = $_GET['act'];
+                    if($act != 'refill') {
+                        session::instance()->start();
+                        Log::record("member_id=" . session_helper::memberid(),Log::DEBUG);
+                    }
+
+                    Base::mobile_control();
+                }
+            }
+            else
+            {
+                fcgi_header("Content-Type: text/html; charset=UTF-8");
+                echo "no such file.";
+            }
+        }
+        catch (UnloginException $ex) {
+            mobileControl::outerr(errcode::ErrUnLogin,errcode::msg(errcode::ErrUnLogin),'','android');
+        }
+        catch (Exception $ex) {
+            mobileControl::outerr($ex->getCode(),$ex->getMessage(),'','android');
+            Log::record("run_looper exception catch code={$ex->getCode()} msg={$ex->getMessage()} trace={$ex->getTraceAsString()}",Log::ERR);
+        }
+        session::instance()->end();
+    }
+}

+ 57 - 0
helper/fcgisrv/RAccServer.php

@@ -0,0 +1,57 @@
+<?php
+
+
+namespace fcgisrv;
+
+require_once(BASE_HELPER_PATH . '/fcgisrv/BaseServer.php');
+
+require_once(BASE_ROOT_PATH . '/helper/area_helper.php');
+require_once(BASE_CORE_PATH . '/framework/function/http.php');
+require_once(BASE_ROOT_PATH . '/helper/session_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/sensitive_word/dfa.php');
+require_once(BASE_ROOT_PATH . '/helper/exceptionex.php');
+require_once(BASE_PATH . '/control/merchant.php');
+
+use Log;
+use Base;
+use UnSignException;
+use Exception;
+use merchantControl;
+use errcode;
+
+class RAccServer extends BaseServer
+{
+    public function __construct($subPath)
+    {
+        parent::__construct($subPath);
+    }
+
+
+    function handle_req($file)
+    {
+        try
+        {
+            if(file_exists($file))
+            {
+                if($this->is_exclude($file)) {
+                    Log::record("Call {$file}",Log::DEBUG);
+                    include $file;
+                } else {
+                    Base::mobile_control();
+                }
+            }
+            else
+            {
+                fcgi_header("Content-Type: text/html; charset=UTF-8");
+                echo "no such file.";
+            }
+        }
+        catch (UnSignException $ex) {
+            merchantControl::outerr(errcode::ErrUnLogin,errcode::msg(errcode::ErrUnLogin));
+        }
+        catch (Exception $ex) {
+            merchantControl::outerr($ex->getCode(),$ex->getMessage());
+            Log::record("run_looper exception catch code={$ex->getCode()} msg={$ex->getMessage()} trace={$ex->getTraceAsString()}",Log::ERR);
+        }
+    }
+}

+ 2 - 3
helper/mtopcard/mtopcard.php

@@ -109,8 +109,6 @@ function topcard_format($card_list)
     return $ret;
 }
 
-
-
 function card_type($cardno)
 {
     if(preg_match( '/^1[0-9]{18}$/',$cardno,$matches)) {
@@ -121,7 +119,8 @@ function card_type($cardno)
     }
     elseif(preg_match('/^1\d{10}$/',$cardno,$matches))
     {
-        $checker = function ($phone) {
+        $checker = function ($phone)
+        {
             if (empty($phone)) return false;  //手机号不能为空
             $url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel={$phone}";
             $resp = file_get_contents($url);  //获取API返回 的数据

+ 192 - 0
helper/queue/iqueue.php

@@ -0,0 +1,192 @@
+<?php
+declare(strict_types=1);
+
+namespace queue;
+use Redis;
+use Exception;
+use Log;
+
+
+class IQueueDB
+{
+    private $_redis;
+
+    private $_tb_prefix;
+    //存定义存储表的数量,系统会随机分配存储
+    private $_tb_num = 3;
+
+    public function __construct($queue_name)
+    {
+        if ( !extension_loaded('redis') ) {
+            throw_exception('redis failed to load');
+        }
+        $this->_tb_prefix = $queue_name;
+        $this->_redis = new Redis();
+        $this->_redis->connect(C('queue.host'), C('queue.port'), 20);
+        $this->_redis->setOption(Redis::OPT_READ_TIMEOUT, 10);
+    }
+
+    public function rpush($value)
+    {
+        try {
+            return $this->_redis->rPush($this->_tb_prefix.rand(1,$this->_tb_num),$value);
+        } catch(Exception $e) {
+            throw_exception($e->getMessage());
+        }
+    }
+
+    public function lpush($value)
+    {
+        try {
+            return $this->_redis->lPush($this->_tb_prefix.rand(1,$this->_tb_num),$value);
+        } catch(Exception $e) {
+            throw_exception($e->getMessage());
+        }
+    }
+
+    public function scan()
+    {
+        $list_key = [];
+        for($i=1;$i<=$this->_tb_num;$i++) {
+            $list_key[] = $this->_tb_prefix.$i;
+        }
+        return $list_key;
+    }
+
+    public function rpop($key, $time)
+    {
+        $result = $this->_redis->brPop($key, $time);
+        if ($result) {
+            return $result[1];
+        } else {
+            return null;
+        }
+    }
+    public function lpop($key, $time)
+    {
+        $result = $this->_redis->blPop($key, $time);
+        if ($result) {
+            return $result[1];
+        } else {
+            return null;
+        }
+    }
+
+    public function clear() {
+        $this->_redis->flushAll();
+    }
+}
+
+/**
+ * 队列处理
+ *
+ *
+ * @package    
+ */
+
+class IClient
+{
+    private $mQueuedb;
+
+    public function __construct($queueDb)
+    {
+        $this->mQueuedb = $queueDb;
+    }
+    public function push($key, $value)
+    {
+        return $this->mQueuedb->lpush(serialize([$key=>$value]));
+    }
+}
+
+class IServer
+{
+    private $_queuedb;
+    
+    public function __construct($queueDb) {
+        $this->_queuedb = $queueDb;
+    }
+
+    public function pop($key,$time)
+    {
+        $result = $this->_queuedb->rpop($key,$time);
+        if($result != null) {
+            return unserialize($result);
+        } else {
+            return false;
+        }
+    }
+    public function lpop($key,$time)
+    {
+        $result = $this->_queuedb->lpop($key,$time);
+        if($result != null) {
+            return unserialize($result);
+        } else {
+            return false;
+        }
+    }
+
+    public function scan() {
+        return $this->_queuedb->scan();
+    }
+}
+
+abstract class ILooper
+{
+    private $_stop = false;
+    private $mServer;
+
+    protected function __construct($server)
+    {
+        $this->mServer = $server;
+    }
+
+    public function prepare()
+    {
+        if (ob_get_level()) ob_end_clean();
+
+        pcntl_signal(SIGINT,  [$this,'sig_handler']);
+        pcntl_signal(SIGHUP,  [$this,'sig_handler']);
+        pcntl_signal(SIGQUIT, [$this,'sig_handler']);
+        pcntl_signal(SIGTERM, [$this,'sig_handler']);
+    }
+
+    abstract protected function handle($msg);
+
+    public function run()
+    {
+        $queues = $this->mServer->scan();
+        while (true)
+        {
+//          pcntl_signal_dispatch();
+            try
+            {
+                if ($this->_stop) break;
+                $content = $this->mServer->pop($queues,1);
+                $this->handle($content);
+            }
+            catch (Exception $e)
+            {
+                $err = $e->getMessage();
+                $code = $e->getCode();
+                Log::record("QueueDB pop err: code={$code} err={$err}",Log::ERR);
+                break;
+            }
+        }
+    }
+
+    private function sig_handler($signo)
+    {
+        Log::record("queue quit at sig_handler.",Log::DEBUG);
+        switch($signo) {
+            case SIGINT:
+            case SIGHUP:
+            case SIGQUIT:
+            case SIGTERM:
+                $this->_stop = true;
+                break;
+            default:
+                break;
+        }
+    }
+}
+

+ 42 - 0
helper/queue/rdispatcher.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace queue;
+
+require_once(BASE_HELPER_PATH . '/queue/iqueue.php');
+
+
+class DispatcherClient extends IClient
+{
+    private static $stInstance = null;
+
+    public static function instance()
+    {
+        if (self::$stInstance == null) {
+            self::$stInstance = new DispatcherClient();
+        }
+
+        return self::$stInstance;
+    }
+
+    public function __construct()
+    {
+        $db = new DispatcherDB();
+        parent::__construct($db);
+    }
+}
+
+class DispatcherDB extends IQueueDB
+{
+    public function __construct()
+    {
+        parent::__construct('QUEUE_DISPATCHER_');
+    }
+}
+
+class DispatcherServer extends IServer
+{
+    public function __construct() {
+        $queuedb = new DispatcherDB();
+        parent::__construct($queuedb);
+    }
+}

+ 20 - 0
helper/refill/RefillFactory.php

@@ -3,9 +3,11 @@
 
 namespace refill;
 
+require_once(BASE_HELPER_PATH . '/queue/rdispatcher.php');
 require_once(BASE_HELPER_PATH . '/mtopcard/mtopcard.php');
 require_once(BASE_HELPER_PATH . '/rbridge/RBridgeFactory.php');
 
+
 require_once(BASE_HELPER_PATH . '/refill/IRefill.php');
 require_once(BASE_HELPER_PATH . '/refill/IRefillOil.php');
 require_once(BASE_HELPER_PATH . '/refill/IRefillPhone.php');
@@ -85,6 +87,7 @@ use Exception;
 use rbridge\RBridgeFactory;
 use trans_wapper;
 use StatesHelper;
+use queue;
 
 
 class RefillFactory
@@ -402,6 +405,7 @@ class RefillFactory
                     try
                     {
                         $mod_refill = Model('refill_order');
+
                         $trans = new trans_wapper($mod_refill, __METHOD__);
                         $refill_info = $mod_refill->getOrderInfo(['order_id' => $order_id,'inner_status' => 0]);
                         if(!empty($refill_info))
@@ -415,6 +419,7 @@ class RefillFactory
                         }
 
                         $trans->commit();
+
                     }
                     catch (Exception $ex) {
                         $trans->rollback();
@@ -483,6 +488,21 @@ class RefillFactory
         return ($success === true);
     }
 
+    public function push_add($params)
+    {
+        return queue\DispatcherClient::instance()->push('add',$params);
+    }
+
+    public function push_notify($params)
+    {
+        queue\DispatcherClient::instance()->push('notify',$params);
+    }
+
+    public function push_notify_merchant($params)
+    {
+        queue\DispatcherClient::instance()->push('notify_mechant',$params);
+    }
+
     public function add($mchid, $buyer_id, $amount, $card_no, $mch_order, $idcard, $card_name, $notify_url, $order_time = 0, $commit_times = 0)
     {
         $card_type = mtopcard\card_type($card_no);

+ 1 - 0
helper/refill/bjbyd/RefillPhone.php

@@ -47,6 +47,7 @@ class RefillPhone extends refill\IRefillPhone
             }
         }
     }
+
     public function query($refill_info)
     {
         $params['ord'] = $refill_info['order_sn'];

+ 1 - 0
mobile/control/control.php

@@ -63,6 +63,7 @@ class mobileControl
             $unused = 0;
         }
     }
+
     private function verify()
     {
         $pub = $this->pubKey();

+ 0 - 5
mobile/index.php

@@ -5,10 +5,5 @@
  *
  */
 
-define('APP_ID','mobile');
-
-define('BASE_PATH',str_replace('\\','/',dirname(__FILE__)));
-
-////框架扩展
 require_once (BASE_PATH . '/framework/function/function.php');
 require_once (BASE_PATH . '/control/control.php');

+ 49 - 51
fcgi_run.php

@@ -1,51 +1,49 @@
-<?php
-declare(strict_types=1);
-
-define('MOBILE_SERVER',true);
-
-define('BASE_ROOT_PATH',str_replace('\\','/',dirname(__FILE__)));
-define('BASE_PATH', BASE_ROOT_PATH . '/mobile');
-require_once(BASE_ROOT_PATH . '/global.php');
-require_once(BASE_ROOT_PATH . '/fooder.php');
-require_once('mobile/index.php');
-
-require_once(BASE_ROOT_PATH . '/helper/http_header.php');
-require_once(BASE_ROOT_PATH . '/helper/session.php');
-require_once(BASE_ROOT_PATH . '/helper/img_helper.php');
-require_once(BASE_ROOT_PATH . '/helper/exceptionex.php');
-require_once(BASE_ROOT_PATH . '/helper/fcgi_server.php');
-require_once(BASE_ROOT_PATH . '/helper/message/msgstates.php');
-require_once(BASE_ROOT_PATH . '/helper/message/msgutil.php');
-require_once(BASE_ROOT_PATH . '/helper/message/subscriber.php');
-require_once(BASE_ROOT_PATH . '/helper/index_tab.php');
-require_once(BASE_ROOT_PATH . '/helper/bonus_helper.php');
-require_once(BASE_ROOT_PATH . '/helper/session_helper.php');
-require_once(BASE_ROOT_PATH . '/helper/sms_helper.php');
-require_once(BASE_ROOT_PATH . '/helper/model_helper.php');
-require_once(BASE_ROOT_PATH . '/helper/category_helper.php');
-require_once(BASE_ROOT_PATH . '/helper/brand_helper.php');
-require_once(BASE_ROOT_PATH . '/helper/search/tcp_client.php');
-require_once(BASE_ROOT_PATH . '/helper/search/util.php');
-require_once(BASE_ROOT_PATH . '/helper/search_param.php');
-require_once(BASE_ROOT_PATH . '/helper/goods_helper.php');
-require_once(BASE_ROOT_PATH . '/helper/session_helper.php');
-require_once(BASE_ROOT_PATH . '/helper/login_helper.php');
-require_once(BASE_ROOT_PATH . '/helper/third_author/wxauthor.php');
-require_once(BASE_ROOT_PATH . '/helper/fcode/present_manager.php');
-require_once(BASE_ROOT_PATH . '/helper/url_helper.php');
-require_once(BASE_ROOT_PATH . '/helper/activity_helper.php');
-
-function all_channels() {
-    return ['ch_index','activity','goods','refill'];
-}
-
-Base::mobile_init();
-$trdid = Thread::getCurrentThreadId();
-Log::record("thread id = {$trdid}",Log::INFO);
-
-$gMessageStates = new MsgStates();
-StatesHelper::init();
-$listener = new message\subscriber($gMessageStates);
-$listener->start();
-
-fcgi_server::instance()->run_looper();
+<?php
+
+define('APP_ID', 'mobile');
+define('MOBILE_SERVER',true);
+define('BASE_ROOT_PATH', str_replace('/mobile', '', dirname(__FILE__)));
+define('BASE_PATH', BASE_ROOT_PATH . '/mobile');
+
+require_once(BASE_ROOT_PATH . '/global.php');
+require_once(BASE_ROOT_PATH . '/fooder.php');
+require_once(BASE_PATH . '/index.php');
+
+require_once(BASE_ROOT_PATH . '/helper/session.php');
+require_once(BASE_ROOT_PATH . '/helper/img_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/message/msgstates.php');
+require_once(BASE_ROOT_PATH . '/helper/message/msgutil.php');
+require_once(BASE_ROOT_PATH . '/helper/message/subscriber.php');
+require_once(BASE_ROOT_PATH . '/helper/index_tab.php');
+require_once(BASE_ROOT_PATH . '/helper/bonus_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/session_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/sms_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/model_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/category_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/brand_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/search/tcp_client.php');
+require_once(BASE_ROOT_PATH . '/helper/search/util.php');
+require_once(BASE_ROOT_PATH . '/helper/search_param.php');
+require_once(BASE_ROOT_PATH . '/helper/goods_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/session_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/login_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/third_author/wxauthor.php');
+require_once(BASE_ROOT_PATH . '/helper/fcode/present_manager.php');
+require_once(BASE_ROOT_PATH . '/helper/url_helper.php');
+require_once(BASE_ROOT_PATH . '/helper/activity_helper.php');
+require_once(BASE_HELPER_PATH . '/fcgisrv/MobileServer.php');
+
+function all_channels() {
+    return ['ch_index','activity','goods','refill'];
+}
+
+Base::mobile_init();
+$trdid = Thread::getCurrentThreadId();
+Log::record("thread id = {$trdid}",Log::INFO);
+
+$gMessageStates = new MsgStates();
+StatesHelper::init();
+$listener = new message\subscriber($gMessageStates);
+$listener->start();
+
+fcgisrv\MobileServer::instance()->run_looper();

+ 146 - 0
racc/control/merchant.php

@@ -0,0 +1,146 @@
+<?php
+
+
+class merchantControl
+{
+    private $mMchid;
+    private $mAdminid;
+    private $mUseKey;
+    public function __construct()
+    {
+        $mchid = $_POST['mchid'];
+        $mchinfo = Model('merchant')->getMerchantInfo(['mchid' => $mchid]);
+        if(empty($mchinfo)) {
+            throw new Exception("合作方ID:{$mchid}不存在");
+        }
+        else {
+            $this->mAdminid = intval($mchinfo['admin_id']);
+        }
+
+        if ($mchinfo['merchant_state'] != 1) {
+            throw new Exception("机构已被关闭。");
+        }
+
+        $ips = unserialize($mchinfo['ip_white_list']);
+
+        if(!empty($ips)) {
+            $addr = $_SERVER['REMOTE_ADDR'];
+            Log::record("request ip:{$addr}",Log::DEBUG);
+
+            if(!in_array($addr,$ips)) {
+                throw new Exception("请求地址不在白名单中");
+            }
+        }
+
+        $this->mUseKey = intval($mchinfo['use_key']);
+        if($this->mUseKey && !$this->verify_md5($mchinfo['secure_key'])) {
+            throw new UnSignException();
+        }
+
+        $this->mMchid = intval($mchid);
+    }
+
+    public function mchid() : int
+    {
+        return $this->mMchid;
+    }
+    public function adminid() : int {
+        return $this->mAdminid;
+    }
+
+    private function pubKey($mchid)
+    {
+        static $pubs = [];
+
+        if(array_key_exists($mchid,$pubs)) {
+            return $pubs[$mchid];
+        }
+        else {
+            $pub_key = BASE_DATA_PATH . "/api/merchant/key/{$mchid}_pub.pem";
+            $key = file_get_contents($pub_key);
+            $pub = openssl_get_publickey($key);
+            $pubs[$mchid] = $pub;
+            return $pub;
+        }
+    }
+
+    private function verify_md5($key)
+    {
+        $input = $_GET;
+        $sign = $input['sign'];
+
+        $input['sign'] = null;
+        $input['from'] = null;
+
+        $body = $this->sign_body($input);
+
+        if($this->mUseKey) {
+            $body .= "&key={$key}";
+        }
+
+        return ($sign == md5($body));
+    }
+
+    private function verify_rsa($mchid)
+    {
+        $pub = $this->pubKey($mchid);
+        if(empty($pub)) {
+            return false;
+        }
+        $input = $_GET;
+        $sign = $input['sign'];
+        $input['sign'] = null;
+        $input['from'] = null;
+
+        $data = $this->sign_body($input);
+        $res = openssl_verify($data,base64_decode($sign),$pub);
+        Log::record("openssl_verify res={$res}",Log::DEBUG);
+
+        return ($res == 1);
+    }
+
+    protected function check_empty($value)
+    {
+        if (!isset($value))
+            return true;
+        if ($value === null)
+            return true;
+        if (trim($value) === "")
+            return true;
+
+        return false;
+    }
+
+    private function sign_body($params)
+    {
+        ksort($params);
+
+        $content = "";
+        $i = 0;
+        foreach ($params as $k => $v)
+        {
+            if (false === $this->check_empty($v) && "@" != substr($v, 0, 1))
+            {
+                if ($i == 0) {
+                    $content .= "{$k}" . "=" . urlencode($v);
+                } else {
+                    $content .= "&" . "{$k}" . "=" . urlencode($v);
+                }
+                $i++;
+            }
+        }
+
+        return $content;
+    }
+
+    public static function outsuccess($data)
+    {
+        joutput_data($data);
+        return true;
+    }
+    public static function outerr($code, $msg = '')
+    {
+        joutput_error($code, $msg);
+        return true;
+    }
+}

+ 223 - 0
racc/control/refill.php

@@ -0,0 +1,223 @@
+<?php
+
+use refill\CalcMerchantPrice;
+
+require_once(BASE_ROOT_PATH .   '/mobile/control/merchant.php');
+require_once(BASE_HELPER_PATH . '/refill/RefillFactory.php');
+require_once(BASE_HELPER_PATH . '/mtopcard/mtopcard.php');
+require_once(BASE_HELPER_PATH . '/model/member_info.php');
+
+
+//商家充值接口中心
+class refillControl extends merchantControl
+{
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    public function goodsOp()
+    {
+        $result = refill\RefillFactory::instance()->goods();
+
+        $sorter = function (array $items) {
+            $ret = [];
+            foreach ($items as $key => $val) {
+                sort($val);
+                $ret[$key] = $val;
+            }
+            return $ret;
+        };
+
+        $result = $sorter($result);
+        return self::outsuccess($result);
+    }
+
+    private function check_params($params)
+    {
+        if(empty($params['cardno'])) {
+            return [false,'参数没有包含cardno'];
+        }
+        if(empty($params['amount'])) {
+            return [false,'参数没有包含充值金额:amount'];
+        }
+
+        $card_no = $_GET['cardno'];
+        $card_type = mtopcard\card_type($card_no);
+
+        if($card_type == mtopcard\UnknownCard) {
+            return [false,'卡类型无法识别'];
+        }
+
+        if(empty($params['notifyurl'])) {
+            return [false,'参数没有包含notifyurl'];
+        }
+        if(empty($params['order_sn'])) {
+            return [false,'参数没有包含贵方唯一订单号:order_sn'];
+        }
+
+        return [true,""];
+    }
+
+    public function addOp()
+    {
+        [$success,$error] = $this->check_params($_GET);
+        if($success === false) {
+            return self::outerr(201,$error);
+        }
+
+        $amount = intval($_GET['amount']);
+        $card_no = $_GET['cardno'];
+        $notify_url = $_GET['notifyurl'];
+        $mch_order = $_GET['order_sn']; //对方的order编号
+        $idcard = $_GET['idcard'] ?? '';
+        $card_name = $_GET['card_name'] ?? '';
+
+        if(!$this->check_mchorder($this->mchid(),$mch_order)) {
+            return self::outerr(205,"客户订单号重复或者为空.");
+        }
+
+        if(!$this->can_refill($card_no)) {
+            return self::outerr(206,"平台不支持该卡充值.");
+        }
+
+        $card_type = mtopcard\card_type($card_no);
+        if($card_type === mtopcard\SinopecCard || $card_type === mtopcard\PetroChinaCard)
+        {
+            $allow = refill\RefillFactory::instance()->allow($this->mchid(),$card_type,$amount);
+            if(!$allow) {
+                if ($card_type === mtopcard\SinopecCard) {
+                    $text = "中石化";
+                }
+                else {
+                    $text = "中石油";
+                }
+                return self::outerr(207,"今日贵司{$amount}{$text}充值库存已经用完.");
+            }
+        }
+
+        if(!$this->check_amount($amount)) {
+            return self::outerr(203, "余额不足");
+        }
+
+        $params = [ 'mchid' => $this->mchid(),
+                    'buyer_id' => $this->adminid(),
+                    'amount' => $amount,
+                    'card_no' => $card_no,
+                    'mch_order' => $mch_order,
+                    'notify_url' => $notify_url ];
+
+        refill\RefillFactory::instance()->push_add($params);
+        return self::outsuccess(['state' => true]);
+    }
+
+    private function check_amount($amount)
+    {
+        $minfo = new member_info($this->adminid());
+        $available = $minfo->available_predeposit();
+
+        return ($amount > $available);
+    }
+
+    private function can_refill($cardno)
+    {
+        $card_info = refill\util::read_card($cardno);
+        if(empty($card_info)) return false;
+
+        return intval($card_info['black_card']) === 0;
+    }
+
+    private function check_mchorder($mchid,$mch_order)
+    {
+        if(empty($mch_order)) {
+            return false;
+        }
+        else {
+            $refill_order = Model('refill_order');
+            $ret = $refill_order->getOrderInfo(['mchid' => $mchid,'mch_order' => $mch_order]);
+
+            return empty($ret);
+        }
+    }
+
+    public function balanceOp()
+    {
+        $uid = $this->adminid();
+        $minfo = new member_info($uid);
+        $available = $minfo->available_predeposit();
+        return self::outsuccess(['balance' => $available]);
+    }
+
+    public function query_tradeOp()
+    {
+        $mchid = $this->mchid();
+        $trade_no = $_GET['trade_no'];
+        if(empty($trade_no)) {
+            return self::outerr(201,"交易号trade_no错误");
+        }
+
+        $mod_refill = Model('refill_order');
+        $refill_info = $mod_refill->getOrderInfo(['order_sn' => $trade_no,'mchid' => $mchid]);
+
+        $vr_order = Model('vr_order');
+        $order_info = $vr_order->getOrderInfo(['order_sn' => $trade_no]);
+
+        if(empty($refill_info) || empty($order_info)) {
+            return self::outerr(201,"无此交易号");
+        }
+
+        $result = $this->format($order_info,$refill_info);
+
+        return self::outsuccess($result);
+    }
+
+    private function format($order_info,$refill_info)
+    {
+        $result = [];
+
+        $result['mchid'] = $refill_info['mchid'];
+        $result['trade_no'] = $refill_info['order_sn'];
+        $result['order_sn'] = $refill_info['mch_order'];
+        $result['card_no'] = $refill_info['card_no'];
+        $result['card_type'] = $refill_info['card_type'];
+        $result['refill_amount'] = $refill_info['refill_amount'];
+        $result['order_amount'] = $refill_info['mch_amount'];
+        $result['order_time'] = $refill_info['order_time'];
+        $result['success_time'] = $refill_info['notify_time'];
+        $result['order_state'] = $order_info['order_state'];
+
+        return $result;
+    }
+
+    public function queryOp()
+    {
+        $mchid = $this->mchid();
+        $order_sn = $_GET['order_sn']; //用户方的订单号,对应数据库中的mch_order
+
+        if(empty($order_sn)) {
+            return self::outerr(201,"客户订单号order_sn错误");
+        }
+
+        $mod_refill = Model('refill_order');
+        $refill_info = $mod_refill->getOrderInfo(['mch_order' => $order_sn,'mchid' => $mchid,'inner_status' => 0]);
+
+        if(empty($refill_info)) {
+            return self::outerr(201,"无此订单");
+        }
+
+        $vr_order = Model('vr_order');
+        $order_info = $vr_order->getOrderInfo(['order_sn' => $refill_info['order_sn']]);
+
+        if(empty($order_info)) {
+            return self::outerr(201,"无此交易号");
+        }
+
+        if($order_info['order_state'] == ORDER_STATE_SEND) {
+            QueueClient::push("QueryRefillState",['order_id' => $refill_info['order_id']]);
+        }
+
+        $result = $this->format($order_info,$refill_info);
+
+        return self::outsuccess($result);
+    }
+}

+ 8 - 0
racc/index.php

@@ -0,0 +1,8 @@
+<?php
+/**
+ * 手机接口初始化文件
+ *
+ *
+ */
+
+require_once (BASE_PATH . '/control/merchant.php');

+ 39 - 0
rdispatcher/dispatcher.php

@@ -0,0 +1,39 @@
+<?php
+declare(strict_types=0);
+
+define('APP_ID', 'rdispatcher');
+define('MOBILE_SERVER',true);
+
+define('BASE_ROOT_PATH',str_replace('/rdispatcher','',dirname(__FILE__)));
+define('BASE_PATH',BASE_ROOT_PATH . '/rdispatcher');
+
+require_once(BASE_ROOT_PATH . '/global.php');
+require_once(BASE_ROOT_PATH . '/fooder.php');
+require_once(BASE_ROOT_PATH . '/fooder.php');
+require_once(BASE_ROOT_PATH . '/helper/event_looper.php');
+require_once(BASE_HELPER_PATH . '/queue/rdispatcher.php');
+require_once(BASE_HELPER_PATH . '/refill/RefillFactory.php');
+
+
+require_once(BASE_PATH . '/processor.php');
+require_once(BASE_PATH . '/proxy.php');
+require_once(BASE_PATH . '/yzpolicy.php');
+
+//Co::set(['hook_flags' => SWOOLE_HOOK_NATIVE_CURL]);
+//Co::set(['hook_flags' => SWOOLE_HOOK_ALL | SWOOLE_HOOK_NATIVE_CURL]);
+
+
+if (empty($_SERVER['argv'][1])) exit('parameter error');
+$count = intval($_SERVER['argv'][1]);
+
+function work_proc() {
+    Base::run_util();
+    $looper = new processor();
+//    go(function () use ($looper){
+//        $looper->run();
+//    });
+    $looper->run();
+
+}
+
+event\util::fork_workerex('work_proc',$count);

+ 52 - 0
rdispatcher/processor.php

@@ -0,0 +1,52 @@
+<?php
+
+require_once(BASE_CORE_PATH . '/framework/function/http.php');
+
+
+class processor extends queue\ILooper
+{
+    private $mProxy;
+
+    public function __construct()
+    {
+        parent::__construct(new queue\DispatcherServer());
+        $this->mProxy = new proxy();
+    }
+
+    protected function handle($msg)
+    {
+        if(empty($msg)) {
+            Log::record('empty body',Log::DEBUG);
+            Co::resume();
+        }
+        else
+        {
+            foreach ($msg as $key => $params)
+            {
+                Log::record("start one", Log::DEBUG);
+//                Swoole\Coroutine\run(function () use ($key) {
+//                    Log::record("recv {$key}", Log::DEBUG);
+//                    $resp = http_request('https://www.xyzshops.cn/mobile/index.php?act=index&op=index&client_type=ios');
+//                    Log::record("recv {$key} size=" . strlen($resp), Log::DEBUG);
+//                });
+
+                $method = strtolower($key);
+                if($method == 'add') {
+                    $proxy = $this->mProxy;
+                    Swoole\Coroutine\run(function () use ($proxy,$params) {
+                        $proxy->add($params);
+                    });
+                }
+                elseif($method == 'notify') {
+
+                }
+                elseif($method == 'notify_mechant') {
+
+                }
+                else {
+                    Log::record("Error msg",Log::DEBUG);
+                }
+            }
+        }
+    }
+}

+ 44 - 0
rdispatcher/proxy.php

@@ -0,0 +1,44 @@
+<?php
+
+
+require_once (BASE_ROOT_PATH . '/helper/model_helper.php');
+
+use refill;
+
+class proxy
+{
+    public function add($params)
+    {
+
+        $mchid = $params['mchid'];
+        $buyer_id = $params['buyer_id'];
+        $amount = $params['amount'];
+        $card_no = $params['card_no'];
+        $mch_order = $params['mch_order'];
+        $notify_url = $params['notify_url'];
+        $idcard = $params['idcard'] ?? '';
+        $card_name = $params['card_name'] ?? '';
+        $order_time = $params['order_time'] ?? 0;
+        $commit_times = $params['commit_times'] ?? 0;
+
+        $minfo = new member_info($buyer_id);
+        $available = $minfo->available_predeposit();
+        Log::record("available = {$available}",Log::DEBUG);
+
+        $resp = http_request('https://www.xyzshops.cn/mobile/index.php?act=index&op=index&client_type=ios');
+        Log::record("recv size=" . strlen($resp), Log::DEBUG);
+
+        [$ret,$err] = refill\RefillFactory::instance()->add($mchid, $buyer_id, $amount, $card_no,
+            $mch_order, $idcard, $card_name, $notify_url, $order_time, $commit_times);
+    }
+
+    public function notify($params)
+    {
+
+    }
+
+    public function notify_mechant()
+    {
+
+    }
+}

+ 13 - 0
rdispatcher/yzpolicy.php

@@ -0,0 +1,13 @@
+<?php
+
+class yzpolicy
+{
+    public function __construct()
+    {
+
+    }
+
+    private function init() {
+
+    }
+}

+ 94 - 0
test/TestDispatcher.php

@@ -0,0 +1,94 @@
+<?php
+declare(strict_types=1);
+
+define('APP_ID', 'test');
+define('BASE_ROOT_PATH', str_replace('/test', '', dirname(__FILE__)));
+require_once(BASE_ROOT_PATH . '/global.php');
+require_once(BASE_CORE_PATH . '/lrlz.php');
+require_once(BASE_ROOT_PATH . '/fooder.php');
+require_once(BASE_HELPER_PATH . '/queue/rdispatcher.php');
+require_once(BASE_HELPER_PATH . '/refill/RefillFactory.php');
+
+
+use PHPUnit\Framework\TestCase;
+
+const LocalTest = 1;
+const NetTest = 2;
+
+const CurrentTest = LocalTest;
+
+class TestDispatcher extends TestCase
+{
+    private $mMchid;
+
+    public static function setUpBeforeClass() : void
+    {
+        Base::run_util();
+    }
+
+    public function __construct(?string $name = null, array $data = [], $dataName = '')
+    {
+        parent::__construct($name, $data, $dataName);
+
+        if (CurrentTest == LocalTest) {
+            $this->mMchid = 1;
+        } else {
+            $this->mMchid = 1092;
+        }
+    }
+
+    public function testPushMessage()
+    {
+        foreach (range(1,2000,1) as $i) {
+            queue\DispatcherClient::instance()->push('xxx',$i);
+        }
+    }
+
+    public function testAdd()
+    {
+        foreach (range(1,2000,1) as $i) {
+            queue\DispatcherClient::instance()->push('add',[]);
+        }
+    }
+
+    public function testAddoil()
+    {
+        foreach (range(1,200,1) as $i) {
+            $ret = refill\RefillFactory::instance()->push_add($this->make_order());
+        }
+    }
+
+    private function make_order()
+    {
+        $mchid = $this->mMchid;
+        $mchinfo = Model('merchant')->getMerchantInfo(['mchid' => $mchid]);
+        $buyer_id = intval($mchinfo['admin_id']);
+
+        $params = [ 'mchid' => $this->mMchid,
+            'buyer_id' => $buyer_id,
+            'amount' => 50,
+            'card_no' => 13911129867,
+            'mch_order' => $this->make_sn(),
+            'notify_url' => 'https://www.xyzshops.cn/mobile/signature.php'];
+
+        return $params;
+    }
+
+    private function make_sn()
+    {
+        return mt_rand(1000, 9999)
+            . sprintf('%010d', time())
+            . sprintf('%06d', (float)microtime() * 1000000);
+    }
+
+    public function testCurl()
+    {
+        Swoole\Coroutine\run(function () {
+            $curl = curl_init();
+            var_dump($curl, (int) $curl);
+            //resource(4) of type (Swoole-Coroutine-cURL Handle)
+            //int(4)
+        });
+    }
+
+}

+ 0 - 4
test/TestRedis.php

@@ -37,10 +37,6 @@ class TestRedis extends TestCase
         $ins = Cache::getInstance('cacheredis');
         $ins->set_org($key,0);
         $ins->incr($key);
-
-
-
-
     }
 
     public function testzIncr()

+ 0 - 8
test/TestRefill.php

@@ -78,8 +78,6 @@ class TestRefill extends TestCase
     public function testOilticket()
     {
         $providers = new refill\bjb\RefillPhone([]);
-
-
     }
 
     public function testIpWhiteList()
@@ -152,9 +150,6 @@ class TestRefill extends TestCase
     public function testYifaCB()
     {
         $body = '{"app_id":"e4a61b2acf1119c72c1ed9b61781494e","nonce_str":"OQMEBRQWJGPKOWYUXDVPTNMLEQJHXFWG","timestamp":1610275083,"order_sn":"161027325773032634","coder_order_sn":"60641610273255214687","isp_order_sn":null,"phone":"15120035568","amount":"94.000","discount":"0.9400","create_time":"2021-01-10 18:07:42","recharge_time":"","status":"fail","channel_id":3,"sign":"47278AD74EFA7F5FC8DE3A6D362C409B"}';
-//        $resp = http_post_data($this->mReqHost . "/mobile/refill_yifa.php", $body);
-
-//        $content = $_SERVER['post_content'];
         $input = json_decode($body,true);
         refill\RefillFactory::instance()->notify('yifa',$input);
     }
@@ -196,7 +191,6 @@ class TestRefill extends TestCase
         $data = '{"channelOrderNumber":"79091610959059372019","orderNumber":"GYFL1610959060397001","message":"充值成功","signature":"881036222bd8f067ff47d248c75f4c8d","voucher":"","status":101}';
         $url = "http://192.168.1.220/mobile/refill_gftd.php?" . $data;
         $resp = http_post_data($url, $data, ['Content-Type: application/json;charset=UTF-8;','Accept:application/json;charset=UTF-8;']);
-
     }
 
     public function testJiecPhone()
@@ -208,7 +202,6 @@ class TestRefill extends TestCase
     public function testBxtwtCB()
     {
         $data = '{"order_number":18219726,"shipping_status":4,"shipping_status_desc":"发货失败","shipping_status_message":"","sign":"863b4d972f2a4d39a9af7396879116c4","voucher":"","vouchertype":"","voucherurl":"","tradeNo":"100662475851197741"}';
-
     }
 
     public function testTianjtJDVerify()
@@ -229,7 +222,6 @@ class TestRefill extends TestCase
     public function testSuhcTMVerify()
     {
         $data = 'onlystr=180662473867058221&sign=5ff5f95d54a89e78dbb49923f6b20c08&amt=100&notifyurl=https%3A%2F%2Fwww.xyzshops.cn%2Fmobile%2Frefill_suhctm.php&cardtype=Sinoepc&batchid=3&cardno=1000111100020445281&orgid=1590993600&status=3';
-//        $url = "http://192.168.1.220/mobile/refill_suhctm.php?" . $data;
         $url = "https://www.xyzshops.cn/mobile/refill_suhctm.php?" . $data;
         $resp = http_request($url);
     }

+ 49 - 0
test/TestSwool.php

@@ -0,0 +1,49 @@
+<?php declare(strict_types=1);
+
+use PHPUnit\Framework\TestCase;
+
+define('APP_ID', 'test');
+define('BASE_ROOT_PATH', str_replace('/test', '', dirname(__FILE__)));
+
+require_once(BASE_ROOT_PATH . '/global.php');
+require_once(BASE_CORE_PATH . '/lrlz.php');
+require_once(BASE_ROOT_PATH . '/fooder.php');
+
+class TestSwool extends TestCase
+{
+    public static function setUpBeforeClass() : void
+    {
+        Base::run_util();
+    }
+
+    public function testCurl()
+    {
+        Swoole\Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
+        Swoole\Runtime::enableCoroutine(SWOOLE_HOOK_CURL);
+
+        $n = 100;
+        $i = 0;
+        while($n--)
+        {
+            go(function () use($i) {
+                Log::record("start {$i}",Log::DEBUG);
+                $ch = curl_init();
+                curl_setopt($ch, CURLOPT_URL, "http://www.xinhuanet.com/");
+                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+                curl_setopt($ch, CURLOPT_HEADER, 0);
+                $output = curl_exec($ch);
+                if ($output === FALSE) {
+                    Log::record("index = {$i} CURL Error:" . curl_error($ch),Log::DEBUG);
+
+                }
+                curl_close($ch);
+                Log::record("index={$i}  length=" . strlen($output) . " bytes",Log::DEBUG);
+            });
+            $i++;
+
+            Coroutine::sleep(.1);
+        }
+
+        swoole_event_wait();
+    }
+}

+ 117 - 0
test/coroutine/TestHttpServ.php

@@ -0,0 +1,117 @@
+<?php
+/**
+ * @Author: winterswang
+ * @Date:   2015-06-18 16:45:09
+ * @Last Modified by:   winterswang
+ * @Last Modified time: 2016-09-18 17:33:51
+ */
+
+class TestHttpServer {
+
+	public $http;
+	public $queue;
+	public $setting = array();
+
+	/**
+	 * [__construct description]
+	 * @param array $setting [description]
+	 */
+	public function __construct(){
+
+	}
+
+	public function set($setting){
+
+		$this ->setting = $setting;
+	}
+
+	/**
+	 * [init description]
+	 * @return [type] [description]
+	 */
+	public function init(){
+
+		if (!isset($this ->setting['host'])) {
+			$this ->setting['host'] = '0.0.0.0';
+		}
+		if (!isset($this ->setting['port'])) {
+			$this ->setting['port'] = '9999';
+		}
+
+		$this ->http = new swoole_http_server($this ->setting['host'], $this ->setting['port']);
+		$this ->http ->set($this ->setting);
+
+		$this ->http ->on('request', array($this, 'onRequest'));
+		$this ->http ->on('close', array($this, 'onClose'));
+	}
+
+	/**
+	 * [onRequest description]
+	 * @param  [type] $request  [description]
+	 * @param  [type] $response [description]
+	 * @return [type]           [description]
+	 */
+	public function onRequest($request, $response){
+
+		// $udp = new swoole_client(SWOOLE_SOCK_UDP, SWOOLE_SOCK_ASYNC);
+		// $udp->on("connect", function(swoole_client $cli) {
+		//     $cli->send("udp test");
+		// });
+		// $udp->on("receive", function(swoole_client $cli, $data)use($response){
+
+			$tcp = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
+			$tcp->on("connect", function(swoole_client $cli) {
+			    $cli->send("tcp test");
+			});
+			$tcp->on("receive", function(swoole_client $cli, $data)use($response){
+				$response ->end("<h1> swoole response</h1>");
+			});
+			$tcp->on("close", function(swoole_client $cli){
+			});
+			$tcp->on("error", function(swoole_client $cli){
+			});
+			$tcp->connect('10.100.64.151', 9805);
+
+		// });
+		// $udp->on("close", function(swoole_client $cli){
+		// });
+		// $udp->connect('10.100.65.222', 9906);
+
+	}
+
+	/**
+	 * [onClose description]
+	 * @param  [type] $server  [description]
+	 * @param  [type] $fd      [description]
+	 * @param  [type] $reactor_id [description]
+	 * @return [type]          [description]
+	 */
+	public function onClose($server, $fd, $reactor_id){
+
+		//echo " on close fd = $fd reactor_id = $reactor_id \n";
+	}
+
+	/**
+	 * [start description]
+	 * @return [type] [description]
+	 */
+	public function start(){
+
+		$this ->init();
+		$this ->http ->start();
+	}
+}
+
+$setting = array(
+		'host' => '0.0.0.0',
+		'port' => 10005,
+		'worker_num' => 4,
+		'dispatch_mode' => 2,   //固定分配请求到worker
+		'reactor_num' => 4,     //亲核
+		'daemonize' => 1,       //守护进程
+		'backlog' => 128,
+		'log_file' => '/data/log/test_http_server.log',
+);
+$th = new TestHttpServer();
+$th ->set($setting);
+$th ->start();

+ 59 - 0
test/coroutine/backtrace.php

@@ -0,0 +1,59 @@
+<?php
+function test1() {
+    test2();
+}
+
+function test2() {
+    while(true) {
+        co::sleep(10);
+        echo __FUNCTION__." \n";
+    }
+}
+
+$cid = go(function () {
+    test1();
+});
+
+go(function () use ($cid) {
+    while(true) {
+        echo "BackTrace[$cid]:\n-----------------------------------------------\n";
+        echo get_debug_print_backtrace(co::getBackTrace($cid))."\n";
+        co::sleep(3);
+    }
+});
+
+function get_debug_print_backtrace($traces){
+    $ret = array();
+    foreach($traces as $i => $call){
+        $object = '';
+        if (isset($call['class'])) {
+            $object = $call['class'].$call['type'];
+            if (is_array($call['args'])) {
+                foreach ($call['args'] as &$arg) {
+                    get_arg($arg);
+                }
+            }
+        }
+
+        $ret[] = '#'.str_pad($i - $traces_to_ignore, 3, ' ')
+        .$object.$call['function'].'('.implode(', ', $call['args'])
+        .') called at ['.$call['file'].':'.$call['line'].']';
+    }
+
+    return implode("\n",$ret);
+}
+
+function get_arg(&$arg) {
+    if (is_object($arg)) {
+        $arr = (array)$arg;
+        $args = array();
+        foreach($arr as $key => $value) {
+            if (strpos($key, chr(0)) !== false) {
+                $key = '';    // Private variable found
+            }
+            $args[] =  '['.$key.'] => '.get_arg($value);
+        }
+
+        $arg = get_class($arg) . ' Object ('.implode(',', $args).')';
+    }
+}

+ 25 - 0
test/coroutine/before_server_start.php

@@ -0,0 +1,25 @@
+<?php
+go(function ()
+{
+    co::sleep(1);
+
+    $http = new swoole_http_server("127.0.0.1", 9501, SWOOLE_BASE);
+
+    $http->on("start", function ($server)
+    {
+        echo "Swoole http server is started at http://127.0.0.1:9501\n";
+    });
+
+    $http->on("request", function ($request, $response)
+    {
+        var_dump($request->header);
+        var_dump($request->server);
+
+        $response->header("Content-Type", "text/plain");
+        $response->status(200);
+        $response->end("test");
+    });
+    echo "start\n";
+    $http->start();
+    echo "end\n";
+});

+ 18 - 0
test/coroutine/behavior/do-while.php

@@ -0,0 +1,18 @@
+<?php
+Swoole\Coroutine::set([
+    'max_death_ms' => 2000,
+    'death_loop_threshold' => 5,
+]);
+echo "start\n";
+go(function () {
+    echo "coro start\n";
+    do{
+        echo "111\n";
+        sleep(1);
+    } while(1);
+});
+
+go(function () {
+    echo "222222\n";
+});
+echo "end\n";

+ 27 - 0
test/coroutine/behavior/for.php

@@ -0,0 +1,27 @@
+<?php
+co::set(['enable_preemptive_scheduler' => true]);
+$start = microtime(1);
+echo "start\n";
+$flag = 1;
+
+go(function () use (&$flag) {    
+    echo "coro 1 start to loop\n";
+    $i = 0;
+    for (;;) {
+//         echo "$i\n";
+        if (!$flag) {
+            break;
+        }
+        $i++;
+    }
+    echo "coro 1 can exit\n";
+});
+    
+$end = microtime(1);
+$msec = ($end - $start) * 1000;
+echo "use time $msec\n";
+go(function () use (&$flag) {
+    echo "coro 2 set flag = false\n";
+    $flag = false;
+});
+echo "end\n";

+ 14 - 0
test/coroutine/behavior/foreach.php

@@ -0,0 +1,14 @@
+<?php
+echo "start\n";
+go(function () {
+    echo "coro start\n";
+    $arr = range(0, 20);
+    foreach($arr as $k=>$v){
+        echo $v."\n";
+    }
+});
+
+go(function () {
+    echo "222222\n";
+});
+echo "end\n";

+ 14 - 0
test/coroutine/behavior/goto.php

@@ -0,0 +1,14 @@
+<?php
+echo "start\n";
+go(function () {
+    echo "coro start\n";
+    loop:
+    echo "111\n";
+    sleep(1);
+    goto loop;
+});
+
+go(function () {
+    echo "222222\n";
+});
+echo "end\n";

+ 24 - 0
test/coroutine/behavior/preemptive_timer.php

@@ -0,0 +1,24 @@
+<?php
+co::set(['enable_preemptive_scheduler' => true]);
+go(function (){
+    $exit = false;
+    while (true){
+        $res = Swoole\Coroutine::stats();
+        $num = $res['coroutine_num'];
+        if ($num < 10){
+            go(function () use(&$exit){
+                echo "cid:".Swoole\Coroutine::getCid()." start\n";
+                Swoole\Coroutine::sleep(1);
+                echo "cid ".Swoole\Coroutine::getCid()." end\n";
+                $exit = true;
+            });
+        }
+        if ($exit) {
+            echo "cid ".Swoole\Coroutine::getCid()." break\n";
+            break;
+        }
+    }
+    echo "cid ".Swoole\Coroutine::getCid()." exit\n";
+});
+echo "main end\n";
+

+ 32 - 0
test/coroutine/behavior/tick.php

@@ -0,0 +1,32 @@
+<?php
+declare(ticks=10);
+
+$max_msec = 10;
+Swoole\Coroutine::set([
+    'max_exec_msec' => $max_msec,
+]);
+
+$s = microtime(1);
+echo "start\n";
+$flag = 1;
+go(function () use (&$flag, $max_msec, $s){
+    echo "coro 1 start to loop for $max_msec msec\n";
+    $n = 10000000;
+    $i = 0;
+    while($n--) {
+        $i ++;
+    }
+    echo "coro 1 can exit\n";
+    $t = microtime(1);
+    $u = $t-$s;
+    echo "coro 1 use time ".(($t-$s) * 1000)." ms\n";
+});
+
+$t = microtime(1);
+$u = $t-$s;
+echo "shedule use time ".($u * 1000)." ms\n";
+go(function () use (&$flag){
+    echo "coro 2 set flag = false\n";
+    $flag = false;
+});
+echo "end\n";

+ 35 - 0
test/coroutine/behavior/while.php

@@ -0,0 +1,35 @@
+<?php
+Swoole\Coroutine::set([
+    'max_death_ms' => 5000,
+]);
+$s = microtime(1);
+echo "start\n";
+go(function () {
+    echo "coro 1  start\n";
+    $x = 5;
+    $i = 0;
+    while(!0) {
+        $i ++;
+        echo "coro 1 $i\n";
+        sleep(1);
+    }
+});
+
+go(function () {
+    echo "coro 2  start\n";
+    $x = 5;
+    $i = 0;
+    while(1) {
+        $i ++;
+        echo "coro 2 $i\n";
+        sleep(1);
+    }
+});
+
+$t = microtime(1);
+$u = $t-$s;
+echo "use time $u s\n";
+go(function () {
+    echo "----------------------\n";
+});
+echo "end\n";

+ 27 - 0
test/coroutine/behavior/while2.php

@@ -0,0 +1,27 @@
+<?php
+Swoole\Coroutine::set([
+    'max_death_ms' => 5000,
+]);
+$s = microtime(1);
+echo "start\n";
+
+$flag = 1;
+go(function () use (&$flag){
+    echo "coro 1 start\n";
+    $i = 0;
+    while($flag) {
+        $i ++;
+        echo "$i\n";
+        sleep(1);
+    }
+    echo "coro 1 can exit\n";
+});
+
+$t = microtime(1);
+$u = $t-$s;
+echo "use time $u s\n";
+go(function () use (&$flag){
+    echo " coro 2 set flag = false\n";
+    $flag = false;
+});
+echo "end\n";

+ 32 - 0
test/coroutine/channel/test.php

@@ -0,0 +1,32 @@
+<?php
+function BatchExecMethodByCo()
+{
+    $args = func_get_args();
+    $channel = new \Swoole\Coroutine\Channel(count($args));
+    foreach ($args as $key => $func) {
+        go(function()use($channel,$func,$key){
+            $res = $func();
+            $channel->push([$key=>$res]);
+        });
+    }
+    $list = [];
+    go(function()use(&$list,$args,$channel){
+        foreach ($args as $key => $chan) {
+            $list[$key] = $channel->pop();
+        }
+    });
+    swoole_event_wait();
+    return $list;
+}
+function test($value='')
+{
+    \Co::sleep(1);
+    return "test\n";
+}
+function test2($value='')
+{
+    \Co::sleep(1);
+    return "test2 ".rand(1,10)."\n";
+}
+$r = BatchExecMethodByCo("test","test2","test");
+var_dump($r);

+ 27 - 0
test/coroutine/client_send_yield.php

@@ -0,0 +1,27 @@
+<?php
+go(function () {
+    $client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
+    $client->set(array(
+        'socket_buffer_size' => 1024 * 512,
+    ));
+    if (!$client->connect('127.0.0.1', 9501, -1))
+    {
+        exit("connect failed. Error: {$client->errCode}\n");
+    }
+    $length = 0;
+    $size = 1024 * 64;
+    while (true)
+    {
+        $ret = $client->send(str_repeat('A', $size));
+        if ($ret == false)
+        {
+            var_dump($ret);
+            break;
+        }
+        $length += $size;
+        echo "send $length success\n";
+    }
+    var_dump($client->errCode);
+});
+
+swoole_event_wait();

+ 27 - 0
test/coroutine/client_send_yield_server.php

@@ -0,0 +1,27 @@
+<?php
+$socket = stream_socket_server("tcp://0.0.0.0:9501", $errno, $errstr);
+if (!$socket) {
+    echo "$errstr ($errno)<br />\n";
+} else {
+    while (true) {
+        $conn = stream_socket_accept($socket);
+        if (!$conn) {
+            continue;
+        }
+        $i = 0;
+        $length = 0;
+        while(true) {
+            $data = fread($conn, 8192);
+            if ($data == false)
+            {
+                break;
+            }
+            $length += strlen($data);
+            echo "recv " . $length . " bytes\n";
+            usleep(100000);
+        }
+        fclose($conn);
+        echo "closed\n";
+    }
+    fclose($socket);
+}

+ 19 - 0
test/coroutine/coro_array_map.php

@@ -0,0 +1,19 @@
+<?php
+
+use Swoole\Coroutine as co;
+
+co::create(function() {
+    array_map("test",array("func param\n"));
+    echo "co flow end\n";
+});
+
+function test($p) {
+    go(function() use ($p){
+        echo $p;
+        $client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
+        $res = $client->connect('127.0.0.1', 9501, 1);
+        echo "co resume : connect ret = ".var_export($res,1)."\n";
+        echo "map func end \n";
+    });
+}
+echo "main end\n";

+ 19 - 0
test/coroutine/coro_call_user.php

@@ -0,0 +1,19 @@
+<?php
+use Swoole\Coroutine as co;
+co::set(['trace_flags' => 1]);
+
+co::create(function() {
+    echo "co func start\n";
+    $name = "call_user_func";
+    $ret = $name("test","test\n");
+	echo "co func end ret:{$ret}\n";
+});
+
+function test($params)
+{
+    echo "func params:$params";
+    co::sleep(1);
+    echo "func end\n";
+    return "test return\n";
+}
+echo "main script last\n";

+ 25 - 0
test/coroutine/coro_channel.php

@@ -0,0 +1,25 @@
+<?php
+$http = new swoole_http_server("127.0.0.1", 9501, SWOOLE_BASE);
+$http->set(array(
+    'log_file' => '/dev/null'
+));
+use Swoole\Coroutine as co;
+// $http->on("WorkerStart", function (\swoole_server $serv)
+// {
+//
+// });
+$http->on('request', function (swoole_http_request $request, swoole_http_response $response)
+{
+    $ch = new co\Channel(1);
+    $out = new co\Channel(1);
+    Swoole\Coroutine::create(function() use ($ch, $out) {
+        $out->push("OK");
+        $out->push("OK");
+    });
+    $ret = $out->pop();
+    var_dump($ret);
+    $ret = $out->pop();
+    var_dump($ret);
+    $response->end("$ret\n");
+});
+$http->start();

+ 28 - 0
test/coroutine/coro_destruct.php

@@ -0,0 +1,28 @@
+<?php
+use Swoole\Coroutine as co;
+class T
+{
+    function __construct()
+    {
+
+    }
+
+    function test()
+    {
+        echo "call function \n";
+    }
+
+    function __destruct()
+    {
+        go(function () {
+            echo "coro start\n";
+            co::sleep(1.0);
+            echo "coro exit\n";
+        });
+        echo "111\n";
+    }
+}
+
+$t = new T();
+$t->test();
+echo "end \n";

+ 32 - 0
test/coroutine/coro_destuct.php

@@ -0,0 +1,32 @@
+<?php
+require __DIR__ . "/coro_include.php";
+
+class T
+{
+    function __construct()
+    {
+        echo "call __construct \n";
+    }
+
+      function test()
+      {
+        echo "call function \n";
+      }
+
+      function __destruct()
+      {
+        echo "call __destruct \n";
+        go(function () {
+            echo "co[1] start\n";
+            $client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
+            $res = $client->connect('127.0.0.1', 9501, 1);
+            co::sleep(1.0);
+            echo "co[1] resume : connect ret = ".var_export($res,1)."\n";
+            echo "co[1] exit\n";
+        });
+      }
+}
+
+$t = new T();
+$t->test();
+unset($t);

+ 7 - 0
test/coroutine/coro_empty.php

@@ -0,0 +1,7 @@
+<?php
+// co::set(['trace_flags' => 1]);
+
+co::create(function () {
+    echo "no coro exit\n";
+});
+echo "exec file end\n";

+ 11 - 0
test/coroutine/coro_gethost.php

@@ -0,0 +1,11 @@
+<?php
+require __DIR__ . "/coro_include.php";
+use Swoole\Coroutine as co;
+
+co::create(function () {
+    $ip = co::gethostbyname('www.baidu.com');
+    var_dump($ip);
+});
+echo "111\n";
+
+echo "222\n";

+ 9 - 0
test/coroutine/coro_include.php

@@ -0,0 +1,9 @@
+<?php
+if (substr(PHP_OS, 0, 3) == 'WIN')
+{
+    exit("skip for Windows");
+}
+if (!extension_loaded("swoole"))
+{
+    exit("swoole extension is required");
+}

+ 22 - 0
test/coroutine/coro_invoke.php

@@ -0,0 +1,22 @@
+<?php
+use Swoole\Coroutine as co;
+co::set(['trace_flags' => 1]);
+
+co::create(function() {
+
+
+    $function = new ReflectionFunction('title');
+
+    $function->invoke();
+    echo "invoke444\n";
+
+});
+
+function title() {
+    echo "333invoke_________________________________\n";
+    $tcpclient = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
+    var_dump($tcpclient->connect('127.0.0.1', 9501, 1));
+
+}
+
+echo "111\n";

+ 17 - 0
test/coroutine/coro_nested.php

@@ -0,0 +1,17 @@
+<?php
+require __DIR__ . "/coro_include.php";
+echo "before coro\n";
+go(function () {
+    echo "co[1] start\n";
+
+    $client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
+    $res = $client->connect('127.0.0.1', 9501, 1);
+    echo "co[1] connect ret = ".var_export($res,1)."\n";
+    co::sleep(1);
+    $res = $client->send("hello world\n");
+    echo "co[1] send ret = ".var_export($res,1)."\n";
+    $res =  $client->recv();
+    echo "co[1] recv ret = ".var_export($res,1)."\n";
+    echo "co[1] exit\n";
+});
+echo "out coro \n";

+ 16 - 0
test/coroutine/coro_nested_empty.php

@@ -0,0 +1,16 @@
+<?php
+require __DIR__ . "/coro_include.php";
+function test()
+{
+    echo "before coro\n";
+    go(function () {
+        echo "co[1] start\n";
+        go(function () {
+            echo "co[2] start\n";
+            echo "co[2] exit\n";
+        });
+        echo "co[1] exit\n";
+    });
+    echo "func end \n";
+}
+test();

+ 39 - 0
test/coroutine/coro_serialize.php

@@ -0,0 +1,39 @@
+<?php
+use Swoole\Coroutine as co;
+class Obj {
+  public $a;
+  protected $b;
+  private $c;
+  var $d;
+
+  function __construct($a, $b, $c, $d) {
+    $this->a = $a;
+    $this->b = $b;
+    $this->c = $c;
+    $this->d = $d;
+  }
+
+  function __sleep() {
+      // co::sleep(0.5);
+	$client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
+	$res = $client->connect('127.0.0.1', 9501, 10);
+    var_dump($res);
+	if ($res)
+	{
+	    echo("connect success. Error: {$client->errCode}\n");
+	}
+    echo "sleep\n";
+    return array('a', 'b', 'c');
+  }
+
+    // function __wakeup() {
+    //    $this->d = $this->a + $this->b + $this->c;
+    // }
+}
+$o = new Obj(1, 2, 3, 4);
+co::create(function() use($o) {
+    $serialized = serialize($o);
+    $unserialized = unserialize($serialized);
+    echo "res:".var_export($unserialized,1)."\n";
+    echo "call user\n";
+});

+ 10 - 0
test/coroutine/coro_set_stack_size.php

@@ -0,0 +1,10 @@
+<?php
+use Swoole\Coroutine as co;
+
+co::set(['stack_size' => 1024*1024*4]);
+
+co::create(function () {
+    var_dump(co::stats());
+    echo "no coro exit\n";
+});
+echo "exec file end\n";

+ 11 - 0
test/coroutine/coro_sleep.php

@@ -0,0 +1,11 @@
+<?php
+// require  __DIR__ . "/coro_include.php";
+use Swoole\Coroutine as co;
+co::create(function () {
+    echo "start\n";
+//    co::sleep(0.5);
+    co::yield();
+    echo "OK\n";
+});
+echo "11\n";
+co::resume(1);

+ 19 - 0
test/coroutine/coro_stackless.php

@@ -0,0 +1,19 @@
+<?php
+require __DIR__ . "/coro_include.php";
+use Swoole\Coroutine as co;
+
+echo "start\n";
+co::create(function () {
+    $client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
+    $res = $client->connect('127.0.0.1', 9501, 1);
+    var_dump($res);
+    if ($res) {
+        echo ("connect success. Error: {$client->errCode}\n");
+    }
+
+    $res = $client->send("hello");
+    echo "send res:" . var_export($res, 1) . "\n";
+    $data = $client->recv();
+    echo "recv data" . var_export($data, 1) . "\n";
+});
+echo "end\n";

+ 16 - 0
test/coroutine/coro_util.php

@@ -0,0 +1,16 @@
+<?php
+use Swoole\Coroutine as co;
+
+$id = go(function(){
+    $id = co::getUid();
+    echo "start coro $id\n";
+    co::suspend($id);
+    echo "resume coro $id @1\n";
+    co::suspend($id);
+    echo "resume coro $id @2\n";
+});
+echo "start to resume $id @1\n";
+co::resume($id);
+echo "start to resume $id @2\n";
+co::resume($id);
+echo "main\n";

+ 40 - 0
test/coroutine/csp.php

@@ -0,0 +1,40 @@
+<?php
+$serv = new \swoole_http_server("127.0.0.1", 9503, SWOOLE_BASE);
+
+$serv->on('request', function ($req, $resp) {
+    $chan = new chan(2);
+    go(function () use ($chan) {
+        $cli = new Swoole\Coroutine\Http\Client('www.baidu.com', 443, true);
+            $cli->set(['timeout' => 10]);
+            $cli->setHeaders([
+            'Host' => "www.baidu.com",
+            "User-Agent" => 'Chrome/49.0.2587.3',
+            'Accept' => 'text/html,application/xhtml+xml,application/xml',
+            'Accept-Encoding' => 'gzip',
+        ]);
+        $ret = $cli->get('/');
+        $chan->push(['www.baidu.com' => substr(trim(strip_tags($cli->body)), 0, 100)]);
+    });
+
+    go(function () use ($chan) {
+        $cli = new Swoole\Coroutine\Http\Client('www.taobao.com', 443, true);
+        $cli->set(['timeout' => 10]);
+        $cli->setHeaders([
+            'Host' => "www.taobao.com",
+            "User-Agent" => 'Chrome/49.0.2587.3',
+            'Accept' => 'text/html,application/xhtml+xml,application/xml',
+            'Accept-Encoding' => 'gzip',
+        ]);
+        $ret = $cli->get('/');
+        $chan->push(['www.taobao.com' => substr(trim(strip_tags($cli->body)), 0, 100)]);
+    });
+
+    $result = [];
+    for ($i = 0; $i < 2; $i++)
+    {
+        $result += $chan->pop();
+    }
+    $resp->header('Content-Type', 'text/html;charset=utf-8');
+    $resp->end(var_export($result, true));
+});
+$serv->start();

+ 11 - 0
test/coroutine/deadlock.php

@@ -0,0 +1,11 @@
+<?php
+$lock = new Swoole\Lock();
+$c = 2;
+
+while ($c--) {
+    go(function () use ($lock) {
+        $lock->lock();
+        Co::sleep(1);
+        $lock->unlock();
+    });
+}

+ 27 - 0
test/coroutine/defer.php

@@ -0,0 +1,27 @@
+<?php
+go(function () {
+
+    defer(function () {
+        co::sleep(1);
+        echo "end 2\n";
+
+        defer(function () {
+            co::sleep(1);
+            echo "end 3\n";
+        });
+
+        defer(function () {
+            co::sleep(1);
+            echo "end 5\n";
+        });
+    });
+
+    defer(function () {
+        co::sleep(1);
+        echo "end 4\n";
+    });
+
+    echo "begin\n";
+    co::sleep(1);
+    echo "end 1\n";
+});

+ 79 - 0
test/coroutine/defer_client.php

@@ -0,0 +1,79 @@
+<?php
+/* new multi implement test */
+$server = new Swoole\Http\Server("127.0.0.1", 9502, SWOOLE_BASE);
+
+$server->set([
+	'worker_num' => 1,
+]);
+
+$server->on('Request', function ($request, $response) {
+	$redis = new Swoole\Coroutine\Redis();
+	$res = $redis->connect('127.0.0.1', 6379);
+	if ($res == false) {
+		$response->end("Redis connect fail!");
+		return;
+	}
+	$redis->setDefer(true);
+	$redis->get('key');
+	$res = $redis->get('key');//get false
+	var_dump($res);
+
+	var_dump($redis->setDefer());//get true
+	var_dump($redis->setDefer(false));//get false
+
+	//穿插其他client也能正常工作
+	$redis_tmp = new Swoole\Coroutine\Redis();
+	$res = $redis_tmp->connect('127.0.0.1', 6379);
+	if ($res == false) {
+		$response->end("Redis connect fail!");
+		return;
+	}
+	$res = $redis_tmp->set('key_tmp', 'HaHa');//get true
+	var_dump($res);
+
+
+	$http_client= new Swoole\Coroutine\Http\Client('km.oa.com', 80);
+	$http_client->setDefer();
+	$http_client->get('/');
+
+	$mysql = new Swoole\Coroutine\MySQL();
+	$res = $mysql->connect(['host' => '192.168.244.128', 'user' => 'mha_manager', 'password' => 'mhapass', 'database' => 'tt']);
+	if ($res == false) {
+		$response->end("MySQL connect fail!");
+		return;
+	}
+	$mysql->setDefer(true);
+	$mysql->query('select sleep(1)', 2);
+
+	$udp = new Swoole\Coroutine\Client(SWOOLE_SOCK_UDP);
+    $res = $udp->connect("127.0.0.1", 9906, 2);
+	$udp->send('Hello World!');
+
+	//穿插其他client也能正常工作
+	$udp_tmp = new Swoole\Coroutine\Client(SWOOLE_SOCK_UDP);
+    $res = $udp_tmp->connect("127.0.0.1", 9909, 2);//nonexistent server
+	$res = $udp_tmp->recv();//get false with timeout
+	var_dump($res);
+
+	$udp_res = $udp->recv();
+	$res = $mysql->query('select sleep(1)', 2);//get false
+	var_dump($res);
+	$res = $mysql->setDefer(false);
+	var_dump($res);//get false
+	$res = $mysql->setDefer();
+	var_dump($res);//get true
+	$mysql_res = $mysql->recv();
+	$res = $redis->get('key');//get false
+	var_dump($res);
+	$redis_res = $redis->recv();
+	$res = $http_client->get('/');
+	var_dump($res);//get false
+	$res = $http_client->recv();
+	var_dump($res);//get true
+
+	var_dump($udp_res, $mysql_res, $redis_res, $http_client);
+	var_dump($http_client->setDefer(false));
+	var_dump($mysql->getDefer(), $redis->getDefer(), $http_client->getDefer());
+	$response->end('Test End');
+});
+$server->start();

+ 27 - 0
test/coroutine/enable_coroutine.php

@@ -0,0 +1,27 @@
+<?php
+
+use Swoole\Http\Request;
+use Swoole\Http\Response;
+
+$http = new swoole_http_server('127.0.0.1', 9501);
+
+$http->set([
+    'enable_coroutine' => false, // close build-in coroutine
+]);
+
+$http->on('workerStart', function () {
+    echo "Coroutine is " . (Co::getuid() > 0 ? 'enable' : 'disable')."\n";
+});
+
+$http->on("request", function (Request $request, Response $response) {
+    $response->header("Content-Type", "text/plain");
+    if ($request->server['request_uri'] == '/co') {
+        go(function () use ($response) {
+            $response->end("Hello Coroutine #" . Co::getuid());
+        });
+    } else {
+        $response->end("Hello Swoole #" . Co::getuid());
+    }
+});
+
+$http->start();

+ 14 - 0
test/coroutine/exception/empty.php

@@ -0,0 +1,14 @@
+<?php
+go(function () {
+    try {
+        echo "before\n";
+        co::sleep(0.5);
+        echo "after\n";
+        throw new Exception('coro Exception.');
+    } catch (Exception $e) {
+        echo 'Caught exception: ',  $e->getMessage(), "\n";
+    } finally {
+        echo "First finally.\n";
+    }
+});
+echo "exec file end\n";

+ 5 - 0
test/coroutine/exec.php

@@ -0,0 +1,5 @@
+<?php
+go(function () {
+
+	var_dump(co::exec("ls /"));
+});

+ 26 - 0
test/coroutine/exit_in_coroutine.php

@@ -0,0 +1,26 @@
+<?php
+function route()
+{
+    controller();
+}
+
+function controller()
+{
+    your_code();
+}
+
+function your_code()
+{
+    co::sleep(.001);
+    exit(1);
+}
+
+go(function () {
+    try {
+        route();
+    } catch (\Swoole\ExitException $e) {
+        assert($e->getStatus() === 1);
+        assert($e->getFlags() === SWOOLE_EXIT_IN_COROUTINE);
+        return;
+    }
+});

+ 12 - 0
test/coroutine/exit_with_status.php

@@ -0,0 +1,12 @@
+<?php
+$exit_status = 0;
+go(function () {
+    try {
+        exit(123);
+    } catch (\Swoole\ExitException $e) {
+        global $exit_status;
+        $exit_status = $e->getStatus();
+    }
+});
+swoole_event_wait();
+exit($exit_status);

+ 20 - 0
test/coroutine/fgets.php

@@ -0,0 +1,20 @@
+<?Php
+$fp = fopen(__DIR__ . "/defer_client.php", "r");
+stream_set_chunk_size($fp, 1024);
+
+go(function () use ($fp)
+{
+    for($i = 0; $i<100;$i++) {
+        $r =  co::fgets($fp);
+        if (empty($r) and feof($fp))
+        {
+            //echo "EOF\n";
+            break;
+        }
+        //echo "len=".strlen($r)."\n";
+        echo $r;
+        //echo "---------------------------------------\n";
+        //var_dump($r);
+        //co::sleep(1);
+    }
+});

+ 11 - 0
test/coroutine/fread.php

@@ -0,0 +1,11 @@
+<?php
+use Swoole\Coroutine as co;
+
+$fp = fopen(__DIR__ . "/defer_client.php", "r");
+
+co::create(function () use ($fp)
+{
+    fseek($fp, 256);
+    $r =  co::fread($fp);
+    var_dump($r);
+});

+ 10 - 0
test/coroutine/fwrite.php

@@ -0,0 +1,10 @@
+<?php
+use Swoole\Coroutine as co;
+
+$fp = fopen(__DIR__ . "/test.data", "a+");
+
+co::create(function () use ($fp)
+{
+    $r =  co::fwrite($fp, "hello world\n", 5);
+    var_dump($r);
+});

+ 7 - 0
test/coroutine/gethostbyname.php

@@ -0,0 +1,7 @@
+<?php
+use Swoole\Coroutine as co;
+
+co::create(function() {
+    $ip = co::gethostbyname("www.baidu.com");
+    echo "IP: $ip\n";
+});

+ 53 - 0
test/coroutine/http/server.php

@@ -0,0 +1,53 @@
+<?php
+Co::set([
+    'trace_flags' => SWOOLE_TRACE_HTTP2,
+    'log_level' => 0,
+]);
+go(function () {
+	$server = new Co\Http\Server("127.0.0.1", 9501, false);
+	/**
+	 * 静态文件处理器
+	 */
+	//$server->handle('/static', $server->getStaticHandler());
+	/**
+	 * WebSocket应用
+	 */
+	$server->handle('/websocket', function ($request, $ws) {
+		$ws->upgrade();
+
+        $frame1 = $ws->recv();
+        $frame2 = $ws->recv();
+		var_dump($frame1, $frame2);
+
+		$ws->push("hello world\n");
+
+		while(true) {
+			echo "recv begin:\n";
+			$frame = $ws->recv();
+			if ($frame == false) {
+			    echo "ws client is closed\n";
+                var_dump("Error: ", swoole_last_error());
+			    break;
+            }
+			echo $frame->data ."\n";
+			$ws->push("hello world");
+		}
+	});
+	/**
+	 * Http应用
+	 */
+	$server->handle('/', function ($request, $response) {
+	    var_dump($request);
+		var_dump($request->get);
+		$response->end("<h1>hello world</h1>");
+	});
+
+	$server->handle('/test', function ($request, $response) {
+		var_dump($request->get);
+		$response->end("<h1>Test</h1>");
+	});
+
+	$server->start();
+});
+
+swoole_event_wait();

+ 81 - 0
test/coroutine/http2_client.php

@@ -0,0 +1,81 @@
+<?php
+use Swoole\Coroutine as co;
+
+const TEST = array('get', 'post', 'pipeline');
+//const TEST = array('pipeline');
+//const TEST = array('get',);
+
+CO::set(['trace_flags' => SWOOLE_TRACE_HTTP2, 
+// 'log_level' => SWOOLE_LOG_TRACE,
+
+
+
+]);
+
+
+
+co::create(function () use ($fp)
+{
+    $cli = new co\Http2\Client('127.0.0.1', 9518);
+
+    $cli->set([ 'timeout' => 1, 'package_max_length' => 1024*1024*8]);
+    var_dump($cli->connect());
+
+    if (in_array('get', TEST))
+    {
+        $req = new Swoole\Http2\Request;
+        $req->path = "/index.html";
+        $req->headers = [
+            'host' => "localhost",
+            "user-agent" => 'Chrome/49.0.2587.3',
+            'accept' => 'text/html,application/xhtml+xml,application/xml',
+            'accept-encoding' => 'gzip',
+        ];
+        $req->cookies = ['name' => 'rango', 'email' => '1234@qq.com'];
+        var_dump($cli->send($req));
+
+        $resp = $cli->recv();
+        var_dump($resp);
+    }
+
+    if (in_array('post', TEST))
+    {
+        $req2 = new Swoole\Http2\Request;
+        $req2->path = "/index.php";
+        $req2->headers = [
+            'host' => "localhost",
+            "user-agent" => 'Chrome/49.0.2587.3',
+            'accept' => 'text/html,application/xhtml+xml,application/xml',
+            'accept-encoding' => 'gzip',
+        ];
+        $req2->data = "hello world\n";
+        var_dump($cli->send($req2));
+
+        $resp = $cli->recv();
+        var_dump($resp);
+    }
+
+    if (in_array('pipeline', TEST))
+    {
+        $req3 = new Swoole\Http2\Request;
+        $req3->path = "/index.php";
+        $req3->headers = [
+            'host' => "localhost",
+            "user-agent" => 'Chrome/49.0.2587.3',
+            'accept' => 'text/html,application/xhtml+xml,application/xml',
+            'accept-encoding' => 'gzip',
+        ];
+        $req3->pipeline = true;
+        $req3->method = "POST";
+        $streamId = $cli->send($req3);
+
+        $cli->write($streamId, ['int' => rand(1000, 9999)]);
+        $cli->write($streamId, ['int' => rand(1000, 9999)]);
+        //end stream
+        $cli->write($streamId, ['int' => rand(1000, 9999), 'end' => true], true);
+
+        var_dump($cli->recv());
+    }
+
+//    $cli->close();
+});

+ 40 - 0
test/coroutine/http_backend_serv.php

@@ -0,0 +1,40 @@
+<?php
+/**
+ * @Author: syyuanyizhi@163.com
+    connect refuse: errorCode  111
+    I/O     timeout:errorCode  110
+    http 9510
+    tcp  9511
+
+ */
+class Server
+{
+    public $server;
+
+    public function run()
+    {
+        $this->server = new Swoole\Http\Server("0.0.0.0", 9510);
+        $this->server->set([
+            'worker_num' => 1,
+            'daemonize' => true,
+            'log_file' => '/data/markyuan/swoole.log',
+        ]);
+        $this->server->on('Request', ['Server', 'onRequest']);
+        $this->server->start();
+    }
+    public static function onRequest($request, $response)
+    {
+
+        $response->end('xxxx');
+    }
+
+
+    public static function staticFunc()
+    {
+        echo "in static function";
+    }
+}
+
+$server = new Server();
+
+$server->run();

+ 12 - 0
test/coroutine/http_client.php

@@ -0,0 +1,12 @@
+<?php
+use Swoole\Coroutine as co;
+co::create(function () {
+    $cli = new co\http\client('127.0.0.1', 9501);
+    $cli->setHeaders(['Host' => 'localhost']);
+    $cli->set(['http_proxy_host' => HTTP_PROXY_HOST, 'http_proxy_port' => HTTP_PROXY_PORT]);
+    $result = $cli->get('/get?json=true');
+    var_dump($cli->body);
+//     assert($result);
+//     $ret = json_decode($cli->body, true);
+//     assert(is_array($ret) and $ret['json'] == 'true');
+});

+ 13 - 0
test/coroutine/http_download.php

@@ -0,0 +1,13 @@
+<?php
+go(function () {
+    $host = 'www.swoole.com';
+    $cli = new \Swoole\Coroutine\Http\Client($host, 443, true);
+    $cli->set(['timeout' => -1]);
+    $cli->setHeaders([
+        'Host' => $host,
+        "User-Agent" => 'Chrome/49.0.2587.3',
+        'Accept' => '*',
+        'Accept-Encoding' => 'gzip'
+    ]);
+    $cli->download('/static/files/swoole-logo.svg', __DIR__ . '/logo.svg');
+});

+ 37 - 0
test/coroutine/http_server.php

@@ -0,0 +1,37 @@
+<?php
+ini_set("memory_limit","512M");
+use Swoole\Coroutine as co;
+class Server
+{
+    public $server;
+    public $redisPool = [];
+
+    public function run()
+    {
+        $this->server = new Swoole\Http\Server("0.0.0.0", 9502, SWOOLE_BASE);
+        $this->server->set([
+            'worker_num' => 1,
+        ]);
+
+        // $this->server->on('Connect', [$this, 'onConnect']);
+        $this->server->on('Request', [$this, 'onRequest']);
+//         $this->server->on('Close', [$this, 'onClose']);
+        $this->server->set(['trace_flags' => 1 << 15, 'log_level' => 0]);
+        $this->server->start();
+    }
+
+    public function onRequest($request, $response)
+    {
+        $fd = $request->fd;
+        co::create(function () {
+            co::sleep(0.1);
+        });
+        $response->end(111);
+    }
+}
+
+$server = new Server();
+Swoole\Coroutine::set(array(
+    'max_coroutine' => 1000,
+));
+$server->run();

+ 162 - 0
test/coroutine/httpmulti.php

@@ -0,0 +1,162 @@
+<?php
+/**
+ * @Author: syyuanyizhi@163.com
+    connect refuse: errorCode  111
+    I/O     timeout:errorCode  110
+    http 9510
+    tcp  9511
+
+ */
+class Server
+{
+    public $server;
+
+    public function run()
+    {
+        $this->server = new Swoole\Http\Server("0.0.0.0", 9508);
+        $this->server->set([
+            'worker_num' => 1,
+            'daemonize' => true,
+            'log_file' => '/data/markyuan/swoole.log',
+        ]);
+        $this->server->on('Request', ['Server', 'onRequest']);
+        $this->server->start();
+    }
+
+    private static function https(){
+        //--enable-openssl
+        for($i=0;$i<2;$i++){
+            $cli = new Swoole\Coroutine\Http\Client('0.0.0.0',443,TRUE );
+            $cli->set([ 'timeout' => 1]);
+            $cli->setHeaders([
+                'Host' => "api.mp.qq.com",
+                "User-Agent" => 'Chrome/49.0.2587.3',
+                'Accept' => 'text/html,application/xhtml+xml,application/xml',
+                'Accept-Encoding' => 'gzip',
+            ]);
+            $ret = ($cli->get('/cgi-bin/token?appid=3333&secret=222'.$i.$i.$i.$i.$i));
+            error_log(__LINE__.var_export($cli,true).PHP_EOL,3,'/tmp/markyuan');
+            $cli->close();
+        }
+    }
+
+    private static function http(){
+        error_log(__LINE__.'---------- begin --- http --------------'.PHP_EOL,3,'/tmp/markyuan');
+        for($i=0;$i<2;$i++){
+            $cli = new Swoole\Coroutine\Http\Client('0.0.0.0', 9510);
+            $cli->set([ 'timeout' => 1]);
+            $cli->setHeaders([
+                'Host' => "api.mp.qq.com",
+                "User-Agent" => 'Chrome/49.0.2587.3',
+                'Accept' => 'text/html,application/xhtml+xml,application/xml',
+                'Accept-Encoding' => 'gzip',
+            ]);
+            error_log(__LINE__.var_export($cli,true).PHP_EOL,3,'/tmp/markyuan');
+            $ret = ($cli->get('/cn/token?appid=1FxxxxS9V'.$i.$i.$i.$i.$i));
+            error_log(__LINE__.var_export($ret,true).PHP_EOL,3,'/tmp/markyuan');
+            error_log(__LINE__.var_export($cli,true).PHP_EOL,3,'/tmp/markyuan');
+            $cli->close();
+        }
+        error_log(__LINE__.'---------- end --- http --------------'.PHP_EOL,3,'/tmp/markyuan');
+
+    }
+
+    private static function multihttp(){
+
+        error_log(__LINE__.'---------- begin --- multi --------------'.PHP_EOL,3,'/tmp/markyuan');
+
+        $cliAA= new Swoole\Coroutine\Http\Client('0.0.0.0', 9510);
+        $cliAA->set(['timeout' => 1]);
+        $cliAA->setHeaders([
+            'Host' => "api.mp.qq.com",
+            "User-Agent" => 'Chrome/49.0.2587.3',
+        ]);
+        $cliBB= new Swoole\Coroutine\Http\Client('0.0.0.0', 9510);
+        $cliBB->set([ 'timeout' => 1]);//
+        $cliBB->setHeaders([
+            'Host' => "api.mp.qq.com",
+            "User-Agent" => 'Chrome/49.0.2587.3',
+        ]);
+        error_log(__LINE__.var_export($cliAA,true).PHP_EOL,3,'/tmp/markyuan');
+        error_log(__LINE__.var_export($cliBB,true).PHP_EOL,3,'/tmp/markyuan');
+        $retAA=$cliAA->setDefer(1);
+        $retBB=$cliBB->setDefer(1);
+        error_log(__LINE__.var_export($retAA,true).PHP_EOL,3,'/tmp/markyuan');
+        error_log(__LINE__.var_export($retBB,true).PHP_EOL,3,'/tmp/markyuan');
+        error_log(__LINE__.var_export($cliAA,true).PHP_EOL,3,'/tmp/markyuan');
+        error_log(__LINE__.var_export($cliBB,true).PHP_EOL,3,'/tmp/markyuan');
+        $retAA = ($cliAA->get('/cn/token?appid=AAA'));
+        $retBB = ($cliBB->get('/cn/token?appid=BBB'));
+        error_log(__LINE__.var_export($retAA,true).PHP_EOL,3,'/tmp/markyuan');
+        error_log(__LINE__.var_export($retBB,true).PHP_EOL,3,'/tmp/markyuan');
+        error_log(__LINE__.var_export($cliAA,true).PHP_EOL,3,'/tmp/markyuan');
+        error_log(__LINE__.var_export($cliBB,true).PHP_EOL,3,'/tmp/markyuan');
+        $retAA=$cliAA->recv();
+        $retBB=$cliBB->recv();
+        error_log(__LINE__.var_export($retAA,true).PHP_EOL,3,'/tmp/markyuan');
+        error_log(__LINE__.var_export($retBB,true).PHP_EOL,3,'/tmp/markyuan');
+        error_log(__LINE__.var_export($cliAA,true).PHP_EOL,3,'/tmp/markyuan');
+        error_log(__LINE__.var_export($cliBB,true).PHP_EOL,3,'/tmp/markyuan');
+        $retAA=$cliAA->close();
+        $retBB=$cliBB->close();
+        error_log(__LINE__.'---------- end --- multi --------------'.PHP_EOL,3,'/tmp/markyuan');
+    }
+
+
+
+    private static function tcp(){
+        for($i=0;$i<2;$i++){
+            $tcp_cli = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
+            $ret = $tcp_cli ->connect("0.0.0.0", 9511);
+            $ret = $tcp_cli ->send('test for the coro');
+            $ret = $tcp_cli ->recv();
+            $ret=$tcp_cli->close();
+        }
+    }
+
+ private static function coro_dns(){
+    swoole_async_set(array('use_async_resolver'=>1));
+    swoole_async_set(array('dns_cache_refresh_time'=>0));
+    $ret=swoole_async_dns_lookup_coro("www.baidu.com",0.5);
+    error_log(' ip and host '.$host.print_r($ret,true),'3','/home/yuanyizhi/markyuan/markyuan.log');
+    return $ret;
+//  swoole_async_dns_lookup("www.baidu.com", function($host, $ip){
+//  error_log(' ip and host '.$host.'  and  ip '.$ip,'3','/home/yuanyizhi/markyuan/markyuan.log');
+//  });
+    }
+
+
+private static function tcpmulti(){
+        $cliAA = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
+        $cliBB = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
+        $retAA = $cliAA ->connect("0.0.0.0", 9511);
+        $retBB = $cliBB ->connect("0.0.0.0", 9511);
+        $retAA = $cliAA ->send('test for the coro');
+        $retBB = $cliBB ->send('test for the coro');
+        $retAA = $cliAA->recv();
+        $retBB = $cliBB->recv();
+        $cliAA->close();
+        $cliBB->close();
+    }
+
+    public static function onRequest($request, $response)
+    {
+//        self::multihttp();
+//        self::http();
+        //self::https();
+//        self::tcp();
+      //  self::tcpmulti();
+        $ret=self::coro_dns();
+        $response->end(print_r($ret,true));
+    }
+
+
+    public static function staticFunc()
+    {
+        echo "in static function";
+    }
+}
+
+$server = new Server();
+
+$server->run();

+ 40 - 0
test/coroutine/library/base.php

@@ -0,0 +1,40 @@
+<?php
+class R
+{
+    public function __construct()
+    {
+        $cid = \Swoole\Coroutine::getCid();
+        echo "cid:$cid ".__CLASS__ . '#' . \spl_object_id((object)$this) . ' constructed' . PHP_EOL;
+    }
+    
+    public function __destruct()
+    {
+        $cid = \Swoole\Coroutine::getCid();
+        echo "cid:$cid ".__CLASS__ . '#' . \spl_object_id((object)$this) . ' destructed' . PHP_EOL;
+    }
+}
+
+class Pool extends \Swoole\Coroutine\ObjectPool
+{
+    public function __construct($type)
+    {
+        parent::__construct($type);
+    }
+    
+    public function create()
+    {
+        return new R;
+    }
+}
+
+$pool = new Pool("test");
+go(function() use ($pool){
+    $object = $pool->get();
+    $cid = \Swoole\Coroutine::getCid();
+    echo "cid:$cid ".var_export($object,1)."\n";
+});
+go(function() use ($pool){
+    $object = $pool->get();
+    $cid = \Swoole\Coroutine::getCid();
+    echo "cid:$cid ".var_export($object,1)."\n";
+});

+ 21 - 0
test/coroutine/list_coroutines.php

@@ -0,0 +1,21 @@
+<?php
+foreach(range(1, 100) as $i) {
+    go(function () use ($i) {
+        if ($i % 9 == 7) {
+            return;
+        }
+        while(true) {
+            co::sleep(10);
+            echo "CORO: $i\n";
+        }
+    });
+}
+
+go(function () {
+    while(true) {
+        co::sleep(3);
+        $coros = Co::listCoroutines();
+        $cids = iterator_to_array($coros );
+        var_dump($cids);
+    }
+});

+ 32 - 0
test/coroutine/mysql_chan.php

@@ -0,0 +1,32 @@
+<?php
+
+use Swoole\Coroutine as co;
+
+$chan = new chan(4);
+
+go(function () use ($chan) {
+
+    $db = new co\MySQL();
+    $server = array(
+        'host' => '127.0.0.1',
+        'user' => 'root',
+        'password' => 'root',
+        'database' => 'test',
+    );
+
+    echo "connect\n";
+    $ret1 = $db->connect($server);
+    var_dump($ret1);
+
+    echo "prepare\n";
+    $ret2 = $db->query('SELECT * FROM userinfo WHERE id=3');
+    var_dump($ret2);
+
+    $chan->push($db);
+});
+
+go(function () use ($chan) {
+    $db = $chan->pop();
+    $ret2 = $db->query('SELECT * FROM userinfo WHERE id=3');
+    var_dump($ret2);
+});

+ 16 - 0
test/coroutine/mysql_escape.php

@@ -0,0 +1,16 @@
+<?php
+
+go(function(){
+    $swoole_mysql = new \Swoole\Coroutine\MySQL();
+    
+    $swoole_mysql->connect([
+        'host' => '127.0.0.1',
+        'port' => 3306,
+        'user' => 'root',
+        'password' => 'root',
+        'database' => 'test',
+    ]);
+    $res = $swoole_mysql->escape("");
+    var_dump($res);
+});
+    

+ 14 - 0
test/coroutine/mysql_execute_empty.php

@@ -0,0 +1,14 @@
+<?php
+go(function () {
+    $db = new Swoole\Coroutine\Mysql;
+    $server = [
+        'host'     => '127.0.0.1',
+        'user'     => 'root',
+        'password' => 'root',
+        'database' => 'test'
+    ];
+    $db->connect($server);
+    $stmt = $db->prepare('SELECT * FROM `userinfo`');
+    $ret = $stmt->execute();
+    var_dump($ret);
+});

+ 41 - 0
test/coroutine/mysql_prepare.php

@@ -0,0 +1,41 @@
+<?php
+use Swoole\Coroutine as co;
+
+co::create(function() {
+
+    $db = new co\MySQL();
+    $server = array(
+        'host' => '127.0.0.1',
+        'user' => 'root',
+        'password' => 'root',
+        'database' => 'test',
+    );
+
+    echo "connect\n";
+    $ret1 = $db->connect($server);
+    var_dump($ret1);
+
+    echo "prepare [1]\n";
+    $stmt1 = $db->prepare('SELECT * FROM userinfo WHERE id=?');
+    var_dump($stmt1);
+    if ($stmt1 == false)
+    {
+        var_dump($db->errno, $db->error);
+    }
+
+    echo "execute\n";
+    $ret3 = $stmt1->execute(array(10));
+    var_dump(count($ret3));
+
+    echo "prepare [2]\n";
+    $stmt2 = $db->prepare('SELECT * FROM userinfo WHERE id > ? and level > ?');
+    var_dump($stmt2);
+    if ($stmt2 == false)
+    {
+        var_dump($db->errno, $db->error);
+    }
+
+    echo "execute\n";
+    $ret4 = $stmt2->execute(array(10, 99));
+    var_dump($ret4);
+});

+ 24 - 0
test/coroutine/mysql_prepare_2.php

@@ -0,0 +1,24 @@
+<?php
+
+
+go(function() {
+
+    $db = new Co\MySQL();
+    $server = array(
+        'host' => '127.0.0.1',
+        'user' => 'root',
+        'password' => 'root',
+        'database' => 'test',
+    );
+
+    echo "connect\n";
+    $ret1 = $db->connect($server);
+    var_dump($ret1);
+
+    echo "prepare [1]\n";
+    $stmt1 = $db->prepare('show tables');
+    echo "execute\n";
+    $ret1 = $stmt1->execute([]);
+    var_dump($ret1);
+
+});

+ 28 - 0
test/coroutine/mysql_procedure_exec.php

@@ -0,0 +1,28 @@
+<?php
+
+go(function () {
+    $db = new Swoole\Coroutine\Mysql;
+    $server = [
+        'host' => '127.0.0.1',
+        'user' => 'root',
+        'password' => 'root',
+        'database' => 'test'
+    ];
+
+    $clear = <<<SQL
+    DROP PROCEDURE IF EXISTS `say`
+SQL;
+    $procedure = <<<SQL
+  CREATE DEFINER=`root`@`localhost` PROCEDURE `say`(content varchar(255))
+  BEGIN
+    SELECT concat('you said: \"', content, '\"');
+  END
+SQL;
+
+    $db->connect($server);
+    if ($db->query($clear) && $db->query($procedure)) {
+        $stmt = $db->prepare('CALL say(?)');
+        $ret = $stmt->execute(['hello mysql!']);
+        var_dump(current($ret[0])); // you said: "hello mysql!"
+    }
+});

+ 26 - 0
test/coroutine/mysql_query.php

@@ -0,0 +1,26 @@
+<?php
+use Swoole\Coroutine as co;
+co::set(['trace_flags' => 1]);
+
+co::create(function() {
+
+
+    $function = new ReflectionFunction('title');
+
+    $function->invoke();
+    echo "invoke444\n";
+
+});
+
+function title() {
+    echo "333invoke_________________________________\n";
+    $tcpclient = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
+    var_dump($tcpclient->connect('127.0.0.1', 9501, 1));
+
+}
+
+echo "111\n";
+
+
+echo "222\n";
+co::go();

+ 15 - 0
test/coroutine/mysql_unixsocket.php

@@ -0,0 +1,15 @@
+<?php
+
+go(function(){
+    $db = new Swoole\Coroutine\Mysql;
+    $server = [
+        'host'     => 'unix:/tmp/mysql.sock',
+        'user'     => 'root',
+        'password' => 'root',
+        'database' => 'test'
+    ];
+    $db->connect($server);
+    $stmt = $db->prepare('SELECT * FROM `user` WHERE id=?');
+    $ret = $stmt->execute([1]);
+    var_dump($ret);
+});

+ 20 - 0
test/coroutine/proc_open.php

@@ -0,0 +1,20 @@
+<?php
+Swoole\Runtime::setHookFlags(SWOOLE_HOOK_ALL);
+Swoole\Coroutine\run(function () {
+
+    $descriptorspec = array(
+        0 => array("pipe", "r"),
+        1 => array("pipe", "w"),
+        2 => array("pipe", "w"),
+    );
+
+    $process = proc_open('unknown', $descriptorspec, $pipes);
+
+    var_dump($pipes);
+
+    var_dump(fread($pipes[2], 8192));
+
+    $return_value = proc_close($process);
+
+    echo "command returned $return_value\n";
+});

+ 71 - 0
test/coroutine/reconnect_test.php

@@ -0,0 +1,71 @@
+<?php
+/* new multi implement test */
+$server = new Swoole\Http\Server("127.0.0.1", 9502, SWOOLE_BASE);
+
+$server->set([
+	'worker_num' => 1,
+]);
+
+$server->on('Request', function ($request, $response) {
+
+	/*
+	$mysql = new Swoole\Coroutine\MySQL();
+	$res = $mysql->connect(['host' => '192.168.244.128', 'user' => 'mha_manager', 'password' => 'mhapass', 'database' => 'tt']);
+	if ($res == false) {
+		$response->end("MySQL connect fail!");
+		return;
+	}
+	$res = $mysql->connect(['host' => '192.168.244.128', 'user' => 'mha_manager', 'password' => 'mhapass', 'database' => 'tt']);
+	if ($res == false) {
+		$response->end("MySQL connect fail!");
+		return;
+	}
+	$mysql->close();
+
+	$res = $mysql->connect(['host' => '192.168.244.128', 'user' => 'mha_manager', 'password' => 'mhapass', 'database' => 'tt']);
+	if ($res == false) {
+		$response->end("MySQL connect fail!");
+		return;
+	}
+	$res = $mysql->query('select sleep(1)', 2);
+	var_dump($res);
+
+	$res = $mysql->connect(['host' => '192.168.244.128', 'user' => 'mha_manager', 'password' => 'mhapass', 'database' => 'tt']);
+	if ($res == false) {
+		$response->end("MySQL connect fail!");
+		return;
+	}
+	$res = $mysql->query('select sleep(1)', 2);
+	var_dump($res);
+	*/
+
+	$redis = new Swoole\Coroutine\Redis();
+	$res = $redis->connect('127.0.0.1', 6379);
+	if ($res == false) {
+		$response->end("Redis connect fail!");
+		return;
+	}
+	$res = $redis->connect('127.0.0.1', 6379);
+	if ($res == false) {
+		$response->end("Redis connect fail!");
+		return;
+	}
+	$redis->close();
+	$res = $redis->connect('127.0.0.1', 6379);
+	if ($res == false) {
+		$response->end("Redis connect fail!");
+		return;
+	}
+	$res = $redis->get('key');
+	var_dump($res);
+	$res = $redis->connect('127.0.0.1', 6379);
+	if ($res == false) {
+		$response->end("Redis connect fail!");
+		return;
+	}
+	$res = $redis->get('key');
+	var_dump($res);
+
+	$response->end('Test End');
+});
+$server->start();

+ 8 - 0
test/coroutine/redis/auth.php

@@ -0,0 +1,8 @@
+<?php
+go(function () {
+    $redis = new Swoole\Coroutine\Redis;
+    $redis->connect('127.0.0.1', 6379);
+    $redis->auth('root');
+    $redis->set('key', 'swoole redis work');
+    var_dump($redis->get('key'));
+});

+ 24 - 0
test/coroutine/redis/defer.php

@@ -0,0 +1,24 @@
+<?php
+
+const REDIS_SERVER_HOST = '127.0.0.1';
+const REDIS_SERVER_PORT = 6379;
+
+
+go(function () {
+    $redis = new Swoole\Coroutine\Redis();
+    $redis->connect(REDIS_SERVER_HOST, REDIS_SERVER_PORT);
+    $redis->setDefer();
+    $redis->set('key1', 'value');
+
+    $redis2 = new Swoole\Coroutine\Redis();
+    $redis2->connect(REDIS_SERVER_HOST, REDIS_SERVER_PORT);
+    $redis2->setDefer();
+    $redis2->get('key1');
+
+    $result1 = $redis->recv();
+    $result2 = $redis2->recv();
+
+    var_dump($result1, $result2);
+});
+
+

+ 7 - 0
test/coroutine/redis/eval.php

@@ -0,0 +1,7 @@
+<?php
+go(function (){
+    $redis = new Co\Redis;
+    $redis->connect('127.0.0.1', 6379);
+    $res = $redis->eval("return redis.call('get', 'key')");
+    var_dump($res);
+});

+ 8 - 0
test/coroutine/redis/get.php

@@ -0,0 +1,8 @@
+<?php
+go(function (){
+	$redis = new CO\Redis;
+	var_dump($redis->connect("127.0.0.1", 6379));
+	var_dump($redis->get("key"));
+	var_dump($redis->set("key_22", str_repeat('A', 8192*256)));
+	var_dump($redis->mget(["key", "key_22"]));
+});

+ 19 - 0
test/coroutine/redis/multi.php

@@ -0,0 +1,19 @@
+<?php
+const REDIS_SERVER_HOST = '127.0.0.1';
+const REDIS_SERVER_PORT = 6379;
+
+
+go(function () {
+    $redis = new Swoole\Coroutine\Redis();
+    $redis->connect(REDIS_SERVER_HOST, REDIS_SERVER_PORT);
+    $redis->multi();
+    $redis->set('key3', 'rango');
+    $redis->get('key1');
+    $redis->get('key2');
+    $redis->get('key3');
+
+    $result = $redis->exec();
+    var_dump($result);
+});
+
+

+ 0 - 0
test/coroutine/redis/pipeline.php


Some files were not shown because too many files changed in this diff