/php8/src/util.c

https://bitbucket.org/osmanov/pecl-event · C · 200 lines · 151 code · 19 blank · 30 comment · 57 complexity · 65cd30a76c3e092821dae29b2c5961ef MD5 · raw file

  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 8 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2020 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Ruslan Osmanov <osmanov@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include "common.h"
  19. #include "util.h"
  20. #ifndef PHP_WIN32
  21. # include <fcntl.h>
  22. #endif
  23. #include "zend_exceptions.h"
  24. /* {{{ php_event_zval_to_fd
  25. * Get numeric file descriptor from PHP stream or Socket resource */
  26. php_socket_t php_event_zval_to_fd(zval *pfd)
  27. {
  28. php_socket_t file_desc = -1;
  29. php_stream *stream;
  30. FILE *fp = NULL;
  31. #ifdef PHP_EVENT_SOCKETS_SUPPORT
  32. php_socket *php_sock;
  33. #endif
  34. const char* invalid_fd_error = "Invalid file descriptor";
  35. if (Z_TYPE_P(pfd) == IS_RESOURCE) {
  36. /* PHP stream or PHP socket resource */
  37. if ((stream = (php_stream *)zend_fetch_resource2(Z_RES_P(pfd), NULL, php_file_le_stream(), php_file_le_pstream())) != NULL) {
  38. if (php_stream_is(stream, PHP_STREAM_IS_MEMORY) || php_stream_is(stream, PHP_STREAM_IS_TEMP)) {
  39. zend_throw_exception(zend_ce_exception,
  40. "Cannot fetch file descriptor from memory based stream", 0);
  41. return -1;
  42. }
  43. php_stream_from_zval_no_verify(stream, pfd);
  44. if (stream == NULL) {
  45. zend_throw_exception(zend_ce_exception, "Failed obtaining fd", 0);
  46. return -1;
  47. }
  48. /* PHP stream */
  49. if (php_stream_can_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL) == SUCCESS) {
  50. if (php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
  51. (void *) &file_desc, 1) != SUCCESS || file_desc < 0) {
  52. return -1;
  53. }
  54. } else if (php_stream_can_cast(stream, PHP_STREAM_AS_FD | PHP_STREAM_CAST_INTERNAL) == SUCCESS) {
  55. if (php_stream_cast(stream, PHP_STREAM_AS_FD | PHP_STREAM_CAST_INTERNAL,
  56. (void *) &file_desc, 1) != SUCCESS || file_desc < 0) {
  57. return -1;
  58. }
  59. } else if (php_stream_can_cast(stream, PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_INTERNAL) == SUCCESS) {
  60. if (php_stream_cast(stream, PHP_STREAM_AS_STDIO,
  61. (void **) &fp, 1) != SUCCESS) {
  62. return -1;
  63. }
  64. file_desc = fileno(fp);
  65. } else { /* STDIN, STDOUT, STDERR etc. */
  66. file_desc = Z_LVAL_P(pfd);
  67. }
  68. } else {
  69. zend_throw_exception(zend_ce_exception,
  70. "valid PHP stream resource expected", 0);
  71. return -1;
  72. }
  73. #ifdef PHP_EVENT_SOCKETS_SUPPORT
  74. } else if (Z_TYPE_P(pfd) == IS_OBJECT && Z_OBJCE_P(pfd) == socket_ce) {
  75. php_sock = Z_SOCKET_P(pfd);
  76. if (php_sock->error) {
  77. if (!php_sock->blocking && php_sock->error == EINPROGRESS) {
  78. #ifdef PHP_EVENT_DEBUG
  79. php_error_docref(NULL, E_NOTICE, "Operation in progress");
  80. #endif
  81. } else {
  82. return -1;
  83. }
  84. }
  85. return php_sock->bsd_socket;
  86. #endif
  87. } else if (Z_TYPE_P(pfd) == IS_LONG) {
  88. file_desc = Z_LVAL_P(pfd);
  89. if (file_desc < 0) {
  90. zend_throw_exception(zend_ce_exception, invalid_fd_error, 0);
  91. return -1;
  92. }
  93. } else {
  94. zend_throw_exception(zend_ce_exception, invalid_fd_error, 0);
  95. return -1;
  96. }
  97. if (!ZEND_VALID_SOCKET(file_desc)) {
  98. zend_throw_exception(zend_ce_exception, invalid_fd_error, 0);
  99. return -1;
  100. }
  101. return file_desc;
  102. }
  103. /* }}} */
  104. int _php_event_getsockname(evutil_socket_t fd, zval *pzaddr, zval *pzport)/*{{{*/
  105. {
  106. php_sockaddr_storage sa_storage;
  107. struct sockaddr *sa = (struct sockaddr *)&sa_storage;
  108. socklen_t sa_len = sizeof(php_sockaddr_storage);
  109. zend_long port = -1;
  110. if (getsockname(fd, sa, &sa_len)) {
  111. php_error_docref(NULL, E_WARNING,
  112. "Unable to retreive socket name, errno: %d", errno);
  113. return FAILURE;
  114. }
  115. switch (sa->sa_family) {
  116. case AF_INET:
  117. {
  118. struct sockaddr_in *sin = (struct sockaddr_in *) sa;
  119. char addr[INET_ADDRSTRLEN + 1];
  120. if (evutil_inet_ntop(sa->sa_family, &sin->sin_addr,
  121. (void *) &addr, sizeof(addr))) {
  122. if (!Z_ISUNDEF_P(pzaddr)) {
  123. zval_dtor(pzaddr);
  124. }
  125. ZVAL_STRING(pzaddr, addr);
  126. if (pzport != NULL) {
  127. port = ntohs(sin->sin_port);
  128. }
  129. }
  130. }
  131. break;
  132. #if HAVE_IPV6
  133. case AF_INET6:
  134. {
  135. struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
  136. char addr6[INET6_ADDRSTRLEN + 1];
  137. if (evutil_inet_ntop(sa->sa_family, &sin6->sin6_addr,
  138. (void *) &addr6, sizeof(addr6))) {
  139. if (!Z_ISUNDEF_P(pzaddr)) {
  140. zval_dtor(pzaddr);
  141. }
  142. ZVAL_STRING(pzaddr, addr6);
  143. if (pzport != NULL) {
  144. port = ntohs(sin6->sin6_port);
  145. }
  146. }
  147. }
  148. break;
  149. #endif
  150. #ifdef AF_UNIX
  151. case AF_UNIX:
  152. {
  153. struct sockaddr_un *ua = (struct sockaddr_un *) sa;
  154. if (!Z_ISUNDEF_P(pzaddr)) {
  155. zval_dtor(pzaddr);
  156. }
  157. ZVAL_STRING(pzaddr, ua->sun_path);
  158. }
  159. break;
  160. #endif
  161. default:
  162. php_error_docref(NULL, E_WARNING,
  163. "Unsupported address family: %d", sa->sa_family);
  164. return FAILURE;
  165. }
  166. if (port != -1) {
  167. if (pzport && !Z_ISUNDEF_P(pzport)) {
  168. zval_dtor(pzport);
  169. }
  170. ZVAL_LONG(pzport, port);
  171. }
  172. return SUCCESS;
  173. }/*}}}*/
  174. /*
  175. * Local variables:
  176. * tab-width: 4
  177. * c-basic-offset: 4
  178. * End:
  179. * vim600: fdm=marker
  180. * vim: noet sts=4 sw=4 ts=4
  181. */