/app-servers/genericWebSocketServer.php

https://github.com/Erika31/phpdaemon · PHP · 267 lines · 114 code · 41 blank · 112 comment · 10 complexity · 61578f7cd731e682584817d835ab485a MD5 · raw file

  1. <?php
  2. class genericWebSocketServer extends AsyncServer
  3. {
  4. public $sessions = array();
  5. public $routes = array();
  6. protected $timeout_cb;
  7. const BINARY = 0x80;
  8. const STRING = 0x00;
  9. /**
  10. * Registering event timeout callback function
  11. * @param Closure Callback function
  12. * @return void
  13. */
  14. public function registerEventTimeout($cb)
  15. {
  16. if ($cb === NULL || is_callable($cb))
  17. {
  18. $this->timeout_cb = $cb ;
  19. }
  20. }
  21. /**
  22. * Setting default config options
  23. * Overriden from AppInstance::getConfigDefaults
  24. * @return array|false
  25. */
  26. protected function getConfigDefaults()
  27. {
  28. return array(
  29. // listen to
  30. 'listen' => 'tcp://0.0.0.0',
  31. // listen port
  32. 'listenport' => 55556,
  33. // max allowed packet size
  34. 'maxallowedpacket' => new Daemon_ConfigEntrySize('16k'),
  35. // disabled by default
  36. 'enable' => 0,
  37. // no event_timeout by default
  38. 'ev_timeout' => -1
  39. );
  40. }
  41. /**
  42. * Event of appInstance. Adds default settings and binds sockets.
  43. * @return void
  44. */
  45. public function init()
  46. {
  47. $this->update();
  48. if ($this->config->enable->value)
  49. {
  50. $this->bindSockets(
  51. $this->config->listen->value,
  52. $this->config->listenport->value
  53. );
  54. }
  55. }
  56. /**
  57. * Enable all events of sockets
  58. * @return void
  59. */
  60. public function enableSocketEvents()
  61. {
  62. foreach ($this->socketEvents as $ev)
  63. {
  64. event_base_set($ev, Daemon::$process->eventBase);
  65. event_add($ev, $this->config->ev_timeout->value); // With specified timeout
  66. }
  67. }
  68. /**
  69. * Called when a request to HTTP-server looks like WebSocket handshake query.
  70. * @return void
  71. */
  72. /*
  73. public function inheritFromRequest($req, $appInstance)
  74. {
  75. $connId = $req->attrs->connId;
  76. unset(Daemon::$process->queue[$connId . '-' . $req->attrs->id]);
  77. $this->buf[$connId] = $appInstance->buf[$connId];
  78. unset($appInstance->buf[$connId]);
  79. unset($appInstance->poolState[$connId]);
  80. $set = event_buffer_set_callback(
  81. $this->buf[$connId],
  82. $this->directReads ? NULL : array($this, 'onReadEvent'),
  83. array($this, 'onWriteEvent'),
  84. array($this, 'onFailureEvent'),
  85. array($connId)
  86. );
  87. unset(Daemon::$process->readPoolState[$connId]);
  88. $this->poolState[$connId] = array();
  89. $this->sessions[$connId] = new genericWebSocketSession($connId, $this);
  90. $this->sessions[$connId]->clientAddr = $req->attrs->server['REMOTE_ADDR'];
  91. $this->sessions[$connId]->server = $req->attrs->server;
  92. $this->sessions[$connId]->firstline = TRUE;
  93. $this->sessions[$connId]->stdin("\r\n" . $req->attrs->inbuf);
  94. }
  95. */
  96. /**
  97. * Adds a route if it doesn't exist already.
  98. * @param string Route name.
  99. * @param mixed Route's callback.
  100. * @return boolean Success.
  101. */
  102. public function addRoute($route, $cb)
  103. {
  104. if (isset($this->routes[$route]))
  105. {
  106. Daemon::log(__METHOD__ . ' Route \'' . $route . '\' is already taken.');
  107. return FALSE;
  108. }
  109. $this->routes[$route] = $cb;
  110. return TRUE;
  111. }
  112. /**
  113. * Force add/replace a route.
  114. * @param string Route name.
  115. * @param mixed Route's callback.
  116. * @return boolean Success.
  117. */
  118. public function setRoute($route, $cb)
  119. {
  120. $this->routes[$route] = $cb;
  121. return TRUE;
  122. }
  123. /**
  124. * Removes a route.
  125. * @param string Route name.
  126. * @return boolean Success.
  127. */
  128. public function removeRoute($route)
  129. {
  130. if (!isset($this->routes[$route]))
  131. {
  132. return FALSE;
  133. }
  134. unset($this->routes[$route]);
  135. return TRUE;
  136. }
  137. /**
  138. * Event of appInstance.
  139. * @return void
  140. */
  141. public function onReady()
  142. {
  143. if ($this->config->enable->value)
  144. {
  145. $this->enableSocketEvents();
  146. }
  147. }
  148. /**
  149. * Called when remote host is trying to establish the connection
  150. * @param resource Descriptor
  151. * @param integer Events
  152. * @param mixed Attached variable
  153. * @return boolean If true then we can accept new connections, else we can't
  154. */
  155. public function checkAccept($stream, $events, $arg)
  156. {
  157. if (!parent::checkAccept($stream, $events, $arg))
  158. {
  159. return FALSE;
  160. }
  161. $sockId = $arg[0];
  162. event_add($this->socketEvents[$sockId], $this->config->ev_timeout->value) ; // With specified timeout
  163. // Always return FALSE to skip adding event without timeout in "parent::onAcceptEvent"...
  164. return FALSE ;
  165. }
  166. /**
  167. * Called when remote host is trying to establish the connection
  168. * @param integer Connection's ID
  169. * @param string Address
  170. * @return boolean Accept/Drop the connection
  171. */
  172. public function onAccept($connId, $addr)
  173. {
  174. if (parent::onAccept($connId, $addr))
  175. {
  176. Daemon::log("New client : " . $addr) ;
  177. return TRUE ;
  178. }
  179. return FALSE ;
  180. }
  181. /**
  182. * Event of asyncServer
  183. * @param integer Connection's ID
  184. * @param string Peer's address
  185. * @return void
  186. */
  187. protected function onAccepted($connId, $addr)
  188. {
  189. $this->sessions[$connId] = new genericWebSocketSession($connId, $this);
  190. $this->sessions[$connId]->clientAddr = $addr;
  191. }
  192. /**
  193. * Called when new connections is waiting for accept
  194. * @param resource Descriptor
  195. * @param integer Events
  196. * @param mixed Attached variable
  197. * @return void
  198. */
  199. public function onAcceptEvent($stream, $events, $arg)
  200. {
  201. if ($events & EV_TIMEOUT)
  202. {
  203. $sockId = $arg[0];
  204. if ($this->timeout_cb !== NULL)
  205. {
  206. call_user_func($this->timeout_cb) ;
  207. }
  208. event_add($this->socketEvents[$sockId], $this->config->ev_timeout->value) ;
  209. return ;
  210. }
  211. parent::onAcceptEvent($stream, $events, $arg);
  212. }
  213. /*
  214. public function onTimeout()
  215. {
  216. }
  217. */
  218. }