PageRenderTime 61ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/includes/net/dns2/socket/sockets.php

https://bitbucket.org/speedealing/speedealing
PHP | 345 lines | 142 code | 54 blank | 149 comment | 28 complexity | 19f5a86cf1b96f13e43393ae2c202ac4 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, GPL-3.0, MIT
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * DNS Library for handling lookups and updates.
  5. *
  6. * PHP Version 5
  7. *
  8. * Copyright (c) 2010, Mike Pultz <mike@mikepultz.com>.
  9. * All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. *
  15. * * Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. *
  18. * * Redistributions in binary form must reproduce the above copyright
  19. * notice, this list of conditions and the following disclaimer in
  20. * the documentation and/or other materials provided with the
  21. * distribution.
  22. *
  23. * * Neither the name of Mike Pultz nor the names of his contributors
  24. * may be used to endorse or promote products derived from this
  25. * software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  28. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  29. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  30. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  31. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  32. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  33. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  35. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  37. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. * @category Networking
  41. * @package Net_DNS2
  42. * @author Mike Pultz <mike@mikepultz.com>
  43. * @copyright 2010 Mike Pultz <mike@mikepultz.com>
  44. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  45. * @version SVN: $Id: Sockets.php 172 2012-11-01 03:42:32Z mike.pultz $
  46. * @link http://pear.php.net/package/Net_DNS2
  47. * @since File available since Release 0.6.0
  48. *
  49. */
  50. /**
  51. * Socket handling class using the PHP sockets extension
  52. *
  53. * The sockets extension is faster than the stream functions in PHP, but it's
  54. * not standard. So if the extension is loaded, then this class is used, if
  55. * it's not, then the Net_DNS2_Socket_Streams class is used.
  56. *
  57. * @category Networking
  58. * @package Net_DNS2
  59. * @author Mike Pultz <mike@mikepultz.com>
  60. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  61. * @link http://pear.php.net/package/Net_DNS2
  62. * @see Net_DNS2_Socket
  63. *
  64. */
  65. class Net_DNS2_Socket_Sockets extends Net_DNS2_Socket
  66. {
  67. /**
  68. * opens a socket connection to the DNS server
  69. *
  70. * @return boolean
  71. * @access public
  72. *
  73. */
  74. public function open()
  75. {
  76. //
  77. // create the socket
  78. //
  79. if (Net_DNS2::isIPv4($this->host) == true) {
  80. $this->sock = @socket_create(
  81. AF_INET, $this->type,
  82. ($this->type == Net_DNS2_Socket::SOCK_STREAM) ? SOL_TCP : SOL_UDP
  83. );
  84. } else if (Net_DNS2::isIPv6($this->host) == true) {
  85. $this->sock = @socket_create(
  86. AF_INET6, $this->type,
  87. ($this->type == Net_DNS2_Socket::SOCK_STREAM) ? SOL_TCP : SOL_UDP
  88. );
  89. } else {
  90. $this->last_error = 'invalid address type: ' . $this->host;
  91. return false;
  92. }
  93. if ($this->sock === false) {
  94. $this->last_error = socket_strerror(socket_last_error());
  95. return false;
  96. }
  97. @socket_set_option($this->sock, SOL_SOCKET, SO_REUSEADDR, 1);
  98. //
  99. // bind to a local IP/port if it's set
  100. //
  101. if (strlen($this->local_host) > 0) {
  102. $result = @socket_bind(
  103. $this->sock, $this->local_host,
  104. ($this->local_port > 0) ? $this->local_port : null
  105. );
  106. if ($result === false) {
  107. $this->last_error = socket_strerror(socket_last_error());
  108. return false;
  109. }
  110. }
  111. //
  112. // mark the socket as non-blocking
  113. //
  114. if (@socket_set_nonblock($this->sock) === false) {
  115. $this->last_error = socket_strerror(socket_last_error());
  116. return false;
  117. }
  118. //
  119. // connect to the socket; don't check for status here, we'll check it on the
  120. // socket_select() call so we can handle timeouts properly
  121. //
  122. @socket_connect($this->sock, $this->host, $this->port);
  123. $read = null;
  124. $write = array($this->sock);
  125. $except = null;
  126. //
  127. // select on write to check if the call to connect worked
  128. //
  129. switch(@socket_select($read, $write, $except, $this->timeout)) {
  130. case false:
  131. $this->last_error = socket_strerror(socket_last_error());
  132. return false;
  133. break;
  134. case 0:
  135. return false;
  136. break;
  137. default:
  138. ;
  139. }
  140. return true;
  141. }
  142. /**
  143. * closes a socket connection to the DNS server
  144. *
  145. * @return boolean
  146. * @access public
  147. *
  148. */
  149. public function close()
  150. {
  151. if (is_resource($this->sock) === true) {
  152. @socket_close($this->sock);
  153. }
  154. return true;
  155. }
  156. /**
  157. * writes the given string to the DNS server socket
  158. *
  159. * @param string $data a binary packed DNS packet
  160. *
  161. * @return boolean
  162. * @access public
  163. *
  164. */
  165. public function write($data)
  166. {
  167. $length = strlen($data);
  168. if ($length == 0) {
  169. $this->last_error = 'empty data on write()';
  170. return false;
  171. }
  172. $read = null;
  173. $write = array($this->sock);
  174. $except = null;
  175. //
  176. // select on write
  177. //
  178. switch(@socket_select($read, $write, $except, $this->timeout)) {
  179. case false:
  180. $this->last_error = socket_strerror(socket_last_error());
  181. return false;
  182. break;
  183. case 0:
  184. return false;
  185. break;
  186. default:
  187. ;
  188. }
  189. //
  190. // if it's a TCP socket, then we need to packet and send the length of the
  191. // data as the first 16bit of data.
  192. //
  193. if ($this->type == Net_DNS2_Socket::SOCK_STREAM) {
  194. $s = chr($length >> 8) . chr($length);
  195. if (@socket_write($this->sock, $s) === false) {
  196. $this->last_error = socket_strerror(socket_last_error());
  197. return false;
  198. }
  199. }
  200. //
  201. // write the data to the socket
  202. //
  203. $size = @socket_write($this->sock, $data);
  204. if ( ($size === false) || ($size != $length) ) {
  205. $this->last_error = socket_strerror(socket_last_error());
  206. return false;
  207. }
  208. return true;
  209. }
  210. /**
  211. * reads a response from a DNS server
  212. *
  213. * @param integer &$size the size of the DNS packet read is passed back
  214. *
  215. * @return mixed returns the data on success and false on error
  216. * @access public
  217. *
  218. */
  219. public function read(&$size)
  220. {
  221. $read = array($this->sock);
  222. $write = null;
  223. $except = null;
  224. //
  225. // make sure our socket is non-blocking
  226. //
  227. if (@socket_set_nonblock($this->sock) === false) {
  228. $this->last_error = socket_strerror(socket_last_error());
  229. return false;
  230. }
  231. //
  232. // select on read
  233. //
  234. switch(@socket_select($read, $write, $except, $this->timeout)) {
  235. case false:
  236. $this->last_error = socket_strerror(socket_last_error());
  237. return false;
  238. break;
  239. case 0:
  240. return false;
  241. break;
  242. default:
  243. ;
  244. }
  245. $data = '';
  246. $length = Net_DNS2_Lookups::DNS_MAX_UDP_SIZE;
  247. //
  248. // if it's a TCP socket, then the first two bytes is the length of the DNS
  249. // packet- we need to read that off first, then use that value for the
  250. // packet read.
  251. //
  252. if ($this->type == Net_DNS2_Socket::SOCK_STREAM) {
  253. if (($size = @socket_recv($this->sock, $data, 2, 0)) === false) {
  254. $this->last_error = socket_strerror(socket_last_error());
  255. return false;
  256. }
  257. $length = ord($data[0]) << 8 | ord($data[1]);
  258. if ($length < Net_DNS2_Lookups::DNS_HEADER_SIZE) {
  259. return false;
  260. }
  261. }
  262. //
  263. // at this point, we know that there is data on the socket to be read,
  264. // because we've already extracted the length from the first two bytes.
  265. //
  266. // so the easiest thing to do, is just turn off socket blocking, and
  267. // wait for the data.
  268. //
  269. if (@socket_set_block($this->sock) === false) {
  270. $this->last_error = socket_strerror(socket_last_error());
  271. return false;
  272. }
  273. //
  274. // read the data from the socket
  275. //
  276. $size = @socket_recv($this->sock, $data, $length, MSG_WAITALL);
  277. if ($size === false) {
  278. $this->last_error = socket_strerror(socket_last_error());
  279. return false;
  280. }
  281. return $data;
  282. }
  283. }
  284. /*
  285. * Local variables:
  286. * tab-width: 4
  287. * c-basic-offset: 4
  288. * c-hanging-comment-ender-p: nil
  289. * End:
  290. */
  291. ?>