sacn_unofficial/lib.rs
1// Copyright 2020 sacn Developers
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7//
8// This file was modified as part of a University of St Andrews Computer Science BSC Senior Honours Dissertation Project.
9
10//! Implementation of the sACN network protocol.
11//!
12//! This crate implements the Streaming ACN (sACN) network protocol as specified in ANSI E1.31-2018. Streaming ACN is built on top of and is
13//! compatible with the ACN protocol suite (ANSI E1.17-2015). This library supports sending and receiving data, universe synchronisation and
14//! universe discovery. This library supports linux (fully) and windows (no receiving multicast) and IP unicast, multicast and broadcast.
15//!
16//! Installation instructions are detailed within the README file.
17//!
18//!
19//!
20//! This file was modified as part of a University of St Andrews Computer Science BSC Senior Honours Dissertation Project.
21//!
22//! # Examples
23//!
24//! Creating an sACN receiver and receiving data. This automatically handles receiving synchronised data at the right time with the array of received data
25//! containing all the data which should be acted upon at the same time (so if there are 2 synchronised data packets the array will have length 2).
26//! ```
27//! use sacn::receive::SacnReceiver;
28//! use sacn::packet::ACN_SDT_MULTICAST_PORT;
29//!
30//! use std::net::{IpAddr, Ipv4Addr, SocketAddr};
31//! use std::time::Duration;
32//!
33//! const UNIVERSE1: u16 = 1;
34//! const TIMEOUT: Option<Duration> = Some(Duration::from_secs(1)); // A timeout of None means blocking behaviour, some indicates the actual timeout.
35//!
36//! let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), ACN_SDT_MULTICAST_PORT);
37//!
38//! let mut dmx_rcv = SacnReceiver::with_ip(addr, None).unwrap();
39//!
40//! dmx_rcv.listen_universes(&[UNIVERSE1]).unwrap();
41//!
42//! // .recv(TIMEOUT) handles processing synchronised as-well as normal data.
43//! match dmx_rcv.recv(TIMEOUT) {
44//! Err(e) => {
45//! // Print out the error.
46//! println!("{:?}", e);
47//! }
48//! Ok(p) => {
49//! // Print out the data.
50//! println!("{:?}", p);
51//! }
52//! }
53//! ```
54//!
55//! Creating an sACN receiver and checking for discovered sources through universe discovery.
56//! ```
57//! use sacn::receive::SacnReceiver;
58//! use sacn::packet::ACN_SDT_MULTICAST_PORT;
59//!
60//! use std::net::{IpAddr, Ipv4Addr, SocketAddr};
61//! use std::time::Duration;
62//!
63//! const TIMEOUT: Option<Duration> = Some(Duration::from_secs(1)); // A timeout of None means blocking behaviour, some indicates the actual timeout.
64//!
65//! let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), ACN_SDT_MULTICAST_PORT);
66//!
67//! // Creating the receiver, automatically listens for universe discovery packets.
68//! let mut dmx_rcv = SacnReceiver::with_ip(addr, None).unwrap();
69//!
70//! // Cause source discovery to be announced by a returned error. If this isn't true then discovery packets are still handled by the user must poll
71//! // the discovered sources list periodically as there will be no announcement that a discovery packet has been processed. By default this option is
72//! // off (false) based on the assumption that when receiving data the majority of the time the receiver just wants to process more data from the same
73//! // universe and doesn't want to discover sources.
74//! dmx_rcv.set_announce_source_discovery(true);
75//!
76//! // Receive for a short period, no data is expected but this allows universe discovery packets to be received.
77//! // This example will always timeout if run in isolation as there are no sources running on the network.
78//! match dmx_rcv.recv(TIMEOUT) {
79//! Err(e) => {
80//! match e.kind() {
81//! sacn::error::errors::ErrorKind::SourceDiscovered(source_name) => {
82//! println!("Source name: {} discovered!", source_name);
83//! }
84//! other => {
85//! // Print out the error.
86//! println!("{:?}", other);
87//! }
88//! }
89//! }
90//! Ok(p) => {
91//! // Print out the data. Note that no data is expected as no universes are registered for receiving data.
92//! println!("{:?}", p);
93//! }
94//! }
95//! ```
96//!
97//! Creating a sACN sender and sending some unsychronised data. An sACNSender automatically sends universe discovery packets.
98//!
99//! ```
100//! use sacn::source::SacnSource;
101//! use sacn::packet::ACN_SDT_MULTICAST_PORT;
102//! use std::net::{IpAddr, SocketAddr};
103//!
104//! let local_addr: SocketAddr = SocketAddr::new(IpAddr::V4("0.0.0.0".parse().unwrap()), ACN_SDT_MULTICAST_PORT + 1);
105//!
106//! let mut src = SacnSource::with_ip("Source", local_addr).unwrap();
107//!
108//! let universe: u16 = 1; // Universe the data is to be sent on.
109//! let sync_uni: Option<u16> = None; // Don't want the packet to be delayed on the receiver awaiting synchronisation.
110//! let priority: u8 = 100; // The priority for the sending data, must be 1-200 inclusive, None means use default.
111//! let dst_ip: Option<SocketAddr> = None; // Sending the data using IP multicast so don't have a destination IP.
112//!
113//! src.register_universe(universe).unwrap(); // Register with the source that will be sending on the given universe.
114//!
115//! let mut data: Vec<u8> = vec![0, 0, 0, 0, 255, 255, 128, 128]; // Some arbitrary data, must have length <= 513 (including start-code).
116//!
117//! src.send(&[universe], &data, Some(priority), dst_ip, sync_uni).unwrap(); // Actually send the data
118//!
119//! ```
120//!
121//! Creating a sACN sender and sending some synchronised data.
122//!
123//! ```
124//! use sacn::source::SacnSource;
125//! use sacn::packet::ACN_SDT_MULTICAST_PORT;
126//!
127//! use std::net::{IpAddr, SocketAddr};
128//! use std::thread::sleep;
129//! use std::time::Duration;
130//!
131//! let local_addr: SocketAddr = SocketAddr::new(IpAddr::V4("0.0.0.0".parse().unwrap()), ACN_SDT_MULTICAST_PORT + 1);
132//!
133//! let mut src = SacnSource::with_ip("Source", local_addr).unwrap();
134//!
135//! let universe: u16 = 1; // Universe the data is to be sent on.
136//! let sync_uni: Option<u16> = Some(1); // Data packets use a synchronisation address of 1.
137//! let priority: u8 = 100; // The priority for the sending data, must be 1-200 inclusive, None means use default.
138//! let dst_ip: Option<SocketAddr> = None; // Sending the data using IP multicast so don't have a destination IP.
139//!
140//! src.register_universe(universe).unwrap(); // Register with the source that will be sending on the given universe.
141//!
142//! let mut data: Vec<u8> = vec![0, 0, 0, 0, 255, 255, 128, 128]; // Some arbitrary data, must have length <= 513 (including start-code).
143//!
144//! // Actually send the data, since the sync_uni is not 0 the data will be synchronised at the receiver (if the receiver supports synchronisation).
145//! src.send(&[universe], &data, Some(priority), dst_ip, sync_uni).unwrap();
146//!
147//! // A small delay between sending data and sending the sync packet as recommend in ANSI E1.31-2018 Section 11.2.2.
148//! sleep(Duration::from_millis(10));
149//!
150//! // To actually trigger the data need to send a synchronisation packet like so.
151//! src.send_sync_packet(sync_uni.unwrap(), dst_ip).unwrap();
152//! ```
153//!
154//! Creating a sACN sender and sending data using unicast.
155//!
156//! ```
157//! use sacn::source::SacnSource;
158//! use sacn::packet::ACN_SDT_MULTICAST_PORT;
159//!
160//! use std::net::{IpAddr, SocketAddr};
161//! use std::thread::sleep;
162//! use std::time::Duration;
163//!
164//! let local_addr: SocketAddr = SocketAddr::new(IpAddr::V4("0.0.0.0".parse().unwrap()), ACN_SDT_MULTICAST_PORT + 1);
165//!
166//! let mut src = SacnSource::with_ip("Source", local_addr).unwrap();
167//!
168//! let universe: u16 = 1; // Universe the data is to be sent on.
169//! let sync_uni: Option<u16> = None; // Data packets are unsynchronised in this example but unicast transmission supports synchronised and unsynchronised sending.
170//! let priority: Option<u8> = Some(100); // The priority for the sending data, must be 1-200 inclusive, None means use default.
171//!
172//! // To send using unicast the dst_ip argument is set to a Some() value with the address to send the data to. By default the port should be the
173//! // ACN_SDT_MULTICAST_PORT but this can be configured differently if required in a specific situation. Change this address to the correct address for your
174//! // application, 192.168.0.1 is just a stand-in.
175//! let destination_address: SocketAddr = SocketAddr::new(IpAddr::V4("192.168.0.1".parse().unwrap()), ACN_SDT_MULTICAST_PORT);
176//! let dst_ip: Option<SocketAddr> = Some(destination_address);
177//!
178//! src.register_universe(universe).unwrap(); // Register with the source that will be sending on the given universe.
179//!
180//! let mut data: Vec<u8> = vec![0, 0, 0, 0, 255, 255, 128, 128]; // Some arbitrary data, must have length <= 513 (including start-code).
181//!
182//! // Actually send the data, since the sync_uni is not 0 the data will be synchronised at the receiver (if the receiver supports synchronisation).
183//! src.send(&[universe], &data, priority, dst_ip, sync_uni).unwrap();
184//! ```
185
186#![doc(html_root_url = "https://docs.rs/sacn/")]
187// #![warn(missing_docs)]
188// Recursion limit for error_chain.
189#![recursion_limit="1024"]
190
191#[macro_use]
192extern crate error_chain;
193
194/// The errors within the sACN crate related to parse/pack errors.
195/// Error-chain is used for errors within the library to allow chaining errors together to provide more informative backtraces.
196/// This completely replaces the old error system (sACN crate version 0.4.4) which relied on a simple Enum model without proper backtraces.
197pub mod sacn_parse_pack_error;
198
199/// The errors used within the sACN crate, parse/pack errors are seperated out into sacn_parse_pack_error.
200pub mod error;
201
202/// The library is built on top of socket2 to provide the underlying UDP networking interface.
203extern crate socket2;
204extern crate libc;
205
206/// The core crate is used for string processing during packet parsing/packing as well as to provide access to the Hash trait.
207extern crate core;
208
209/// The byteorder crate is used for marshalling data on/off the network in Network Byte Order.
210extern crate byteorder;
211
212/// The uuid crate is used for working with/generating UUIDs which sACN uses as part of the cid field in the protocol.
213extern crate uuid;
214
215/// The packet module handles the sACN packets including parsing/packing and sACN related constants.
216pub mod packet;
217
218/// The source module handles generation of sACN on the network.
219pub mod source;
220
221/// The receive module handles the receiving of sACN on the network.
222pub mod receive;