178 |
178 |
return -1;
|
179 |
179 |
}
|
180 |
180 |
|
|
181 |
static void
|
|
182 |
iptv_udp_stop ( iptv_mux_t *im)
|
|
183 |
{
|
|
184 |
int solip, ipv6 = 0;
|
|
185 |
struct ifreq ifr;
|
|
186 |
struct in_addr saddr;
|
|
187 |
struct in6_addr s6addr;
|
|
188 |
char name[256], buf[256];
|
|
189 |
url_t url;
|
|
190 |
|
|
191 |
im->mm_display_name((mpegts_mux_t*)im, name, sizeof(name));
|
|
192 |
|
|
193 |
/* Parse URL */
|
|
194 |
im->mm_display_name((mpegts_mux_t*)im, buf, sizeof(buf));
|
|
195 |
if (urlparse(im->mm_iptv_url ?: "", &url)) {
|
|
196 |
tvherror("iptv", "%s - invalid URL [%s]", buf, im->mm_iptv_url);
|
|
197 |
return;
|
|
198 |
}
|
|
199 |
|
|
200 |
/* Determine if this is IPv6 */
|
|
201 |
if (!inet_pton(AF_INET, url.host, &saddr)) {
|
|
202 |
ipv6 = 1;
|
|
203 |
if (!inet_pton(AF_INET6, url.host, &s6addr)) {
|
|
204 |
tvherror("iptv", "%s - failed to stop (invalid addr)", name);
|
|
205 |
return;
|
|
206 |
}
|
|
207 |
}
|
|
208 |
|
|
209 |
if (im->mm_iptv_fd < 0) {
|
|
210 |
tvherror("iptv", "%s - failed to stop (invalid fd)", name);
|
|
211 |
return;
|
|
212 |
}
|
|
213 |
|
|
214 |
/* Bind to interface */
|
|
215 |
memset(&ifr, 0, sizeof(ifr));
|
|
216 |
if (im->mm_iptv_interface && *im->mm_iptv_interface) {
|
|
217 |
snprintf(ifr.ifr_name, IFNAMSIZ, "%s", im->mm_iptv_interface);
|
|
218 |
if (ioctl(im->mm_iptv_fd, SIOCGIFINDEX, &ifr)) {
|
|
219 |
tvherror("iptv", "%s - could not find interface %s",
|
|
220 |
name, im->mm_iptv_interface);
|
|
221 |
return;
|
|
222 |
}
|
|
223 |
}
|
|
224 |
|
|
225 |
/* IPv4 */
|
|
226 |
if (!ipv6) {
|
|
227 |
struct ip_mreqn m;
|
|
228 |
struct sockaddr_in sin;
|
|
229 |
memset(&m, 0, sizeof(m));
|
|
230 |
memset(&sin, 0, sizeof(sin));
|
|
231 |
|
|
232 |
/* Prepare */
|
|
233 |
sin.sin_family = AF_INET;
|
|
234 |
sin.sin_port = htons(url.port);
|
|
235 |
sin.sin_addr = saddr;
|
|
236 |
|
|
237 |
/* Leave group */
|
|
238 |
m.imr_multiaddr = sin.sin_addr;
|
|
239 |
m.imr_address.s_addr = 0;
|
|
240 |
#if defined(PLATFORM_LINUX)
|
|
241 |
m.imr_ifindex = ifr.ifr_ifindex;
|
|
242 |
#elif defined(PLATFORM_FREEBSD)
|
|
243 |
m.imr_ifindex = ifr.ifr_index;
|
|
244 |
#endif
|
|
245 |
#ifdef SOL_IP
|
|
246 |
solip = SOL_IP;
|
|
247 |
#else
|
|
248 |
{
|
|
249 |
struct protoent *pent;
|
|
250 |
pent = getprotobyname("ip");
|
|
251 |
solip = (pent != NULL) ? pent->p_proto : 0;
|
|
252 |
}
|
|
253 |
#endif
|
|
254 |
tvhlog(LOG_INFO, "iptv_udp" , "now leaving group");
|
|
255 |
if (setsockopt(im->mm_iptv_fd, solip, IP_DROP_MEMBERSHIP, &m, sizeof(m))) {
|
|
256 |
inet_ntop(AF_INET, &m.imr_multiaddr, buf, sizeof(buf));
|
|
257 |
tvhwarn("iptv", "%s - cannot drop membership %s [%s]",
|
|
258 |
name, buf, strerror(errno));
|
|
259 |
}
|
|
260 |
|
|
261 |
/* Bind to IPv6 group */
|
|
262 |
} else {
|
|
263 |
struct ipv6_mreq m;
|
|
264 |
struct sockaddr_in6 sin;
|
|
265 |
memset(&m, 0, sizeof(m));
|
|
266 |
memset(&sin, 0, sizeof(sin));
|
|
267 |
|
|
268 |
/* Prepare */
|
|
269 |
sin.sin6_family = AF_INET6;
|
|
270 |
sin.sin6_port = htons(url.port);
|
|
271 |
sin.sin6_addr = s6addr;
|
|
272 |
|
|
273 |
/* Leave group */
|
|
274 |
m.ipv6mr_multiaddr = sin.sin6_addr;
|
|
275 |
#if defined(PLATFORM_LINUX)
|
|
276 |
m.ipv6mr_interface = ifr.ifr_ifindex;
|
|
277 |
#elif defined(PLATFORM_FREEBSD)
|
|
278 |
m.ipv6mr_interface = ifr.ifr_index;
|
|
279 |
#endif
|
|
280 |
#ifdef SOL_IPV6
|
|
281 |
if (setsockopt(im->mm_iptv_fd, SOL_IPV6, IPV6_DROP_MEMBERSHIP, &m, sizeof(m))) {
|
|
282 |
inet_ntop(AF_INET, &m.ipv6mr_multiaddr, buf, sizeof(buf));
|
|
283 |
tvhwarn("iptv", "%s - cannot join drop membership %s [%s]",
|
|
284 |
name, buf, strerror(errno));
|
|
285 |
}
|
|
286 |
#else
|
|
287 |
tvherror("iptv", "IPv6 multicast not supported");
|
|
288 |
#endif
|
|
289 |
}
|
|
290 |
|
|
291 |
/* Done */
|
|
292 |
// close(im->mm_iptv_fd);
|
|
293 |
}
|
|
294 |
|
181 |
295 |
static ssize_t
|
182 |
296 |
iptv_udp_read ( iptv_mux_t *im, size_t *off )
|
183 |
297 |
{
|
... | ... | |
242 |
356 |
{
|
243 |
357 |
.scheme = "udp",
|
244 |
358 |
.start = iptv_udp_start,
|
|
359 |
.stop = iptv_udp_stop,
|
245 |
360 |
.read = iptv_udp_read,
|
246 |
361 |
},
|
247 |
362 |
{
|
248 |
363 |
.scheme = "rtp",
|
249 |
364 |
.start = iptv_udp_start,
|
|
365 |
.stop = iptv_udp_stop,
|
250 |
366 |
.read = iptv_rtp_read,
|
251 |
367 |
}
|
252 |
368 |
};
|
253 |
|
-
|