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