Browse Source
- Added multicast support to the sockets extension (bug #40510).
experimental/with_scalar_types
- Added multicast support to the sockets extension (bug #40510).
experimental/with_scalar_types
10 changed files with 1591 additions and 30 deletions
-
4ext/sockets/config.m4
-
3ext/sockets/config.w32
-
496ext/sockets/multicast.c
-
59ext/sockets/multicast.h
-
392ext/sockets/sockets.c
-
192ext/sockets/tests/mcast_ipv4_recv.phpt
-
65ext/sockets/tests/mcast_ipv4_send.phpt
-
216ext/sockets/tests/mcast_ipv6_recv.phpt
-
126ext/sockets/tests/mcast_ipv6_recv_limited.phpt
-
68ext/sockets/tests/mcast_ipv6_send.phpt
@ -0,0 +1,496 @@ |
|||
#ifdef HAVE_CONFIG_H |
|||
#include "config.h" |
|||
#endif |
|||
|
|||
#include "php.h" |
|||
|
|||
#if HAVE_SOCKETS |
|||
|
|||
#include "php_network.h" |
|||
#ifdef PHP_WIN32 |
|||
# include "win32/inet.h" |
|||
# include <winsock2.h> |
|||
# include <windows.h> |
|||
# include <Ws2tcpip.h> |
|||
# include <Ws2ipdef.h> |
|||
# include "php_sockets.h" |
|||
# include "win32/sockets.h" |
|||
# define NTDDI_XP NTDDI_WINXP /* bug in SDK */ |
|||
# include <IPHlpApi.h> |
|||
# undef NTDDI_XP |
|||
#else |
|||
#include <sys/socket.h> |
|||
#include <sys/ioctl.h> |
|||
#include <net/if.h> |
|||
#include <netinet/in.h> |
|||
#include <arpa/inet.h> |
|||
#endif |
|||
|
|||
#include "php_sockets.h" |
|||
#include "multicast.h" |
|||
#include "main/php_network.h" |
|||
|
|||
#if defined(MCAST_JOIN_GROUP) && 1 &&\ |
|||
(!defined(PHP_WIN32) || (_WIN32_WINNT >= 0x600 && SOCKETS_ENABLE_VISTA_API)) |
|||
#define RFC3678_API 1 |
|||
#endif |
|||
|
|||
|
|||
enum source_op { |
|||
JOIN_SOURCE, |
|||
LEAVE_SOURCE, |
|||
BLOCK_SOURCE, |
|||
UNBLOCK_SOURCE |
|||
}; |
|||
|
|||
static int _php_mcast_join_leave(php_socket *sock, int level, struct sockaddr *group, socklen_t group_len, unsigned int if_index, int join TSRMLS_DC); |
|||
static int _php_mcast_source_op(php_socket *sock, int level, struct sockaddr *group, socklen_t group_len, struct sockaddr *source, socklen_t source_len, unsigned int if_index, enum source_op sop TSRMLS_DC); |
|||
#if RFC3678_API |
|||
static int _php_source_op_to_rfc3678_op(enum source_op sop); |
|||
#else |
|||
static const char *_php_source_op_to_string(enum source_op sop); |
|||
static int _php_source_op_to_ipv4_op(enum source_op sop); |
|||
#endif |
|||
|
|||
int php_mcast_join( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
unsigned int if_index TSRMLS_DC) |
|||
{ |
|||
return _php_mcast_join_leave(sock, level, group, group_len, if_index, 1 TSRMLS_CC); |
|||
} |
|||
|
|||
int php_mcast_leave( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
unsigned int if_index TSRMLS_DC) |
|||
{ |
|||
return _php_mcast_join_leave(sock, level, group, group_len, if_index, 0 TSRMLS_CC); |
|||
} |
|||
|
|||
int php_mcast_join_source( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
struct sockaddr *source, |
|||
socklen_t source_len, |
|||
unsigned int if_index TSRMLS_DC) |
|||
{ |
|||
return _php_mcast_source_op(sock, level, group, group_len, source, source_len, if_index, JOIN_SOURCE TSRMLS_CC); |
|||
} |
|||
|
|||
int php_mcast_leave_source( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
struct sockaddr *source, |
|||
socklen_t source_len, |
|||
unsigned int if_index TSRMLS_DC) |
|||
{ |
|||
return _php_mcast_source_op(sock, level, group, group_len, source, source_len, if_index, LEAVE_SOURCE TSRMLS_CC); |
|||
} |
|||
|
|||
int php_mcast_block_source( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
struct sockaddr *source, |
|||
socklen_t source_len, |
|||
unsigned int if_index TSRMLS_DC) |
|||
{ |
|||
return _php_mcast_source_op(sock, level, group, group_len, source, source_len, if_index, BLOCK_SOURCE TSRMLS_CC); |
|||
} |
|||
|
|||
int php_mcast_unblock_source( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
struct sockaddr *source, |
|||
socklen_t source_len, |
|||
unsigned int if_index TSRMLS_DC) |
|||
{ |
|||
return _php_mcast_source_op(sock, level, group, group_len, source, source_len, if_index, UNBLOCK_SOURCE TSRMLS_CC); |
|||
} |
|||
|
|||
static int _php_mcast_join_leave( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, /* struct sockaddr_in/sockaddr_in6 */ |
|||
socklen_t group_len, |
|||
unsigned int if_index, |
|||
int join TSRMLS_DC) |
|||
{ |
|||
#ifdef RFC3678_API |
|||
struct group_req greq = {0}; |
|||
|
|||
memcpy(&greq.gr_group, group, group_len); |
|||
assert(greq.gr_group.ss_family != 0); /* the caller has set this */ |
|||
greq.gr_interface = if_index; |
|||
|
|||
return setsockopt(sock->bsd_socket, level, |
|||
join ? MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP, (char*)&greq, |
|||
sizeof(greq)); |
|||
#else |
|||
if (sock->type == AF_INET) { |
|||
struct ip_mreq mreq = {0}; |
|||
struct in_addr addr; |
|||
|
|||
assert(group_len == sizeof(struct sockaddr_in)); |
|||
|
|||
if (if_index != 0) { |
|||
if (php_if_index_to_addr4(if_index, sock, &addr TSRMLS_CC) == |
|||
FAILURE) |
|||
return -2; /* failure, but notice already emitted */ |
|||
mreq.imr_interface = addr; |
|||
} else { |
|||
mreq.imr_interface.s_addr = htonl(INADDR_ANY); |
|||
} |
|||
mreq.imr_multiaddr = ((struct sockaddr_in*)group)->sin_addr; |
|||
return setsockopt(sock->bsd_socket, level, |
|||
join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, (char*)&mreq, |
|||
sizeof(mreq)); |
|||
} |
|||
#if HAVE_IPV6 |
|||
else if (sock->type == AF_INET6) { |
|||
struct ipv6_mreq mreq = {0}; |
|||
|
|||
assert(group_len == sizeof(struct sockaddr_in6)); |
|||
|
|||
mreq.ipv6mr_multiaddr = ((struct sockaddr_in6*)group)->sin6_addr; |
|||
mreq.ipv6mr_interface = if_index; |
|||
|
|||
return setsockopt(sock->bsd_socket, level, |
|||
join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, (char*)&mreq, |
|||
sizeof(mreq)); |
|||
} |
|||
#endif |
|||
else { |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, |
|||
"Option %s is inapplicable to this socket type", |
|||
join ? "MCAST_JOIN_GROUP" : "MCAST_LEAVE_GROUP"); |
|||
return -2; |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
static int _php_mcast_source_op( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
struct sockaddr *source, |
|||
socklen_t source_len, |
|||
unsigned int if_index, |
|||
enum source_op sop TSRMLS_DC) |
|||
{ |
|||
#ifdef RFC3678_API |
|||
struct group_source_req gsreq = {0}; |
|||
|
|||
memcpy(&gsreq.gsr_group, group, group_len); |
|||
assert(gsreq.gsr_group.ss_family != 0); |
|||
memcpy(&gsreq.gsr_source, source, source_len); |
|||
assert(gsreq.gsr_source.ss_family != 0); |
|||
gsreq.gsr_interface = if_index; |
|||
|
|||
return setsockopt(sock->bsd_socket, level, |
|||
_php_source_op_to_rfc3678_op(sop), (char*)&gsreq, sizeof(gsreq)); |
|||
#else |
|||
if (sock->type == AF_INET) { |
|||
struct ip_mreq_source mreqs = {0}; |
|||
struct in_addr addr; |
|||
|
|||
mreqs.imr_multiaddr = ((struct sockaddr_in*)group)->sin_addr; |
|||
mreqs.imr_sourceaddr = ((struct sockaddr_in*)source)->sin_addr; |
|||
|
|||
assert(group_len == sizeof(struct sockaddr_in)); |
|||
assert(source_len == sizeof(struct sockaddr_in)); |
|||
|
|||
if (if_index != 0) { |
|||
if (php_if_index_to_addr4(if_index, sock, &addr TSRMLS_CC) == |
|||
FAILURE) |
|||
return -2; /* failure, but notice already emitted */ |
|||
mreqs.imr_interface = addr; |
|||
} else { |
|||
mreqs.imr_interface.s_addr = htonl(INADDR_ANY); |
|||
} |
|||
|
|||
return setsockopt(sock->bsd_socket, level, |
|||
_php_source_op_to_ipv4_op(sop), (char*)&mreqs, sizeof(mreqs)); |
|||
} |
|||
#if HAVE_IPV6 |
|||
else if (sock->type == AF_INET6) { |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, |
|||
"This platform does not support %s for IPv6 sockets", |
|||
_php_source_op_to_string(sop)); |
|||
return -2; |
|||
} |
|||
#endif |
|||
else { |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, |
|||
"Option %s is inapplicable to this socket type", |
|||
_php_source_op_to_string(sop)); |
|||
return -2; |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
#if RFC3678_API |
|||
static int _php_source_op_to_rfc3678_op(enum source_op sop) |
|||
{ |
|||
switch (sop) { |
|||
case JOIN_SOURCE: |
|||
return MCAST_JOIN_SOURCE_GROUP; |
|||
case LEAVE_SOURCE: |
|||
return MCAST_LEAVE_SOURCE_GROUP; |
|||
case BLOCK_SOURCE: |
|||
return MCAST_BLOCK_SOURCE; |
|||
case UNBLOCK_SOURCE: |
|||
return MCAST_UNBLOCK_SOURCE; |
|||
} |
|||
|
|||
assert(0); |
|||
return 0; |
|||
} |
|||
#else |
|||
static const char *_php_source_op_to_string(enum source_op sop) |
|||
{ |
|||
switch (sop) { |
|||
case JOIN_SOURCE: |
|||
return "MCAST_JOIN_SOURCE_GROUP"; |
|||
case LEAVE_SOURCE: |
|||
return "MCAST_LEAVE_SOURCE_GROUP"; |
|||
case BLOCK_SOURCE: |
|||
return "MCAST_BLOCK_SOURCE"; |
|||
case UNBLOCK_SOURCE: |
|||
return "MCAST_UNBLOCK_SOURCE"; |
|||
} |
|||
|
|||
assert(0); |
|||
return ""; |
|||
} |
|||
|
|||
static int _php_source_op_to_ipv4_op(enum source_op sop) |
|||
{ |
|||
switch (sop) { |
|||
case JOIN_SOURCE: |
|||
return IP_ADD_SOURCE_MEMBERSHIP; |
|||
case LEAVE_SOURCE: |
|||
return IP_DROP_SOURCE_MEMBERSHIP; |
|||
case BLOCK_SOURCE: |
|||
return IP_BLOCK_SOURCE; |
|||
case UNBLOCK_SOURCE: |
|||
return IP_UNBLOCK_SOURCE; |
|||
} |
|||
|
|||
assert(0); |
|||
return 0; |
|||
} |
|||
#endif |
|||
|
|||
#if PHP_WIN32 |
|||
int php_if_index_to_addr4(unsigned if_index, php_socket *php_sock, struct in_addr *out_addr TSRMLS_DC) |
|||
{ |
|||
MIB_IPADDRTABLE *addr_table; |
|||
ULONG size; |
|||
DWORD retval; |
|||
DWORD i; |
|||
|
|||
(void) php_sock; /* not necessary */ |
|||
|
|||
if (if_index == 0) { |
|||
out_addr->s_addr = INADDR_ANY; |
|||
return SUCCESS; |
|||
} |
|||
|
|||
size = 4 * (sizeof *addr_table); |
|||
addr_table = emalloc(size); |
|||
retry: |
|||
retval = GetIpAddrTable(addr_table, &size, 0); |
|||
if (retval == ERROR_INSUFFICIENT_BUFFER) { |
|||
efree(addr_table); |
|||
addr_table = emalloc(size); |
|||
goto retry; |
|||
} |
|||
if (retval != NO_ERROR) { |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, |
|||
"GetIpAddrTable failed with error %lu", retval); |
|||
return FAILURE; |
|||
} |
|||
for (i = 0; i < addr_table->dwNumEntries; i++) { |
|||
MIB_IPADDRROW r = addr_table->table[i]; |
|||
if (r.dwIndex == if_index) { |
|||
out_addr->s_addr = r.dwAddr; |
|||
return SUCCESS; |
|||
} |
|||
} |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, |
|||
"No interface with index %u was found", if_index); |
|||
return FAILURE; |
|||
} |
|||
|
|||
int php_add4_to_if_index(struct in_addr *addr, php_socket *php_sock, unsigned *if_index TSRMLS_DC) |
|||
{ |
|||
MIB_IPADDRTABLE *addr_table; |
|||
ULONG size; |
|||
DWORD retval; |
|||
DWORD i; |
|||
|
|||
(void) php_sock; /* not necessary */ |
|||
|
|||
if (addr->s_addr == INADDR_ANY) { |
|||
*if_index = 0; |
|||
return SUCCESS; |
|||
} |
|||
|
|||
size = 4 * (sizeof *addr_table); |
|||
addr_table = emalloc(size); |
|||
retry: |
|||
retval = GetIpAddrTable(addr_table, &size, 0); |
|||
if (retval == ERROR_INSUFFICIENT_BUFFER) { |
|||
efree(addr_table); |
|||
addr_table = emalloc(size); |
|||
goto retry; |
|||
} |
|||
if (retval != NO_ERROR) { |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, |
|||
"GetIpAddrTable failed with error %lu", retval); |
|||
return FAILURE; |
|||
} |
|||
for (i = 0; i < addr_table->dwNumEntries; i++) { |
|||
MIB_IPADDRROW r = addr_table->table[i]; |
|||
if (r.dwAddr == addr->s_addr) { |
|||
*if_index = r.dwIndex; |
|||
return SUCCESS; |
|||
} |
|||
} |
|||
|
|||
{ |
|||
char addr_str[17] = {0}; |
|||
inet_ntop(AF_INET, addr, addr_str, sizeof(addr_str)); |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, |
|||
"The interface with IP address %s was not found", addr_str); |
|||
} |
|||
return FAILURE; |
|||
} |
|||
|
|||
#else |
|||
|
|||
int php_if_index_to_addr4(unsigned if_index, php_socket *php_sock, struct in_addr *out_addr TSRMLS_DC) |
|||
{ |
|||
struct ifreq if_req; |
|||
|
|||
if (if_index == 0) { |
|||
out_addr->s_addr = INADDR_ANY; |
|||
return SUCCESS; |
|||
} |
|||
|
|||
if_req.ifr_ifindex = if_index; |
|||
if (ioctl(php_sock->bsd_socket, SIOCGIFNAME, &if_req) == -1) { |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, |
|||
"Failed obtaining address for interface %u: error %d", if_index, errno); |
|||
return FAILURE; |
|||
} |
|||
if (ioctl(php_sock->bsd_socket, SIOCGIFADDR, &if_req) == -1) { |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, |
|||
"Failed obtaining address for interface %u: error %d", if_index, errno); |
|||
return FAILURE; |
|||
} |
|||
|
|||
memcpy(out_addr, &((struct sockaddr_in *) &if_req.ifr_addr)->sin_addr, |
|||
sizeof *out_addr); |
|||
return SUCCESS; |
|||
} |
|||
|
|||
int php_add4_to_if_index(struct in_addr *addr, php_socket *php_sock, unsigned *if_index TSRMLS_DC) |
|||
{ |
|||
struct ifconf if_conf = {0}; |
|||
char *buf = NULL, |
|||
*p; |
|||
int size = 0, |
|||
lastsize = 0; |
|||
size_t entry_len; |
|||
|
|||
if (addr->s_addr == INADDR_ANY) { |
|||
*if_index = 0; |
|||
return SUCCESS; |
|||
} |
|||
|
|||
for(;;) { |
|||
size += 5 * sizeof(struct ifreq); |
|||
buf = ecalloc(size, 1); |
|||
if_conf.ifc_len = size; |
|||
if_conf.ifc_buf = buf; |
|||
|
|||
if (ioctl(php_sock->bsd_socket, SIOCGIFCONF, (char*)&if_conf) == -1 && |
|||
(errno != EINVAL || lastsize != 0)) { |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, |
|||
"Failed obtaining interfaces list: error %d", errno); |
|||
goto err; |
|||
} |
|||
|
|||
if (if_conf.ifc_len == lastsize) |
|||
/* not increasing anymore */ |
|||
break; |
|||
else { |
|||
lastsize = if_conf.ifc_len; |
|||
efree(buf); |
|||
buf = NULL; |
|||
} |
|||
} |
|||
|
|||
for (p = if_conf.ifc_buf; |
|||
p < if_conf.ifc_buf + if_conf.ifc_len; |
|||
p += entry_len) { |
|||
struct ifreq *cur_req; |
|||
|
|||
/* let's hope the pointer is aligned */ |
|||
cur_req = (struct ifreq*) p; |
|||
|
|||
#ifdef HAVE_SOCKADDR_SA_LEN |
|||
entry_len = cur_req->ifr_addr.sa_len + sizeof(cur_req->ifr_name); |
|||
#else |
|||
/* if there's no sa_len, assume the ifr_addr field is a sockaddr */ |
|||
entry_len = sizeof(struct sockaddr) + sizeof(cur_req->ifr_name); |
|||
#endif |
|||
entry_len = MAX(entry_len, sizeof(*cur_req)); |
|||
|
|||
if ((((struct sockaddr*)&cur_req->ifr_addr)->sa_family == AF_INET) && |
|||
(((struct sockaddr_in*)&cur_req->ifr_addr)->sin_addr.s_addr == |
|||
addr->s_addr)) { |
|||
if (ioctl(php_sock->bsd_socket, SIOCGIFINDEX, (char*)cur_req) |
|||
== -1) { |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, |
|||
"Error converting interface name to index: error %d", |
|||
errno); |
|||
goto err; |
|||
} else { |
|||
*if_index = cur_req->ifr_ifindex; |
|||
efree(buf); |
|||
return SUCCESS; |
|||
} |
|||
} |
|||
} |
|||
|
|||
{ |
|||
char addr_str[17] = {0}; |
|||
inet_ntop(AF_INET, addr, addr_str, sizeof(addr_str)); |
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, |
|||
"The interface with IP address %s was not found", addr_str); |
|||
} |
|||
|
|||
err: |
|||
if (buf != NULL) |
|||
efree(buf); |
|||
return FAILURE; |
|||
} |
|||
#endif |
|||
|
|||
#endif /* HAVE_SOCKETS */ |
|||
@ -0,0 +1,59 @@ |
|||
int php_if_index_to_addr4( |
|||
unsigned if_index, |
|||
php_socket *php_sock, |
|||
struct in_addr *out_addr TSRMLS_DC); |
|||
|
|||
int php_add4_to_if_index( |
|||
struct in_addr *addr, |
|||
php_socket *php_sock, |
|||
unsigned *if_index TSRMLS_DC); |
|||
|
|||
int php_mcast_join( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
unsigned int if_index TSRMLS_DC); |
|||
|
|||
int php_mcast_leave( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
unsigned int if_index TSRMLS_DC); |
|||
|
|||
int php_mcast_join_source( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
struct sockaddr *source, |
|||
socklen_t source_len, |
|||
unsigned int if_index TSRMLS_DC); |
|||
|
|||
int php_mcast_leave_source( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
struct sockaddr *source, |
|||
socklen_t source_len, |
|||
unsigned int if_index TSRMLS_DC); |
|||
|
|||
int php_mcast_block_source( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
struct sockaddr *source, |
|||
socklen_t source_len, |
|||
unsigned int if_index TSRMLS_DC); |
|||
|
|||
int php_mcast_unblock_source( |
|||
php_socket *sock, |
|||
int level, |
|||
struct sockaddr *group, |
|||
socklen_t group_len, |
|||
struct sockaddr *source, |
|||
socklen_t source_len, |
|||
unsigned int if_index TSRMLS_DC); |
|||
@ -0,0 +1,192 @@ |
|||
--TEST-- |
|||
Multicast support: IPv4 receive options |
|||
--SKIPIF-- |
|||
<?php |
|||
if (!extension_loaded('sockets')) { |
|||
die('skip sockets extension not available.'); |
|||
} |
|||
$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); |
|||
$br = socket_bind($s, '0.0.0.0', 3000); |
|||
$so = socket_set_option($s, IPPROTO_IP, MCAST_JOIN_GROUP, array( |
|||
"group" => '224.0.0.23', |
|||
"interface" => 'lo', |
|||
)); |
|||
if ($so === false) { |
|||
die('skip interface \'lo\' is unavailable.'); |
|||
} |
|||
--FILE-- |
|||
<?php |
|||
$domain = AF_INET; |
|||
$level = IPPROTO_IP; |
|||
$interface = "lo"; |
|||
$mcastaddr = '224.0.0.23'; |
|||
$sblock = "127.0.0.1"; |
|||
|
|||
echo "creating send socket bound to 127.0.0.1\n"; |
|||
$sends1 = socket_create($domain, SOCK_DGRAM, SOL_UDP); |
|||
$br = socket_bind($sends1, '127.0.0.1'); |
|||
var_dump($br); |
|||
|
|||
echo "creating unbound socket and hoping the routing table causes an interface other than lo to be used for sending messages to $mcastaddr\n"; |
|||
$sends2 = socket_create($domain, SOCK_DGRAM, SOL_UDP); |
|||
var_dump($br); |
|||
|
|||
echo "creating receive socket\n"; |
|||
$s = socket_create($domain, SOCK_DGRAM, SOL_UDP); |
|||
var_dump($s); |
|||
$br = socket_bind($s, '0.0.0.0', 3000); |
|||
var_dump($br); |
|||
|
|||
$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
)); |
|||
var_dump($so); |
|||
|
|||
$r = socket_sendto($sends1, $m = "initial packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
|
|||
$i = 0; |
|||
while (($str = socket_read($s, 3000)) !== FALSE) { |
|||
$i++; |
|||
echo "$i> ", $str, "\n"; |
|||
|
|||
if ($i == 1) { |
|||
echo "leaving group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 2) { |
|||
echo "re-joining group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends2, $m = "ignored mcast packet (different interface)", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
$r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 3) { |
|||
echo "blocking source\n"; |
|||
$so = socket_set_option($s, $level, MCAST_BLOCK_SOURCE, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
"source" => $sblock, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "ignored packet (blocked source)", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 4) { |
|||
echo "unblocking source\n"; |
|||
$so = socket_set_option($s, $level, MCAST_UNBLOCK_SOURCE, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
"source" => $sblock, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "mcast packet from 127.0.0.1", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 5) { |
|||
echo "leaving group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 6) { |
|||
echo "joining source group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_JOIN_SOURCE_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
"source" => $sblock, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "mcast packet from 127.0.0.1", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 7) { |
|||
echo "leaving source group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_LEAVE_SOURCE_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
"source" => $sblock, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 8) { |
|||
/* echo "rjsg\n"; |
|||
$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
)); |
|||
var_dump($so);*/ |
|||
break; |
|||
} |
|||
|
|||
} |
|||
--EXPECT-- |
|||
creating send socket bound to 127.0.0.1 |
|||
bool(true) |
|||
creating unbound socket and hoping the routing table causes an interface other than lo to be used for sending messages to 224.0.0.23 |
|||
bool(true) |
|||
creating receive socket |
|||
resource(6) of type (Socket) |
|||
bool(true) |
|||
bool(true) |
|||
int(14) |
|||
1> initial packet |
|||
leaving group |
|||
bool(true) |
|||
int(20) |
|||
int(14) |
|||
2> unicast packet |
|||
re-joining group |
|||
bool(true) |
|||
int(42) |
|||
int(12) |
|||
3> mcast packet |
|||
blocking source |
|||
bool(true) |
|||
int(31) |
|||
int(14) |
|||
4> unicast packet |
|||
unblocking source |
|||
bool(true) |
|||
int(27) |
|||
5> mcast packet from 127.0.0.1 |
|||
leaving group |
|||
bool(true) |
|||
int(20) |
|||
int(14) |
|||
6> unicast packet |
|||
joining source group |
|||
bool(true) |
|||
int(27) |
|||
7> mcast packet from 127.0.0.1 |
|||
leaving source group |
|||
bool(true) |
|||
int(20) |
|||
int(14) |
|||
8> unicast packet |
|||
@ -0,0 +1,65 @@ |
|||
--TEST-- |
|||
Multicast support: IPv4 send options |
|||
--SKIPIF-- |
|||
<?php |
|||
if (!extension_loaded('sockets')) { |
|||
die('skip sockets extension not available.'); |
|||
} |
|||
if (socket_set_option($s, $level, IP_MULTICAST_IF, 1) === false) { |
|||
die("skip interface 1 either doesn't exist or has no ipv4 address"); |
|||
} |
|||
--FILE-- |
|||
<?php |
|||
$domain = AF_INET; |
|||
$level = IPPROTO_IP; |
|||
$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err"); |
|||
|
|||
echo "Setting IP_MULTICAST_TTL\n"; |
|||
$r = socket_set_option($s, $level, IP_MULTICAST_TTL, 9); |
|||
var_dump($r); |
|||
$r = socket_get_option($s, $level, IP_MULTICAST_TTL); |
|||
var_dump($r); |
|||
echo "\n"; |
|||
|
|||
echo "Setting IP_MULTICAST_LOOP\n"; |
|||
$r = socket_set_option($s, $level, IP_MULTICAST_LOOP, 0); |
|||
var_dump($r); |
|||
$r = socket_get_option($s, $level, IP_MULTICAST_LOOP); |
|||
var_dump($r); |
|||
$r = socket_set_option($s, $level, IP_MULTICAST_LOOP, 1); |
|||
var_dump($r); |
|||
$r = socket_get_option($s, $level, IP_MULTICAST_LOOP); |
|||
var_dump($r); |
|||
echo "\n"; |
|||
|
|||
echo "Setting IP_MULTICAST_IF\n"; |
|||
echo "interface 0:\n"; |
|||
$r = socket_set_option($s, $level, IP_MULTICAST_IF, 0); |
|||
var_dump($r); |
|||
$r = socket_get_option($s, $level, IP_MULTICAST_IF); |
|||
var_dump($r); |
|||
echo "interface 1:\n"; |
|||
$r = socket_set_option($s, $level, IP_MULTICAST_IF, 1); |
|||
var_dump($r); |
|||
$r = socket_get_option($s, $level, IP_MULTICAST_IF); |
|||
var_dump($r); |
|||
echo "\n"; |
|||
|
|||
--EXPECT-- |
|||
Setting IP_MULTICAST_TTL |
|||
bool(true) |
|||
int(9) |
|||
|
|||
Setting IP_MULTICAST_LOOP |
|||
bool(true) |
|||
int(0) |
|||
bool(true) |
|||
int(1) |
|||
|
|||
Setting IP_MULTICAST_IF |
|||
interface 0: |
|||
bool(true) |
|||
int(0) |
|||
interface 1: |
|||
bool(true) |
|||
int(1) |
|||
@ -0,0 +1,216 @@ |
|||
--TEST-- |
|||
Multicast support: IPv6 receive options |
|||
--SKIPIF-- |
|||
<?php |
|||
if (!extension_loaded('sockets')) { |
|||
die('skip sockets extension not available.'); |
|||
} |
|||
if (!defined('IPPROTO_IPV6')) { |
|||
die('skip IPv6 not available.'); |
|||
} |
|||
$s = socket_create(AF_INET6, SOCK_DGRAM, SOL_UDP); |
|||
$br = socket_bind($s, '::', 3000); |
|||
/* On Linux, there is no route ff00::/8 by default on lo, which makes it |
|||
* troublesome to send multicast traffic from lo, which we must since |
|||
* we're dealing with interface-local traffic... */ |
|||
$so = socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_GROUP, array( |
|||
"group" => 'ff01::114', |
|||
"interface" => 0, |
|||
)); |
|||
if ($so === false) { |
|||
die('skip unable to join multicast group on any interface.'); |
|||
} |
|||
$r = socket_sendto($s, $m = "testing packet", strlen($m), 0, 'ff01::114', 3000); |
|||
if ($r === false) { |
|||
die('skip unable to send multicast packet.'); |
|||
} |
|||
$so = socket_set_option($s, IPPROTO_IPV6, MCAST_LEAVE_GROUP, array( |
|||
"group" => 'ff01::114', |
|||
"interface" => 0, |
|||
)); |
|||
$so = socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP, array( |
|||
"group" => 'ff01::114', |
|||
"interface" => 0, |
|||
"source" => '2001::dead:beef', |
|||
)); |
|||
if ($so === false) { |
|||
die('skip protocol independent multicast API is unavailable.'); |
|||
} |
|||
|
|||
--FILE-- |
|||
<?php |
|||
$domain = AF_INET6; |
|||
$level = IPPROTO_IPV6; |
|||
$interface = 0; |
|||
$mcastaddr = 'ff01::114'; |
|||
$sblock = "?"; |
|||
|
|||
echo "creating send socket\n"; |
|||
$sends1 = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err"); |
|||
var_dump($sends1); |
|||
|
|||
echo "creating receive socket\n"; |
|||
$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err"); |
|||
var_dump($s); |
|||
$br = socket_bind($s, '::0', 3000) or die("err"); |
|||
var_dump($br); |
|||
|
|||
$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
)) or die("err"); |
|||
var_dump($so); |
|||
|
|||
$r = socket_sendto($sends1, $m = "testing packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
$r = socket_recvfrom($s, $str, 2000, 0, $from, $fromPort); |
|||
var_dump($r, $str, $from); |
|||
$sblock = $from; |
|||
|
|||
$r = socket_sendto($sends1, $m = "initial packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
|
|||
$i = 0; |
|||
while (($str = socket_read($s, 3000)) !== FALSE) { |
|||
$i++; |
|||
echo "$i> ", $str, "\n"; |
|||
|
|||
if ($i == 1) { |
|||
echo "leaving group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 2) { |
|||
echo "re-joining group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 3) { |
|||
echo "blocking source\n"; |
|||
$so = socket_set_option($s, $level, MCAST_BLOCK_SOURCE, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
"source" => $sblock, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "ignored packet (blocked source)", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 4) { |
|||
echo "unblocking source\n"; |
|||
$so = socket_set_option($s, $level, MCAST_UNBLOCK_SOURCE, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
"source" => $sblock, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 5) { |
|||
echo "leaving group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 6) { |
|||
echo "joining source group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_JOIN_SOURCE_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
"source" => $sblock, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "mcast packet from desired source", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 7) { |
|||
echo "leaving source group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_LEAVE_SOURCE_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
"source" => $sblock, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 8) { |
|||
/*echo "joining source group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_JOIN_SOURCE_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
"source" => $sblock, |
|||
)); |
|||
var_dump($so);*/ |
|||
break; |
|||
} |
|||
|
|||
} |
|||
--EXPECTF-- |
|||
creating send socket |
|||
resource(4) of type (Socket) |
|||
creating receive socket |
|||
resource(5) of type (Socket) |
|||
bool(true) |
|||
bool(true) |
|||
int(14) |
|||
int(14) |
|||
string(14) "testing packet" |
|||
string(%d) "%s" |
|||
int(14) |
|||
1> initial packet |
|||
leaving group |
|||
bool(true) |
|||
int(20) |
|||
int(14) |
|||
2> unicast packet |
|||
re-joining group |
|||
bool(true) |
|||
int(12) |
|||
3> mcast packet |
|||
blocking source |
|||
bool(true) |
|||
int(31) |
|||
int(14) |
|||
4> unicast packet |
|||
unblocking source |
|||
bool(true) |
|||
int(12) |
|||
5> mcast packet |
|||
leaving group |
|||
bool(true) |
|||
int(20) |
|||
int(14) |
|||
6> unicast packet |
|||
joining source group |
|||
bool(true) |
|||
int(32) |
|||
7> mcast packet from desired source |
|||
leaving source group |
|||
bool(true) |
|||
int(20) |
|||
int(14) |
|||
8> unicast packet |
|||
@ -0,0 +1,126 @@ |
|||
--TEST-- |
|||
Multicast support: IPv6 receive options (limited) |
|||
--SKIPIF-- |
|||
<?php |
|||
if (!extension_loaded('sockets')) { |
|||
die('skip sockets extension not available.'); |
|||
} |
|||
if (!defined('IPPROTO_IPV6')) { |
|||
die('skip IPv6 not available.'); |
|||
} |
|||
$s = socket_create(AF_INET6, SOCK_DGRAM, SOL_UDP); |
|||
$br = socket_bind($s, '::', 3000); |
|||
/* On Linux, there is no route ff00::/8 by default on lo, which makes it |
|||
* troublesome to send multicast traffic from lo, which we must since |
|||
* we're dealing with interface-local traffic... */ |
|||
$so = socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_GROUP, array( |
|||
"group" => 'ff01::114', |
|||
"interface" => 0, |
|||
)); |
|||
if ($so === false) { |
|||
die('skip unable to join multicast group on any interface.'); |
|||
} |
|||
$r = socket_sendto($s, $m = "testing packet", strlen($m), 0, 'ff01::114', 3000); |
|||
if ($r === false) { |
|||
die('skip unable to send multicast packet.'); |
|||
} |
|||
$so = socket_set_option($s, IPPROTO_IPV6, MCAST_LEAVE_GROUP, array( |
|||
"group" => 'ff01::114', |
|||
"interface" => 0, |
|||
)); |
|||
$so = socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP, array( |
|||
"group" => 'ff01::114', |
|||
"interface" => 0, |
|||
"source" => '2001::dead:beef', |
|||
)); |
|||
if ($so !== false) { |
|||
die('skip protocol independent multicast API is available.'); |
|||
} |
|||
|
|||
--FILE-- |
|||
<?php |
|||
$domain = AF_INET6; |
|||
$level = IPPROTO_IPV6; |
|||
$interface = 0; |
|||
$mcastaddr = 'ff01::114'; |
|||
$sblock = "?"; |
|||
|
|||
echo "creating send socket\n"; |
|||
$sends1 = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err"); |
|||
var_dump($sends1); |
|||
|
|||
echo "creating receive socket\n"; |
|||
$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err"); |
|||
var_dump($s); |
|||
$br = socket_bind($s, '::0', 3000) or die("err"); |
|||
var_dump($br); |
|||
|
|||
$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
)) or die("err"); |
|||
var_dump($so); |
|||
|
|||
$r = socket_sendto($sends1, $m = "testing packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
$r = socket_recvfrom($s, $str, 2000, 0, $from, $fromPort); |
|||
var_dump($r, $str, $from); |
|||
$sblock = $from; |
|||
|
|||
$r = socket_sendto($sends1, $m = "initial packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
|
|||
$i = 0; |
|||
while (($str = socket_read($s, 3000)) !== FALSE) { |
|||
$i++; |
|||
echo "$i> ", $str, "\n"; |
|||
|
|||
if ($i == 1) { |
|||
echo "leaving group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 2) { |
|||
echo "re-joining group\n"; |
|||
$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array( |
|||
"group" => $mcastaddr, |
|||
"interface" => $interface, |
|||
)); |
|||
var_dump($so); |
|||
$r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000); |
|||
var_dump($r); |
|||
} |
|||
if ($i == 3) { |
|||
break; |
|||
} |
|||
|
|||
} |
|||
--EXPECTF-- |
|||
creating send socket |
|||
resource(4) of type (Socket) |
|||
creating receive socket |
|||
resource(5) of type (Socket) |
|||
bool(true) |
|||
bool(true) |
|||
int(14) |
|||
int(14) |
|||
string(14) "testing packet" |
|||
string(%d) "%s" |
|||
int(14) |
|||
1> initial packet |
|||
leaving group |
|||
bool(true) |
|||
int(20) |
|||
int(14) |
|||
2> unicast packet |
|||
re-joining group |
|||
bool(true) |
|||
int(12) |
|||
3> mcast packet |
|||
@ -0,0 +1,68 @@ |
|||
--TEST-- |
|||
Multicast support: IPv6 send options |
|||
--SKIPIF-- |
|||
<?php |
|||
if (!extension_loaded('sockets')) { |
|||
die('skip sockets extension not available.'); |
|||
} |
|||
if (!defined('IPPROTO_IPV6')) { |
|||
die('skip IPv6 not available.'); |
|||
} |
|||
if (socket_set_option($s, $level, IP_MULTICAST_IF, 1) === false) { |
|||
die("skip interface 1 either doesn't exist or has no ipv6 address"); |
|||
} |
|||
--FILE-- |
|||
<?php |
|||
$domain = AF_INET6; |
|||
$level = IPPROTO_IPV6; |
|||
$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err"); |
|||
|
|||
echo "Setting IPV6_MULTICAST_TTL\n"; |
|||
$r = socket_set_option($s, $level, IPV6_MULTICAST_HOPS, 9); |
|||
var_dump($r); |
|||
$r = socket_get_option($s, $level, IPV6_MULTICAST_HOPS); |
|||
var_dump($r); |
|||
echo "\n"; |
|||
|
|||
echo "Setting IPV6_MULTICAST_LOOP\n"; |
|||
$r = socket_set_option($s, $level, IPV6_MULTICAST_LOOP, 0); |
|||
var_dump($r); |
|||
$r = socket_get_option($s, $level, IPV6_MULTICAST_LOOP); |
|||
var_dump($r); |
|||
$r = socket_set_option($s, $level, IPV6_MULTICAST_LOOP, 1); |
|||
var_dump($r); |
|||
$r = socket_get_option($s, $level, IPV6_MULTICAST_LOOP); |
|||
var_dump($r); |
|||
echo "\n"; |
|||
|
|||
echo "Setting IPV6_MULTICAST_IF\n"; |
|||
echo "interface 0:\n"; |
|||
$r = socket_set_option($s, $level, IPV6_MULTICAST_IF, 0); |
|||
var_dump($r); |
|||
$r = socket_get_option($s, $level, IPV6_MULTICAST_IF); |
|||
var_dump($r); |
|||
echo "interface 1:\n"; |
|||
$r = socket_set_option($s, $level, IPV6_MULTICAST_IF, 1); |
|||
var_dump($r); |
|||
$r = socket_get_option($s, $level, IPV6_MULTICAST_IF); |
|||
var_dump($r); |
|||
echo "\n"; |
|||
|
|||
--EXPECT-- |
|||
Setting IPV6_MULTICAST_TTL |
|||
bool(true) |
|||
int(9) |
|||
|
|||
Setting IPV6_MULTICAST_LOOP |
|||
bool(true) |
|||
int(0) |
|||
bool(true) |
|||
int(1) |
|||
|
|||
Setting IPV6_MULTICAST_IF |
|||
interface 0: |
|||
bool(true) |
|||
int(0) |
|||
interface 1: |
|||
bool(true) |
|||
int(1) |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue