This source file includes following definitions.
- php_sockets_le_socket
- php_create_socket
- php_destroy_socket
- php_open_listen_sock
- php_accept_connect
- php_read
- sockets_strerror
- PHP_GINIT_FUNCTION
- PHP_MINIT_FUNCTION
- PHP_MSHUTDOWN_FUNCTION
- PHP_MINFO_FUNCTION
- PHP_RSHUTDOWN_FUNCTION
- php_sock_array_to_fd_set
- php_sock_array_from_fd_set
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- socket_import_file_descriptor
- PHP_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "php.h"
30
31 #include "php_network.h"
32 #include "ext/standard/file.h"
33 #include "ext/standard/info.h"
34 #include "php_ini.h"
35 #ifdef PHP_WIN32
36 # include "windows_common.h"
37 # include <win32/inet.h>
38 # include <windows.h>
39 # include <Ws2tcpip.h>
40 # include "php_sockets.h"
41 # include <win32/sockets.h>
42 #else
43 # include <sys/types.h>
44 # include <sys/socket.h>
45 # include <netdb.h>
46 # include <netinet/in.h>
47 # include <netinet/tcp.h>
48 # include <sys/un.h>
49 # include <arpa/inet.h>
50 # include <sys/time.h>
51 # include <unistd.h>
52 # include <errno.h>
53 # include <fcntl.h>
54 # include <signal.h>
55 # include <sys/uio.h>
56 # define IS_INVALID_SOCKET(a) (a->bsd_socket < 0)
57 # define set_errno(a) (errno = a)
58 # include "php_sockets.h"
59 # if HAVE_IF_NAMETOINDEX
60 # include <net/if.h>
61 # endif
62 #endif
63
64 #include <stddef.h>
65
66 #include "sockaddr_conv.h"
67 #include "multicast.h"
68 #include "sendrecvmsg.h"
69
70 ZEND_DECLARE_MODULE_GLOBALS(sockets)
71
72 #ifndef MSG_WAITALL
73 #ifdef LINUX
74 #define MSG_WAITALL 0x00000100
75 #else
76 #define MSG_WAITALL 0x00000000
77 #endif
78 #endif
79
80 #ifndef MSG_EOF
81 #ifdef MSG_FIN
82 #define MSG_EOF MSG_FIN
83 #endif
84 #endif
85
86 #ifndef SUN_LEN
87 #define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
88 #endif
89
90 #ifndef PF_INET
91 #define PF_INET AF_INET
92 #endif
93
94 #define PHP_NORMAL_READ 0x0001
95 #define PHP_BINARY_READ 0x0002
96
97 static int le_socket;
98 #define le_socket_name php_sockets_le_socket_name
99
100
101 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_select, 0, 0, 4)
102 ZEND_ARG_INFO(1, read_fds)
103 ZEND_ARG_INFO(1, write_fds)
104 ZEND_ARG_INFO(1, except_fds)
105 ZEND_ARG_INFO(0, tv_sec)
106 ZEND_ARG_INFO(0, tv_usec)
107 ZEND_END_ARG_INFO()
108
109 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create_listen, 0, 0, 1)
110 ZEND_ARG_INFO(0, port)
111 ZEND_ARG_INFO(0, backlog)
112 ZEND_END_ARG_INFO()
113
114 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_accept, 0, 0, 1)
115 ZEND_ARG_INFO(0, socket)
116 ZEND_END_ARG_INFO()
117
118 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_set_nonblock, 0, 0, 1)
119 ZEND_ARG_INFO(0, socket)
120 ZEND_END_ARG_INFO()
121
122 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_set_block, 0, 0, 1)
123 ZEND_ARG_INFO(0, socket)
124 ZEND_END_ARG_INFO()
125
126 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_listen, 0, 0, 1)
127 ZEND_ARG_INFO(0, socket)
128 ZEND_ARG_INFO(0, backlog)
129 ZEND_END_ARG_INFO()
130
131 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_close, 0, 0, 1)
132 ZEND_ARG_INFO(0, socket)
133 ZEND_END_ARG_INFO()
134
135 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_write, 0, 0, 2)
136 ZEND_ARG_INFO(0, socket)
137 ZEND_ARG_INFO(0, buf)
138 ZEND_ARG_INFO(0, length)
139 ZEND_END_ARG_INFO()
140
141 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_read, 0, 0, 2)
142 ZEND_ARG_INFO(0, socket)
143 ZEND_ARG_INFO(0, length)
144 ZEND_ARG_INFO(0, type)
145 ZEND_END_ARG_INFO()
146
147 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_getsockname, 0, 0, 2)
148 ZEND_ARG_INFO(0, socket)
149 ZEND_ARG_INFO(1, addr)
150 ZEND_ARG_INFO(1, port)
151 ZEND_END_ARG_INFO()
152
153 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_getpeername, 0, 0, 2)
154 ZEND_ARG_INFO(0, socket)
155 ZEND_ARG_INFO(1, addr)
156 ZEND_ARG_INFO(1, port)
157 ZEND_END_ARG_INFO()
158
159 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create, 0, 0, 3)
160 ZEND_ARG_INFO(0, domain)
161 ZEND_ARG_INFO(0, type)
162 ZEND_ARG_INFO(0, protocol)
163 ZEND_END_ARG_INFO()
164
165 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_connect, 0, 0, 2)
166 ZEND_ARG_INFO(0, socket)
167 ZEND_ARG_INFO(0, addr)
168 ZEND_ARG_INFO(0, port)
169 ZEND_END_ARG_INFO()
170
171 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_strerror, 0, 0, 1)
172 ZEND_ARG_INFO(0, errno)
173 ZEND_END_ARG_INFO()
174
175 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_bind, 0, 0, 2)
176 ZEND_ARG_INFO(0, socket)
177 ZEND_ARG_INFO(0, addr)
178 ZEND_ARG_INFO(0, port)
179 ZEND_END_ARG_INFO()
180
181 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_recv, 0, 0, 4)
182 ZEND_ARG_INFO(0, socket)
183 ZEND_ARG_INFO(1, buf)
184 ZEND_ARG_INFO(0, len)
185 ZEND_ARG_INFO(0, flags)
186 ZEND_END_ARG_INFO()
187
188 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_send, 0, 0, 4)
189 ZEND_ARG_INFO(0, socket)
190 ZEND_ARG_INFO(0, buf)
191 ZEND_ARG_INFO(0, len)
192 ZEND_ARG_INFO(0, flags)
193 ZEND_END_ARG_INFO()
194
195 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_recvfrom, 0, 0, 5)
196 ZEND_ARG_INFO(0, socket)
197 ZEND_ARG_INFO(1, buf)
198 ZEND_ARG_INFO(0, len)
199 ZEND_ARG_INFO(0, flags)
200 ZEND_ARG_INFO(1, name)
201 ZEND_ARG_INFO(1, port)
202 ZEND_END_ARG_INFO()
203
204 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_sendto, 0, 0, 5)
205 ZEND_ARG_INFO(0, socket)
206 ZEND_ARG_INFO(0, buf)
207 ZEND_ARG_INFO(0, len)
208 ZEND_ARG_INFO(0, flags)
209 ZEND_ARG_INFO(0, addr)
210 ZEND_ARG_INFO(0, port)
211 ZEND_END_ARG_INFO()
212
213 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_get_option, 0, 0, 3)
214 ZEND_ARG_INFO(0, socket)
215 ZEND_ARG_INFO(0, level)
216 ZEND_ARG_INFO(0, optname)
217 ZEND_END_ARG_INFO()
218
219 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_set_option, 0, 0, 4)
220 ZEND_ARG_INFO(0, socket)
221 ZEND_ARG_INFO(0, level)
222 ZEND_ARG_INFO(0, optname)
223 ZEND_ARG_INFO(0, optval)
224 ZEND_END_ARG_INFO()
225
226 #ifdef HAVE_SOCKETPAIR
227 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create_pair, 0, 0, 4)
228 ZEND_ARG_INFO(0, domain)
229 ZEND_ARG_INFO(0, type)
230 ZEND_ARG_INFO(0, protocol)
231 ZEND_ARG_INFO(1, fd)
232 ZEND_END_ARG_INFO()
233 #endif
234
235 #ifdef HAVE_SHUTDOWN
236 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_shutdown, 0, 0, 1)
237 ZEND_ARG_INFO(0, socket)
238 ZEND_ARG_INFO(0, how)
239 ZEND_END_ARG_INFO()
240 #endif
241
242 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_last_error, 0, 0, 0)
243 ZEND_ARG_INFO(0, socket)
244 ZEND_END_ARG_INFO()
245
246 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_clear_error, 0, 0, 0)
247 ZEND_ARG_INFO(0, socket)
248 ZEND_END_ARG_INFO()
249
250 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_import_stream, 0, 0, 1)
251 ZEND_ARG_INFO(0, stream)
252 ZEND_END_ARG_INFO()
253
254 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_sendmsg, 0, 0, 3)
255 ZEND_ARG_INFO(0, socket)
256 ZEND_ARG_INFO(0, msghdr)
257 ZEND_ARG_INFO(0, flags)
258 ZEND_END_ARG_INFO()
259
260 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_recvmsg, 0, 0, 3)
261 ZEND_ARG_INFO(0, socket)
262 ZEND_ARG_INFO(1, msghdr)
263 ZEND_ARG_INFO(0, flags)
264 ZEND_END_ARG_INFO()
265
266 ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_cmsg_space, 0, 0, 2)
267 ZEND_ARG_INFO(0, level)
268 ZEND_ARG_INFO(0, type)
269 ZEND_END_ARG_INFO()
270
271
272 static PHP_GINIT_FUNCTION(sockets);
273 static PHP_MINIT_FUNCTION(sockets);
274 static PHP_MSHUTDOWN_FUNCTION(sockets);
275 static PHP_MINFO_FUNCTION(sockets);
276 static PHP_RSHUTDOWN_FUNCTION(sockets);
277
278 PHP_FUNCTION(socket_select);
279 PHP_FUNCTION(socket_create_listen);
280 #ifdef HAVE_SOCKETPAIR
281 PHP_FUNCTION(socket_create_pair);
282 #endif
283 PHP_FUNCTION(socket_accept);
284 PHP_FUNCTION(socket_set_nonblock);
285 PHP_FUNCTION(socket_set_block);
286 PHP_FUNCTION(socket_listen);
287 PHP_FUNCTION(socket_close);
288 PHP_FUNCTION(socket_write);
289 PHP_FUNCTION(socket_read);
290 PHP_FUNCTION(socket_getsockname);
291 PHP_FUNCTION(socket_getpeername);
292 PHP_FUNCTION(socket_create);
293 PHP_FUNCTION(socket_connect);
294 PHP_FUNCTION(socket_strerror);
295 PHP_FUNCTION(socket_bind);
296 PHP_FUNCTION(socket_recv);
297 PHP_FUNCTION(socket_send);
298 PHP_FUNCTION(socket_recvfrom);
299 PHP_FUNCTION(socket_sendto);
300 PHP_FUNCTION(socket_get_option);
301 PHP_FUNCTION(socket_set_option);
302 #ifdef HAVE_SHUTDOWN
303 PHP_FUNCTION(socket_shutdown);
304 #endif
305 PHP_FUNCTION(socket_last_error);
306 PHP_FUNCTION(socket_clear_error);
307 PHP_FUNCTION(socket_import_stream);
308
309
310
311 const zend_function_entry sockets_functions[] = {
312 PHP_FE(socket_select, arginfo_socket_select)
313 PHP_FE(socket_create, arginfo_socket_create)
314 PHP_FE(socket_create_listen, arginfo_socket_create_listen)
315 #ifdef HAVE_SOCKETPAIR
316 PHP_FE(socket_create_pair, arginfo_socket_create_pair)
317 #endif
318 PHP_FE(socket_accept, arginfo_socket_accept)
319 PHP_FE(socket_set_nonblock, arginfo_socket_set_nonblock)
320 PHP_FE(socket_set_block, arginfo_socket_set_block)
321 PHP_FE(socket_listen, arginfo_socket_listen)
322 PHP_FE(socket_close, arginfo_socket_close)
323 PHP_FE(socket_write, arginfo_socket_write)
324 PHP_FE(socket_read, arginfo_socket_read)
325 PHP_FE(socket_getsockname, arginfo_socket_getsockname)
326 PHP_FE(socket_getpeername, arginfo_socket_getpeername)
327 PHP_FE(socket_connect, arginfo_socket_connect)
328 PHP_FE(socket_strerror, arginfo_socket_strerror)
329 PHP_FE(socket_bind, arginfo_socket_bind)
330 PHP_FE(socket_recv, arginfo_socket_recv)
331 PHP_FE(socket_send, arginfo_socket_send)
332 PHP_FE(socket_recvfrom, arginfo_socket_recvfrom)
333 PHP_FE(socket_sendto, arginfo_socket_sendto)
334 PHP_FE(socket_get_option, arginfo_socket_get_option)
335 PHP_FE(socket_set_option, arginfo_socket_set_option)
336 #ifdef HAVE_SHUTDOWN
337 PHP_FE(socket_shutdown, arginfo_socket_shutdown)
338 #endif
339 PHP_FE(socket_last_error, arginfo_socket_last_error)
340 PHP_FE(socket_clear_error, arginfo_socket_clear_error)
341 PHP_FE(socket_import_stream, arginfo_socket_import_stream)
342 PHP_FE(socket_sendmsg, arginfo_socket_sendmsg)
343 PHP_FE(socket_recvmsg, arginfo_socket_recvmsg)
344 PHP_FE(socket_cmsg_space, arginfo_socket_cmsg_space)
345
346
347 PHP_FALIAS(socket_getopt, socket_get_option, arginfo_socket_get_option)
348 PHP_FALIAS(socket_setopt, socket_set_option, arginfo_socket_set_option)
349
350 PHP_FE_END
351 };
352
353
354 zend_module_entry sockets_module_entry = {
355 STANDARD_MODULE_HEADER,
356 "sockets",
357 sockets_functions,
358 PHP_MINIT(sockets),
359 PHP_MSHUTDOWN(sockets),
360 NULL,
361 PHP_RSHUTDOWN(sockets),
362 PHP_MINFO(sockets),
363 PHP_SOCKETS_VERSION,
364 PHP_MODULE_GLOBALS(sockets),
365 PHP_GINIT(sockets),
366 NULL,
367 NULL,
368 STANDARD_MODULE_PROPERTIES_EX
369 };
370
371
372 #ifdef COMPILE_DL_SOCKETS
373 #ifdef ZTS
374 ZEND_TSRMLS_CACHE_DEFINE()
375 #endif
376 ZEND_GET_MODULE(sockets)
377 #endif
378
379
380 int inet_ntoa_lock = 0;
381
382 PHP_SOCKETS_API int php_sockets_le_socket(void)
383 {
384 return le_socket;
385 }
386
387
388
389
390 PHP_SOCKETS_API php_socket *php_create_socket(void)
391 {
392 php_socket *php_sock = emalloc(sizeof(php_socket));
393
394 php_sock->bsd_socket = -1;
395 php_sock->type = PF_UNSPEC;
396 php_sock->error = 0;
397 php_sock->blocking = 1;
398 ZVAL_UNDEF(&php_sock->zstream);
399
400 return php_sock;
401 }
402
403
404 PHP_SOCKETS_API void php_destroy_socket(zend_resource *rsrc)
405 {
406 php_socket *php_sock = rsrc->ptr;
407
408 if (Z_ISUNDEF(php_sock->zstream)) {
409 if (!IS_INVALID_SOCKET(php_sock)) {
410 close(php_sock->bsd_socket);
411 }
412 } else {
413 zval_ptr_dtor(&php_sock->zstream);
414 }
415 efree(php_sock);
416 }
417
418
419 static int php_open_listen_sock(php_socket **php_sock, int port, int backlog)
420 {
421 struct sockaddr_in la;
422 struct hostent *hp;
423 php_socket *sock = php_create_socket();
424
425 *php_sock = sock;
426
427 #ifndef PHP_WIN32
428 if ((hp = gethostbyname("0.0.0.0")) == NULL) {
429 #else
430 if ((hp = gethostbyname("localhost")) == NULL) {
431 #endif
432 efree(sock);
433 return 0;
434 }
435
436 memcpy((char *) &la.sin_addr, hp->h_addr, hp->h_length);
437 la.sin_family = hp->h_addrtype;
438 la.sin_port = htons((unsigned short) port);
439
440 sock->bsd_socket = socket(PF_INET, SOCK_STREAM, 0);
441 sock->blocking = 1;
442
443 if (IS_INVALID_SOCKET(sock)) {
444 PHP_SOCKET_ERROR(sock, "unable to create listening socket", errno);
445 efree(sock);
446 return 0;
447 }
448
449 sock->type = PF_INET;
450
451 if (bind(sock->bsd_socket, (struct sockaddr *)&la, sizeof(la)) != 0) {
452 PHP_SOCKET_ERROR(sock, "unable to bind to given address", errno);
453 close(sock->bsd_socket);
454 efree(sock);
455 return 0;
456 }
457
458 if (listen(sock->bsd_socket, backlog) != 0) {
459 PHP_SOCKET_ERROR(sock, "unable to listen on socket", errno);
460 close(sock->bsd_socket);
461 efree(sock);
462 return 0;
463 }
464
465 return 1;
466 }
467
468
469 static int php_accept_connect(php_socket *in_sock, php_socket **new_sock, struct sockaddr *la, socklen_t *la_len)
470 {
471 php_socket *out_sock = php_create_socket();
472
473 *new_sock = out_sock;
474
475 out_sock->bsd_socket = accept(in_sock->bsd_socket, la, la_len);
476
477 if (IS_INVALID_SOCKET(out_sock)) {
478 PHP_SOCKET_ERROR(out_sock, "unable to accept incoming connection", errno);
479 efree(out_sock);
480 return 0;
481 }
482
483 out_sock->error = 0;
484 out_sock->blocking = 1;
485 out_sock->type = la->sa_family;
486
487 return 1;
488 }
489
490
491
492 static int php_read(php_socket *sock, void *buf, size_t maxlen, int flags)
493 {
494 int m = 0;
495 size_t n = 0;
496 int no_read = 0;
497 int nonblock = 0;
498 char *t = (char *) buf;
499
500 #ifndef PHP_WIN32
501 m = fcntl(sock->bsd_socket, F_GETFL);
502 if (m < 0) {
503 return m;
504 }
505 nonblock = (m & O_NONBLOCK);
506 m = 0;
507 #else
508 nonblock = !sock->blocking;
509 #endif
510 set_errno(0);
511
512 *t = '\0';
513 while (*t != '\n' && *t != '\r' && n < maxlen) {
514 if (m > 0) {
515 t++;
516 n++;
517 } else if (m == 0) {
518 no_read++;
519 if (nonblock && no_read >= 2) {
520 return n;
521
522
523
524 }
525
526 if (no_read > 200) {
527 set_errno(ECONNRESET);
528 return -1;
529 }
530 }
531
532 if (n < maxlen) {
533 m = recv(sock->bsd_socket, (void *) t, 1, flags);
534 }
535
536 if (errno != 0 && errno != ESPIPE && errno != EAGAIN) {
537 return -1;
538 }
539
540 set_errno(0);
541 }
542
543 if (n < maxlen) {
544 n++;
545
546
547
548
549
550 }
551
552 return n;
553 }
554
555
556 char *sockets_strerror(int error)
557 {
558 const char *buf;
559
560 #ifndef PHP_WIN32
561 if (error < -10000) {
562 error = -error - 10000;
563
564 #ifdef HAVE_HSTRERROR
565 buf = hstrerror(error);
566 #else
567 {
568 if (SOCKETS_G(strerror_buf)) {
569 efree(SOCKETS_G(strerror_buf));
570 }
571
572 spprintf(&(SOCKETS_G(strerror_buf)), 0, "Host lookup error %d", error);
573 buf = SOCKETS_G(strerror_buf);
574 }
575 #endif
576 } else {
577 buf = strerror(error);
578 }
579 #else
580 {
581 LPTSTR tmp = NULL;
582 buf = NULL;
583
584 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
585 NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &tmp, 0, NULL)
586 ) {
587 if (SOCKETS_G(strerror_buf)) {
588 efree(SOCKETS_G(strerror_buf));
589 }
590
591 SOCKETS_G(strerror_buf) = estrdup(tmp);
592 LocalFree(tmp);
593
594 buf = SOCKETS_G(strerror_buf);
595 }
596 }
597 #endif
598
599 return (buf ? (char *) buf : "");
600 }
601
602
603
604 static PHP_GINIT_FUNCTION(sockets)
605 {
606 #if defined(COMPILE_DL_SOCKETS) && defined(ZTS)
607 ZEND_TSRMLS_CACHE_UPDATE();
608 #endif
609 sockets_globals->last_error = 0;
610 sockets_globals->strerror_buf = NULL;
611 }
612
613
614
615
616 static PHP_MINIT_FUNCTION(sockets)
617 {
618 #if defined(COMPILE_DL_SOCKETS) && defined(ZTS)
619 ZEND_TSRMLS_CACHE_UPDATE();
620 #endif
621 le_socket = zend_register_list_destructors_ex(php_destroy_socket, NULL, le_socket_name, module_number);
622
623 REGISTER_LONG_CONSTANT("AF_UNIX", AF_UNIX, CONST_CS | CONST_PERSISTENT);
624 REGISTER_LONG_CONSTANT("AF_INET", AF_INET, CONST_CS | CONST_PERSISTENT);
625 #if HAVE_IPV6
626 REGISTER_LONG_CONSTANT("AF_INET6", AF_INET6, CONST_CS | CONST_PERSISTENT);
627 #endif
628 REGISTER_LONG_CONSTANT("SOCK_STREAM", SOCK_STREAM, CONST_CS | CONST_PERSISTENT);
629 REGISTER_LONG_CONSTANT("SOCK_DGRAM", SOCK_DGRAM, CONST_CS | CONST_PERSISTENT);
630 REGISTER_LONG_CONSTANT("SOCK_RAW", SOCK_RAW, CONST_CS | CONST_PERSISTENT);
631 REGISTER_LONG_CONSTANT("SOCK_SEQPACKET",SOCK_SEQPACKET, CONST_CS | CONST_PERSISTENT);
632 REGISTER_LONG_CONSTANT("SOCK_RDM", SOCK_RDM, CONST_CS | CONST_PERSISTENT);
633
634 REGISTER_LONG_CONSTANT("MSG_OOB", MSG_OOB, CONST_CS | CONST_PERSISTENT);
635 REGISTER_LONG_CONSTANT("MSG_WAITALL", MSG_WAITALL, CONST_CS | CONST_PERSISTENT);
636 REGISTER_LONG_CONSTANT("MSG_CTRUNC", MSG_CTRUNC, CONST_CS | CONST_PERSISTENT);
637 REGISTER_LONG_CONSTANT("MSG_TRUNC", MSG_TRUNC, CONST_CS | CONST_PERSISTENT);
638 REGISTER_LONG_CONSTANT("MSG_PEEK", MSG_PEEK, CONST_CS | CONST_PERSISTENT);
639 REGISTER_LONG_CONSTANT("MSG_DONTROUTE", MSG_DONTROUTE, CONST_CS | CONST_PERSISTENT);
640 #ifdef MSG_EOR
641 REGISTER_LONG_CONSTANT("MSG_EOR", MSG_EOR, CONST_CS | CONST_PERSISTENT);
642 #endif
643 #ifdef MSG_EOF
644 REGISTER_LONG_CONSTANT("MSG_EOF", MSG_EOF, CONST_CS | CONST_PERSISTENT);
645 #endif
646
647 #ifdef MSG_CONFIRM
648 REGISTER_LONG_CONSTANT("MSG_CONFIRM", MSG_CONFIRM, CONST_CS | CONST_PERSISTENT);
649 #endif
650 #ifdef MSG_ERRQUEUE
651 REGISTER_LONG_CONSTANT("MSG_ERRQUEUE", MSG_ERRQUEUE, CONST_CS | CONST_PERSISTENT);
652 #endif
653 #ifdef MSG_NOSIGNAL
654 REGISTER_LONG_CONSTANT("MSG_NOSIGNAL", MSG_NOSIGNAL, CONST_CS | CONST_PERSISTENT);
655 #endif
656 #ifdef MSG_DONTWAIT
657 REGISTER_LONG_CONSTANT("MSG_DONTWAIT", MSG_DONTWAIT, CONST_CS | CONST_PERSISTENT);
658 #endif
659 #ifdef MSG_MORE
660 REGISTER_LONG_CONSTANT("MSG_MORE", MSG_MORE, CONST_CS | CONST_PERSISTENT);
661 #endif
662 #ifdef MSG_WAITFORONE
663 REGISTER_LONG_CONSTANT("MSG_WAITFORONE",MSG_WAITFORONE, CONST_CS | CONST_PERSISTENT);
664 #endif
665 #ifdef MSG_CMSG_CLOEXEC
666 REGISTER_LONG_CONSTANT("MSG_CMSG_CLOEXEC",MSG_CMSG_CLOEXEC,CONST_CS | CONST_PERSISTENT);
667 #endif
668
669 REGISTER_LONG_CONSTANT("SO_DEBUG", SO_DEBUG, CONST_CS | CONST_PERSISTENT);
670 REGISTER_LONG_CONSTANT("SO_REUSEADDR", SO_REUSEADDR, CONST_CS | CONST_PERSISTENT);
671 #ifdef SO_REUSEPORT
672 REGISTER_LONG_CONSTANT("SO_REUSEPORT", SO_REUSEPORT, CONST_CS | CONST_PERSISTENT);
673 #endif
674 REGISTER_LONG_CONSTANT("SO_KEEPALIVE", SO_KEEPALIVE, CONST_CS | CONST_PERSISTENT);
675 REGISTER_LONG_CONSTANT("SO_DONTROUTE", SO_DONTROUTE, CONST_CS | CONST_PERSISTENT);
676 REGISTER_LONG_CONSTANT("SO_LINGER", SO_LINGER, CONST_CS | CONST_PERSISTENT);
677 REGISTER_LONG_CONSTANT("SO_BROADCAST", SO_BROADCAST, CONST_CS | CONST_PERSISTENT);
678 REGISTER_LONG_CONSTANT("SO_OOBINLINE", SO_OOBINLINE, CONST_CS | CONST_PERSISTENT);
679 REGISTER_LONG_CONSTANT("SO_SNDBUF", SO_SNDBUF, CONST_CS | CONST_PERSISTENT);
680 REGISTER_LONG_CONSTANT("SO_RCVBUF", SO_RCVBUF, CONST_CS | CONST_PERSISTENT);
681 REGISTER_LONG_CONSTANT("SO_SNDLOWAT", SO_SNDLOWAT, CONST_CS | CONST_PERSISTENT);
682 REGISTER_LONG_CONSTANT("SO_RCVLOWAT", SO_RCVLOWAT, CONST_CS | CONST_PERSISTENT);
683 REGISTER_LONG_CONSTANT("SO_SNDTIMEO", SO_SNDTIMEO, CONST_CS | CONST_PERSISTENT);
684 REGISTER_LONG_CONSTANT("SO_RCVTIMEO", SO_RCVTIMEO, CONST_CS | CONST_PERSISTENT);
685 REGISTER_LONG_CONSTANT("SO_TYPE", SO_TYPE, CONST_CS | CONST_PERSISTENT);
686 #ifdef SO_FAMILY
687 REGISTER_LONG_CONSTANT("SO_FAMILY", SO_FAMILY, CONST_CS | CONST_PERSISTENT);
688 #endif
689 REGISTER_LONG_CONSTANT("SO_ERROR", SO_ERROR, CONST_CS | CONST_PERSISTENT);
690 #ifdef SO_BINDTODEVICE
691 REGISTER_LONG_CONSTANT("SO_BINDTODEVICE", SO_BINDTODEVICE, CONST_CS | CONST_PERSISTENT);
692 #endif
693 REGISTER_LONG_CONSTANT("SOL_SOCKET", SOL_SOCKET, CONST_CS | CONST_PERSISTENT);
694 REGISTER_LONG_CONSTANT("SOMAXCONN", SOMAXCONN, CONST_CS | CONST_PERSISTENT);
695 #ifdef TCP_NODELAY
696 REGISTER_LONG_CONSTANT("TCP_NODELAY", TCP_NODELAY, CONST_CS | CONST_PERSISTENT);
697 #endif
698 REGISTER_LONG_CONSTANT("PHP_NORMAL_READ", PHP_NORMAL_READ, CONST_CS | CONST_PERSISTENT);
699 REGISTER_LONG_CONSTANT("PHP_BINARY_READ", PHP_BINARY_READ, CONST_CS | CONST_PERSISTENT);
700
701 REGISTER_LONG_CONSTANT("MCAST_JOIN_GROUP", PHP_MCAST_JOIN_GROUP, CONST_CS | CONST_PERSISTENT);
702 REGISTER_LONG_CONSTANT("MCAST_LEAVE_GROUP", PHP_MCAST_LEAVE_GROUP, CONST_CS | CONST_PERSISTENT);
703 #ifdef HAS_MCAST_EXT
704 REGISTER_LONG_CONSTANT("MCAST_BLOCK_SOURCE", PHP_MCAST_BLOCK_SOURCE, CONST_CS | CONST_PERSISTENT);
705 REGISTER_LONG_CONSTANT("MCAST_UNBLOCK_SOURCE", PHP_MCAST_UNBLOCK_SOURCE, CONST_CS | CONST_PERSISTENT);
706 REGISTER_LONG_CONSTANT("MCAST_JOIN_SOURCE_GROUP", PHP_MCAST_JOIN_SOURCE_GROUP, CONST_CS | CONST_PERSISTENT);
707 REGISTER_LONG_CONSTANT("MCAST_LEAVE_SOURCE_GROUP", PHP_MCAST_LEAVE_SOURCE_GROUP, CONST_CS | CONST_PERSISTENT);
708 #endif
709
710 REGISTER_LONG_CONSTANT("IP_MULTICAST_IF", IP_MULTICAST_IF, CONST_CS | CONST_PERSISTENT);
711 REGISTER_LONG_CONSTANT("IP_MULTICAST_TTL", IP_MULTICAST_TTL, CONST_CS | CONST_PERSISTENT);
712 REGISTER_LONG_CONSTANT("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP, CONST_CS | CONST_PERSISTENT);
713 #if HAVE_IPV6
714 REGISTER_LONG_CONSTANT("IPV6_MULTICAST_IF", IPV6_MULTICAST_IF, CONST_CS | CONST_PERSISTENT);
715 REGISTER_LONG_CONSTANT("IPV6_MULTICAST_HOPS", IPV6_MULTICAST_HOPS, CONST_CS | CONST_PERSISTENT);
716 REGISTER_LONG_CONSTANT("IPV6_MULTICAST_LOOP", IPV6_MULTICAST_LOOP, CONST_CS | CONST_PERSISTENT);
717 #endif
718
719 #ifdef IPV6_V6ONLY
720 REGISTER_LONG_CONSTANT("IPV6_V6ONLY", IPV6_V6ONLY, CONST_CS | CONST_PERSISTENT);
721 #endif
722
723 #ifndef WIN32
724 # include "unix_socket_constants.h"
725 #else
726 # include "win32_socket_constants.h"
727 #endif
728
729 REGISTER_LONG_CONSTANT("IPPROTO_IP", IPPROTO_IP, CONST_CS | CONST_PERSISTENT);
730 #if HAVE_IPV6
731 REGISTER_LONG_CONSTANT("IPPROTO_IPV6", IPPROTO_IPV6, CONST_CS | CONST_PERSISTENT);
732 #endif
733
734 REGISTER_LONG_CONSTANT("SOL_TCP", IPPROTO_TCP, CONST_CS | CONST_PERSISTENT);
735 REGISTER_LONG_CONSTANT("SOL_UDP", IPPROTO_UDP, CONST_CS | CONST_PERSISTENT);
736
737 #if HAVE_IPV6
738 REGISTER_LONG_CONSTANT("IPV6_UNICAST_HOPS", IPV6_UNICAST_HOPS, CONST_CS | CONST_PERSISTENT);
739 #endif
740
741 php_socket_sendrecvmsg_init(INIT_FUNC_ARGS_PASSTHRU);
742
743 return SUCCESS;
744 }
745
746
747
748
749 static PHP_MSHUTDOWN_FUNCTION(sockets)
750 {
751 php_socket_sendrecvmsg_shutdown(SHUTDOWN_FUNC_ARGS_PASSTHRU);
752
753 return SUCCESS;
754 }
755
756
757
758
759 static PHP_MINFO_FUNCTION(sockets)
760 {
761 php_info_print_table_start();
762 php_info_print_table_row(2, "Sockets Support", "enabled");
763 php_info_print_table_end();
764 }
765
766
767
768 static PHP_RSHUTDOWN_FUNCTION(sockets)
769 {
770 if (SOCKETS_G(strerror_buf)) {
771 efree(SOCKETS_G(strerror_buf));
772 SOCKETS_G(strerror_buf) = NULL;
773 }
774
775 return SUCCESS;
776 }
777
778
779 static int php_sock_array_to_fd_set(zval *sock_array, fd_set *fds, PHP_SOCKET *max_fd)
780 {
781 zval *element;
782 php_socket *php_sock;
783 int num = 0;
784
785 if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0;
786
787 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(sock_array), element) {
788 php_sock = (php_socket*) zend_fetch_resource_ex(element, le_socket_name, le_socket);
789 if (!php_sock) continue;
790
791 PHP_SAFE_FD_SET(php_sock->bsd_socket, fds);
792 if (php_sock->bsd_socket > *max_fd) {
793 *max_fd = php_sock->bsd_socket;
794 }
795 num++;
796 } ZEND_HASH_FOREACH_END();
797
798 return num ? 1 : 0;
799 }
800
801
802 static int php_sock_array_from_fd_set(zval *sock_array, fd_set *fds)
803 {
804 zval *element;
805 zval *dest_element;
806 php_socket *php_sock;
807 zval new_hash;
808 int num = 0;
809 zend_ulong num_key;
810 zend_string *key;
811
812 if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0;
813
814 array_init(&new_hash);
815 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(sock_array), num_key, key, element) {
816 php_sock = (php_socket*) zend_fetch_resource_ex(element, le_socket_name, le_socket);
817 if (!php_sock) continue;
818
819 if (PHP_SAFE_FD_ISSET(php_sock->bsd_socket, fds)) {
820
821 if (key) {
822 dest_element = zend_hash_add(Z_ARRVAL(new_hash), key, element);
823 } else {
824 dest_element = zend_hash_index_update(Z_ARRVAL(new_hash), num_key, element);
825 }
826 if (dest_element) {
827 Z_ADDREF_P(dest_element);
828 }
829 }
830 num++;
831 } ZEND_HASH_FOREACH_END();
832
833
834 zval_ptr_dtor(sock_array);
835
836 ZVAL_COPY_VALUE(sock_array, &new_hash);
837
838 return num ? 1 : 0;
839 }
840
841
842
843
844 PHP_FUNCTION(socket_select)
845 {
846 zval *r_array, *w_array, *e_array, *sec;
847 struct timeval tv;
848 struct timeval *tv_p = NULL;
849 fd_set rfds, wfds, efds;
850 PHP_SOCKET max_fd = 0;
851 int retval, sets = 0;
852 zend_long usec = 0;
853
854 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/!a/!a/!z!|l", &r_array, &w_array, &e_array, &sec, &usec) == FAILURE) {
855 return;
856 }
857
858 FD_ZERO(&rfds);
859 FD_ZERO(&wfds);
860 FD_ZERO(&efds);
861
862 if (r_array != NULL) sets += php_sock_array_to_fd_set(r_array, &rfds, &max_fd);
863 if (w_array != NULL) sets += php_sock_array_to_fd_set(w_array, &wfds, &max_fd);
864 if (e_array != NULL) sets += php_sock_array_to_fd_set(e_array, &efds, &max_fd);
865
866 if (!sets) {
867 php_error_docref(NULL, E_WARNING, "no resource arrays were passed to select");
868 RETURN_FALSE;
869 }
870
871 PHP_SAFE_MAX_FD(max_fd, 0);
872
873
874 if (sec != NULL) {
875 zval tmp;
876
877 if (Z_TYPE_P(sec) != IS_LONG) {
878 tmp = *sec;
879 zval_copy_ctor(&tmp);
880 convert_to_long(&tmp);
881 sec = &tmp;
882 }
883
884
885 if (usec > 999999) {
886 tv.tv_sec = Z_LVAL_P(sec) + (usec / 1000000);
887 tv.tv_usec = usec % 1000000;
888 } else {
889 tv.tv_sec = Z_LVAL_P(sec);
890 tv.tv_usec = usec;
891 }
892
893 tv_p = &tv;
894
895 if (sec == &tmp) {
896 zval_dtor(&tmp);
897 }
898 }
899
900 retval = select(max_fd+1, &rfds, &wfds, &efds, tv_p);
901
902 if (retval == -1) {
903 SOCKETS_G(last_error) = errno;
904 php_error_docref(NULL, E_WARNING, "unable to select [%d]: %s", errno, sockets_strerror(errno));
905 RETURN_FALSE;
906 }
907
908 if (r_array != NULL) php_sock_array_from_fd_set(r_array, &rfds);
909 if (w_array != NULL) php_sock_array_from_fd_set(w_array, &wfds);
910 if (e_array != NULL) php_sock_array_from_fd_set(e_array, &efds);
911
912 RETURN_LONG(retval);
913 }
914
915
916
917
918 PHP_FUNCTION(socket_create_listen)
919 {
920 php_socket *php_sock;
921 zend_long port, backlog = 128;
922
923 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &port, &backlog) == FAILURE) {
924 return;
925 }
926
927 if (!php_open_listen_sock(&php_sock, port, backlog)) {
928 RETURN_FALSE;
929 }
930
931 php_sock->error = 0;
932 php_sock->blocking = 1;
933
934 RETURN_RES(zend_register_resource(php_sock, le_socket));
935 }
936
937
938
939
940 PHP_FUNCTION(socket_accept)
941 {
942 zval *arg1;
943 php_socket *php_sock, *new_sock;
944 php_sockaddr_storage sa;
945 socklen_t php_sa_len = sizeof(sa);
946
947 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg1) == FAILURE) {
948 return;
949 }
950
951 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
952 RETURN_FALSE;
953 }
954
955 if (!php_accept_connect(php_sock, &new_sock, (struct sockaddr*)&sa, &php_sa_len)) {
956 RETURN_FALSE;
957 }
958
959 RETURN_RES(zend_register_resource(new_sock, le_socket));
960 }
961
962
963
964
965 PHP_FUNCTION(socket_set_nonblock)
966 {
967 zval *arg1;
968 php_socket *php_sock;
969
970 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg1) == FAILURE) {
971 return;
972 }
973
974 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
975 RETURN_FALSE;
976 }
977
978 if (!Z_ISUNDEF(php_sock->zstream)) {
979 php_stream *stream;
980
981 stream = zend_fetch_resource2_ex(&php_sock->zstream, NULL, php_file_le_stream(), php_file_le_pstream());
982 if (stream != NULL) {
983 if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, 0,
984 NULL) != -1) {
985 php_sock->blocking = 0;
986 RETURN_TRUE;
987 }
988 }
989 }
990
991 if (php_set_sock_blocking(php_sock->bsd_socket, 0) == SUCCESS) {
992 php_sock->blocking = 0;
993 RETURN_TRUE;
994 } else {
995 PHP_SOCKET_ERROR(php_sock, "unable to set nonblocking mode", errno);
996 RETURN_FALSE;
997 }
998 }
999
1000
1001
1002
1003 PHP_FUNCTION(socket_set_block)
1004 {
1005 zval *arg1;
1006 php_socket *php_sock;
1007
1008 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg1) == FAILURE) {
1009 return;
1010 }
1011
1012 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1013 RETURN_FALSE;
1014 }
1015
1016
1017
1018
1019 if (!Z_ISUNDEF(php_sock->zstream)) {
1020 php_stream *stream;
1021 stream = zend_fetch_resource2_ex(&php_sock->zstream, NULL, php_file_le_stream(), php_file_le_pstream());
1022 if (stream != NULL) {
1023 if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, 1,
1024 NULL) != -1) {
1025 php_sock->blocking = 1;
1026 RETURN_TRUE;
1027 }
1028 }
1029 }
1030
1031 if (php_set_sock_blocking(php_sock->bsd_socket, 1) == SUCCESS) {
1032 php_sock->blocking = 1;
1033 RETURN_TRUE;
1034 } else {
1035 PHP_SOCKET_ERROR(php_sock, "unable to set blocking mode", errno);
1036 RETURN_FALSE;
1037 }
1038 }
1039
1040
1041
1042
1043 PHP_FUNCTION(socket_listen)
1044 {
1045 zval *arg1;
1046 php_socket *php_sock;
1047 zend_long backlog = 0;
1048
1049 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &arg1, &backlog) == FAILURE) {
1050 return;
1051 }
1052
1053 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1054 RETURN_FALSE;
1055 }
1056
1057 if (listen(php_sock->bsd_socket, backlog) != 0) {
1058 PHP_SOCKET_ERROR(php_sock, "unable to listen on socket", errno);
1059 RETURN_FALSE;
1060 }
1061 RETURN_TRUE;
1062 }
1063
1064
1065
1066
1067 PHP_FUNCTION(socket_close)
1068 {
1069 zval *arg1;
1070 php_socket *php_sock;
1071
1072 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg1) == FAILURE) {
1073 return;
1074 }
1075
1076 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1077 RETURN_FALSE;
1078 }
1079
1080 if (!Z_ISUNDEF(php_sock->zstream)) {
1081 php_stream *stream = NULL;
1082 php_stream_from_zval_no_verify(stream, &php_sock->zstream);
1083 if (stream != NULL) {
1084
1085
1086 php_stream_free(stream,
1087 PHP_STREAM_FREE_KEEP_RSRC | PHP_STREAM_FREE_CLOSE |
1088 (stream->is_persistent?PHP_STREAM_FREE_CLOSE_PERSISTENT:0));
1089 }
1090 }
1091 zend_list_close(Z_RES_P(arg1));
1092 }
1093
1094
1095
1096
1097 PHP_FUNCTION(socket_write)
1098 {
1099 zval *arg1;
1100 php_socket *php_sock;
1101 int retval;
1102 size_t str_len;
1103 zend_long length = 0;
1104 char *str;
1105
1106 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &arg1, &str, &str_len, &length) == FAILURE) {
1107 return;
1108 }
1109
1110 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1111 RETURN_FALSE;
1112 }
1113
1114 if (ZEND_NUM_ARGS() < 3) {
1115 length = str_len;
1116 }
1117
1118 #ifndef PHP_WIN32
1119 retval = write(php_sock->bsd_socket, str, MIN(length, str_len));
1120 #else
1121 retval = send(php_sock->bsd_socket, str, min(length, str_len), 0);
1122 #endif
1123
1124 if (retval < 0) {
1125 PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno);
1126 RETURN_FALSE;
1127 }
1128
1129 RETURN_LONG(retval);
1130 }
1131
1132
1133
1134
1135 PHP_FUNCTION(socket_read)
1136 {
1137 zval *arg1;
1138 php_socket *php_sock;
1139 zend_string *tmpbuf;
1140 int retval;
1141 zend_long length, type = PHP_BINARY_READ;
1142
1143 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|l", &arg1, &length, &type) == FAILURE) {
1144 return;
1145 }
1146
1147
1148 if ((length + 1) < 2) {
1149 RETURN_FALSE;
1150 }
1151
1152 tmpbuf = zend_string_alloc(length, 0);
1153
1154 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1155 RETURN_FALSE;
1156 }
1157
1158 if (type == PHP_NORMAL_READ) {
1159 retval = php_read(php_sock, ZSTR_VAL(tmpbuf), length, 0);
1160 } else {
1161 retval = recv(php_sock->bsd_socket, ZSTR_VAL(tmpbuf), length, 0);
1162 }
1163
1164 if (retval == -1) {
1165
1166
1167 if (errno == EAGAIN
1168 #ifdef EWOULDBLOCK
1169 || errno == EWOULDBLOCK
1170 #endif
1171 ) {
1172 php_sock->error = errno;
1173 SOCKETS_G(last_error) = errno;
1174 } else {
1175 PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno);
1176 }
1177
1178 zend_string_free(tmpbuf);
1179 RETURN_FALSE;
1180 } else if (!retval) {
1181 zend_string_free(tmpbuf);
1182 RETURN_EMPTY_STRING();
1183 }
1184
1185 tmpbuf = zend_string_truncate(tmpbuf, retval, 0);
1186 ZSTR_LEN(tmpbuf) = retval;
1187 ZSTR_VAL(tmpbuf)[ZSTR_LEN(tmpbuf)] = '\0' ;
1188
1189 RETURN_NEW_STR(tmpbuf);
1190 }
1191
1192
1193
1194
1195 PHP_FUNCTION(socket_getsockname)
1196 {
1197 zval *arg1, *addr, *port = NULL;
1198 php_sockaddr_storage sa_storage;
1199 php_socket *php_sock;
1200 struct sockaddr *sa;
1201 struct sockaddr_in *sin;
1202 #if HAVE_IPV6
1203 struct sockaddr_in6 *sin6;
1204 char addr6[INET6_ADDRSTRLEN+1];
1205 #endif
1206 struct sockaddr_un *s_un;
1207 char *addr_string;
1208 socklen_t salen = sizeof(php_sockaddr_storage);
1209
1210 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/|z/", &arg1, &addr, &port) == FAILURE) {
1211 return;
1212 }
1213
1214 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1215 RETURN_FALSE;
1216 }
1217
1218 sa = (struct sockaddr *) &sa_storage;
1219
1220 if (getsockname(php_sock->bsd_socket, sa, &salen) != 0) {
1221 PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket name", errno);
1222 RETURN_FALSE;
1223 }
1224
1225 if (port != NULL) {
1226 ZVAL_DEREF(port);
1227 }
1228
1229 switch (sa->sa_family) {
1230 #if HAVE_IPV6
1231 case AF_INET6:
1232 sin6 = (struct sockaddr_in6 *) sa;
1233 inet_ntop(AF_INET6, &sin6->sin6_addr, addr6, INET6_ADDRSTRLEN);
1234 zval_dtor(addr);
1235 ZVAL_STRING(addr, addr6);
1236
1237 if (port != NULL) {
1238 zval_dtor(port);
1239 ZVAL_LONG(port, htons(sin6->sin6_port));
1240 }
1241 RETURN_TRUE;
1242 break;
1243 #endif
1244 case AF_INET:
1245 sin = (struct sockaddr_in *) sa;
1246 while (inet_ntoa_lock == 1);
1247 inet_ntoa_lock = 1;
1248 addr_string = inet_ntoa(sin->sin_addr);
1249 inet_ntoa_lock = 0;
1250
1251 zval_dtor(addr);
1252 ZVAL_STRING(addr, addr_string);
1253
1254 if (port != NULL) {
1255 zval_dtor(port);
1256 ZVAL_LONG(port, htons(sin->sin_port));
1257 }
1258 RETURN_TRUE;
1259 break;
1260
1261 case AF_UNIX:
1262 s_un = (struct sockaddr_un *) sa;
1263
1264 zval_dtor(addr);
1265 ZVAL_STRING(addr, s_un->sun_path);
1266 RETURN_TRUE;
1267 break;
1268
1269 default:
1270 php_error_docref(NULL, E_WARNING, "Unsupported address family %d", sa->sa_family);
1271 RETURN_FALSE;
1272 }
1273 }
1274
1275
1276
1277
1278 PHP_FUNCTION(socket_getpeername)
1279 {
1280 zval *arg1, *arg2, *arg3 = NULL;
1281 php_sockaddr_storage sa_storage;
1282 php_socket *php_sock;
1283 struct sockaddr *sa;
1284 struct sockaddr_in *sin;
1285 #if HAVE_IPV6
1286 struct sockaddr_in6 *sin6;
1287 char addr6[INET6_ADDRSTRLEN+1];
1288 #endif
1289 struct sockaddr_un *s_un;
1290 char *addr_string;
1291 socklen_t salen = sizeof(php_sockaddr_storage);
1292
1293 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/|z/", &arg1, &arg2, &arg3) == FAILURE) {
1294 return;
1295 }
1296
1297 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1298 RETURN_FALSE;
1299 }
1300
1301 sa = (struct sockaddr *) &sa_storage;
1302
1303 if (getpeername(php_sock->bsd_socket, sa, &salen) < 0) {
1304 PHP_SOCKET_ERROR(php_sock, "unable to retrieve peer name", errno);
1305 RETURN_FALSE;
1306 }
1307
1308 switch (sa->sa_family) {
1309 #if HAVE_IPV6
1310 case AF_INET6:
1311 sin6 = (struct sockaddr_in6 *) sa;
1312 inet_ntop(AF_INET6, &sin6->sin6_addr, addr6, INET6_ADDRSTRLEN);
1313 zval_dtor(arg2);
1314 ZVAL_STRING(arg2, addr6);
1315
1316 if (arg3 != NULL) {
1317 zval_dtor(arg3);
1318 ZVAL_LONG(arg3, htons(sin6->sin6_port));
1319 }
1320
1321 RETURN_TRUE;
1322 break;
1323 #endif
1324 case AF_INET:
1325 sin = (struct sockaddr_in *) sa;
1326 while (inet_ntoa_lock == 1);
1327 inet_ntoa_lock = 1;
1328 addr_string = inet_ntoa(sin->sin_addr);
1329 inet_ntoa_lock = 0;
1330
1331 zval_dtor(arg2);
1332 ZVAL_STRING(arg2, addr_string);
1333
1334 if (arg3 != NULL) {
1335 zval_dtor(arg3);
1336 ZVAL_LONG(arg3, htons(sin->sin_port));
1337 }
1338
1339 RETURN_TRUE;
1340 break;
1341
1342 case AF_UNIX:
1343 s_un = (struct sockaddr_un *) sa;
1344
1345 zval_dtor(arg2);
1346 ZVAL_STRING(arg2, s_un->sun_path);
1347 RETURN_TRUE;
1348 break;
1349
1350 default:
1351 php_error_docref(NULL, E_WARNING, "Unsupported address family %d", sa->sa_family);
1352 RETURN_FALSE;
1353 }
1354 }
1355
1356
1357
1358
1359 PHP_FUNCTION(socket_create)
1360 {
1361 zend_long arg1, arg2, arg3;
1362 php_socket *php_sock = php_create_socket();
1363
1364 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lll", &arg1, &arg2, &arg3) == FAILURE) {
1365 efree(php_sock);
1366 return;
1367 }
1368
1369 if (arg1 != AF_UNIX
1370 #if HAVE_IPV6
1371 && arg1 != AF_INET6
1372 #endif
1373 && arg1 != AF_INET) {
1374 php_error_docref(NULL, E_WARNING, "invalid socket domain [%pd] specified for argument 1, assuming AF_INET", arg1);
1375 arg1 = AF_INET;
1376 }
1377
1378 if (arg2 > 10) {
1379 php_error_docref(NULL, E_WARNING, "invalid socket type [%pd] specified for argument 2, assuming SOCK_STREAM", arg2);
1380 arg2 = SOCK_STREAM;
1381 }
1382
1383 php_sock->bsd_socket = socket(arg1, arg2, arg3);
1384 php_sock->type = arg1;
1385
1386 if (IS_INVALID_SOCKET(php_sock)) {
1387 SOCKETS_G(last_error) = errno;
1388 php_error_docref(NULL, E_WARNING, "Unable to create socket [%d]: %s", errno, sockets_strerror(errno));
1389 efree(php_sock);
1390 RETURN_FALSE;
1391 }
1392
1393 php_sock->error = 0;
1394 php_sock->blocking = 1;
1395
1396 RETURN_RES(zend_register_resource(php_sock, le_socket));
1397 }
1398
1399
1400
1401
1402 PHP_FUNCTION(socket_connect)
1403 {
1404 zval *arg1;
1405 php_socket *php_sock;
1406 char *addr;
1407 int retval;
1408 size_t addr_len;
1409 zend_long port = 0;
1410 int argc = ZEND_NUM_ARGS();
1411
1412 if (zend_parse_parameters(argc, "rs|l", &arg1, &addr, &addr_len, &port) == FAILURE) {
1413 return;
1414 }
1415
1416 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1417 RETURN_FALSE;
1418 }
1419
1420 switch(php_sock->type) {
1421 #if HAVE_IPV6
1422 case AF_INET6: {
1423 struct sockaddr_in6 sin6 = {0};
1424
1425 if (argc != 3) {
1426 php_error_docref(NULL, E_WARNING, "Socket of type AF_INET6 requires 3 arguments");
1427 RETURN_FALSE;
1428 }
1429
1430 memset(&sin6, 0, sizeof(struct sockaddr_in6));
1431
1432 sin6.sin6_family = AF_INET6;
1433 sin6.sin6_port = htons((unsigned short int)port);
1434
1435 if (! php_set_inet6_addr(&sin6, addr, php_sock)) {
1436 RETURN_FALSE;
1437 }
1438
1439 retval = connect(php_sock->bsd_socket, (struct sockaddr *)&sin6, sizeof(struct sockaddr_in6));
1440 break;
1441 }
1442 #endif
1443 case AF_INET: {
1444 struct sockaddr_in sin = {0};
1445
1446 if (argc != 3) {
1447 php_error_docref(NULL, E_WARNING, "Socket of type AF_INET requires 3 arguments");
1448 RETURN_FALSE;
1449 }
1450
1451 sin.sin_family = AF_INET;
1452 sin.sin_port = htons((unsigned short int)port);
1453
1454 if (! php_set_inet_addr(&sin, addr, php_sock)) {
1455 RETURN_FALSE;
1456 }
1457
1458 retval = connect(php_sock->bsd_socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
1459 break;
1460 }
1461
1462 case AF_UNIX: {
1463 struct sockaddr_un s_un = {0};
1464
1465 if (addr_len >= sizeof(s_un.sun_path)) {
1466 php_error_docref(NULL, E_WARNING, "Path too long");
1467 RETURN_FALSE;
1468 }
1469
1470 s_un.sun_family = AF_UNIX;
1471 memcpy(&s_un.sun_path, addr, addr_len);
1472 retval = connect(php_sock->bsd_socket, (struct sockaddr *) &s_un,
1473 (socklen_t)(XtOffsetOf(struct sockaddr_un, sun_path) + addr_len));
1474 break;
1475 }
1476
1477 default:
1478 php_error_docref(NULL, E_WARNING, "Unsupported socket type %d", php_sock->type);
1479 RETURN_FALSE;
1480 }
1481
1482 if (retval != 0) {
1483 PHP_SOCKET_ERROR(php_sock, "unable to connect", errno);
1484 RETURN_FALSE;
1485 }
1486
1487 RETURN_TRUE;
1488 }
1489
1490
1491
1492
1493 PHP_FUNCTION(socket_strerror)
1494 {
1495 zend_long arg1;
1496
1497 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &arg1) == FAILURE) {
1498 return;
1499 }
1500
1501 RETURN_STRING(sockets_strerror(arg1));
1502 }
1503
1504
1505
1506
1507 PHP_FUNCTION(socket_bind)
1508 {
1509 zval *arg1;
1510 php_sockaddr_storage sa_storage = {0};
1511 struct sockaddr *sock_type = (struct sockaddr*) &sa_storage;
1512 php_socket *php_sock;
1513 char *addr;
1514 size_t addr_len;
1515 zend_long port = 0;
1516 zend_long retval = 0;
1517
1518 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &arg1, &addr, &addr_len, &port) == FAILURE) {
1519 return;
1520 }
1521
1522 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1523 RETURN_FALSE;
1524 }
1525
1526 switch(php_sock->type) {
1527 case AF_UNIX:
1528 {
1529 struct sockaddr_un *sa = (struct sockaddr_un *) sock_type;
1530
1531 sa->sun_family = AF_UNIX;
1532
1533 if (addr_len >= sizeof(sa->sun_path)) {
1534 php_error_docref(NULL, E_WARNING,
1535 "Invalid path: too long (maximum size is %d)",
1536 (int)sizeof(sa->sun_path) - 1);
1537 RETURN_FALSE;
1538 }
1539 memcpy(&sa->sun_path, addr, addr_len);
1540
1541 retval = bind(php_sock->bsd_socket, (struct sockaddr *) sa,
1542 offsetof(struct sockaddr_un, sun_path) + addr_len);
1543 break;
1544 }
1545
1546 case AF_INET:
1547 {
1548 struct sockaddr_in *sa = (struct sockaddr_in *) sock_type;
1549
1550 sa->sin_family = AF_INET;
1551 sa->sin_port = htons((unsigned short) port);
1552
1553 if (! php_set_inet_addr(sa, addr, php_sock)) {
1554 RETURN_FALSE;
1555 }
1556
1557 retval = bind(php_sock->bsd_socket, (struct sockaddr *)sa, sizeof(struct sockaddr_in));
1558 break;
1559 }
1560 #if HAVE_IPV6
1561 case AF_INET6:
1562 {
1563 struct sockaddr_in6 *sa = (struct sockaddr_in6 *) sock_type;
1564
1565 sa->sin6_family = AF_INET6;
1566 sa->sin6_port = htons((unsigned short) port);
1567
1568 if (! php_set_inet6_addr(sa, addr, php_sock)) {
1569 RETURN_FALSE;
1570 }
1571
1572 retval = bind(php_sock->bsd_socket, (struct sockaddr *)sa, sizeof(struct sockaddr_in6));
1573 break;
1574 }
1575 #endif
1576 default:
1577 php_error_docref(NULL, E_WARNING, "unsupported socket type '%d', must be AF_UNIX, AF_INET, or AF_INET6", php_sock->type);
1578 RETURN_FALSE;
1579 }
1580
1581 if (retval != 0) {
1582 PHP_SOCKET_ERROR(php_sock, "unable to bind address", errno);
1583 RETURN_FALSE;
1584 }
1585
1586 RETURN_TRUE;
1587 }
1588
1589
1590
1591
1592 PHP_FUNCTION(socket_recv)
1593 {
1594 zval *php_sock_res, *buf;
1595 zend_string *recv_buf;
1596 php_socket *php_sock;
1597 int retval;
1598 zend_long len, flags;
1599
1600 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/ll", &php_sock_res, &buf, &len, &flags) == FAILURE) {
1601 return;
1602 }
1603
1604 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(php_sock_res), le_socket_name, le_socket)) == NULL) {
1605 RETURN_FALSE;
1606 }
1607
1608
1609 if ((len + 1) < 2) {
1610 RETURN_FALSE;
1611 }
1612
1613 recv_buf = zend_string_alloc(len, 0);
1614
1615 if ((retval = recv(php_sock->bsd_socket, ZSTR_VAL(recv_buf), len, flags)) < 1) {
1616 efree(recv_buf);
1617
1618 zval_dtor(buf);
1619 ZVAL_NULL(buf);
1620 } else {
1621 ZSTR_LEN(recv_buf) = retval;
1622 ZSTR_VAL(recv_buf)[ZSTR_LEN(recv_buf)] = '\0';
1623
1624
1625 zval_dtor(buf);
1626 ZVAL_NEW_STR(buf, recv_buf);
1627 }
1628
1629 if (retval == -1) {
1630 PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno);
1631 RETURN_FALSE;
1632 }
1633
1634 RETURN_LONG(retval);
1635 }
1636
1637
1638
1639
1640 PHP_FUNCTION(socket_send)
1641 {
1642 zval *arg1;
1643 php_socket *php_sock;
1644 size_t buf_len, retval;
1645 zend_long len, flags;
1646 char *buf;
1647
1648 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsll", &arg1, &buf, &buf_len, &len, &flags) == FAILURE) {
1649 return;
1650 }
1651
1652 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1653 RETURN_FALSE;
1654 }
1655
1656 retval = send(php_sock->bsd_socket, buf, (buf_len < len ? buf_len : len), flags);
1657
1658 if (retval == -1) {
1659 PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno);
1660 RETURN_FALSE;
1661 }
1662
1663 RETURN_LONG(retval);
1664 }
1665
1666
1667
1668
1669 PHP_FUNCTION(socket_recvfrom)
1670 {
1671 zval *arg1, *arg2, *arg5, *arg6 = NULL;
1672 php_socket *php_sock;
1673 struct sockaddr_un s_un;
1674 struct sockaddr_in sin;
1675 #if HAVE_IPV6
1676 struct sockaddr_in6 sin6;
1677 char addr6[INET6_ADDRSTRLEN];
1678 #endif
1679 socklen_t slen;
1680 int retval;
1681 zend_long arg3, arg4;
1682 char *address;
1683 zend_string *recv_buf;
1684
1685 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/llz/|z/", &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) {
1686 return;
1687 }
1688
1689 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1690 RETURN_FALSE;
1691 }
1692
1693
1694 if ((arg3 + 2) < 3) {
1695 RETURN_FALSE;
1696 }
1697
1698 recv_buf = zend_string_alloc(arg3 + 1, 0);
1699
1700 switch (php_sock->type) {
1701 case AF_UNIX:
1702 slen = sizeof(s_un);
1703 s_un.sun_family = AF_UNIX;
1704 retval = recvfrom(php_sock->bsd_socket, ZSTR_VAL(recv_buf), arg3, arg4, (struct sockaddr *)&s_un, (socklen_t *)&slen);
1705
1706 if (retval < 0) {
1707 PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno);
1708 zend_string_free(recv_buf);
1709 RETURN_FALSE;
1710 }
1711 ZSTR_LEN(recv_buf) = retval;
1712 ZSTR_VAL(recv_buf)[ZSTR_LEN(recv_buf)] = '\0';
1713
1714 zval_dtor(arg2);
1715 zval_dtor(arg5);
1716
1717 ZVAL_NEW_STR(arg2, recv_buf);
1718 ZVAL_STRING(arg5, s_un.sun_path);
1719 break;
1720
1721 case AF_INET:
1722 slen = sizeof(sin);
1723 memset(&sin, 0, slen);
1724 sin.sin_family = AF_INET;
1725
1726 if (arg6 == NULL) {
1727 zend_string_free(recv_buf);
1728 WRONG_PARAM_COUNT;
1729 }
1730
1731 retval = recvfrom(php_sock->bsd_socket, ZSTR_VAL(recv_buf), arg3, arg4, (struct sockaddr *)&sin, (socklen_t *)&slen);
1732
1733 if (retval < 0) {
1734 PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno);
1735 zend_string_free(recv_buf);
1736 RETURN_FALSE;
1737 }
1738 ZSTR_LEN(recv_buf) = retval;
1739 ZSTR_VAL(recv_buf)[ZSTR_LEN(recv_buf)] = '\0';
1740
1741 zval_dtor(arg2);
1742 zval_dtor(arg5);
1743 zval_dtor(arg6);
1744
1745 address = inet_ntoa(sin.sin_addr);
1746
1747 ZVAL_NEW_STR(arg2, recv_buf);
1748 ZVAL_STRING(arg5, address ? address : "0.0.0.0");
1749 ZVAL_LONG(arg6, ntohs(sin.sin_port));
1750 break;
1751 #if HAVE_IPV6
1752 case AF_INET6:
1753 slen = sizeof(sin6);
1754 memset(&sin6, 0, slen);
1755 sin6.sin6_family = AF_INET6;
1756
1757 if (arg6 == NULL) {
1758 efree(recv_buf);
1759 WRONG_PARAM_COUNT;
1760 }
1761
1762 retval = recvfrom(php_sock->bsd_socket, ZSTR_VAL(recv_buf), arg3, arg4, (struct sockaddr *)&sin6, (socklen_t *)&slen);
1763
1764 if (retval < 0) {
1765 PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno);
1766 zend_string_free(recv_buf);
1767 RETURN_FALSE;
1768 }
1769 ZSTR_LEN(recv_buf) = retval;
1770 ZSTR_VAL(recv_buf)[ZSTR_LEN(recv_buf)] = '\0';
1771
1772 zval_dtor(arg2);
1773 zval_dtor(arg5);
1774 zval_dtor(arg6);
1775
1776 memset(addr6, 0, INET6_ADDRSTRLEN);
1777 inet_ntop(AF_INET6, &sin6.sin6_addr, addr6, INET6_ADDRSTRLEN);
1778
1779 ZVAL_NEW_STR(arg2, recv_buf);
1780 ZVAL_STRING(arg5, addr6[0] ? addr6 : "::");
1781 ZVAL_LONG(arg6, ntohs(sin6.sin6_port));
1782 break;
1783 #endif
1784 default:
1785 php_error_docref(NULL, E_WARNING, "Unsupported socket type %d", php_sock->type);
1786 RETURN_FALSE;
1787 }
1788
1789 RETURN_LONG(retval);
1790 }
1791
1792
1793
1794
1795 PHP_FUNCTION(socket_sendto)
1796 {
1797 zval *arg1;
1798 php_socket *php_sock;
1799 struct sockaddr_un s_un;
1800 struct sockaddr_in sin;
1801 #if HAVE_IPV6
1802 struct sockaddr_in6 sin6;
1803 #endif
1804 int retval;
1805 size_t buf_len, addr_len;
1806 zend_long len, flags, port = 0;
1807 char *buf, *addr;
1808 int argc = ZEND_NUM_ARGS();
1809
1810 if (zend_parse_parameters(argc, "rslls|l", &arg1, &buf, &buf_len, &len, &flags, &addr, &addr_len, &port) == FAILURE) {
1811 return;
1812 }
1813
1814 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1815 RETURN_FALSE;
1816 }
1817
1818 switch (php_sock->type) {
1819 case AF_UNIX:
1820 memset(&s_un, 0, sizeof(s_un));
1821 s_un.sun_family = AF_UNIX;
1822 snprintf(s_un.sun_path, 108, "%s", addr);
1823
1824 retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &s_un, SUN_LEN(&s_un));
1825 break;
1826
1827 case AF_INET:
1828 if (argc != 6) {
1829 WRONG_PARAM_COUNT;
1830 }
1831
1832 memset(&sin, 0, sizeof(sin));
1833 sin.sin_family = AF_INET;
1834 sin.sin_port = htons((unsigned short) port);
1835
1836 if (! php_set_inet_addr(&sin, addr, php_sock)) {
1837 RETURN_FALSE;
1838 }
1839
1840 retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &sin, sizeof(sin));
1841 break;
1842 #if HAVE_IPV6
1843 case AF_INET6:
1844 if (argc != 6) {
1845 WRONG_PARAM_COUNT;
1846 }
1847
1848 memset(&sin6, 0, sizeof(sin6));
1849 sin6.sin6_family = AF_INET6;
1850 sin6.sin6_port = htons((unsigned short) port);
1851
1852 if (! php_set_inet6_addr(&sin6, addr, php_sock)) {
1853 RETURN_FALSE;
1854 }
1855
1856 retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &sin6, sizeof(sin6));
1857 break;
1858 #endif
1859 default:
1860 php_error_docref(NULL, E_WARNING, "Unsupported socket type %d", php_sock->type);
1861 RETURN_FALSE;
1862 }
1863
1864 if (retval == -1) {
1865 PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno);
1866 RETURN_FALSE;
1867 }
1868
1869 RETURN_LONG(retval);
1870 }
1871
1872
1873
1874
1875 PHP_FUNCTION(socket_get_option)
1876 {
1877 zval *arg1;
1878 struct linger linger_val;
1879 struct timeval tv;
1880 #ifdef PHP_WIN32
1881 int timeout = 0;
1882 #endif
1883 socklen_t optlen;
1884 php_socket *php_sock;
1885 int other_val;
1886 zend_long level, optname;
1887
1888 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rll", &arg1, &level, &optname) == FAILURE) {
1889 return;
1890 }
1891
1892 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
1893 RETURN_FALSE;
1894 }
1895
1896 if (level == IPPROTO_IP) {
1897 switch (optname) {
1898 case IP_MULTICAST_IF: {
1899 struct in_addr if_addr;
1900 unsigned int if_index;
1901 optlen = sizeof(if_addr);
1902 if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&if_addr, &optlen) != 0) {
1903 PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
1904 RETURN_FALSE;
1905 }
1906 if (php_add4_to_if_index(&if_addr, php_sock, &if_index) == SUCCESS) {
1907 RETURN_LONG((zend_long) if_index);
1908 } else {
1909 RETURN_FALSE;
1910 }
1911 }
1912 }
1913 }
1914 #if HAVE_IPV6
1915 else if (level == IPPROTO_IPV6) {
1916 int ret = php_do_getsockopt_ipv6_rfc3542(php_sock, level, optname, return_value);
1917 if (ret == SUCCESS) {
1918 return;
1919 } else if (ret == FAILURE) {
1920 RETURN_FALSE;
1921 }
1922 }
1923 #endif
1924
1925
1926 switch(optname) {
1927 case SO_LINGER:
1928 optlen = sizeof(linger_val);
1929
1930 if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&linger_val, &optlen) != 0) {
1931 PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
1932 RETURN_FALSE;
1933 }
1934
1935 array_init(return_value);
1936 add_assoc_long(return_value, "l_onoff", linger_val.l_onoff);
1937 add_assoc_long(return_value, "l_linger", linger_val.l_linger);
1938 break;
1939
1940 case SO_RCVTIMEO:
1941 case SO_SNDTIMEO:
1942 #ifndef PHP_WIN32
1943 optlen = sizeof(tv);
1944
1945 if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&tv, &optlen) != 0) {
1946 PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
1947 RETURN_FALSE;
1948 }
1949 #else
1950 optlen = sizeof(int);
1951
1952 if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&timeout, &optlen) != 0) {
1953 PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
1954 RETURN_FALSE;
1955 }
1956
1957 tv.tv_sec = timeout ? timeout / 1000 : 0;
1958 tv.tv_usec = timeout ? (timeout * 1000) % 1000000 : 0;
1959 #endif
1960
1961 array_init(return_value);
1962
1963 add_assoc_long(return_value, "sec", tv.tv_sec);
1964 add_assoc_long(return_value, "usec", tv.tv_usec);
1965 break;
1966
1967 default:
1968 optlen = sizeof(other_val);
1969
1970 if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&other_val, &optlen) != 0) {
1971 PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
1972 RETURN_FALSE;
1973 }
1974 if (optlen == 1)
1975 other_val = *((unsigned char *)&other_val);
1976
1977 RETURN_LONG(other_val);
1978 break;
1979 }
1980 }
1981
1982
1983
1984
1985 PHP_FUNCTION(socket_set_option)
1986 {
1987 zval *arg1, *arg4;
1988 struct linger lv;
1989 php_socket *php_sock;
1990 int ov, optlen, retval;
1991 #ifdef PHP_WIN32
1992 int timeout;
1993 #else
1994 struct timeval tv;
1995 #endif
1996 zend_long level, optname;
1997 void *opt_ptr;
1998 HashTable *opt_ht;
1999 zval *l_onoff, *l_linger;
2000 zval *sec, *usec;
2001
2002
2003 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllz", &arg1, &level, &optname, &arg4) == FAILURE) {
2004 return;
2005 }
2006
2007 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
2008 RETURN_FALSE;
2009 }
2010
2011 set_errno(0);
2012
2013 #define HANDLE_SUBCALL(res) \
2014 do { \
2015 if (res == 1) { goto default_case; } \
2016 else if (res == SUCCESS) { RETURN_TRUE; } \
2017 else { RETURN_FALSE; } \
2018 } while (0)
2019
2020
2021 if (level == IPPROTO_IP) {
2022 int res = php_do_setsockopt_ip_mcast(php_sock, level, optname, arg4);
2023 HANDLE_SUBCALL(res);
2024 }
2025
2026 #if HAVE_IPV6
2027 else if (level == IPPROTO_IPV6) {
2028 int res = php_do_setsockopt_ipv6_mcast(php_sock, level, optname, arg4);
2029 if (res == 1) {
2030 res = php_do_setsockopt_ipv6_rfc3542(php_sock, level, optname, arg4);
2031 }
2032 HANDLE_SUBCALL(res);
2033 }
2034 #endif
2035
2036 switch (optname) {
2037 case SO_LINGER: {
2038 const char l_onoff_key[] = "l_onoff";
2039 const char l_linger_key[] = "l_linger";
2040
2041 convert_to_array_ex(arg4);
2042 opt_ht = Z_ARRVAL_P(arg4);
2043
2044 if ((l_onoff = zend_hash_str_find(opt_ht, l_onoff_key, sizeof(l_onoff_key) - 1)) == NULL) {
2045 php_error_docref(NULL, E_WARNING, "no key \"%s\" passed in optval", l_onoff_key);
2046 RETURN_FALSE;
2047 }
2048 if ((l_linger = zend_hash_str_find(opt_ht, l_linger_key, sizeof(l_linger_key) - 1)) == NULL) {
2049 php_error_docref(NULL, E_WARNING, "no key \"%s\" passed in optval", l_linger_key);
2050 RETURN_FALSE;
2051 }
2052
2053 convert_to_long_ex(l_onoff);
2054 convert_to_long_ex(l_linger);
2055
2056 lv.l_onoff = (unsigned short)Z_LVAL_P(l_onoff);
2057 lv.l_linger = (unsigned short)Z_LVAL_P(l_linger);
2058
2059 optlen = sizeof(lv);
2060 opt_ptr = &lv;
2061 break;
2062 }
2063
2064 case SO_RCVTIMEO:
2065 case SO_SNDTIMEO: {
2066 const char sec_key[] = "sec";
2067 const char usec_key[] = "usec";
2068
2069 convert_to_array_ex(arg4);
2070 opt_ht = Z_ARRVAL_P(arg4);
2071
2072 if ((sec = zend_hash_str_find(opt_ht, sec_key, sizeof(sec_key) - 1)) == NULL) {
2073 php_error_docref(NULL, E_WARNING, "no key \"%s\" passed in optval", sec_key);
2074 RETURN_FALSE;
2075 }
2076 if ((usec = zend_hash_str_find(opt_ht, usec_key, sizeof(usec_key) - 1)) == NULL) {
2077 php_error_docref(NULL, E_WARNING, "no key \"%s\" passed in optval", usec_key);
2078 RETURN_FALSE;
2079 }
2080
2081 convert_to_long_ex(sec);
2082 convert_to_long_ex(usec);
2083 #ifndef PHP_WIN32
2084 tv.tv_sec = Z_LVAL_P(sec);
2085 tv.tv_usec = Z_LVAL_P(usec);
2086 optlen = sizeof(tv);
2087 opt_ptr = &tv;
2088 #else
2089 timeout = Z_LVAL_P(sec) * 1000 + Z_LVAL_P(usec) / 1000;
2090 optlen = sizeof(int);
2091 opt_ptr = &timeout;
2092 #endif
2093 break;
2094 }
2095 #ifdef SO_BINDTODEVICE
2096 case SO_BINDTODEVICE: {
2097 if (Z_TYPE_P(arg4) == IS_STRING) {
2098 opt_ptr = Z_STRVAL_P(arg4);
2099 optlen = Z_STRLEN_P(arg4);
2100 } else {
2101 opt_ptr = "";
2102 optlen = 0;
2103 }
2104 break;
2105 }
2106 #endif
2107
2108 default:
2109 default_case:
2110 convert_to_long_ex(arg4);
2111 ov = Z_LVAL_P(arg4);
2112
2113 optlen = sizeof(ov);
2114 opt_ptr = &ov;
2115 break;
2116 }
2117
2118 retval = setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen);
2119 if (retval != 0) {
2120 PHP_SOCKET_ERROR(php_sock, "unable to set socket option", errno);
2121 RETURN_FALSE;
2122 }
2123
2124 RETURN_TRUE;
2125 }
2126
2127
2128 #ifdef HAVE_SOCKETPAIR
2129
2130
2131 PHP_FUNCTION(socket_create_pair)
2132 {
2133 zval retval[2], *fds_array_zval;
2134 php_socket *php_sock[2];
2135 PHP_SOCKET fds_array[2];
2136 zend_long domain, type, protocol;
2137
2138 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lllz/", &domain, &type, &protocol, &fds_array_zval) == FAILURE) {
2139 return;
2140 }
2141
2142 php_sock[0] = php_create_socket();
2143 php_sock[1] = php_create_socket();
2144
2145 if (domain != AF_INET
2146 #if HAVE_IPV6
2147 && domain != AF_INET6
2148 #endif
2149 && domain != AF_UNIX) {
2150 php_error_docref(NULL, E_WARNING, "invalid socket domain [%pd] specified for argument 1, assuming AF_INET", domain);
2151 domain = AF_INET;
2152 }
2153
2154 if (type > 10) {
2155 php_error_docref(NULL, E_WARNING, "invalid socket type [%pd] specified for argument 2, assuming SOCK_STREAM", type);
2156 type = SOCK_STREAM;
2157 }
2158
2159 if (socketpair(domain, type, protocol, fds_array) != 0) {
2160 SOCKETS_G(last_error) = errno;
2161 php_error_docref(NULL, E_WARNING, "unable to create socket pair [%d]: %s", errno, sockets_strerror(errno));
2162 efree(php_sock[0]);
2163 efree(php_sock[1]);
2164 RETURN_FALSE;
2165 }
2166
2167 zval_dtor(fds_array_zval);
2168 array_init(fds_array_zval);
2169
2170 php_sock[0]->bsd_socket = fds_array[0];
2171 php_sock[1]->bsd_socket = fds_array[1];
2172 php_sock[0]->type = domain;
2173 php_sock[1]->type = domain;
2174 php_sock[0]->error = 0;
2175 php_sock[1]->error = 0;
2176 php_sock[0]->blocking = 1;
2177 php_sock[1]->blocking = 1;
2178
2179 ZVAL_RES(&retval[0], zend_register_resource(php_sock[0], le_socket));
2180 ZVAL_RES(&retval[1], zend_register_resource(php_sock[1], le_socket));
2181
2182 add_index_zval(fds_array_zval, 0, &retval[0]);
2183 add_index_zval(fds_array_zval, 1, &retval[1]);
2184
2185 RETURN_TRUE;
2186 }
2187
2188 #endif
2189
2190 #ifdef HAVE_SHUTDOWN
2191
2192
2193 PHP_FUNCTION(socket_shutdown)
2194 {
2195 zval *arg1;
2196 zend_long how_shutdown = 2;
2197 php_socket *php_sock;
2198
2199 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &arg1, &how_shutdown) == FAILURE) {
2200 return;
2201 }
2202
2203 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
2204 RETURN_FALSE;
2205 }
2206
2207 if (shutdown(php_sock->bsd_socket, how_shutdown) != 0) {
2208 PHP_SOCKET_ERROR(php_sock, "unable to shutdown socket", errno);
2209 RETURN_FALSE;
2210 }
2211
2212 RETURN_TRUE;
2213 }
2214
2215 #endif
2216
2217
2218
2219 PHP_FUNCTION(socket_last_error)
2220 {
2221 zval *arg1 = NULL;
2222 php_socket *php_sock;
2223
2224 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &arg1) == FAILURE) {
2225 return;
2226 }
2227
2228 if (arg1) {
2229 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
2230 RETURN_FALSE;
2231 }
2232 RETVAL_LONG(php_sock->error);
2233 } else {
2234 RETVAL_LONG(SOCKETS_G(last_error));
2235 }
2236 }
2237
2238
2239
2240
2241 PHP_FUNCTION(socket_clear_error)
2242 {
2243 zval *arg1 = NULL;
2244 php_socket *php_sock;
2245
2246 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &arg1) == FAILURE) {
2247 return;
2248 }
2249
2250 if (arg1) {
2251 if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
2252 RETURN_FALSE;
2253 }
2254 php_sock->error = 0;
2255 } else {
2256 SOCKETS_G(last_error) = 0;
2257 }
2258
2259 return;
2260 }
2261
2262
2263 php_socket *socket_import_file_descriptor(PHP_SOCKET socket)
2264 {
2265 #ifdef SO_DOMAIN
2266 int type;
2267 socklen_t type_len = sizeof(type);
2268 #endif
2269 php_socket *retsock;
2270 php_sockaddr_storage addr;
2271 socklen_t addr_len = sizeof(addr);
2272 #ifndef PHP_WIN32
2273 int t;
2274 #endif
2275
2276 retsock = php_create_socket();
2277 retsock->bsd_socket = socket;
2278
2279
2280 #ifdef SO_DOMAIN
2281 if (getsockopt(socket, SOL_SOCKET, SO_DOMAIN, &type, &type_len) == 0) {
2282 retsock->type = type;
2283 } else
2284 #endif
2285 if (getsockname(socket, (struct sockaddr*)&addr, &addr_len) == 0) {
2286 retsock->type = addr.ss_family;
2287 } else {
2288 PHP_SOCKET_ERROR(retsock, "unable to obtain socket family", errno);
2289 goto error;
2290 }
2291
2292
2293 #ifndef PHP_WIN32
2294 t = fcntl(socket, F_GETFL);
2295 if (t == -1) {
2296 PHP_SOCKET_ERROR(retsock, "unable to obtain blocking state", errno);
2297 goto error;
2298 } else {
2299 retsock->blocking = !(t & O_NONBLOCK);
2300 }
2301 #endif
2302
2303 return retsock;
2304
2305 error:
2306 efree(retsock);
2307 return NULL;
2308 }
2309
2310
2311
2312 PHP_FUNCTION(socket_import_stream)
2313 {
2314 zval *zstream;
2315 php_stream *stream;
2316 php_socket *retsock = NULL;
2317 PHP_SOCKET socket;
2318
2319 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zstream) == FAILURE) {
2320 return;
2321 }
2322 php_stream_from_zval(stream, zstream);
2323
2324 if (php_stream_cast(stream, PHP_STREAM_AS_SOCKETD, (void**)&socket, 1)) {
2325
2326 RETURN_FALSE;
2327 }
2328
2329 retsock = socket_import_file_descriptor(socket);
2330 if (retsock == NULL) {
2331 RETURN_FALSE;
2332 }
2333
2334 #ifdef PHP_WIN32
2335
2336
2337 if (php_stream_is(stream, PHP_STREAM_IS_SOCKET)) {
2338 retsock->blocking =
2339 ((php_netstream_data_t *)stream->abstract)->is_blocked;
2340 } else {
2341 retsock->blocking = 1;
2342 }
2343 #endif
2344
2345
2346
2347
2348 ZVAL_COPY(&retsock->zstream, zstream);
2349
2350 php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER,
2351 PHP_STREAM_BUFFER_NONE, NULL);
2352
2353 RETURN_RES(zend_register_resource(retsock, le_socket));
2354 }
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364