Guest User

Untitled

a guest
Sep 24th, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.78 KB | None | 0 0
  1. <?php
  2. /**
  3. * Run this script as-is and it will segfault. My setup is Ubuntu
  4. * 11.10, library details:
  5. *
  6. * php5-cli : 5.3.6-13ubuntu3.6 (output from dpkg -l)
  7. * libevent : 0.0.5 beta (output from pecl list)
  8. * php-pear : 5.3.6-13ubuntu3.6 (output from dpkg -l)
  9. *
  10. * There are 2 things you can do to stop the segfault:
  11. *
  12. * 1. Comment out the given line in ELoop->checkAddEvent()
  13. * 2. Only add a single client to the loop
  14. */
  15. class ELoop
  16. {
  17. private $evBase;
  18. private $clients = array();
  19.  
  20. function addClient ($client) {
  21. $this->clients[] = $client;
  22. }
  23. function loop () {
  24. $this->initLibevent();
  25. $hasWork = false;
  26. foreach ($this->clients as $c) {
  27. if ($ev = $this->checkAddEvent($c)) {
  28. $hasWork = true;
  29. }
  30. }
  31. if ($hasWork) {
  32. event_base_loop($this->evBase);
  33. }
  34. }
  35. private function checkAddEvent ($c, $ev=null) {
  36. $flags = 0;
  37. if ($c->canRead())
  38. $flags = $flags | EV_READ;
  39. if ($c->canWrite())
  40. $flags = $flags | EV_WRITE;
  41. if (! $flags) {
  42. if ($ev) {
  43. event_del($ev);
  44. event_free($ev); // Comment this line and the segfault doesn't happen
  45. }
  46. if (false === ($i = array_search($c, $this->clients))) {
  47. throw new \Exception("Failed to locate client within local collection during removal", 9062);
  48. } else {
  49. unset($this->clients[$i]);
  50. }
  51. return;
  52. }
  53. if (! $ev)
  54. $ev = event_new();
  55. event_set($ev, $c->getSocketHandle(), $flags, array($this, 'loopEventDispatch'), array($c, $ev));
  56. event_base_set($ev, $this->evBase);
  57. event_add($ev);
  58. return $ev;
  59. }
  60. function loopEventDispatch ($fd, $events, $params) {
  61. list($client, $event) = $params;
  62. if ($events & EV_READ)
  63. $client->read();
  64. if ($events & EV_WRITE)
  65. $client->write();
  66. $this->checkAddEvent($client, $event);
  67. }
  68. private function initLibevent () {
  69. $this->evBase = event_base_new();
  70. }
  71. }
  72.  
  73. class SocketClient
  74. {
  75. private $host, $port, $sock;
  76.  
  77. function open ($host, $port) {
  78. $this->host = $host;
  79. $this->port = $port;
  80. if (! ($this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
  81. throw new \Exception("Failed to create inet socket", 7895);
  82. } else if (! socket_connect($this->sock, $this->host, $this->port)) {
  83. throw new \Exception("Failed to connect inet socket ({$this->host}, {$this->port})", 7564);
  84. } else if (! socket_set_nonblock($this->sock)) {
  85. throw new \Exception("Failed to switch connection in to non-blocking mode.", 2357);
  86. }
  87. }
  88. function getSocketHandle () {
  89. return $this->sock;
  90. }
  91. function read () {
  92. $buff = '';
  93. while (@socket_recv($this->sock, $tmp, 4096, MSG_DONTWAIT)) {
  94. $buff .= $tmp;
  95. }
  96. return $buff;
  97. }
  98. function write ($buff='') {
  99. if (($tmp = socket_write($this->sock, $buff)) === false) {
  100. throw new \Exception(sprintf("Socket write failed: %s",
  101. socket_strerror(socket_last_error($this->sock))), 7854);
  102. }
  103. }
  104. }
  105. class HttpClient extends SocketClient
  106. {
  107. private $state = 0, $domain;
  108.  
  109. function __construct ($domain) {
  110. $ip = gethostbyname($domain);
  111. if ($ip == $domain) {
  112. throw new \Exception("Failed to resolve HTTP host", 2351);
  113. }
  114. $this->open($ip, 80);
  115. $this->domain = $domain;
  116. }
  117. function canRead () {
  118. switch ($this->state) {
  119. case 1:
  120. return true;
  121. default:
  122. return false;
  123. }
  124. }
  125. function canWrite () {
  126. switch ($this->state) {
  127. case 0:
  128. return true;
  129. default:
  130. return false;
  131. }
  132. }
  133. function read () {
  134. $this->state = 2;
  135. $buff = parent::read();
  136. printf("[http] Reads response (%d):\n%s\n", strlen($buff), substr($buff, 0, strpos($buff, "\r\n")));
  137. }
  138. function write ($buff='') {
  139. if ($this->state == 0) {
  140. // Write HTTP header.
  141. parent::write("GET / HTTP/1.1\r\nHost: {$this->domain}\r\n" .
  142. "Connection: close\r\n" .
  143. "User-Agent: php libevent test\r\n" .
  144. "Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7\r\n" .
  145. "Cache-Control: no-cache\r\n" .
  146. "Accept-Language: de,en;q=0.7,en-us;q=0.3\r\n\r\n");
  147. $this->state = 1;
  148. }
  149. }
  150. }
  151. $el = new ELoop;
  152. $el->addClient(new HttpClient('microsoft.com'));
  153. $el->addClient(new HttpClient('bluelines.org'));
  154. $el->loop();
Add Comment
Please, Sign In to add comment