1--TEST--
2Multicast support: IPv4 receive options
3--SKIPIF--
4<?php
5if (!extension_loaded('sockets')) {
6    die('skip sockets extension not available.');
7}
8$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
9$br = socket_bind($s, '0.0.0.0', 3000);
10$so = socket_set_option($s, IPPROTO_IP, MCAST_JOIN_GROUP, array(
11	"group"	=> '224.0.0.23',
12	"interface" => 'lo',
13));
14if ($so === false) {
15    die('skip interface \'lo\' is unavailable.');
16}
17if (!defined("MCAST_BLOCK_SOURCE")) {
18    die('skip source operations are unavailable');
19}
20--FILE--
21<?php
22include __DIR__."/mcast_helpers.php.inc";
23$domain = AF_INET;
24$level = IPPROTO_IP;
25$interface = "lo";
26$mcastaddr = '224.0.0.23';
27$sblock = "127.0.0.1";
28
29echo "creating send socket bound to 127.0.0.1\n";
30$sends1 = socket_create($domain, SOCK_DGRAM, SOL_UDP);
31$br = socket_bind($sends1, '127.0.0.1');
32var_dump($br);
33
34echo "creating unbound socket and hoping the routing table causes an interface other than lo to be used for sending messages to $mcastaddr\n";
35$sends2 = socket_create($domain, SOCK_DGRAM, SOL_UDP);
36var_dump($br);
37
38echo "creating receive socket\n";
39$s = socket_create($domain, SOCK_DGRAM, SOL_UDP);
40var_dump($s);
41$br = socket_bind($s, '0.0.0.0', 3000);
42var_dump($br);
43
44$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
45	"group"	=> $mcastaddr,
46	"interface" => $interface,
47));
48var_dump($so);
49
50$r = socket_sendto($sends1, $m = "initial packet", strlen($m), 0, $mcastaddr, 3000);
51var_dump($r);
52
53$i = 0;
54checktimeout($s, 500);
55while (($str = socket_read($s, 3000)) !== FALSE) {
56	$i++;
57	echo "$i> ", $str, "\n";
58
59if ($i == 1) {
60	echo "leaving group\n";
61	$so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
62		"group"	=> $mcastaddr,
63		"interface" => $interface,
64	));
65	var_dump($so);
66	$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
67	var_dump($r);
68	$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000);
69	var_dump($r);
70}
71if ($i == 2) {
72	echo "re-joining group\n";
73	$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
74		"group"	=> $mcastaddr,
75		"interface" => $interface,
76	));
77	var_dump($so);
78	$r = socket_sendto($sends2, $m = "ignored mcast packet (different interface)", strlen($m), 0, $mcastaddr, 3000);
79	var_dump($r);
80	$r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000);
81	var_dump($r);
82}
83if ($i == 3) {
84	echo "blocking source\n";
85	$so = socket_set_option($s, $level, MCAST_BLOCK_SOURCE, array(
86		"group"	=> $mcastaddr,
87		"interface" => $interface,
88		"source" => $sblock,
89	));
90	var_dump($so);
91	$r = socket_sendto($sends1, $m = "ignored packet (blocked source)", strlen($m), 0, $mcastaddr, 3000);
92	var_dump($r);
93	$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000);
94	var_dump($r);
95}
96if ($i == 4) {
97	echo "unblocking source\n";
98	$so = socket_set_option($s, $level, MCAST_UNBLOCK_SOURCE, array(
99		"group"	=> $mcastaddr,
100		"interface" => $interface,
101		"source" => $sblock,
102	));
103	var_dump($so);
104	$r = socket_sendto($sends1, $m = "mcast packet from 127.0.0.1", strlen($m), 0, $mcastaddr, 3000);
105	var_dump($r);
106}
107if ($i == 5) {
108	echo "leaving group\n";
109	$so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
110		"group"	=> $mcastaddr,
111		"interface" => $interface,
112	));
113	var_dump($so);
114	$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
115	var_dump($r);
116	$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000);
117	var_dump($r);
118}
119if ($i == 6) {
120	echo "joining source group\n";
121	$so = socket_set_option($s, $level, MCAST_JOIN_SOURCE_GROUP, array(
122		"group"	=> $mcastaddr,
123		"interface" => $interface,
124		"source" => $sblock,
125	));
126	var_dump($so);
127	$r = socket_sendto($sends1, $m = "mcast packet from 127.0.0.1", strlen($m), 0, $mcastaddr, 3000);
128	var_dump($r);
129}
130if ($i == 7) {
131	echo "leaving source group\n";
132	$so = socket_set_option($s, $level, MCAST_LEAVE_SOURCE_GROUP, array(
133		"group"	=> $mcastaddr,
134		"interface" => $interface,
135		"source" => $sblock,
136	));
137	var_dump($so);
138	$r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
139	var_dump($r);
140	$r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000);
141	var_dump($r);
142}
143if ($i == 8) {
144/*	echo "rjsg\n";
145	$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
146		"group"	=> $mcastaddr,
147		"interface" => $interface,
148	));
149	var_dump($so);*/
150	break;
151}
152
153}
154--EXPECTF--
155creating send socket bound to 127.0.0.1
156bool(true)
157creating unbound socket and hoping the routing table causes an interface other than lo to be used for sending messages to 224.0.0.23
158bool(true)
159creating receive socket
160resource(%d) of type (Socket)
161bool(true)
162bool(true)
163int(14)
1641> initial packet
165leaving group
166bool(true)
167int(20)
168int(14)
1692> unicast packet
170re-joining group
171bool(true)
172int(42)
173int(12)
1743> mcast packet
175blocking source
176bool(true)
177int(31)
178int(14)
1794> unicast packet
180unblocking source
181bool(true)
182int(27)
1835> mcast packet from 127.0.0.1
184leaving group
185bool(true)
186int(20)
187int(14)
1886> unicast packet
189joining source group
190bool(true)
191int(27)
1927> mcast packet from 127.0.0.1
193leaving source group
194bool(true)
195int(20)
196int(14)
1978> unicast packet
198