php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
network.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Stig Venaas <venaas@uninett.no> |
14 | Streams work by Wez Furlong <wez@thebrainroom.com> |
15 +----------------------------------------------------------------------+
16 */
17
18/*#define DEBUG_MAIN_NETWORK 1*/
19
20#include "php.h"
21
22#include <stddef.h>
23#include <errno.h>
24
25
26#ifdef PHP_WIN32
27# include <Ws2tcpip.h>
28# include "win32/winutil.h"
29# define O_RDONLY _O_RDONLY
30# include "win32/param.h"
31#else
32#include <sys/param.h>
33#endif
34
35#include <sys/types.h>
36#ifdef HAVE_SYS_SOCKET_H
37#include <sys/socket.h>
38#endif
39
40#ifndef _FCNTL_H
41#include <fcntl.h>
42#endif
43
44#ifdef HAVE_SYS_SELECT_H
45#include <sys/select.h>
46#endif
47#ifdef HAVE_POLL_H
48#include <poll.h>
49#elif HAVE_SYS_POLL_H
50#include <sys/poll.h>
51#endif
52
53
54#ifndef PHP_WIN32
55#include <netinet/in.h>
56#include <netdb.h>
57#ifdef HAVE_ARPA_INET_H
58#include <arpa/inet.h>
59#endif
60#endif
61
62#include "php_network.h"
63
64#if defined(PHP_WIN32) || defined(__riscos__)
65#undef AF_UNIX
66#endif
67
68#if defined(AF_UNIX)
69#include <sys/un.h>
70#endif
71
72#include "ext/standard/file.h"
73
74#ifdef PHP_WIN32
75# include "win32/time.h"
76# define SOCK_ERR INVALID_SOCKET
77# define SOCK_CONN_ERR SOCKET_ERROR
78# define PHP_TIMEOUT_ERROR_VALUE WSAETIMEDOUT
79
80#ifdef HAVE_IPV6
81const struct in6_addr in6addr_any = {0}; /* IN6ADDR_ANY_INIT; */
82#endif
83
84#else
85# define SOCK_ERR -1
86# define SOCK_CONN_ERR -1
87# define PHP_TIMEOUT_ERROR_VALUE ETIMEDOUT
88#endif
89
90#ifdef HAVE_GETADDRINFO
91# if !defined(PHP_WIN32) && !defined(HAVE_GAI_STRERROR)
92/* {{{ php_gai_strerror */
93static const char *php_gai_strerror(int code)
94{
95 static struct {
96 int code;
97 const char *msg;
98 } values[] = {
99# ifdef EAI_ADDRFAMILY
100 {EAI_ADDRFAMILY, "Address family for hostname not supported"},
101# endif
102 {EAI_AGAIN, "Temporary failure in name resolution"},
103 {EAI_BADFLAGS, "Bad value for ai_flags"},
104 {EAI_FAIL, "Non-recoverable failure in name resolution"},
105 {EAI_FAMILY, "ai_family not supported"},
106 {EAI_MEMORY, "Memory allocation failure"},
107# ifdef EAI_NODATA
108 {EAI_NODATA, "No address associated with hostname"},
109# endif
110 {EAI_NONAME, "Name or service not known"},
111 {EAI_SERVICE, "Servname not supported for ai_socktype"},
112 {EAI_SOCKTYPE, "ai_socktype not supported"},
113# ifdef EAI_SYSTEM
114 {EAI_SYSTEM, "System error"},
115# endif
116 {0, NULL}
117 };
118 int i;
119
120 for (i = 0; values[i].msg != NULL; i++) {
121 if (values[i].code == code) {
122 return (char *)values[i].msg;
123 }
124 }
125
126 return "Unknown error";
127}
128/* }}} */
129# endif
130#endif
131
132/* {{{ php_network_freeaddresses */
133PHPAPI void php_network_freeaddresses(struct sockaddr **sal)
134{
135 struct sockaddr **sap;
136
137 if (sal == NULL)
138 return;
139 for (sap = sal; *sap != NULL; sap++)
140 efree(*sap);
141 efree(sal);
142}
143/* }}} */
144
145/* {{{ php_network_getaddresses
146 * Returns number of addresses, 0 for none/error
147 */
148PHPAPI int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, zend_string **error_string)
149{
150 struct sockaddr **sap;
151 int n;
152#ifdef HAVE_GETADDRINFO
153# ifdef HAVE_IPV6
154 static int ipv6_borked = -1; /* the way this is used *is* thread safe */
155# endif
156 struct addrinfo hints, *res, *sai;
157#else
158 struct hostent *host_info;
159 struct in_addr in;
160#endif
161
162 if (host == NULL) {
163 return 0;
164 }
165#ifdef HAVE_GETADDRINFO
166 memset(&hints, '\0', sizeof(hints));
167
168 hints.ai_family = AF_INET; /* default to regular inet (see below) */
169 hints.ai_socktype = socktype;
170
171# ifdef HAVE_IPV6
172 /* probe for a working IPv6 stack; even if detected as having v6 at compile
173 * time, at runtime some stacks are slow to resolve or have other issues
174 * if they are not correctly configured.
175 * static variable use is safe here since simple store or fetch operations
176 * are atomic and because the actual probe process is not in danger of
177 * collisions or race conditions. */
178 if (ipv6_borked == -1) {
179 int s;
180
181 s = socket(PF_INET6, SOCK_DGRAM, 0);
182 if (s == SOCK_ERR) {
183 ipv6_borked = 1;
184 } else {
185 ipv6_borked = 0;
186 closesocket(s);
187 }
188 }
189 hints.ai_family = ipv6_borked ? AF_INET : AF_UNSPEC;
190# endif
191
192 if ((n = getaddrinfo(host, NULL, &hints, &res))) {
193# if defined(PHP_WIN32)
194 char *gai_error = php_win32_error_to_msg(n);
195# elif defined(HAVE_GAI_STRERROR)
196 const char *gai_error = gai_strerror(n);
197# else
198 const char *gai_error = php_gai_strerror(n)
199# endif
200 if (error_string) {
201 /* free error string received during previous iteration (if any) */
202 if (*error_string) {
203 zend_string_release_ex(*error_string, 0);
204 }
205 *error_string = strpprintf(0, "php_network_getaddresses: getaddrinfo for %s failed: %s", host, gai_error);
206 php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(*error_string));
207 } else {
208 php_error_docref(NULL, E_WARNING, "php_network_getaddresses: getaddrinfo for %s failed: %s", host, gai_error);
209 }
210# ifdef PHP_WIN32
211 php_win32_error_msg_free(gai_error);
212# endif
213 return 0;
214 } else if (res == NULL) {
215 if (error_string) {
216 /* free error string received during previous iteration (if any) */
217 if (*error_string) {
218 zend_string_release_ex(*error_string, 0);
219 }
220 *error_string = strpprintf(0, "php_network_getaddresses: getaddrinfo for %s failed (null result pointer) errno=%d", host, errno);
221 php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(*error_string));
222 } else {
223 php_error_docref(NULL, E_WARNING, "php_network_getaddresses: getaddrinfo for %s failed (null result pointer)", host);
224 }
225 return 0;
226 }
227
228 sai = res;
229 for (n = 1; (sai = sai->ai_next) != NULL; n++)
230 ;
231
232 *sal = safe_emalloc((n + 1), sizeof(*sal), 0);
233 sai = res;
234 sap = *sal;
235
236 do {
237 *sap = emalloc(sai->ai_addrlen);
238 memcpy(*sap, sai->ai_addr, sai->ai_addrlen);
239 sap++;
240 } while ((sai = sai->ai_next) != NULL);
241
242 freeaddrinfo(res);
243#else
244 if (!inet_pton(AF_INET, host, &in)) {
245 if(strlen(host) > MAXFQDNLEN) {
246 host_info = NULL;
247 errno = E2BIG;
248 } else {
249 host_info = php_network_gethostbyname(host);
250 }
251 if (host_info == NULL) {
252 if (error_string) {
253 /* free error string received during previous iteration (if any) */
254 if (*error_string) {
255 zend_string_release_ex(*error_string, 0);
256 }
257 *error_string = strpprintf(0, "php_network_getaddresses: gethostbyname failed. errno=%d", errno);
258 php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(*error_string));
259 } else {
260 php_error_docref(NULL, E_WARNING, "php_network_getaddresses: gethostbyname failed");
261 }
262 return 0;
263 }
264 in = *((struct in_addr *) host_info->h_addr);
265 }
266
267 *sal = safe_emalloc(2, sizeof(*sal), 0);
268 sap = *sal;
269 *sap = emalloc(sizeof(struct sockaddr_in));
270 (*sap)->sa_family = AF_INET;
271 ((struct sockaddr_in *)*sap)->sin_addr = in;
272 sap++;
273 n = 1;
274#endif
275
276 *sap = NULL;
277 return n;
278}
279/* }}} */
280
281#ifndef O_NONBLOCK
282#define O_NONBLOCK O_NDELAY
283#endif
284
285#ifdef PHP_WIN32
286typedef u_long php_non_blocking_flags_t;
287# define SET_SOCKET_BLOCKING_MODE(sock, save) \
288 save = TRUE; ioctlsocket(sock, FIONBIO, &save)
289# define RESTORE_SOCKET_BLOCKING_MODE(sock, save) \
290 ioctlsocket(sock, FIONBIO, &save)
291#else
293# define SET_SOCKET_BLOCKING_MODE(sock, save) \
294 save = fcntl(sock, F_GETFL, 0); \
295 fcntl(sock, F_SETFL, save | O_NONBLOCK)
296# define RESTORE_SOCKET_BLOCKING_MODE(sock, save) \
297 fcntl(sock, F_SETFL, save)
298#endif
299
300#ifdef HAVE_GETTIMEOFDAY
301/* Subtract times */
302static inline void sub_times(struct timeval a, struct timeval b, struct timeval *result)
303{
304 result->tv_usec = a.tv_usec - b.tv_usec;
305 if (result->tv_usec < 0L) {
306 a.tv_sec--;
307 result->tv_usec += 1000000L;
308 }
309 result->tv_sec = a.tv_sec - b.tv_sec;
310 if (result->tv_sec < 0L) {
311 result->tv_sec++;
312 result->tv_usec -= 1000000L;
313 }
314}
315
316static inline void php_network_set_limit_time(struct timeval *limit_time,
317 struct timeval *timeout)
318{
319 gettimeofday(limit_time, NULL);
320 limit_time->tv_sec += timeout->tv_sec;
321 limit_time->tv_usec += timeout->tv_usec;
322 if (limit_time->tv_usec >= 1000000) {
323 limit_time->tv_usec -= 1000000;
324 limit_time->tv_sec++;
325 }
326}
327#endif
328
329/* Connect to a socket using an interruptible connect with optional timeout.
330 * Optionally, the connect can be made asynchronously, which will implicitly
331 * enable non-blocking mode on the socket.
332 * */
333/* {{{ php_network_connect_socket */
335 const struct sockaddr *addr,
336 socklen_t addrlen,
337 int asynchronous,
338 struct timeval *timeout,
339 zend_string **error_string,
340 int *error_code)
341{
342 php_non_blocking_flags_t orig_flags;
343 int n;
344 int error = 0;
346 int ret = 0;
347
348 SET_SOCKET_BLOCKING_MODE(sockfd, orig_flags);
349
350 if ((n = connect(sockfd, addr, addrlen)) != 0) {
352
353 if (error_code) {
354 *error_code = error;
355 }
356
357 if (error != EINPROGRESS) {
358 if (error_string) {
359 *error_string = php_socket_error_str(error);
360 }
361
362 return -1;
363 }
364 if (asynchronous && error == EINPROGRESS) {
365 /* this is fine by us */
366 return 0;
367 }
368 }
369
370 if (n == 0) {
371 goto ok;
372 }
373# ifdef PHP_WIN32
374 /* The documentation for connect() says in case of non-blocking connections
375 * the select function reports success in the writefds set and failure in
376 * the exceptfds set. Indeed, using PHP_POLLREADABLE results in select
377 * failing only due to the timeout and not immediately as would be
378 * expected when a connection is actively refused. This way,
379 * php_pollfd_for will return a mask with POLLOUT if the connection
380 * is successful and with POLLPRI otherwise. */
381 int events = POLLOUT|POLLPRI;
382#else
383 int events = PHP_POLLREADABLE|POLLOUT;
384#endif
385 struct timeval working_timeout;
386#ifdef HAVE_GETTIMEOFDAY
387 struct timeval limit_time, time_now;
388#endif
389 if (timeout) {
390 memcpy(&working_timeout, timeout, sizeof(working_timeout));
391#ifdef HAVE_GETTIMEOFDAY
392 php_network_set_limit_time(&limit_time, &working_timeout);
393#endif
394 }
395
396 while (true) {
397 n = php_pollfd_for(sockfd, events, timeout ? &working_timeout : NULL);
398 if (n < 0) {
399 if (errno == EINTR) {
400#ifdef HAVE_GETTIMEOFDAY
401 if (timeout) {
402 gettimeofday(&time_now, NULL);
403
404 if (!timercmp(&time_now, &limit_time, <)) {
405 /* time limit expired; no need for another poll */
407 break;
408 } else {
409 /* work out remaining time */
410 sub_times(limit_time, time_now, &working_timeout);
411 }
412 }
413#endif
414 continue;
415 }
416 ret = -1;
417 } else if (n == 0) {
419 } else {
420 len = sizeof(error);
421 /* BSD-derived systems set errno correctly.
422 * Solaris returns -1 from getsockopt in case of error. */
423 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
424 ret = -1;
425 }
426 }
427 break;
428 }
429
430ok:
431 if (!asynchronous) {
432 /* back to blocking mode */
433 RESTORE_SOCKET_BLOCKING_MODE(sockfd, orig_flags);
434 }
435
436 if (error_code) {
437 *error_code = error;
438 }
439
440 if (error) {
441 ret = -1;
442 if (error_string) {
443 *error_string = php_socket_error_str(error);
444 }
445 }
446 return ret;
447}
448/* }}} */
449
450/* Bind to a local IP address.
451 * Returns the bound socket, or -1 on failure.
452 * */
453/* {{{ php_network_bind_socket_to_local_addr */
455 int socktype, long sockopts, zend_string **error_string, int *error_code
456 )
457{
458 int num_addrs, n, err = 0;
459 php_socket_t sock;
460 struct sockaddr **sal, **psal, *sa;
461 socklen_t socklen;
462 int sockoptval = 1;
463
464 num_addrs = php_network_getaddresses(host, socktype, &psal, error_string);
465
466 if (num_addrs == 0) {
467 /* could not resolve address(es) */
468 return -1;
469 }
470
471 for (sal = psal; *sal != NULL; sal++) {
472 sa = *sal;
473
474 switch (sa->sa_family) {
475#if defined(HAVE_GETADDRINFO) && defined(HAVE_IPV6)
476 case AF_INET6:
477 ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
478 socklen = sizeof(struct sockaddr_in6);
479 break;
480#endif
481 case AF_INET:
482 ((struct sockaddr_in *)sa)->sin_port = htons(port);
483 socklen = sizeof(struct sockaddr_in);
484 break;
485 default:
486 /* Unsupported family, skip to the next */
487 continue;
488 }
489
490 /* create a socket for this address */
491 sock = socket(sa->sa_family, socktype, 0);
492
493 if (sock == SOCK_ERR) {
494 continue;
495 }
496
497 /* attempt to bind */
498
499#ifdef SO_REUSEADDR
500 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&sockoptval, sizeof(sockoptval));
501#endif
502#ifdef IPV6_V6ONLY
503 if (sockopts & STREAM_SOCKOP_IPV6_V6ONLY) {
504 int ipv6_val = !!(sockopts & STREAM_SOCKOP_IPV6_V6ONLY_ENABLED);
505 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6_val, sizeof(sockoptval));
506 }
507#endif
508#ifdef SO_REUSEPORT
509 if (sockopts & STREAM_SOCKOP_SO_REUSEPORT) {
510 setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char*)&sockoptval, sizeof(sockoptval));
511 }
512#endif
513#ifdef SO_BROADCAST
514 if (sockopts & STREAM_SOCKOP_SO_BROADCAST) {
515 setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&sockoptval, sizeof(sockoptval));
516 }
517#endif
518#ifdef TCP_NODELAY
519 if (sockopts & STREAM_SOCKOP_TCP_NODELAY) {
520 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&sockoptval, sizeof(sockoptval));
521 }
522#endif
523
524 n = bind(sock, sa, socklen);
525
526 if (n != SOCK_CONN_ERR) {
527 goto bound;
528 }
529
531
532 closesocket(sock);
533 }
534 sock = -1;
535
536 if (error_code) {
537 *error_code = err;
538 }
539 if (error_string) {
540 *error_string = php_socket_error_str(err);
541 }
542
543bound:
544
546
547 return sock;
548
549}
550/* }}} */
551
552PHPAPI zend_result php_network_parse_network_address_with_port(const char *addr, size_t addrlen, struct sockaddr *sa, socklen_t *sl)
553{
554 char *colon;
555 char *tmp;
557 short port;
558 struct sockaddr_in *in4 = (struct sockaddr_in*)sa;
559 struct sockaddr **psal;
560 int n;
561 zend_string *errstr = NULL;
562#ifdef HAVE_IPV6
563 struct sockaddr_in6 *in6 = (struct sockaddr_in6*)sa;
564
565 memset(in6, 0, sizeof(struct sockaddr_in6));
566#else
567 memset(in4, 0, sizeof(struct sockaddr_in));
568#endif
569
570 if (*addr == '[') {
571 colon = memchr(addr + 1, ']', addrlen-1);
572 if (!colon || colon[1] != ':') {
573 return FAILURE;
574 }
575 port = atoi(colon + 2);
576 addr++;
577 } else {
578 colon = memchr(addr, ':', addrlen);
579 if (!colon) {
580 return FAILURE;
581 }
582 port = atoi(colon + 1);
583 }
584
585 tmp = estrndup(addr, colon - addr);
586
587 /* first, try interpreting the address as a numeric address */
588
589#ifdef HAVE_IPV6
590 if (inet_pton(AF_INET6, tmp, &in6->sin6_addr) > 0) {
591 in6->sin6_port = htons(port);
592 in6->sin6_family = AF_INET6;
593 *sl = sizeof(struct sockaddr_in6);
594 ret = SUCCESS;
595 goto out;
596 }
597#endif
598 if (inet_pton(AF_INET, tmp, &in4->sin_addr) > 0) {
599 in4->sin_port = htons(port);
600 in4->sin_family = AF_INET;
601 *sl = sizeof(struct sockaddr_in);
602 ret = SUCCESS;
603 goto out;
604 }
605
606 /* looks like we'll need to resolve it */
607 n = php_network_getaddresses(tmp, SOCK_DGRAM, &psal, &errstr);
608
609 if (n == 0) {
610 if (errstr) {
611 php_error_docref(NULL, E_WARNING, "Failed to resolve `%s': %s", tmp, ZSTR_VAL(errstr));
612 zend_string_release_ex(errstr, 0);
613 }
614 goto out;
615 }
616
617 /* copy the details from the first item */
618 switch ((*psal)->sa_family) {
619#if defined(HAVE_GETADDRINFO) && defined(HAVE_IPV6)
620 case AF_INET6:
621 *in6 = **(struct sockaddr_in6**)psal;
622 in6->sin6_port = htons(port);
623 *sl = sizeof(struct sockaddr_in6);
624 ret = SUCCESS;
625 break;
626#endif
627 case AF_INET:
628 *in4 = **(struct sockaddr_in**)psal;
629 in4->sin_port = htons(port);
630 *sl = sizeof(struct sockaddr_in);
631 ret = SUCCESS;
632 break;
633 }
634
636
637out:
638 efree(tmp);
639 return ret;
640}
641
642
644 /* input address */
645 struct sockaddr *sa, socklen_t sl,
646 /* output readable address */
647 zend_string **textaddr,
648 /* output address */
649 struct sockaddr **addr,
650 socklen_t *addrlen
651 )
652{
653 if (addr) {
654 *addr = emalloc(sl);
655 memcpy(*addr, sa, sl);
656 *addrlen = sl;
657 }
658
659 if (textaddr) {
660 char abuf[256];
661 const char *buf = NULL;
662
663 switch (sa->sa_family) {
664 case AF_INET:
665 /* generally not thread safe, but it *is* thread safe under win32 */
666 buf = inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr, (char *)&abuf, sizeof(abuf));
667 if (buf) {
668 *textaddr = strpprintf(0, "%s:%d",
669 buf, ntohs(((struct sockaddr_in*)sa)->sin_port));
670 }
671
672 break;
673
674#ifdef HAVE_IPV6
675 case AF_INET6:
676 buf = (char*)inet_ntop(sa->sa_family, &((struct sockaddr_in6*)sa)->sin6_addr, (char *)&abuf, sizeof(abuf));
677 if (buf) {
678 *textaddr = strpprintf(0, "[%s]:%d",
679 buf, ntohs(((struct sockaddr_in6*)sa)->sin6_port));
680 }
681
682 break;
683#endif
684#ifdef AF_UNIX
685 case AF_UNIX:
686 {
687 struct sockaddr_un *ua = (struct sockaddr_un*)sa;
688
689 if (ua->sun_path[0] == '\0') {
690 /* abstract name */
691 int len = sl - sizeof(sa_family_t);
692 *textaddr = zend_string_init((char*)ua->sun_path, len, 0);
693 } else {
694 int len = strlen(ua->sun_path);
695 *textaddr = zend_string_init((char*)ua->sun_path, len, 0);
696 }
697 }
698 break;
699#endif
700
701 }
702
703 }
704}
705
707 zend_string **textaddr,
708 struct sockaddr **addr,
709 socklen_t *addrlen
710 )
711{
713 socklen_t sl = sizeof(sa);
714 memset(&sa, 0, sizeof(sa));
715
716 if (getpeername(sock, (struct sockaddr*)&sa, &sl) == 0) {
717 php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
718 textaddr,
719 addr, addrlen
720 );
721 return 0;
722 }
723 return -1;
724}
725
727 zend_string **textaddr,
728 struct sockaddr **addr,
729 socklen_t *addrlen
730 )
731{
733 socklen_t sl = sizeof(sa);
734 memset(&sa, 0, sizeof(sa));
735
736 if (getsockname(sock, (struct sockaddr*)&sa, &sl) == 0) {
737 php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
738 textaddr,
739 addr, addrlen
740 );
741 return 0;
742 }
743 return -1;
744
745}
746
747
748/* Accept a client connection from a server socket,
749 * using an optional timeout.
750 * Returns the peer address in addr/addrlen (it will emalloc
751 * these, so be sure to efree the result).
752 * If you specify textaddr, a text-printable
753 * version of the address will be emalloc'd and returned.
754 * */
755
756/* {{{ php_network_accept_incoming */
758 zend_string **textaddr,
759 struct sockaddr **addr,
760 socklen_t *addrlen,
761 struct timeval *timeout,
762 zend_string **error_string,
763 int *error_code,
764 int tcp_nodelay
765 )
766{
767 php_socket_t clisock = -1;
768 int error = 0, n;
770 socklen_t sl;
771
772 n = php_pollfd_for(srvsock, PHP_POLLREADABLE, timeout);
773
774 if (n == 0) {
776 } else if (n == -1) {
778 } else {
779 sl = sizeof(sa);
780
781 clisock = accept(srvsock, (struct sockaddr*)&sa, &sl);
782
783 if (clisock != SOCK_ERR) {
784 php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
785 textaddr,
786 addr, addrlen
787 );
788 if (tcp_nodelay) {
789#ifdef TCP_NODELAY
790 setsockopt(clisock, IPPROTO_TCP, TCP_NODELAY, (char*)&tcp_nodelay, sizeof(tcp_nodelay));
791#endif
792 }
793 } else {
795 }
796 }
797
798 if (error_code) {
799 *error_code = error;
800 }
801 if (error_string) {
802 *error_string = php_socket_error_str(error);
803 }
804
805 return clisock;
806}
807/* }}} */
808
809/* Connect to a remote host using an interruptible connect with optional timeout.
810 * Optionally, the connect can be made asynchronously, which will implicitly
811 * enable non-blocking mode on the socket.
812 * Returns the connected (or connecting) socket, or -1 on failure.
813 * */
814
815/* {{{ php_network_connect_socket_to_host */
816php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port,
817 int socktype, int asynchronous, struct timeval *timeout, zend_string **error_string,
818 int *error_code, const char *bindto, unsigned short bindport, long sockopts
819 )
820{
821 int num_addrs, n, fatal = 0;
822 php_socket_t sock;
823 struct sockaddr **sal, **psal, *sa;
824 struct timeval working_timeout;
825 socklen_t socklen;
826#ifdef HAVE_GETTIMEOFDAY
827 struct timeval limit_time, time_now;
828#endif
829
830 num_addrs = php_network_getaddresses(host, socktype, &psal, error_string);
831
832 if (num_addrs == 0) {
833 /* could not resolve address(es) */
834 return -1;
835 }
836
837 if (timeout) {
838 memcpy(&working_timeout, timeout, sizeof(working_timeout));
839#ifdef HAVE_GETTIMEOFDAY
840 php_network_set_limit_time(&limit_time, &working_timeout);
841#endif
842 }
843
844 for (sal = psal; !fatal && *sal != NULL; sal++) {
845 sa = *sal;
846
847 switch (sa->sa_family) {
848#if defined(HAVE_GETADDRINFO) && defined(HAVE_IPV6)
849 case AF_INET6:
850 if (!bindto || strchr(bindto, ':')) {
851 ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
852 socklen = sizeof(struct sockaddr_in6);
853 } else {
854 /* Expect IPV4 address, skip to the next */
855 continue;
856 }
857 break;
858#endif
859 case AF_INET:
860 ((struct sockaddr_in *)sa)->sin_port = htons(port);
861 socklen = sizeof(struct sockaddr_in);
862 if (bindto && (strchr(bindto, ':') || !strcmp(bindto, "0"))) {
863 /* IPV4 sock can not bind to IPV6 address */
864 bindto = NULL;
865 }
866 break;
867 default:
868 /* Unsupported family, skip to the next */
869 continue;
870 }
871
872 /* create a socket for this address */
873 sock = socket(sa->sa_family, socktype, 0);
874
875 if (sock == SOCK_ERR) {
876 continue;
877 }
878
879 /* make a connection attempt */
880
881 if (bindto) {
882 union {
883 struct sockaddr common;
884 struct sockaddr_in in4;
885#ifdef HAVE_IPV6
886 struct sockaddr_in6 in6;
887#endif
888 } local_address = {0};
889 size_t local_address_len = 0;
890
891 if (sa->sa_family == AF_INET) {
892 if (inet_pton(AF_INET, bindto, &local_address.in4.sin_addr) == 1) {
893 local_address_len = sizeof(struct sockaddr_in);
894 local_address.in4.sin_family = sa->sa_family;
895 local_address.in4.sin_port = htons(bindport);
896 }
897 }
898#ifdef HAVE_IPV6
899 else { /* IPV6 */
900 if (inet_pton(AF_INET6, bindto, &local_address.in6.sin6_addr) == 1) {
901 local_address_len = sizeof(struct sockaddr_in6);
902 local_address.in6.sin6_family = sa->sa_family;
903 local_address.in6.sin6_port = htons(bindport);
904 }
905 }
906#endif
907#ifdef IP_BIND_ADDRESS_NO_PORT
908 {
909 int val = 1;
910 (void) setsockopt(sock, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &val, sizeof(val));
911 }
912#endif
913 if (local_address_len == 0) {
914 php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto);
915 } else if (bind(sock, &local_address.common, local_address_len)) {
916 php_error_docref(NULL, E_WARNING, "Failed to bind to '%s:%d', system said: %s", bindto, bindport, strerror(errno));
917 }
918 }
919 /* free error string received during previous iteration (if any) */
920 if (error_string && *error_string) {
921 zend_string_release_ex(*error_string, 0);
922 *error_string = NULL;
923 }
924
925#ifdef SO_BROADCAST
926 {
927 int val = 1;
928 if (sockopts & STREAM_SOCKOP_SO_BROADCAST) {
929 setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&val, sizeof(val));
930 }
931 }
932#endif
933
934#ifdef TCP_NODELAY
935 {
936 int val = 1;
937 if (sockopts & STREAM_SOCKOP_TCP_NODELAY) {
938 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(val));
939 }
940 }
941#endif
942 n = php_network_connect_socket(sock, sa, socklen, asynchronous,
943 timeout ? &working_timeout : NULL,
944 error_string, error_code);
945
946 if (n != -1) {
947 goto connected;
948 }
949
950 /* adjust timeout for next attempt */
951#ifdef HAVE_GETTIMEOFDAY
952 if (timeout) {
953 gettimeofday(&time_now, NULL);
954
955 if (!timercmp(&time_now, &limit_time, <)) {
956 /* time limit expired; don't attempt any further connections */
957 fatal = 1;
958 } else {
959 /* work out remaining time */
960 sub_times(limit_time, time_now, &working_timeout);
961 }
962 }
963#else
965 /* Don't even bother trying to connect to the next alternative;
966 * we have no way to determine how long we have already taken
967 * and it is quite likely that the next attempt will fail too. */
968 fatal = 1;
969 } else {
970 /* re-use the same initial timeout.
971 * Not the best thing, but in practice it should be good-enough */
972 if (timeout) {
973 memcpy(&working_timeout, timeout, sizeof(working_timeout));
974 }
975 }
976#endif
977
978 closesocket(sock);
979 }
980 sock = -1;
981
982connected:
983
985
986 return sock;
987}
988/* }}} */
989
990/* {{{ php_any_addr
991 * Fills any (wildcard) address into php_sockaddr_storage
992 */
993PHPAPI void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port)
994{
995 memset(addr, 0, sizeof(php_sockaddr_storage));
996 switch (family) {
997#ifdef HAVE_IPV6
998 case AF_INET6: {
999 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
1000 sin6->sin6_family = AF_INET6;
1001 sin6->sin6_port = htons(port);
1002 sin6->sin6_addr = in6addr_any;
1003 break;
1004 }
1005#endif
1006 case AF_INET: {
1007 struct sockaddr_in *sin = (struct sockaddr_in *) addr;
1008 sin->sin_family = AF_INET;
1009 sin->sin_port = htons(port);
1010 sin->sin_addr.s_addr = htonl(INADDR_ANY);
1011 break;
1012 }
1013 }
1014}
1015/* }}} */
1016
1017/* {{{ php_sockaddr_size
1018 * Returns the size of struct sockaddr_xx for the family
1019 */
1021{
1022 switch (((struct sockaddr *)addr)->sa_family) {
1023 case AF_INET:
1024 return sizeof(struct sockaddr_in);
1025#ifdef HAVE_IPV6
1026 case AF_INET6:
1027 return sizeof(struct sockaddr_in6);
1028#endif
1029#ifdef AF_UNIX
1030 case AF_UNIX:
1031 return sizeof(struct sockaddr_un);
1032#endif
1033 default:
1034 return 0;
1035 }
1036}
1037/* }}} */
1038
1039/* Given a socket error code, if buf == NULL:
1040 * emallocs storage for the error message and returns
1041 * else
1042 * sprintf message into provided buffer and returns buf
1043 */
1044/* {{{ php_socket_strerror */
1045PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
1046{
1047#ifndef PHP_WIN32
1048 char *errstr;
1049
1050 errstr = strerror(err);
1051 if (buf == NULL) {
1052 buf = estrdup(errstr);
1053 } else {
1054 strncpy(buf, errstr, bufsize);
1055 buf[bufsize?(bufsize-1):0] = 0;
1056 }
1057 return buf;
1058#else
1059 char *sysbuf = php_win32_error_to_msg(err);
1060 if (!sysbuf[0]) {
1061 sysbuf = "Unknown Error";
1062 }
1063
1064 if (buf == NULL) {
1065 buf = estrdup(sysbuf);
1066 } else {
1067 strncpy(buf, sysbuf, bufsize);
1068 buf[bufsize?(bufsize-1):0] = 0;
1069 }
1070
1072
1073 return buf;
1074#endif
1075}
1076/* }}} */
1077
1078/* {{{ php_socket_error_str */
1080{
1081#ifndef PHP_WIN32
1082 char *errstr;
1083
1084 errstr = strerror(err);
1085 return zend_string_init(errstr, strlen(errstr), 0);
1086#else
1088
1089 char *sysbuf = php_win32_error_to_msg(err);
1090 if (!sysbuf[0]) {
1091 sysbuf = "Unknown Error";
1092 }
1093
1094 ret = zend_string_init(sysbuf, strlen(sysbuf), 0);
1095
1097
1098 return ret;
1099#endif
1100}
1101/* }}} */
1102
1103/* deprecated */
1105{
1106 php_stream *stream;
1108
1109 sock = pemalloc(sizeof(php_netstream_data_t), persistent_id ? 1 : 0);
1110 memset(sock, 0, sizeof(php_netstream_data_t));
1111
1112 sock->is_blocked = 1;
1113 sock->timeout.tv_sec = FG(default_socket_timeout);
1114 sock->timeout.tv_usec = 0;
1115 sock->socket = socket;
1116
1117 stream = php_stream_alloc_rel(&php_stream_generic_socket_ops, sock, persistent_id, "r+");
1118
1119 if (stream == NULL) {
1120 pefree(sock, persistent_id ? 1 : 0);
1121 } else {
1123 }
1124
1125 return stream;
1126}
1127
1128PHPAPI php_stream *_php_stream_sock_open_host(const char *host, unsigned short port,
1129 int socktype, struct timeval *timeout, const char *persistent_id STREAMS_DC)
1130{
1131 char *res;
1132 zend_long reslen;
1133 php_stream *stream;
1134
1135 reslen = spprintf(&res, 0, "tcp://%s:%d", host, port);
1136
1137 stream = php_stream_xport_create(res, reslen, REPORT_ERRORS,
1138 STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, persistent_id, timeout, NULL, NULL, NULL);
1139
1140 efree(res);
1141
1142 return stream;
1143}
1144
1146{
1148
1149#ifdef PHP_WIN32
1150 u_long flags;
1151
1152 /* with ioctlsocket, a non-zero sets nonblocking, a zero sets blocking */
1153 flags = !block;
1154 if (ioctlsocket(socketd, FIONBIO, &flags) == SOCKET_ERROR) {
1155 ret = FAILURE;
1156 }
1157#else
1158 int myflag = 0;
1159 int flags = fcntl(socketd, F_GETFL);
1160
1161#ifdef O_NONBLOCK
1162 myflag = O_NONBLOCK; /* POSIX version */
1163#elif defined(O_NDELAY)
1164 myflag = O_NDELAY; /* old non-POSIX version */
1165#endif
1166 if (!block) {
1167 flags |= myflag;
1168 } else {
1169 flags &= ~myflag;
1170 }
1171 if (fcntl(socketd, F_SETFL, flags) == -1) {
1172 ret = FAILURE;
1173 }
1174#endif
1175 return ret;
1176}
1177
1179{
1180
1181#ifdef PHP_WIN32
1183 "PHP needs to be recompiled with a larger value of FD_SETSIZE.\n"
1184 "If this binary is from an official www.php.net package, file a bug report\n"
1185 "at https://github.com/php/php-src/issues, including the following information:\n"
1186 "FD_SETSIZE=%d, but you are using %d.\n"
1187 " --enable-fd-setsize=%d is recommended, but you may want to set it\n"
1188 "to match to maximum number of sockets each script will work with at\n"
1189 "one time, in order to avoid seeing this error again at a later date.",
1190 FD_SETSIZE, max_fd, (max_fd + 128) & ~127);
1191#else
1193 "You MUST recompile PHP with a larger value of FD_SETSIZE.\n"
1194 "It is set to %d, but you have descriptors numbered at least as high as %d.\n"
1195 " --enable-fd-setsize=%d is recommended, but you may want to set it\n"
1196 "to equal the maximum number of open files supported by your system,\n"
1197 "in order to avoid seeing this error again at a later date.",
1198 FD_SETSIZE, max_fd, (max_fd + 1024) & ~1023);
1199#endif
1200}
1201
1202#if defined(PHP_USE_POLL_2_EMULATION)
1203
1204/* emulate poll(2) using select(2), safely. */
1205
1206PHPAPI int php_poll2(php_pollfd *ufds, unsigned int nfds, int timeout)
1207{
1208 fd_set rset, wset, eset;
1209 php_socket_t max_fd = SOCK_ERR; /* effectively unused on Windows */
1210 unsigned int i;
1211 int n;
1212 struct timeval tv;
1213
1214#ifndef PHP_WIN32
1215 /* check the highest numbered descriptor */
1216 for (i = 0; i < nfds; i++) {
1217 if (ufds[i].fd > max_fd)
1218 max_fd = ufds[i].fd;
1219 }
1220#endif
1221
1222 if (!PHP_SAFE_MAX_FD(max_fd, nfds + 1)) {
1223#ifdef PHP_WIN32
1224 WSASetLastError(WSAEINVAL);
1225#else
1226 errno = ERANGE;
1227#endif
1228 return -1;
1229 }
1230
1231 FD_ZERO(&rset);
1232 FD_ZERO(&wset);
1233 FD_ZERO(&eset);
1234
1235 for (i = 0; i < nfds; i++) {
1236 if (ufds[i].events & PHP_POLLREADABLE) {
1237 PHP_SAFE_FD_SET(ufds[i].fd, &rset);
1238 }
1239 if (ufds[i].events & POLLOUT) {
1240 PHP_SAFE_FD_SET(ufds[i].fd, &wset);
1241 }
1242 if (ufds[i].events & POLLPRI) {
1243 PHP_SAFE_FD_SET(ufds[i].fd, &eset);
1244 }
1245 }
1246
1247 if (timeout >= 0) {
1248 tv.tv_sec = timeout / 1000;
1249 tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000;
1250 }
1251/* Resetting/initializing */
1252#ifdef PHP_WIN32
1253 WSASetLastError(0);
1254#else
1255 errno = 0;
1256#endif
1257 n = select(max_fd + 1, &rset, &wset, &eset, timeout >= 0 ? &tv : NULL);
1258
1259 if (n >= 0) {
1260 for (i = 0; i < nfds; i++) {
1261 ufds[i].revents = 0;
1262
1263 if (PHP_SAFE_FD_ISSET(ufds[i].fd, &rset)) {
1264 /* could be POLLERR or POLLHUP but can't tell without probing */
1265 ufds[i].revents |= POLLIN;
1266 }
1267 if (PHP_SAFE_FD_ISSET(ufds[i].fd, &wset)) {
1268 ufds[i].revents |= POLLOUT;
1269 }
1270 if (PHP_SAFE_FD_ISSET(ufds[i].fd, &eset)) {
1271 ufds[i].revents |= POLLPRI;
1272 }
1273 }
1274 }
1275 return n;
1276}
1277#endif
1278
1279#if defined(HAVE_GETHOSTBYNAME_R)
1280#ifdef HAVE_FUNC_GETHOSTBYNAME_R_6
1281static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen)
1282{
1283 struct hostent *hp;
1284 int herr,res;
1285
1286 if (*hstbuflen == 0) {
1287 *hstbuflen = 1024;
1288 *tmphstbuf = (char *)malloc (*hstbuflen);
1289 }
1290
1291 while (( res =
1292 gethostbyname_r(host,hostbuf,*tmphstbuf,*hstbuflen,&hp,&herr))
1293 && (errno == ERANGE)) {
1294 /* Enlarge the buffer. */
1295 *hstbuflen *= 2;
1296 *tmphstbuf = (char *)realloc (*tmphstbuf,*hstbuflen);
1297 }
1298
1299 if (res != 0) {
1300 return NULL;
1301 }
1302
1303 return hp;
1304}
1305#endif
1306#ifdef HAVE_FUNC_GETHOSTBYNAME_R_5
1307static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen)
1308{
1309 struct hostent *hp;
1310 int herr;
1311
1312 if (*hstbuflen == 0) {
1313 *hstbuflen = 1024;
1314 *tmphstbuf = (char *)malloc (*hstbuflen);
1315 }
1316
1317 while ((NULL == ( hp =
1318 gethostbyname_r(host,hostbuf,*tmphstbuf,*hstbuflen,&herr)))
1319 && (errno == ERANGE)) {
1320 /* Enlarge the buffer. */
1321 *hstbuflen *= 2;
1322 *tmphstbuf = (char *)realloc (*tmphstbuf,*hstbuflen);
1323 }
1324 return hp;
1325}
1326#endif
1327#ifdef HAVE_FUNC_GETHOSTBYNAME_R_3
1328static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen)
1329{
1330 if (*hstbuflen == 0) {
1331 *hstbuflen = sizeof(struct hostent_data);
1332 *tmphstbuf = (char *)malloc (*hstbuflen);
1333 } else {
1334 if (*hstbuflen < sizeof(struct hostent_data)) {
1335 *hstbuflen = sizeof(struct hostent_data);
1336 *tmphstbuf = (char *)realloc(*tmphstbuf, *hstbuflen);
1337 }
1338 }
1339 memset((void *)(*tmphstbuf),0,*hstbuflen);
1340
1341 if (0 != gethostbyname_r(host,hostbuf,(struct hostent_data *)*tmphstbuf)) {
1342 return NULL;
1343 }
1344
1345 return hostbuf;
1346}
1347#endif
1348#endif
1349
1350PHPAPI struct hostent* php_network_gethostbyname(const char *name) {
1351#if !defined(HAVE_GETHOSTBYNAME_R)
1352 return gethostbyname(name);
1353#else
1354 if (FG(tmp_host_buf)) {
1355 free(FG(tmp_host_buf));
1356 }
1357
1358 FG(tmp_host_buf) = NULL;
1359 FG(tmp_host_buf_len) = 0;
1360
1361 memset(&FG(tmp_host_info), 0, sizeof(struct hostent));
1362
1363 return gethostname_re(name, &FG(tmp_host_info), &FG(tmp_host_buf), &FG(tmp_host_buf_len));
1364#endif
1365}
size_t len
Definition apprentice.c:174
inet_pton(string $ip)
gettimeofday(bool $as_float=false)
sin(float $num)
gethostbyname(string $hostname)
strchr(string $haystack, string $needle, bool $before_needle=false)
char s[4]
Definition cdf.c:77
error($message)
Definition ext_skel.php:22
unsigned int socklen_t
Definition fastcgi.c:87
zend_long n
Definition ffi.c:4979
zend_string * res
Definition ffi.c:4692
memcpy(ptr1, ptr2, size)
char * err
Definition ffi.c:3029
memset(ptr, 0, type->size)
zval * val
Definition ffi.c:4262
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
#define timercmp(a, b, CMP)
Definition fpm_config.h:62
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
inet_ntop(AF_INET, addr, addr_str, sizeof(addr_str))
PHPAPI zend_result php_set_sock_blocking(php_socket_t socketd, bool block)
Definition network.c:1145
PHPAPI int php_network_connect_socket(php_socket_t sockfd, const struct sockaddr *addr, socklen_t addrlen, int asynchronous, struct timeval *timeout, zend_string **error_string, int *error_code)
Definition network.c:334
PHPAPI php_stream * _php_stream_sock_open_host(const char *host, unsigned short port, int socktype, struct timeval *timeout, const char *persistent_id STREAMS_DC)
Definition network.c:1128
PHPAPI void _php_emit_fd_setsize_warning(int max_fd)
Definition network.c:1178
PHPAPI char * php_socket_strerror(long err, char *buf, size_t bufsize)
Definition network.c:1045
#define SET_SOCKET_BLOCKING_MODE(sock, save)
Definition network.c:293
PHPAPI void php_network_freeaddresses(struct sockaddr **sal)
Definition network.c:133
#define O_NONBLOCK
Definition network.c:282
PHPAPI socklen_t php_sockaddr_size(php_sockaddr_storage *addr)
Definition network.c:1020
PHPAPI int php_poll2(php_pollfd *ufds, unsigned int nfds, int timeout)
Definition network.c:1206
PHPAPI void php_network_populate_name_from_sockaddr(struct sockaddr *sa, socklen_t sl, zend_string **textaddr, struct sockaddr **addr, socklen_t *addrlen)
Definition network.c:643
#define SOCK_CONN_ERR
Definition network.c:86
PHPAPI struct hostent * php_network_gethostbyname(const char *name)
Definition network.c:1350
#define SOCK_ERR
Definition network.c:85
PHPAPI zend_result php_network_parse_network_address_with_port(const char *addr, size_t addrlen, struct sockaddr *sa, socklen_t *sl)
Definition network.c:552
PHPAPI int php_network_get_sock_name(php_socket_t sock, zend_string **textaddr, struct sockaddr **addr, socklen_t *addrlen)
Definition network.c:726
PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock, zend_string **textaddr, struct sockaddr **addr, socklen_t *addrlen, struct timeval *timeout, zend_string **error_string, int *error_code, int tcp_nodelay)
Definition network.c:757
int php_non_blocking_flags_t
Definition network.c:292
PHPAPI php_stream * _php_stream_sock_open_from_socket(php_socket_t socket, const char *persistent_id STREAMS_DC)
Definition network.c:1104
PHPAPI zend_string * php_socket_error_str(long err)
Definition network.c:1079
#define RESTORE_SOCKET_BLOCKING_MODE(sock, save)
Definition network.c:296
php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port, int socktype, int asynchronous, struct timeval *timeout, zend_string **error_string, int *error_code, const char *bindto, unsigned short bindport, long sockopts)
Definition network.c:816
php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned port, int socktype, long sockopts, zend_string **error_string, int *error_code)
Definition network.c:454
#define PHP_TIMEOUT_ERROR_VALUE
Definition network.c:87
PHPAPI int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, zend_string **error_string)
Definition network.c:148
PHPAPI void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port)
Definition network.c:993
PHPAPI int php_network_get_peer_name(php_socket_t sock, zend_string **textaddr, struct sockaddr **addr, socklen_t *addrlen)
Definition network.c:706
#define PHPAPI
Definition php.h:71
php_json_error_code error_code
Definition php_json.h:92
#define MAXFQDNLEN
#define PHP_SAFE_FD_ISSET(fd, set)
struct _php_netstream_data_t php_netstream_data_t
#define STREAM_SOCKOP_IPV6_V6ONLY
const php_stream_ops php_stream_generic_socket_ops
Definition xp_socket.c:532
#define PHP_SAFE_FD_SET(fd, set)
#define POLLIN
#define STREAM_SOCKOP_IPV6_V6ONLY_ENABLED
#define STREAM_SOCKOP_TCP_NODELAY
#define POLLOUT
struct _php_pollfd php_pollfd
#define STREAM_SOCKOP_SO_BROADCAST
#define PHP_POLLREADABLE
#define POLLPRI
#define php_socket_errno()
Definition php_network.h:60
#define PHP_SAFE_MAX_FD(m, n)
int php_socket_t
#define STREAM_SOCKOP_SO_REUSEPORT
#define closesocket
Definition php_network.h:24
#define php_stream_xport_create(name, namelen, options, flags, persistent_id, timeout, context, estr, ecode)
#define STREAM_XPORT_CONNECT
#define STREAM_XPORT_CLIENT
struct _php_stream php_stream
Definition php_streams.h:96
#define REPORT_ERRORS
#define STREAMS_DC
Definition php_streams.h:53
#define php_stream_alloc_rel(ops, thisptr, persistent, mode)
Definition php_streams.h:60
#define PHP_STREAM_FLAG_AVOID_BLOCKING
char * msg
Definition phpdbg.h:289
int fd
Definition phpdbg.h:282
struct timeval tv
Definition session.c:1280
const IPV6_V6ONLY
const SOL_SOCKET
const AF_INET
const IP_BIND_ADDRESS_NO_PORT
const TCP_NODELAY
const SO_BROADCAST
const IPPROTO_IPV6
const SO_ERROR
const AF_UNIX
const AF_INET6
const SO_REUSEPORT
const SO_REUSEADDR
const SOCK_DGRAM
#define strpprintf
Definition spprintf.h:30
#define spprintf
Definition spprintf.h:29
#define FG(v)
Definition file.h:117
struct timeval timeout
php_socket_t fd
uint32_t flags
$obj a
Definition test.php:84
#define EINPROGRESS
#define errno
PHP_WINUTIL_API char * php_win32_error_to_msg(HRESULT error)
Definition winutil.c:25
PHP_WINUTIL_API void php_win32_error_msg_free(char *msg)
Definition winutil.c:50
#define estrndup(s, length)
Definition zend_alloc.h:165
#define efree(ptr)
Definition zend_alloc.h:155
#define estrdup(s)
Definition zend_alloc.h:164
#define pefree(ptr, persistent)
Definition zend_alloc.h:191
#define pemalloc(size, persistent)
Definition zend_alloc.h:189
#define safe_emalloc(nmemb, size, offset)
Definition zend_alloc.h:154
#define emalloc(size)
Definition zend_alloc.h:151
strlen(string $string)
strcmp(string $string1, string $string2)
zend_string_release_ex(func->internal_function.function_name, 0)
#define E_WARNING
Definition zend_errors.h:24
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
int32_t zend_long
Definition zend_long.h:42
struct _zend_string zend_string
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
@ FAILURE
Definition zend_types.h:61
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
zend_string * name
bool result
zval * ret
out($f, $s)