- char buf[UDP_AUDIO_HEADER_LEN];
- struct udp_target *ut, *tmp;
- struct udp_audio_header uah = {
- .stream_type = UDP_UNKNOWN_STREAM,
- .packet_type = UDP_EOF_PACKET,
- };
-
- write_udp_audio_header(buf, &uah);
- list_for_each_entry_safe(ut, tmp, &targets, node) {
- if (ut->fd < 0)
- continue;
- write(ut->fd, buf, UDP_AUDIO_HEADER_LEN);
- udp_close_target(ut);
- }
-}
-
-static int need_extra_header(long unsigned current_chunk)
-{
- static struct timeval last_header;
- struct timeval diff;
-
- if (!current_chunk)
- return 0;
- tv_diff(now, &last_header, &diff);
- if (tv2ms(&diff) < conf.udp_header_interval_arg)
- return 0;
- last_header = *now;
- return 1;
-}
-
-static void udp_send(long unsigned current_chunk, __a_unused long unsigned chunks_sent,
- const char *buf, size_t len, const char *header_buf,
- size_t header_len)
-{
- char *sendbuf;
- size_t sendbuf_len;
- struct timeval *chunk_tv;
- struct udp_audio_header uah;
-
-// PARA_NOTICE_LOG("len: %zd, header_len: %zd\n", len, header_len);
- if (sender_status != SENDER_ON)
- return;
-
- /* we might not yet know the chunk time */
- chunk_tv = vss_chunk_time();
- if (!chunk_tv)
- return;
- if (list_empty(&targets))
- return;
- uah.stream_type = header_len? UDP_HEADER_STREAM : UDP_PLAIN_STREAM;
- uah.header_len = need_extra_header(current_chunk)? header_len : 0;
- if (!current_chunk)
- uah.packet_type = UDP_BOF_PACKET;
- else if (uah.header_len)
- uah.packet_type = UDP_HEADER_PACKET;
- else
- uah.packet_type = UDP_DATA_PACKET;
- uah.payload_len = uah.header_len + len;
- sendbuf_len = UDP_AUDIO_HEADER_LEN + uah.payload_len;
- sendbuf = para_malloc(sendbuf_len);
- write_udp_audio_header(sendbuf, &uah);
- if (uah.header_len)
- memcpy(sendbuf + UDP_AUDIO_HEADER_LEN, header_buf,
- uah.header_len);
- memcpy(sendbuf + UDP_AUDIO_HEADER_LEN + uah.header_len, buf, len);
- udp_send_buf(sendbuf, sendbuf_len);
- free(sendbuf);
+ struct sender_client *sc, *tmp;
+ const char *buf;
+ size_t len = vss_get_fec_eof_packet(&buf);
+
+ list_for_each_entry_safe(sc, tmp, &targets, node)
+ if (sc->cq != NULL) {
+ /* ignore return value, closing the target anyway. */
+ (void)write(sc->fd, buf, len);
+ udp_close_target(sc);
+ }