From b266b47ec7da4a1d307c6389d43034e75a71d0be Mon Sep 17 00:00:00 2001 From: cbdev Date: Thu, 1 Mar 2018 17:09:21 +0100 Subject: Implement sACN universe discovery, update configuration syntax --- sacn.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- sacn.h | 9 +++++++-- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/sacn.c b/sacn.c index e12157e..b807e2b 100644 --- a/sacn.c +++ b/sacn.c @@ -226,7 +226,7 @@ static int sacn_configure_instance(instance* inst, char* option, char* value){ data->uni = strtoul(value, NULL, 10); return 0; } - else if(!strcmp(option, "iface")){ + else if(!strcmp(option, "interface")){ data->fd_index = strtoul(value, NULL, 10); if(data->fd_index >= global_cfg.fds){ @@ -239,7 +239,7 @@ static int sacn_configure_instance(instance* inst, char* option, char* value){ data->xmit_prio = strtoul(value, NULL, 10); return 0; } - else if(!strcmp(option, "dest")){ + else if(!strcmp(option, "destination")){ if(sacn_parse_hostspec(value, &host, &port, NULL)){ fprintf(stderr, "Not a valid sACN destination for instance %s: %s\n", inst->name, value); return 1; @@ -474,6 +474,54 @@ static int sacn_process_frame(instance* inst, sacn_frame_root* frame, sacn_frame return 0; } +static void sacn_discovery(size_t fd){ + size_t page = 0, pages = (global_cfg.fd[fd].universes / 512) + 1, universes; + struct sockaddr_in discovery_dest = { + .sin_family = AF_INET, + .sin_port = htobe16(SACN_PORT), + .sin_addr.s_addr = htobe32(((uint32_t) 0xefff0000) | 64214) + }; + + sacn_discovery_pdu pdu = { + .root = { + .preamble_size = htobe16(0x10), + .postamble_size = 0, + .magic = { 0 }, //memcpy'd + .flags = 0, //filled later + .vector = htobe32(ROOT_E131_EXTENDED), + .sender_cid = { 0 }, //memcpy'd + .frame_flags = 0, //filled later + .frame_vector = htobe32(FRAME_E131_DISCOVERY) + }, + .data = { + .source_name = "", //memcpy'd + .flags = 0, //filled later + .vector = htobe32(DISCOVERY_UNIVERSE_LIST), + .page = 0, //filled later + .max_page = pages - 1, + .data = { 0 } //memcpy'd + } + }; + + memcpy(pdu.root.magic, SACN_PDU_MAGIC, sizeof(pdu.root.magic)); + memcpy(pdu.root.sender_cid, global_cfg.cid, sizeof(pdu.root.sender_cid)); + memcpy(pdu.data.source_name, global_cfg.source_name, sizeof(pdu.data.source_name)); + + for(; page < pages; page++){ + universes = (global_cfg.fd[fd].universes - page * 512 >= 512) ? 512 : (global_cfg.fd[fd].universes % 512); + pdu.root.flags = htobe16(0x7000 | (104 + universes * sizeof(uint16_t))); + pdu.root.frame_flags = htobe16(0x7000 | (82 + universes * sizeof(uint16_t))); + pdu.data.flags = htobe16(0x7000 | (8 + universes * sizeof(uint16_t))); + + pdu.data.page = page; + memcpy(pdu.data.data, global_cfg.fd[fd].universe + page * 512, universes); + + if(sendto(global_cfg.fd[fd].fd, &pdu, sizeof(pdu) - (512 - universes) * sizeof(uint16_t), 0, (struct sockaddr*) &discovery_dest, sizeof(discovery_dest)) < 0){ + fprintf(stderr, "Failed to output sACN universe discovery frame for interface %zu: %s\n", fd, strerror(errno)); + } + } +} + static int sacn_handle(size_t num, managed_fd* fds){ size_t u; ssize_t bytes_read; @@ -485,9 +533,14 @@ static int sacn_handle(size_t num, managed_fd* fds){ sacn_frame_root* frame = (sacn_frame_root*) recv_buf; sacn_frame_data* data = (sacn_frame_data*) (recv_buf + sizeof(sacn_frame_root)); - if(global_cfg.last_announce > SACN_DISCOVERY_TIMEOUT){ - //TODO send universe discovery pdu - //TODO this requires the core to provide time deltas + if(mm_timestamp() - global_cfg.last_announce > SACN_DISCOVERY_TIMEOUT){ + //send universe discovery pdu + for(u = 0; u < global_cfg.fds; u++){ + if(global_cfg.fd[u].universes){ + sacn_discovery(u); + } + } + global_cfg.last_announce = mm_timestamp(); } //early exit diff --git a/sacn.h b/sacn.h index 6355550..7804eaf 100644 --- a/sacn.h +++ b/sacn.h @@ -13,7 +13,7 @@ static int sacn_shutdown(); #define SACN_PORT "5568" #define SACN_RECV_BUF 8192 -#define SACN_DISCOVERY_TIMEOUT 100000 +#define SACN_DISCOVERY_TIMEOUT 9000 #define SACN_PDU_MAGIC "ASC-E1.17\0\0\0" #define MAP_COARSE 0x0200 @@ -100,13 +100,18 @@ typedef struct /*_sacn_frame_discovery*/ { uint32_t vector; uint8_t page; uint8_t max_page; - uint16_t universes[512]; + uint16_t data[512]; } sacn_frame_discovery; typedef struct /*_sacn_xmit_data*/ { sacn_frame_root root; sacn_frame_data data; } sacn_data_pdu; + +typedef struct /*_sacn_xmit_discovery*/ { + sacn_frame_root root; + sacn_frame_discovery data; +} sacn_discovery_pdu; #pragma pack(pop) #define ROOT_E131_DATA 0x4 -- cgit v1.2.3