1--TEST--
2Multicast support: IPv6 receive options
3--SKIPIF--
4<?php
5if (!extension_loaded('sockets')) {
6    die('skip sockets extension not available.');
7}
8if (!defined('IPPROTO_IPV6')) {
9	die('skip IPv6 not available.');
10}
11$s = socket_create(AF_INET6, SOCK_DGRAM, SOL_UDP);
12if ($s === false) {
13  die("skip unable to create socket");
14}
15$br = socket_bind($s, '::', 3000);
16/* On Linux, there is no route ff00::/8 by default on lo, which makes it
17 * troublesome to send multicast traffic from lo, which we must since
18 * we're dealing with interface-local traffic... */
19$so = @socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_GROUP, array(
20	"group"	=> 'ff01::114',
21	"interface" => 0,
22));
23if ($so === false) {
24    die('skip unable to join multicast group on any interface.');
25}
26$r = socket_sendto($s, $m = "testing packet", strlen($m), 0, 'ff01::114', 3000);
27if ($r === false) {
28	die('skip unable to send multicast packet.');
29}
30
31if (!defined("MCAST_JOIN_SOURCE_GROUP"))
32    die('skip source operations are unavailable');
33
34$so = @socket_set_option($s, IPPROTO_IPV6, MCAST_LEAVE_GROUP, array(
35	"group"	=> 'ff01::114',
36	"interface" => 0,
37));
38$so = @socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP, array(
39	"group"	=> 'ff01::114',
40	"interface" => 0,
41	"source" => '2001::dead:beef',
42));
43if ($so === false) {
44    die('skip protocol independent multicast API is unavailable.');
45}
46--FILE--
47<?php
48include __DIR__."/mcast_helpers.php.inc";
49$domain = AF_INET6;
50$level = IPPROTO_IPV6;
51$interface = 0;
52$mcastaddr = 'ff01::114';
53$sblock = "?";
54
55echo "creating send socket\n";
56$sends1 = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
57var_dump($sends1);
58
59echo "creating receive socket\n";
60$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
61var_dump($s);
62$br = socket_bind($s, '::0', 3000) or die("err");
63var_dump($br);
64
65$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
66	"group"	=> $mcastaddr,
67	"interface" => $interface,
68)) or die("err");
69var_dump($so);
70
71$r = socket_sendto($sends1, $m = "testing packet", strlen($m), 0, $mcastaddr, 3000);
72var_dump($r);
73checktimeout($s, 500);
74$r = socket_recvfrom($s, $str, 2000, 0, $from, $fromPort);
75var_dump($r, $str, $from);
76$sblock = $from;
77
78$r = socket_sendto($sends1, $m = "initial packet", strlen($m), 0, $mcastaddr, 3000);
79var_dump($r);
80
81$i = 0;
82checktimeout($s, 500);
83while (($str = socket_read($s, 3000)) !== FALSE) {
84	$i++;
85	echo "$i> ", $str, "\n";
86
87if ($i == 1) {
88	echo "leaving group\n";
89	$so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
90		"group"	=> $mcastaddr,
91		"interface" => $interface,
92	));
93	var_dump($so);
94	$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
95	var_dump($r);
96	$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
97	var_dump($r);
98}
99if ($i == 2) {
100	echo "re-joining group\n";
101	$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
102		"group"	=> $mcastaddr,
103		"interface" => $interface,
104	));
105	var_dump($so);
106	$r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000);
107	var_dump($r);
108}
109if ($i == 3) {
110	echo "blocking source\n";
111	$so = socket_set_option($s, $level, MCAST_BLOCK_SOURCE, array(
112		"group"	=> $mcastaddr,
113		"interface" => $interface,
114		"source" => $sblock,
115	));
116	var_dump($so);
117	$r = socket_sendto($sends1, $m = "ignored packet (blocked source)", strlen($m), 0, $mcastaddr, 3000);
118	var_dump($r);
119	$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
120	var_dump($r);
121}
122if ($i == 4) {
123	echo "unblocking source\n";
124	$so = socket_set_option($s, $level, MCAST_UNBLOCK_SOURCE, array(
125		"group"	=> $mcastaddr,
126		"interface" => $interface,
127		"source" => $sblock,
128	));
129	var_dump($so);
130	$r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000);
131	var_dump($r);
132}
133if ($i == 5) {
134	echo "leaving group\n";
135	$so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
136		"group"	=> $mcastaddr,
137		"interface" => $interface,
138	));
139	var_dump($so);
140	$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
141	var_dump($r);
142	$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
143	var_dump($r);
144}
145if ($i == 6) {
146	echo "joining source group\n";
147	$so = socket_set_option($s, $level, MCAST_JOIN_SOURCE_GROUP, array(
148		"group"	=> $mcastaddr,
149		"interface" => $interface,
150		"source" => $sblock,
151	));
152	var_dump($so);
153	$r = socket_sendto($sends1, $m = "mcast packet from desired source", strlen($m), 0, $mcastaddr, 3000);
154	var_dump($r);
155}
156if ($i == 7) {
157	echo "leaving source group\n";
158	$so = socket_set_option($s, $level, MCAST_LEAVE_SOURCE_GROUP, array(
159		"group"	=> $mcastaddr,
160		"interface" => $interface,
161		"source" => $sblock,
162	));
163	var_dump($so);
164	$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
165	var_dump($r);
166	$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
167	var_dump($r);
168}
169if ($i == 8) {
170	/*echo "joining source group\n";
171	$so = socket_set_option($s, $level, MCAST_JOIN_SOURCE_GROUP, array(
172		"group"	=> $mcastaddr,
173		"interface" => $interface,
174		"source" => $sblock,
175	));
176	var_dump($so);*/
177	break;
178}
179
180}
181--EXPECTF--
182creating send socket
183resource(%d) of type (Socket)
184creating receive socket
185resource(%d) of type (Socket)
186bool(true)
187bool(true)
188int(14)
189int(14)
190string(14) "testing packet"
191string(%d) "%s"
192int(14)
1931> initial packet
194leaving group
195bool(true)
196int(20)
197int(14)
1982> unicast packet
199re-joining group
200bool(true)
201int(12)
2023> mcast packet
203blocking source
204bool(true)
205int(31)
206int(14)
2074> unicast packet
208unblocking source
209bool(true)
210int(12)
2115> mcast packet
212leaving group
213bool(true)
214int(20)
215int(14)
2166> unicast packet
217joining source group
218bool(true)
219int(32)
2207> mcast packet from desired source
221leaving source group
222bool(true)
223int(20)
224int(14)
2258> unicast packet
226