|
@@ -6,877 +6,11 @@
|
|
|
* Time: 下午2:28
|
|
|
*/
|
|
|
|
|
|
-interface IProcessor
|
|
|
-{
|
|
|
- public function onStart();
|
|
|
- public function onRequest($bufid, $body);
|
|
|
- public function onClose($bufid);
|
|
|
- public function onConnected($bufid,$stream,$host,$port,$args);
|
|
|
-}
|
|
|
-
|
|
|
-class event_looper
|
|
|
-{
|
|
|
- const body_header_len = 10;
|
|
|
- const read_micotime = 6000000000;
|
|
|
- const connect_micotime = 5000000;
|
|
|
-
|
|
|
- protected $mEvBase;
|
|
|
- protected $mEvSignals;
|
|
|
- protected $mEvSockets;
|
|
|
- protected $mEvTimeouts;
|
|
|
-
|
|
|
- protected $mStreams;
|
|
|
- protected $mContents;
|
|
|
-
|
|
|
- protected $mProcessor;
|
|
|
-
|
|
|
- public function __construct()
|
|
|
- {
|
|
|
- $this->mStreams = [];
|
|
|
- $this->mContents = [];
|
|
|
-
|
|
|
- $this->mEvSignals = [];
|
|
|
- $this->mEvSockets = [];
|
|
|
-
|
|
|
- $this->mEvTimeouts = [];
|
|
|
-
|
|
|
- event_init();
|
|
|
- $this->mEvBase = event_base_new();
|
|
|
- }
|
|
|
-
|
|
|
- public function init(IProcessor $processor)
|
|
|
- {
|
|
|
- $this->mProcessor = $processor;
|
|
|
- $this->mProcessor->onStart();
|
|
|
- }
|
|
|
-
|
|
|
- public function run_loop()
|
|
|
- {
|
|
|
- $this->add_signal(SIGINT);
|
|
|
- $this->add_signal(SIGQUIT);
|
|
|
- $this->add_signal(SIGTERM);
|
|
|
-
|
|
|
- $ret = event_base_loop($this->mEvBase);
|
|
|
- Log::record("event_base_loop ret={$ret}",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- public function add_listen($stream)
|
|
|
- {
|
|
|
- $fd = intval($stream);
|
|
|
- if($fd < 0) return false;
|
|
|
-
|
|
|
- $this->mEvSockets[$fd] = event_new();
|
|
|
- if(event_set($this->mEvSockets[$fd], $stream, EV_READ | EV_PERSIST, [$this, 'onAccept']) == false) {
|
|
|
- Log::record("event_set error EV_READ | EV_PERSIST",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- if(event_base_set($this->mEvSockets[$fd], $this->mEvBase) == false) {
|
|
|
- Log::record("event_set error EV_READ | EV_PERSIST",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- if(event_add($this->mEvSockets[$fd]) == false) {
|
|
|
- Log::record("event_add error EV_READ | EV_PERSIST",Log::DEBUG);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private function add_signal($val)
|
|
|
- {
|
|
|
- $this->mEvSignals[$val] = event_new();
|
|
|
-
|
|
|
- if(event_set($this->mEvSignals[$val], $val, EV_SIGNAL, [$this, 'onSignal']) == false) {
|
|
|
- Log::record("event_set error EV_SIGNAL sig={$val}",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- if(event_base_set($this->mEvSignals[$val], $this->mEvBase) == false) {
|
|
|
- Log::record("event_base_set error EV_SIGNAL sig={$val}",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- if(event_add($this->mEvSignals[$val]) == false) {
|
|
|
- Log::record("event_add error EV_SIGNAL sig={$val}",Log::DEBUG);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function onSignal($sig, $flag)
|
|
|
- {
|
|
|
- Log::record("ev_signal sig={$sig},flag={$flag}",Log::DEBUG);
|
|
|
- if($sig == SIGINT || $sig == SIGQUIT || $sig == SIGTERM)
|
|
|
- {
|
|
|
- event_base_loopexit($this->mEvBase);
|
|
|
-
|
|
|
- foreach ($this->mEvTimeouts as $event) {
|
|
|
- event_del($event);
|
|
|
- event_free($event);
|
|
|
- }
|
|
|
- $this->mEvTimeouts = [];
|
|
|
-
|
|
|
- foreach ($this->mEvSockets as $fd => $event) {
|
|
|
- event_del($event);
|
|
|
- event_free($event);
|
|
|
-
|
|
|
- @socket_shutdown($this->mStreams[$fd],STREAM_SHUT_RDWR);
|
|
|
- @socket_close($this->mStreams[$fd]);
|
|
|
- }
|
|
|
- $this->mEvSockets = [];
|
|
|
- $this->mStreams = [];
|
|
|
- $this->mContents = [];
|
|
|
-
|
|
|
- foreach ($this->mEvSignals as $event) {
|
|
|
- event_del($event);
|
|
|
- event_free($event);
|
|
|
- }
|
|
|
- $this->mEvSignals = [];
|
|
|
- }
|
|
|
- }
|
|
|
- public function onAccept($socket, $event)
|
|
|
- {
|
|
|
- Log::record("onAccept socket_fd={$socket} flag={$event}",Log::DEBUG);
|
|
|
- $stream = socket_accept($socket);
|
|
|
- if($stream == false) {
|
|
|
- Log::record("stream_socket_accept return false socket_fd={$socket}",Log::DEBUG);
|
|
|
- return;
|
|
|
- }
|
|
|
- Log::record("stream_socket_accept stream={$stream}",Log::DEBUG);
|
|
|
- $this->add_stream($stream);
|
|
|
- }
|
|
|
-
|
|
|
- private function add_stream($stream)
|
|
|
- {
|
|
|
- $fd = intval($stream);
|
|
|
- socket_set_nonblock($stream);
|
|
|
-
|
|
|
- $this->mEvSockets[$fd] = event_new();
|
|
|
- $this->mStreams[$fd] = $stream;
|
|
|
- $this->mContents[$fd] = '';
|
|
|
-
|
|
|
- if(event_set($this->mEvSockets[$fd], $stream, EV_READ | EV_TIMEOUT, [$this, 'onRead']) == false) {
|
|
|
- Log::record("event_set error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- if(event_base_set($this->mEvSockets[$fd], $this->mEvBase) == false) {
|
|
|
- Log::record("event_base_set error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- if(event_add($this->mEvSockets[$fd],self::read_micotime) == false) {
|
|
|
- Log::record("event_add error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- return $fd;
|
|
|
- }
|
|
|
-
|
|
|
- public function block($fd)
|
|
|
- {
|
|
|
- $stream = $this->mStreams[$fd];
|
|
|
- $event = $this->mEvSockets[$fd];
|
|
|
-
|
|
|
- event_del($event);
|
|
|
- socket_set_block($stream);
|
|
|
- }
|
|
|
-
|
|
|
- public function unblock($fd)
|
|
|
- {
|
|
|
- $stream = $this->mStreams[$fd];
|
|
|
- $event = $this->mEvSockets[$fd];
|
|
|
-
|
|
|
- event_add($event);
|
|
|
- socket_set_nonblock($stream);
|
|
|
- }
|
|
|
-
|
|
|
- public function onTimer($stream, $event, $params)
|
|
|
- {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- public function onConnect($stream, $event, $params)
|
|
|
- {
|
|
|
- $error = socket_last_error();
|
|
|
- Log::record("onConnect stream={$stream},event={$event},socket error={$error}",Log::DEBUG);
|
|
|
-
|
|
|
- if($event == EV_TIMEOUT)
|
|
|
- {
|
|
|
- $stream = $this->do_connect($params['host'],$params['port'],$params['args'],$params['stream']);
|
|
|
- if($stream != false) {
|
|
|
- $fd = $this->add_stream($stream);
|
|
|
- $this->mProcessor->onConnected($fd, $stream,$params['host'],$params['port'],$params['args']);
|
|
|
- }
|
|
|
- }
|
|
|
- elseif($event == EV_WRITE)
|
|
|
- {
|
|
|
- $ret = socket_getopt($stream,SOL_SOCKET,SO_ERROR);
|
|
|
- if($ret == 0) {
|
|
|
- Log::record("onConnect EV_WRITE success ",Log::DEBUG);
|
|
|
- $fd = intval($stream);
|
|
|
- event_del($this->mEvSockets[$fd]);
|
|
|
- event_free($this->mEvSockets[$fd]);
|
|
|
- unset($this->mEvSockets[$fd]);
|
|
|
-
|
|
|
- $fd = $this->add_stream($stream);
|
|
|
- $this->mProcessor->onConnected($fd, $stream,$params['host'],$params['port'],$params['args']);
|
|
|
- }
|
|
|
- else {
|
|
|
- Log::record("onConnect EV_WRITE Error",Log::DEBUG);
|
|
|
- }
|
|
|
- }
|
|
|
- elseif($event == EV_WRITE | EV_READ)
|
|
|
- {
|
|
|
- Log::record("onConnect EV_WRITE | EV_READ",Log::DEBUG);
|
|
|
-
|
|
|
- $fd = intval($stream);
|
|
|
- event_del($this->mEvSockets[$fd]);
|
|
|
-
|
|
|
- if(event_set($this->mEvSockets[$fd], $stream, EV_TIMEOUT, [$this, 'onConnect'],$params) == false) {
|
|
|
- Log::record("event_set error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- if(event_base_set($this->mEvSockets[$fd], $this->mEvBase) == false) {
|
|
|
- Log::record("event_base_set error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- if(event_add($this->mEvSockets[$fd],self::connect_micotime) == false) {
|
|
|
- Log::record("event_add error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- Log::record("onConnect ETIMEOUT",Log::DEBUG);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private function do_connect($host,$port,$args,$old_stream = false)
|
|
|
- {
|
|
|
- $stream = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
|
|
- socket_set_nonblock($stream);
|
|
|
- $fd = intval($stream);
|
|
|
-
|
|
|
- if($old_stream == false) {
|
|
|
- $this->mEvSockets[$fd] = event_new();
|
|
|
- }
|
|
|
- else {
|
|
|
- $oldfd = intval($old_stream);
|
|
|
- $this->mEvSockets[$fd] = $this->mEvSockets[$oldfd];
|
|
|
- unset($this->mEvSockets[$oldfd]);
|
|
|
- }
|
|
|
-
|
|
|
- $ret = socket_connect($stream,$host,$port);
|
|
|
- if($ret == false)
|
|
|
- {
|
|
|
- if(event_set($this->mEvSockets[$fd], $stream, EV_WRITE | EV_READ | EV_TIMEOUT, [$this, 'onConnect'],
|
|
|
- ['host' => $host,'port' => $port,'args' => $args]) == false) {
|
|
|
- Log::record("event_set error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- if(event_base_set($this->mEvSockets[$fd], $this->mEvBase) == false) {
|
|
|
- Log::record("event_base_set error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- if(event_add($this->mEvSockets[$fd],self::connect_micotime) == false) {
|
|
|
- Log::record("event_add error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
- else {
|
|
|
- event_del($this->mEvSockets[$fd]);
|
|
|
- event_free($this->mEvSockets[$fd]);
|
|
|
- unset($this->mEvSockets[$fd]);
|
|
|
-
|
|
|
- return $stream;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function connect($host,$port,$args)
|
|
|
- {
|
|
|
- $stream = $this->do_connect($host,$port,$args,false);
|
|
|
- if($stream != false) {
|
|
|
- $bufid = $this->add_stream($stream);
|
|
|
- $this->mProcessor->onConnected($bufid, $stream,$host,$port,$args);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function onRead($stream, $event)
|
|
|
- {
|
|
|
- $fd = intval($stream);
|
|
|
- if($event == EV_TIMEOUT) {
|
|
|
- Log::record("onRead stream={$stream} event=EV_TIMEOUT",Log::DEBUG);
|
|
|
- event_add($this->mEvSockets[$fd],self::read_micotime);
|
|
|
- }
|
|
|
- elseif($event == EV_READ)
|
|
|
- {
|
|
|
- Log::record("onRead stream={$stream} event=EV_READ",Log::DEBUG);
|
|
|
- $read = @socket_read($stream, 1024);
|
|
|
- if($read === false) { //WOULD_BLOCK INPROCESS 事件
|
|
|
- event_add($this->mEvSockets[$fd],self::read_micotime);
|
|
|
- return;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if(strlen($read) == 0) {
|
|
|
- $this->close($fd);
|
|
|
- }
|
|
|
- else {
|
|
|
- $this->mContents[$fd] .= $read;
|
|
|
- $this->proc($fd);
|
|
|
- event_add($this->mEvSockets[$fd],self::read_micotime);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- Log::record("onRead stream={$stream} event={$event}",Log::DEBUG);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- static private function all_digit($str)
|
|
|
- {
|
|
|
- $len = strlen($str);
|
|
|
- $base = ord('0');
|
|
|
- for($offset = 0; $offset < $len; $offset++)
|
|
|
- {
|
|
|
- $code = ord(substr($str, $offset,1)) - $base;
|
|
|
- if($code < 0 || $code > 9) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- private function proc($fd)
|
|
|
- {
|
|
|
- $content = &$this->mContents[$fd];
|
|
|
- $start = 0;
|
|
|
- $left = strlen($content);
|
|
|
-
|
|
|
- while($left > self::body_header_len)
|
|
|
- {
|
|
|
- $header = substr($content,$start,self::body_header_len);
|
|
|
- if(!self::all_digit($header)) {
|
|
|
- $this->close($fd);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- $body_len = intval($header);
|
|
|
- if($body_len == 0) { //这是一个心跳包
|
|
|
- $start += self::body_header_len;
|
|
|
- $left -= self::body_header_len;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if($left >= self::body_header_len + $body_len)
|
|
|
- {
|
|
|
- $body = substr($content,$start + self::body_header_len,$body_len);
|
|
|
- $this->mProcessor->onRequest($fd,$body);
|
|
|
-
|
|
|
- $start += self::body_header_len + $body_len;
|
|
|
- $left -= self::body_header_len + $body_len;
|
|
|
- }
|
|
|
- else {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if($start > 0)
|
|
|
- {
|
|
|
- $str = substr($content,$start);
|
|
|
- if($str == false) {
|
|
|
- $this->mContents[$fd] = '';
|
|
|
- }
|
|
|
- else {
|
|
|
- $this->mContents[$fd] = $str;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function onError($stream, $event)
|
|
|
- {
|
|
|
- $fd = intval($stream);
|
|
|
- if ($event == EV_TIMEOUT)
|
|
|
- {
|
|
|
- $ret = $this->write($fd,'');
|
|
|
- if($ret == false) {
|
|
|
- $this->close($fd);
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- Log::record("onError stream={$stream} flag={$event}",Log::DEBUG);
|
|
|
- $this->close($fd);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function write($fd,$data)
|
|
|
- {
|
|
|
- if(!is_string($data)) {
|
|
|
- Log::record(__METHOD__ . " write data is not string.",Log::ERR);
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if(array_key_exists($fd,$this->mStreams)) {
|
|
|
- $stream = $this->mStreams[$fd];
|
|
|
- $header = sprintf("%010d",strlen($data));
|
|
|
- $data = $header . $data;
|
|
|
- $ret = socket_write($stream,$data,strlen($data));
|
|
|
- return ($ret == strlen($data));
|
|
|
- } else {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function close($fd)
|
|
|
- {
|
|
|
- if(!array_key_exists($fd,$this->mStreams)) {
|
|
|
- Log::record(" close socket fd={$fd}.",Log::ERR);
|
|
|
- return false;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- event_del($this->mEvSockets[$fd]);
|
|
|
- event_free($this->mEvSockets[$fd]);
|
|
|
- $stream = $this->mStreams[$fd];
|
|
|
- @socket_shutdown($stream,STREAM_SHUT_RDWR);
|
|
|
- socket_close($stream);
|
|
|
- unset($this->mEvSockets[$fd]);
|
|
|
- unset($this->mStreams[$fd]);
|
|
|
- unset($this->mContents[$fd]);
|
|
|
-
|
|
|
- $this->mProcessor->onClose($fd);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-class eventbuffer_looper
|
|
|
-{
|
|
|
- const body_header_len = 10;
|
|
|
- const read_time_out = 1800;
|
|
|
- const write_time_out = 5;
|
|
|
-
|
|
|
- protected $mEvBase;
|
|
|
- protected $mEvAccepts;
|
|
|
- protected $mEvSignals;
|
|
|
- protected $mEvConnects;
|
|
|
-
|
|
|
- protected $mStreams;
|
|
|
- protected $mBuffers;
|
|
|
- protected $mContents;
|
|
|
- protected $mProcessor;
|
|
|
- protected $mBufferID;
|
|
|
-
|
|
|
- public function __construct()
|
|
|
- {
|
|
|
- $this->mStreams = [];
|
|
|
- $this->mBuffers = [];
|
|
|
- $this->mContents = [];
|
|
|
- $this->mEvAccepts = [];
|
|
|
- $this->mEvSignals = [];
|
|
|
- $this->mEvConnects = [];
|
|
|
- $this->mEvTimeouts = [];
|
|
|
-
|
|
|
- $this->mBufferID = 1;
|
|
|
- event_init();
|
|
|
- $this->mEvBase = event_base_new();
|
|
|
- }
|
|
|
-
|
|
|
- public function init(IProcessor $processor)
|
|
|
- {
|
|
|
- $this->mProcessor = $processor;
|
|
|
- $this->mProcessor->onStart();
|
|
|
- }
|
|
|
-
|
|
|
- public function run_loop()
|
|
|
- {
|
|
|
- $this->add_signal(SIGINT);
|
|
|
- $this->add_signal(SIGQUIT);
|
|
|
- $this->add_signal(SIGTERM);
|
|
|
-
|
|
|
- $ret = event_base_loop($this->mEvBase);
|
|
|
- Log::record("event_base_loop ret={$ret}",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- public function add_listen($stream)
|
|
|
- {
|
|
|
- $fd = intval($stream);
|
|
|
- if($fd < 0) return false;
|
|
|
-
|
|
|
- $this->mEvAccepts[$fd] = event_new();
|
|
|
- if(event_set($this->mEvAccepts[$fd], $stream, EV_READ | EV_PERSIST, [$this, 'onAccept']) == false) {
|
|
|
- Log::record("event_set error EV_READ | EV_PERSIST",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- if(event_base_set($this->mEvAccepts[$fd], $this->mEvBase) == false) {
|
|
|
- Log::record("event_set error EV_READ | EV_PERSIST",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- if(event_add($this->mEvAccepts[$fd]) == false) {
|
|
|
- Log::record("event_add error EV_READ | EV_PERSIST",Log::DEBUG);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private function add_signal($val)
|
|
|
- {
|
|
|
- $this->mEvSignals[$val] = event_new();
|
|
|
-
|
|
|
- if(event_set($this->mEvSignals[$val], $val, EV_SIGNAL, [$this, 'onSignal']) == false) {
|
|
|
- Log::record("event_set error EV_SIGNAL sig={$val}",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- if(event_base_set($this->mEvSignals[$val], $this->mEvBase) == false) {
|
|
|
- Log::record("event_base_set error EV_SIGNAL sig={$val}",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- if(event_add($this->mEvSignals[$val]) == false) {
|
|
|
- Log::record("event_add error EV_SIGNAL sig={$val}",Log::DEBUG);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function onSignal($sig, $flag)
|
|
|
- {
|
|
|
- Log::record("ev_signal sig={$sig},flag={$flag}",Log::DEBUG);
|
|
|
- if($sig == SIGINT || $sig == SIGQUIT || $sig == SIGTERM)
|
|
|
- {
|
|
|
- event_base_loopexit($this->mEvBase);
|
|
|
-
|
|
|
- foreach ($this->mBuffers as $bufid => $buffer) {
|
|
|
- event_buffer_disable($buffer, EV_READ | EV_WRITE);
|
|
|
- event_buffer_free($buffer);
|
|
|
-
|
|
|
- @socket_shutdown($this->mStreams[$bufid],STREAM_SHUT_RDWR);
|
|
|
- socket_close($this->mStreams[$bufid]);
|
|
|
- }
|
|
|
- $this->mStreams = [];
|
|
|
- $this->mContents = [];
|
|
|
- $this->mBuffers = [];
|
|
|
- }
|
|
|
- }
|
|
|
- public function onAccept($socket, $event)
|
|
|
- {
|
|
|
- Log::record("onAccept socket_fd={$socket} flag={$event}",Log::DEBUG);
|
|
|
- $stream = socket_accept($socket);
|
|
|
- if($stream == false) {
|
|
|
- Log::record("stream_socket_accept return false socket_fd={$socket}",Log::DEBUG);
|
|
|
- return;
|
|
|
- }
|
|
|
- Log::record("stream_socket_accept stream={$stream}",Log::DEBUG);
|
|
|
- $this->add_stream($stream);
|
|
|
- }
|
|
|
-
|
|
|
- public function onWrite($buffer, $bufid)
|
|
|
- {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- private function add_stream($stream)
|
|
|
- {
|
|
|
- $bufid = $this->mBufferID;
|
|
|
- socket_set_nonblock($stream);
|
|
|
- $buffer = event_buffer_new($stream, [$this,'onRead'], [$this,'onWrite'], [$this,'onError'], $bufid);
|
|
|
-
|
|
|
- if($buffer == false) {
|
|
|
- socket_close($stream);
|
|
|
- return false;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- event_buffer_base_set($buffer,$this->mEvBase);
|
|
|
- event_buffer_timeout_set($buffer, self::read_time_out, self::write_time_out);
|
|
|
- event_buffer_watermark_set($buffer, EV_READ, 0, 1024*1024);
|
|
|
- event_buffer_watermark_set($buffer, EV_WRITE, 0, 1024*1024);
|
|
|
- event_buffer_priority_set($buffer, 10);
|
|
|
- event_buffer_enable($buffer, EV_READ | EV_PERSIST);
|
|
|
-
|
|
|
- $this->mStreams[$bufid] = $stream;
|
|
|
- $this->mBuffers[$bufid] = $buffer;
|
|
|
- $this->mContents[$bufid] = "";
|
|
|
-
|
|
|
- $this->mBufferID++;
|
|
|
- if($this->mBufferID < 0) $this->mBufferID = 1;
|
|
|
-
|
|
|
- return $bufid;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function block($bufid)
|
|
|
- {
|
|
|
- $stream = $this->mStreams[$bufid];
|
|
|
- $buffer = $this->mBuffers[$bufid];
|
|
|
-
|
|
|
- $success = event_buffer_disable($buffer, EV_READ | EV_PERSIST);
|
|
|
- Log::record("event_buffer_disable success={$success}",Log::DEBUG);
|
|
|
-
|
|
|
- $success = socket_set_block($stream);
|
|
|
- Log::record("socket_set_block success={$success}",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- public function unblock($bufid)
|
|
|
- {
|
|
|
- $stream = $this->mStreams[$bufid];
|
|
|
- $buffer = $this->mBuffers[$bufid];
|
|
|
-
|
|
|
- $success = socket_set_nonblock($stream);
|
|
|
- Log::record("socket_set_nonblock success={$success}",Log::DEBUG);
|
|
|
-
|
|
|
- $success = event_buffer_enable($buffer, EV_READ | EV_PERSIST);
|
|
|
- Log::record("event_buffer_enable success={$success}",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- public function onConnectTimer($stream, $event, $params)
|
|
|
- {
|
|
|
- $error = socket_last_error();
|
|
|
- Log::record("onConnectTimer sig={$stream},flag={$event},error={$error}",Log::DEBUG);
|
|
|
- $stream = $this->do_connect($params['host'],$params['port'],$params['args'],$params['stream']);
|
|
|
- if($stream != false) {
|
|
|
- $bufid = $this->add_stream($stream);
|
|
|
- $this->mProcessor->onConnected($bufid, $stream,$params['host'],$params['port'],$params['args']);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function onConnect($stream, $event, $params)
|
|
|
- {
|
|
|
- $error = socket_last_error();
|
|
|
- Log::record("onConnect sig={$stream},flag={$event},socket error={$error}",Log::DEBUG);
|
|
|
-
|
|
|
- if($event == EV_WRITE) {
|
|
|
- $ret = socket_getopt($stream,SOL_SOCKET,SO_ERROR);
|
|
|
- if($ret == 0) {
|
|
|
- Log::record("onConnect EV_WRITE success ",Log::DEBUG);
|
|
|
- $fd = intval($stream);
|
|
|
- event_del($this->mEvConnects[$fd]);
|
|
|
- event_free($this->mEvConnects[$fd]);
|
|
|
- event_del($this->mEvTimeouts[$fd]);
|
|
|
- event_free($this->mEvTimeouts[$fd]);
|
|
|
- unset($this->mEvConnects[$fd]);
|
|
|
- unset($this->mEvTimeouts[$fd]);
|
|
|
- $bufid = $this->add_stream($stream);
|
|
|
- $this->mProcessor->onConnected($bufid, $stream,$params['host'],$params['port'],$params['args']);
|
|
|
- }
|
|
|
- else {
|
|
|
- Log::record("onConnect EV_WRITE Error",Log::DEBUG);
|
|
|
- }
|
|
|
- }
|
|
|
- elseif($event == EV_WRITE | EV_READ) {
|
|
|
- Log::record("onConnect EV_WRITE | EV_READ",Log::DEBUG);
|
|
|
- }
|
|
|
- else {
|
|
|
- Log::record("onConnect ETIMEOUT",Log::DEBUG);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private function do_connect($host,$port,$args,$old_stream = false)
|
|
|
- {
|
|
|
- $stream = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
|
|
- socket_set_nonblock($stream);
|
|
|
- $fd = intval($stream);
|
|
|
-
|
|
|
- if($old_stream == false)
|
|
|
- {
|
|
|
- $this->mEvConnects[$fd] = event_new();
|
|
|
- $this->mEvTimeouts[$fd] = event_timer_new();
|
|
|
- }
|
|
|
- else {
|
|
|
- $oldfd = intval($old_stream);
|
|
|
- $this->mEvConnects[$fd] = $this->mEvConnects[$oldfd];
|
|
|
- $this->mEvTimeouts[$fd] = $this->mEvTimeouts[$oldfd];
|
|
|
- unset($this->mEvConnects[$oldfd]);
|
|
|
- unset($this->mEvTimeouts[$oldfd]);
|
|
|
- }
|
|
|
-
|
|
|
- $ret = socket_connect($stream,$host,$port);
|
|
|
- if($ret == false)
|
|
|
- {
|
|
|
- if(event_set($this->mEvConnects[$fd], $stream, EV_WRITE | EV_READ, [$this, 'onConnect'],['host' => $host,'port' => $port,'args' => $args]) == false) {
|
|
|
- Log::record("event_set error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- if(event_base_set($this->mEvConnects[$fd], $this->mEvBase) == false) {
|
|
|
- Log::record("event_base_set error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- if(event_timer_set($this->mEvTimeouts[$fd], [$this, 'onConnectTimer'],['stream' => $stream, 'host' => $host,'port' => $port,'args' => $args]) == false) {
|
|
|
- Log::record("event_set error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- if(event_base_set($this->mEvTimeouts[$fd], $this->mEvBase) == false) {
|
|
|
- Log::record("event_base_set error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- if(event_add($this->mEvConnects[$fd]) == false) {
|
|
|
- Log::record("event_add error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
-
|
|
|
- if(event_timer_add($this->mEvTimeouts[$fd],1000000) == false) {
|
|
|
- Log::record("event_base_set error connect fd={$stream}",Log::DEBUG);
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
- else {
|
|
|
- event_del($this->mEvConnects[$fd]);
|
|
|
- event_free($this->mEvConnects[$fd]);
|
|
|
- event_del($this->mEvTimeouts[$fd]);
|
|
|
- event_free($this->mEvTimeouts[$fd]);
|
|
|
-
|
|
|
- unset($this->mEvConnects[$fd]);
|
|
|
- unset($this->mEvTimeouts[$fd]);
|
|
|
-
|
|
|
- return $stream;
|
|
|
- }
|
|
|
- }
|
|
|
- public function connect($host,$port,$args)
|
|
|
- {
|
|
|
- $stream = $this->do_connect($host,$port,$args,false);
|
|
|
- if($stream != false) {
|
|
|
- $bufid = $this->add_stream($stream);
|
|
|
- $this->mProcessor->onConnected($bufid, $stream,$host,$port,$args);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- static private function all_digit($str)
|
|
|
- {
|
|
|
- $len = strlen($str);
|
|
|
- $base = ord('0');
|
|
|
- for($offset = 0; $offset < $len; $offset++)
|
|
|
- {
|
|
|
- $code = ord(substr($str, $offset,1)) - $base;
|
|
|
- if($code < 0 || $code > 9) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public function onRead($buffer, $bufid)
|
|
|
- {
|
|
|
- Log::record("onRead bufid={$bufid}",Log::DEBUG);
|
|
|
-
|
|
|
- $content = &$this->mContents[$bufid];
|
|
|
-// $read = event_buffer_read($this->mBuffers[$bufid], 1024 * 1024);
|
|
|
- $read = event_buffer_read_all($this->mBuffers[$bufid]);
|
|
|
- if(!empty($read)) {
|
|
|
- Log::record("read={$read}",Log::DEBUG);
|
|
|
- $read = substr($read,23);
|
|
|
- $content .= $read;
|
|
|
- }
|
|
|
- else {
|
|
|
- return;
|
|
|
- }
|
|
|
-// while (true)
|
|
|
-// {
|
|
|
-//// $read = event_buffer_read($buffer, 1024);
|
|
|
-// $read = event_buffer_read($this->mBuffers[$bufid], 1024 * 1024);
|
|
|
-// if(empty($read)) {
|
|
|
-// break;
|
|
|
-// } else {
|
|
|
-// Log::record("read={$read}",Log::DEBUG);
|
|
|
-// $read = substr($read,12);
|
|
|
-// $content .= $read;
|
|
|
-// break;
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
- $start = 0;
|
|
|
- $left = strlen($content);
|
|
|
- do
|
|
|
- {
|
|
|
- if($left > self::body_header_len)
|
|
|
- {
|
|
|
- $header = substr($content,$start,self::body_header_len);
|
|
|
- $body_len = intval($header);
|
|
|
-
|
|
|
- if(self::all_digit($header) == false) {
|
|
|
- Log::record("content={$content}",Log::DEBUG);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if($left >= self::body_header_len + $body_len)
|
|
|
- {
|
|
|
- $body = substr($content,$start + self::body_header_len,$body_len);
|
|
|
- if($this->mProcessor != null && !empty($body)) {
|
|
|
-// Log::record("head={$header} body={$body}",Log::DEBUG);
|
|
|
- $this->mProcessor->onRequest($bufid,$body);
|
|
|
- }
|
|
|
-
|
|
|
- $start += self::body_header_len + $body_len;
|
|
|
- $left = $left - self::body_header_len - $body_len;
|
|
|
- }
|
|
|
- else {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- break;
|
|
|
- }
|
|
|
- } while ($left > 0);
|
|
|
-
|
|
|
- if($start > 0) {
|
|
|
- $content = substr($content,$start);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function onError($buffer, $event, $bufid)
|
|
|
- {
|
|
|
- Log::record("onError bufid={$bufid} flag={$event}",Log::DEBUG);
|
|
|
-
|
|
|
- if ($event == (EVBUFFER_READ | EVBUFFER_TIMEOUT)) {
|
|
|
- event_buffer_enable($buffer, EV_READ);
|
|
|
- $this->write($bufid,'');
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- event_buffer_disable($buffer, EV_READ | EV_WRITE);
|
|
|
- event_buffer_free($buffer);
|
|
|
-
|
|
|
- if(array_key_exists($bufid,$this->mStreams)) {
|
|
|
- @socket_shutdown($this->mStreams[$bufid],STREAM_SHUT_RDWR);
|
|
|
- socket_close($this->mStreams[$bufid]);
|
|
|
- unset($this->mStreams[$bufid]);
|
|
|
- }
|
|
|
-
|
|
|
- if(array_key_exists($bufid,$this->mBuffers)) {
|
|
|
- unset($this->mBuffers[$bufid]);
|
|
|
- }
|
|
|
- if(array_key_exists($bufid,$this->mContents)) {
|
|
|
- unset($this->mContents[$bufid]);
|
|
|
- }
|
|
|
-
|
|
|
- if($this->mProcessor != null) {
|
|
|
- $this->mProcessor->onClose($bufid);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function write($bufid,$data)
|
|
|
- {
|
|
|
- if(!is_string($data)) {
|
|
|
- Log::record(__METHOD__ . " write data is not string.",Log::ERR);
|
|
|
- }
|
|
|
- if(array_key_exists($bufid,$this->mBuffers)) {
|
|
|
- $buffer = $this->mBuffers[$bufid];
|
|
|
- $header = sprintf("%010d",strlen($data));
|
|
|
- $data = $header . $data;
|
|
|
- $ret = event_buffer_write($buffer,$data,strlen($data));
|
|
|
- if($ret == false) {
|
|
|
- Log::record(__METHOD__ . " event_buffer_write return false.",Log::ERR);
|
|
|
- }
|
|
|
- return $ret;
|
|
|
- } else {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function close($bufid)
|
|
|
- {
|
|
|
- if(!array_key_exists($bufid,$this->mBuffers)) return false;
|
|
|
-
|
|
|
- Log::record(__METHOD__ . " close socket.",Log::DEBUG);
|
|
|
-
|
|
|
- $buffer = $this->mBuffers[$bufid];
|
|
|
- event_buffer_disable($buffer, EV_READ | EV_WRITE);
|
|
|
- event_buffer_free($buffer);
|
|
|
-
|
|
|
- if(array_key_exists($bufid,$this->mStreams)) {
|
|
|
- @socket_shutdown($this->mStreams[$bufid],STREAM_SHUT_RDWR);
|
|
|
- socket_close($this->mStreams[$bufid]);
|
|
|
- unset($this->mStreams[$bufid]);
|
|
|
- }
|
|
|
-
|
|
|
- if(array_key_exists($bufid,$this->mBuffers)) {
|
|
|
- unset($this->mBuffers[$bufid]);
|
|
|
- }
|
|
|
- if(array_key_exists($bufid,$this->mContents)) {
|
|
|
- unset($this->mContents[$bufid]);
|
|
|
- }
|
|
|
- if($this->mProcessor != null) {
|
|
|
- $this->mProcessor->onClose($bufid);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
+require_once(BASE_ROOT_PATH . '/helper/event/IProcessor.php');
|
|
|
+require_once(BASE_ROOT_PATH . '/helper/event/event_looper.php');
|
|
|
+require_once(BASE_ROOT_PATH . '/helper/event/buffer_looper.php');
|
|
|
|
|
|
-class process_looper extends event_looper
|
|
|
+class process_looper extends event\buffer_looper
|
|
|
{
|
|
|
private static $stInstance;
|
|
|
public static function instance()
|