1--TEST--
2Multicast support: IPv6 receive options (limited)
3--EXTENSIONS--
4sockets
5--SKIPIF--
6<?php
7
8if (!defined('IPPROTO_IPV6')) {
9    die('skip IPv6 not available.');
10}
11// hide the output from socket_create() because it can raise
12// a warning if (for example) the linux kernel is lacking ipv6
13$s = @socket_create(AF_INET6, SOCK_DGRAM, SOL_UDP);
14if ($s === false) {
15    die("skip unable to create socket");
16}
17$br = socket_bind($s, '::', 3000);
18/* On Linux, there is no route ff00::/8 by default on lo, which makes it
19 * troublesome to send multicast traffic from lo, which we must since
20 * we're dealing with interface-local traffic... */
21$so = @socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_GROUP, array(
22    "group"	=> 'ff01::114',
23    "interface" => 0,
24));
25if ($so === false) {
26    die('skip unable to join multicast group on any interface.');
27}
28$r = socket_sendto($s, $m = "testing packet", strlen($m), 0, 'ff01::114', 3000);
29if ($r === false) {
30    die('skip unable to send multicast packet.');
31}
32$so = @socket_set_option($s, IPPROTO_IPV6, MCAST_LEAVE_GROUP, array(
33    "group"	=> 'ff01::114',
34    "interface" => 0,
35));
36if (defined("MCAST_JOIN_SOURCE_GROUP")) {
37    $so = @socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP, array(
38        "group"	=> 'ff01::114',
39        "interface" => 0,
40        "source" => '2001::dead:beef',
41    ));
42    if ($so !== false) {
43        die('skip protocol independent multicast API is available.');
44    }
45}
46?>
47--FILE--
48<?php
49include __DIR__."/mcast_helpers.php.inc";
50$domain = AF_INET6;
51$level = IPPROTO_IPV6;
52$interface = 0;
53$mcastaddr = 'ff01::114';
54$sblock = "?";
55
56echo "creating send socket\n";
57$sends1 = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
58var_dump($sends1);
59
60echo "creating receive socket\n";
61$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
62var_dump($s);
63$br = socket_bind($s, '::0', 3000) or die("err");
64var_dump($br);
65
66$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
67    "group"	=> $mcastaddr,
68    "interface" => $interface,
69)) or die("err");
70var_dump($so);
71
72$r = socket_sendto($sends1, $m = "testing packet", strlen($m), 0, $mcastaddr, 3000);
73var_dump($r);
74checktimeout($s, 500);
75$r = socket_recvfrom($s, $str, 2000, 0, $from, $fromPort);
76var_dump($r, $str, $from);
77$sblock = $from;
78
79$r = socket_sendto($sends1, $m = "initial packet", strlen($m), 0, $mcastaddr, 3000);
80var_dump($r);
81
82$i = 0;
83checktimeout($s, 500);
84while (($str = socket_read($s, 3000, 500)) !== FALSE) {
85    $i++;
86    echo "$i> ", $str, "\n";
87
88if ($i == 1) {
89    echo "leaving group\n";
90    $so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
91        "group"	=> $mcastaddr,
92        "interface" => $interface,
93    ));
94    var_dump($so);
95    $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
96    var_dump($r);
97    $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
98    var_dump($r);
99}
100if ($i == 2) {
101    echo "re-joining group\n";
102    $so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
103        "group"	=> $mcastaddr,
104        "interface" => $interface,
105    ));
106    var_dump($so);
107    $r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000);
108    var_dump($r);
109}
110if ($i == 3) {
111    break;
112}
113
114}
115?>
116--EXPECTF--
117creating send socket
118object(Socket)#%d (0) {
119}
120creating receive socket
121object(Socket)#%d (0) {
122}
123bool(true)
124bool(true)
125int(14)
126int(14)
127string(14) "testing packet"
128string(%d) "%s"
129int(14)
1301> initial packet
131leaving group
132bool(true)
133int(20)
134int(14)
1352> unicast packet
136re-joining group
137bool(true)
138int(12)
1393> mcast packet
140