This source file includes following definitions.
- php_sockop_write
- php_sock_stream_wait_for_data
- php_sockop_read
- php_sockop_close
- php_sockop_flush
- php_sockop_stat
- sock_sendto
- sock_recvfrom
- php_sockop_set_option
- php_sockop_cast
- parse_unix_address
- parse_ip_address_ex
- parse_ip_address
- php_tcp_sockop_bind
- php_tcp_sockop_connect
- php_tcp_sockop_accept
- php_tcp_sockop_set_option
- php_stream_generic_socket_factory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include "php.h"
22 #include "ext/standard/file.h"
23 #include "streams/php_streams_int.h"
24 #include "php_network.h"
25
26 #if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
27 # undef AF_UNIX
28 #endif
29
30 #if defined(AF_UNIX)
31 #include <sys/un.h>
32 #endif
33
34 #ifndef MSG_DONTWAIT
35 # define MSG_DONTWAIT 0
36 #endif
37
38 #ifndef MSG_PEEK
39 # define MSG_PEEK 0
40 #endif
41
42 php_stream_ops php_stream_generic_socket_ops;
43 PHPAPI php_stream_ops php_stream_socket_ops;
44 php_stream_ops php_stream_udp_socket_ops;
45 #ifdef AF_UNIX
46 php_stream_ops php_stream_unix_socket_ops;
47 php_stream_ops php_stream_unixdg_socket_ops;
48 #endif
49
50
51 static int php_tcp_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC);
52
53
54 static size_t php_sockop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
55 {
56 php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
57 int didwrite;
58 struct timeval *ptimeout;
59
60 if (sock->socket == -1) {
61 return 0;
62 }
63
64 if (sock->timeout.tv_sec == -1)
65 ptimeout = NULL;
66 else
67 ptimeout = &sock->timeout;
68
69 retry:
70 didwrite = send(sock->socket, buf, count, (sock->is_blocked && ptimeout) ? MSG_DONTWAIT : 0);
71
72 if (didwrite <= 0) {
73 long err = php_socket_errno();
74 char *estr;
75
76 if (sock->is_blocked && err == EWOULDBLOCK) {
77 int retval;
78
79 sock->timeout_event = 0;
80
81 do {
82 retval = php_pollfd_for(sock->socket, POLLOUT, ptimeout);
83
84 if (retval == 0) {
85 sock->timeout_event = 1;
86 break;
87 }
88
89 if (retval > 0) {
90
91 goto retry;
92 }
93
94 err = php_socket_errno();
95 } while (err == EINTR);
96 }
97 estr = php_socket_strerror(err, NULL, 0);
98 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "send of %ld bytes failed with errno=%ld %s",
99 (long)count, err, estr);
100 efree(estr);
101 }
102
103 if (didwrite > 0) {
104 php_stream_notify_progress_increment(stream->context, didwrite, 0);
105 }
106
107 if (didwrite < 0) {
108 didwrite = 0;
109 }
110
111 return didwrite;
112 }
113
114 static void php_sock_stream_wait_for_data(php_stream *stream, php_netstream_data_t *sock TSRMLS_DC)
115 {
116 int retval;
117 struct timeval *ptimeout;
118
119 if (sock->socket == -1) {
120 return;
121 }
122
123 sock->timeout_event = 0;
124
125 if (sock->timeout.tv_sec == -1)
126 ptimeout = NULL;
127 else
128 ptimeout = &sock->timeout;
129
130 while(1) {
131 retval = php_pollfd_for(sock->socket, PHP_POLLREADABLE, ptimeout);
132
133 if (retval == 0)
134 sock->timeout_event = 1;
135
136 if (retval >= 0)
137 break;
138
139 if (php_socket_errno() != EINTR)
140 break;
141 }
142 }
143
144 static size_t php_sockop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
145 {
146 php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
147 int nr_bytes = 0;
148
149 if (sock->socket == -1) {
150 return 0;
151 }
152
153 if (sock->is_blocked) {
154 php_sock_stream_wait_for_data(stream, sock TSRMLS_CC);
155 if (sock->timeout_event)
156 return 0;
157 }
158
159 nr_bytes = recv(sock->socket, buf, count, (sock->is_blocked && sock->timeout.tv_sec != -1) ? MSG_DONTWAIT : 0);
160
161 stream->eof = (nr_bytes == 0 || (nr_bytes == -1 && php_socket_errno() != EWOULDBLOCK));
162
163 if (nr_bytes > 0) {
164 php_stream_notify_progress_increment(stream->context, nr_bytes, 0);
165 }
166
167 if (nr_bytes < 0) {
168 nr_bytes = 0;
169 }
170
171 return nr_bytes;
172 }
173
174
175 static int php_sockop_close(php_stream *stream, int close_handle TSRMLS_DC)
176 {
177 php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
178 #ifdef PHP_WIN32
179 int n;
180 #endif
181
182 if (close_handle) {
183
184 #ifdef PHP_WIN32
185 if (sock->socket == -1)
186 sock->socket = SOCK_ERR;
187 #endif
188 if (sock->socket != SOCK_ERR) {
189 #ifdef PHP_WIN32
190
191 shutdown(sock->socket, SHUT_RD);
192
193
194
195
196
197
198
199 do {
200 n = php_pollfd_for_ms(sock->socket, POLLOUT, 500);
201 } while (n == -1 && php_socket_errno() == EINTR);
202 #endif
203 closesocket(sock->socket);
204 sock->socket = SOCK_ERR;
205 }
206
207 }
208
209 pefree(sock, php_stream_is_persistent(stream));
210
211 return 0;
212 }
213
214 static int php_sockop_flush(php_stream *stream TSRMLS_DC)
215 {
216 #if 0
217 php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
218 return fsync(sock->socket);
219 #endif
220 return 0;
221 }
222
223 static int php_sockop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
224 {
225 php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
226 #if ZEND_WIN32
227 return 0;
228 #else
229 return fstat(sock->socket, &ssb->sb);
230 #endif
231 }
232
233 static inline int sock_sendto(php_netstream_data_t *sock, const char *buf, size_t buflen, int flags,
234 struct sockaddr *addr, socklen_t addrlen
235 TSRMLS_DC)
236 {
237 int ret;
238 if (addr) {
239 ret = sendto(sock->socket, buf, buflen, flags, addr, addrlen);
240 return (ret == SOCK_CONN_ERR) ? -1 : ret;
241 }
242 return ((ret = send(sock->socket, buf, buflen, flags)) == SOCK_CONN_ERR) ? -1 : ret;
243 }
244
245 static inline int sock_recvfrom(php_netstream_data_t *sock, char *buf, size_t buflen, int flags,
246 char **textaddr, long *textaddrlen,
247 struct sockaddr **addr, socklen_t *addrlen
248 TSRMLS_DC)
249 {
250 php_sockaddr_storage sa;
251 socklen_t sl = sizeof(sa);
252 int ret;
253 int want_addr = textaddr || addr;
254
255 if (want_addr) {
256 ret = recvfrom(sock->socket, buf, buflen, flags, (struct sockaddr*)&sa, &sl);
257 ret = (ret == SOCK_CONN_ERR) ? -1 : ret;
258 php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
259 textaddr, textaddrlen, addr, addrlen TSRMLS_CC);
260 } else {
261 ret = recv(sock->socket, buf, buflen, flags);
262 ret = (ret == SOCK_CONN_ERR) ? -1 : ret;
263 }
264
265 return ret;
266 }
267
268 static int php_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC)
269 {
270 int oldmode, flags;
271 php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
272 php_stream_xport_param *xparam;
273
274 switch(option) {
275 case PHP_STREAM_OPTION_CHECK_LIVENESS:
276 {
277 struct timeval tv;
278 char buf;
279 int alive = 1;
280
281 if (value == -1) {
282 if (sock->timeout.tv_sec == -1) {
283 tv.tv_sec = FG(default_socket_timeout);
284 tv.tv_usec = 0;
285 } else {
286 tv = sock->timeout;
287 }
288 } else {
289 tv.tv_sec = value;
290 tv.tv_usec = 0;
291 }
292
293 if (sock->socket == -1) {
294 alive = 0;
295 } else if (php_pollfd_for(sock->socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) {
296 #ifdef PHP_WIN32
297 int ret;
298 #else
299 ssize_t ret;
300 #endif
301 int err;
302
303 ret = recv(sock->socket, &buf, sizeof(buf), MSG_PEEK);
304 err = php_socket_errno();
305 if (0 == ret ||
306 0 > ret && err != EWOULDBLOCK && err != EAGAIN) {
307 alive = 0;
308 }
309 }
310 return alive ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
311 }
312
313 case PHP_STREAM_OPTION_BLOCKING:
314 oldmode = sock->is_blocked;
315 if (SUCCESS == php_set_sock_blocking(sock->socket, value TSRMLS_CC)) {
316 sock->is_blocked = value;
317 return oldmode;
318 }
319 return PHP_STREAM_OPTION_RETURN_ERR;
320
321 case PHP_STREAM_OPTION_READ_TIMEOUT:
322 sock->timeout = *(struct timeval*)ptrparam;
323 sock->timeout_event = 0;
324 return PHP_STREAM_OPTION_RETURN_OK;
325
326 case PHP_STREAM_OPTION_META_DATA_API:
327 add_assoc_bool((zval *)ptrparam, "timed_out", sock->timeout_event);
328 add_assoc_bool((zval *)ptrparam, "blocked", sock->is_blocked);
329 add_assoc_bool((zval *)ptrparam, "eof", stream->eof);
330 return PHP_STREAM_OPTION_RETURN_OK;
331
332 case PHP_STREAM_OPTION_XPORT_API:
333 xparam = (php_stream_xport_param *)ptrparam;
334
335 switch (xparam->op) {
336 case STREAM_XPORT_OP_LISTEN:
337 xparam->outputs.returncode = (listen(sock->socket, xparam->inputs.backlog) == 0) ? 0: -1;
338 return PHP_STREAM_OPTION_RETURN_OK;
339
340 case STREAM_XPORT_OP_GET_NAME:
341 xparam->outputs.returncode = php_network_get_sock_name(sock->socket,
342 xparam->want_textaddr ? &xparam->outputs.textaddr : NULL,
343 xparam->want_textaddr ? &xparam->outputs.textaddrlen : NULL,
344 xparam->want_addr ? &xparam->outputs.addr : NULL,
345 xparam->want_addr ? &xparam->outputs.addrlen : NULL
346 TSRMLS_CC);
347 return PHP_STREAM_OPTION_RETURN_OK;
348
349 case STREAM_XPORT_OP_GET_PEER_NAME:
350 xparam->outputs.returncode = php_network_get_peer_name(sock->socket,
351 xparam->want_textaddr ? &xparam->outputs.textaddr : NULL,
352 xparam->want_textaddr ? &xparam->outputs.textaddrlen : NULL,
353 xparam->want_addr ? &xparam->outputs.addr : NULL,
354 xparam->want_addr ? &xparam->outputs.addrlen : NULL
355 TSRMLS_CC);
356 return PHP_STREAM_OPTION_RETURN_OK;
357
358 case STREAM_XPORT_OP_SEND:
359 flags = 0;
360 if ((xparam->inputs.flags & STREAM_OOB) == STREAM_OOB) {
361 flags |= MSG_OOB;
362 }
363 xparam->outputs.returncode = sock_sendto(sock,
364 xparam->inputs.buf, xparam->inputs.buflen,
365 flags,
366 xparam->inputs.addr,
367 xparam->inputs.addrlen TSRMLS_CC);
368 if (xparam->outputs.returncode == -1) {
369 char *err = php_socket_strerror(php_socket_errno(), NULL, 0);
370 php_error_docref(NULL TSRMLS_CC, E_WARNING,
371 "%s\n", err);
372 efree(err);
373 }
374 return PHP_STREAM_OPTION_RETURN_OK;
375
376 case STREAM_XPORT_OP_RECV:
377 flags = 0;
378 if ((xparam->inputs.flags & STREAM_OOB) == STREAM_OOB) {
379 flags |= MSG_OOB;
380 }
381 if ((xparam->inputs.flags & STREAM_PEEK) == STREAM_PEEK) {
382 flags |= MSG_PEEK;
383 }
384 xparam->outputs.returncode = sock_recvfrom(sock,
385 xparam->inputs.buf, xparam->inputs.buflen,
386 flags,
387 xparam->want_textaddr ? &xparam->outputs.textaddr : NULL,
388 xparam->want_textaddr ? &xparam->outputs.textaddrlen : NULL,
389 xparam->want_addr ? &xparam->outputs.addr : NULL,
390 xparam->want_addr ? &xparam->outputs.addrlen : NULL
391 TSRMLS_CC);
392 return PHP_STREAM_OPTION_RETURN_OK;
393
394
395 #ifdef HAVE_SHUTDOWN
396 # ifndef SHUT_RD
397 # define SHUT_RD 0
398 # endif
399 # ifndef SHUT_WR
400 # define SHUT_WR 1
401 # endif
402 # ifndef SHUT_RDWR
403 # define SHUT_RDWR 2
404 # endif
405 case STREAM_XPORT_OP_SHUTDOWN: {
406 static const int shutdown_how[] = {SHUT_RD, SHUT_WR, SHUT_RDWR};
407
408 xparam->outputs.returncode = shutdown(sock->socket, shutdown_how[xparam->how]);
409 return PHP_STREAM_OPTION_RETURN_OK;
410 }
411 #endif
412
413 default:
414 return PHP_STREAM_OPTION_RETURN_NOTIMPL;
415 }
416
417 default:
418 return PHP_STREAM_OPTION_RETURN_NOTIMPL;
419 }
420 }
421
422 static int php_sockop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
423 {
424 php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
425
426 switch(castas) {
427 case PHP_STREAM_AS_STDIO:
428 if (ret) {
429 *(FILE**)ret = fdopen(sock->socket, stream->mode);
430 if (*ret)
431 return SUCCESS;
432 return FAILURE;
433 }
434 return SUCCESS;
435 case PHP_STREAM_AS_FD_FOR_SELECT:
436 case PHP_STREAM_AS_FD:
437 case PHP_STREAM_AS_SOCKETD:
438 if (ret)
439 *(php_socket_t *)ret = sock->socket;
440 return SUCCESS;
441 default:
442 return FAILURE;
443 }
444 }
445
446
447
448
449
450
451
452
453 php_stream_ops php_stream_generic_socket_ops = {
454 php_sockop_write, php_sockop_read,
455 php_sockop_close, php_sockop_flush,
456 "generic_socket",
457 NULL,
458 php_sockop_cast,
459 php_sockop_stat,
460 php_sockop_set_option,
461 };
462
463
464 php_stream_ops php_stream_socket_ops = {
465 php_sockop_write, php_sockop_read,
466 php_sockop_close, php_sockop_flush,
467 "tcp_socket",
468 NULL,
469 php_sockop_cast,
470 php_sockop_stat,
471 php_tcp_sockop_set_option,
472 };
473
474 php_stream_ops php_stream_udp_socket_ops = {
475 php_sockop_write, php_sockop_read,
476 php_sockop_close, php_sockop_flush,
477 "udp_socket",
478 NULL,
479 php_sockop_cast,
480 php_sockop_stat,
481 php_tcp_sockop_set_option,
482 };
483
484 #ifdef AF_UNIX
485 php_stream_ops php_stream_unix_socket_ops = {
486 php_sockop_write, php_sockop_read,
487 php_sockop_close, php_sockop_flush,
488 "unix_socket",
489 NULL,
490 php_sockop_cast,
491 php_sockop_stat,
492 php_tcp_sockop_set_option,
493 };
494 php_stream_ops php_stream_unixdg_socket_ops = {
495 php_sockop_write, php_sockop_read,
496 php_sockop_close, php_sockop_flush,
497 "udg_socket",
498 NULL,
499 php_sockop_cast,
500 php_sockop_stat,
501 php_tcp_sockop_set_option,
502 };
503 #endif
504
505
506
507
508 #ifdef AF_UNIX
509 static inline int parse_unix_address(php_stream_xport_param *xparam, struct sockaddr_un *unix_addr TSRMLS_DC)
510 {
511 memset(unix_addr, 0, sizeof(*unix_addr));
512 unix_addr->sun_family = AF_UNIX;
513
514
515
516 if (xparam->inputs.namelen >= sizeof(unix_addr->sun_path)) {
517
518
519
520
521
522 xparam->inputs.namelen = sizeof(unix_addr->sun_path) - 1;
523 php_error_docref(NULL TSRMLS_CC, E_NOTICE,
524 "socket path exceeded the maximum allowed length of %lu bytes "
525 "and was truncated", (unsigned long)sizeof(unix_addr->sun_path));
526 }
527
528 memcpy(unix_addr->sun_path, xparam->inputs.name, xparam->inputs.namelen);
529
530 return 1;
531 }
532 #endif
533
534 static inline char *parse_ip_address_ex(const char *str, size_t str_len, int *portno, int get_err, char **err TSRMLS_DC)
535 {
536 char *colon;
537 char *host = NULL;
538
539 #ifdef HAVE_IPV6
540 char *p;
541
542 if (*(str) == '[' && str_len > 1) {
543
544 p = memchr(str + 1, ']', str_len - 2);
545 if (!p || *(p + 1) != ':') {
546 if (get_err) {
547 spprintf(err, 0, "Failed to parse IPv6 address \"%s\"", str);
548 }
549 return NULL;
550 }
551 *portno = atoi(p + 2);
552 return estrndup(str + 1, p - str - 1);
553 }
554 #endif
555 if (str_len) {
556 colon = memchr(str, ':', str_len - 1);
557 } else {
558 colon = NULL;
559 }
560 if (colon) {
561 *portno = atoi(colon + 1);
562 host = estrndup(str, colon - str);
563 } else {
564 if (get_err) {
565 spprintf(err, 0, "Failed to parse address \"%s\"", str);
566 }
567 return NULL;
568 }
569
570 return host;
571 }
572
573 static inline char *parse_ip_address(php_stream_xport_param *xparam, int *portno TSRMLS_DC)
574 {
575 return parse_ip_address_ex(xparam->inputs.name, xparam->inputs.namelen, portno, xparam->want_errortext, &xparam->outputs.error_text TSRMLS_CC);
576 }
577
578 static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t *sock,
579 php_stream_xport_param *xparam TSRMLS_DC)
580 {
581 char *host = NULL;
582 int portno, err;
583
584 #ifdef AF_UNIX
585 if (stream->ops == &php_stream_unix_socket_ops || stream->ops == &php_stream_unixdg_socket_ops) {
586 struct sockaddr_un unix_addr;
587
588 sock->socket = socket(PF_UNIX, stream->ops == &php_stream_unix_socket_ops ? SOCK_STREAM : SOCK_DGRAM, 0);
589
590 if (sock->socket == SOCK_ERR) {
591 if (xparam->want_errortext) {
592 spprintf(&xparam->outputs.error_text, 0, "Failed to create unix%s socket %s",
593 stream->ops == &php_stream_unix_socket_ops ? "" : "datagram",
594 strerror(errno));
595 }
596 return -1;
597 }
598
599 parse_unix_address(xparam, &unix_addr TSRMLS_CC);
600
601 return bind(sock->socket, (const struct sockaddr *)&unix_addr,
602 (socklen_t) XtOffsetOf(struct sockaddr_un, sun_path) + xparam->inputs.namelen);
603 }
604 #endif
605
606 host = parse_ip_address(xparam, &portno TSRMLS_CC);
607
608 if (host == NULL) {
609 return -1;
610 }
611
612 sock->socket = php_network_bind_socket_to_local_addr(host, portno,
613 stream->ops == &php_stream_udp_socket_ops ? SOCK_DGRAM : SOCK_STREAM,
614 xparam->want_errortext ? &xparam->outputs.error_text : NULL,
615 &err
616 TSRMLS_CC);
617
618 if (host) {
619 efree(host);
620 }
621
622 return sock->socket == -1 ? -1 : 0;
623 }
624
625 static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_t *sock,
626 php_stream_xport_param *xparam TSRMLS_DC)
627 {
628 char *host = NULL, *bindto = NULL;
629 int portno, bindport = 0;
630 int err = 0;
631 int ret;
632 zval **tmpzval = NULL;
633
634 #ifdef AF_UNIX
635 if (stream->ops == &php_stream_unix_socket_ops || stream->ops == &php_stream_unixdg_socket_ops) {
636 struct sockaddr_un unix_addr;
637
638 sock->socket = socket(PF_UNIX, stream->ops == &php_stream_unix_socket_ops ? SOCK_STREAM : SOCK_DGRAM, 0);
639
640 if (sock->socket == SOCK_ERR) {
641 if (xparam->want_errortext) {
642 spprintf(&xparam->outputs.error_text, 0, "Failed to create unix socket");
643 }
644 return -1;
645 }
646
647 parse_unix_address(xparam, &unix_addr TSRMLS_CC);
648
649 ret = php_network_connect_socket(sock->socket,
650 (const struct sockaddr *)&unix_addr, (socklen_t) XtOffsetOf(struct sockaddr_un, sun_path) + xparam->inputs.namelen,
651 xparam->op == STREAM_XPORT_OP_CONNECT_ASYNC, xparam->inputs.timeout,
652 xparam->want_errortext ? &xparam->outputs.error_text : NULL,
653 &err);
654
655 xparam->outputs.error_code = err;
656
657 goto out;
658 }
659 #endif
660
661 host = parse_ip_address(xparam, &portno TSRMLS_CC);
662
663 if (host == NULL) {
664 return -1;
665 }
666
667 if (stream->context && php_stream_context_get_option(stream->context, "socket", "bindto", &tmpzval) == SUCCESS) {
668 if (Z_TYPE_PP(tmpzval) != IS_STRING) {
669 if (xparam->want_errortext) {
670 spprintf(&xparam->outputs.error_text, 0, "local_addr context option is not a string.");
671 }
672 efree(host);
673 return -1;
674 }
675 bindto = parse_ip_address_ex(Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval), &bindport, xparam->want_errortext, &xparam->outputs.error_text TSRMLS_CC);
676 }
677
678
679
680
681
682 sock->socket = php_network_connect_socket_to_host(host, portno,
683 stream->ops == &php_stream_udp_socket_ops ? SOCK_DGRAM : SOCK_STREAM,
684 xparam->op == STREAM_XPORT_OP_CONNECT_ASYNC,
685 xparam->inputs.timeout,
686 xparam->want_errortext ? &xparam->outputs.error_text : NULL,
687 &err,
688 bindto,
689 bindport
690 TSRMLS_CC);
691
692 ret = sock->socket == -1 ? -1 : 0;
693 xparam->outputs.error_code = err;
694
695 if (host) {
696 efree(host);
697 }
698 if (bindto) {
699 efree(bindto);
700 }
701
702 #ifdef AF_UNIX
703 out:
704 #endif
705
706 if (ret >= 0 && xparam->op == STREAM_XPORT_OP_CONNECT_ASYNC && err == EINPROGRESS) {
707
708 return 1;
709 }
710
711 return ret;
712 }
713
714 static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t *sock,
715 php_stream_xport_param *xparam STREAMS_DC TSRMLS_DC)
716 {
717 int clisock;
718
719 xparam->outputs.client = NULL;
720
721 clisock = php_network_accept_incoming(sock->socket,
722 xparam->want_textaddr ? &xparam->outputs.textaddr : NULL,
723 xparam->want_textaddr ? &xparam->outputs.textaddrlen : NULL,
724 xparam->want_addr ? &xparam->outputs.addr : NULL,
725 xparam->want_addr ? &xparam->outputs.addrlen : NULL,
726 xparam->inputs.timeout,
727 xparam->want_errortext ? &xparam->outputs.error_text : NULL,
728 &xparam->outputs.error_code
729 TSRMLS_CC);
730
731 if (clisock >= 0) {
732 php_netstream_data_t *clisockdata;
733
734 clisockdata = emalloc(sizeof(*clisockdata));
735
736 if (clisockdata == NULL) {
737 close(clisock);
738
739 } else {
740 memcpy(clisockdata, sock, sizeof(*clisockdata));
741 clisockdata->socket = clisock;
742
743 xparam->outputs.client = php_stream_alloc_rel(stream->ops, clisockdata, NULL, "r+");
744 if (xparam->outputs.client) {
745 xparam->outputs.client->context = stream->context;
746 if (stream->context) {
747 zend_list_addref(stream->context->rsrc_id);
748 }
749 }
750 }
751 }
752
753 return xparam->outputs.client == NULL ? -1 : 0;
754 }
755
756 static int php_tcp_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC)
757 {
758 php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
759 php_stream_xport_param *xparam;
760
761 switch(option) {
762 case PHP_STREAM_OPTION_XPORT_API:
763 xparam = (php_stream_xport_param *)ptrparam;
764
765 switch(xparam->op) {
766 case STREAM_XPORT_OP_CONNECT:
767 case STREAM_XPORT_OP_CONNECT_ASYNC:
768 xparam->outputs.returncode = php_tcp_sockop_connect(stream, sock, xparam TSRMLS_CC);
769 return PHP_STREAM_OPTION_RETURN_OK;
770
771 case STREAM_XPORT_OP_BIND:
772 xparam->outputs.returncode = php_tcp_sockop_bind(stream, sock, xparam TSRMLS_CC);
773 return PHP_STREAM_OPTION_RETURN_OK;
774
775
776 case STREAM_XPORT_OP_ACCEPT:
777 xparam->outputs.returncode = php_tcp_sockop_accept(stream, sock, xparam STREAMS_CC TSRMLS_CC);
778 return PHP_STREAM_OPTION_RETURN_OK;
779 default:
780
781 ;
782 }
783 }
784 return php_sockop_set_option(stream, option, value, ptrparam TSRMLS_CC);
785 }
786
787
788 PHPAPI php_stream *php_stream_generic_socket_factory(const char *proto, size_t protolen,
789 const char *resourcename, size_t resourcenamelen,
790 const char *persistent_id, int options, int flags,
791 struct timeval *timeout,
792 php_stream_context *context STREAMS_DC TSRMLS_DC)
793 {
794 php_stream *stream = NULL;
795 php_netstream_data_t *sock;
796 php_stream_ops *ops;
797
798
799 if (strncmp(proto, "tcp", protolen) == 0) {
800 ops = &php_stream_socket_ops;
801 } else if (strncmp(proto, "udp", protolen) == 0) {
802 ops = &php_stream_udp_socket_ops;
803 }
804 #ifdef AF_UNIX
805 else if (strncmp(proto, "unix", protolen) == 0) {
806 ops = &php_stream_unix_socket_ops;
807 } else if (strncmp(proto, "udg", protolen) == 0) {
808 ops = &php_stream_unixdg_socket_ops;
809 }
810 #endif
811 else {
812
813 return NULL;
814 }
815
816 sock = pemalloc(sizeof(php_netstream_data_t), persistent_id ? 1 : 0);
817 memset(sock, 0, sizeof(php_netstream_data_t));
818
819 sock->is_blocked = 1;
820 sock->timeout.tv_sec = FG(default_socket_timeout);
821 sock->timeout.tv_usec = 0;
822
823
824
825 sock->socket = -1;
826
827 stream = php_stream_alloc_rel(ops, sock, persistent_id, "r+");
828
829 if (stream == NULL) {
830 pefree(sock, persistent_id ? 1 : 0);
831 return NULL;
832 }
833
834 if (flags == 0) {
835 return stream;
836 }
837
838 return stream;
839 }
840
841
842
843
844
845
846
847
848
849