1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
use failure::Error; use libmodbus_sys as ffi; use modbus::Modbus; use std::ffi::CString; /// The TCP PI (Protocol Independent) backend implements a Modbus variant used for communications over TCP IPv4 and /// IPv6 networks. /// It does not require a checksum calculation as lower layer takes care of the same. /// /// Contrary to the TCP IPv4 only backend, the TCP PI backend offers hostname resolution but it consumes about 1Kb of /// additional memory. /// /// * Create a Modbus TCP context /// - [`new_tcp_pi()`](struct.Modbus.html#method.new_tcp_pi) /// pub trait ModbusTCPPI { fn new_tcp_pi(node: &str, service: &str) -> Result<Modbus, Error>; fn tcp_pi_accept(&mut self, socket: &mut i32) -> Result<i32, Error>; fn tcp_pi_listen(&mut self, num_connection: i32) -> Result<i32, Error>; } impl ModbusTCPPI for Modbus { /// `new_tcp_pi` - create a libmodbus context for TCP Protocol Independent /// /// The [`new_tcp_pi()`](#method.new_tcp_pi) function shall allocate and initialize a modbus_t structure to /// communicate with a Modbus TCP IPv4 or IPv6 server. /// /// The **node** argument specifies the host name or IP address of the host to connect to, eg. "192.168.0.5" , /// "::1" or "server.com". /// A NULL value can be used to listen any addresses in server mode. /// /// The **service** argument is the service name/port number to connect to. To use the default Modbus port use the /// string "502". /// On many Unix systems, it’s convenient to use a port number greater than or equal to 1024 because it’s not /// necessary to have administrator privileges. /// /// # Examples /// /// ``` /// use libmodbus_rs::{Modbus, ModbusTCPPI}; /// /// let modbus = Modbus::new_tcp_pi("::1", "1502").unwrap(); /// /// match modbus.connect() { /// Ok(_) => {} /// Err(e) => println!("Error: {}", e), /// } /// ``` fn new_tcp_pi(node: &str, service: &str) -> Result<Modbus, Error> { unsafe { let node = CString::new(node).unwrap(); let service = CString::new(service).unwrap(); let ctx = ffi::modbus_new_tcp_pi(node.as_ptr(), service.as_ptr()); if ctx.is_null() { bail!(::std::io::Error::last_os_error()) } else { Ok(Modbus { ctx: ctx }) } } } /// `tcp_pi_accept` - accept a new connection on a TCP PI Modbus socket (IPv6) /// /// The [`tcp_pi_accept()`](#method.tcp_pi_accept) function shall extract the first connection on the /// queue of pending connections and create a new socket given as argument. /// /// # Parameters /// /// * `socket` - Socket /// /// # Examples /// /// ```rust,no_run /// use libmodbus_rs::{Modbus, ModbusMapping, ModbusServer, ModbusTCPPI}; /// /// let mut modbus = Modbus::new_tcp_pi("::0", "1502").unwrap(); /// let mut socket = modbus.tcp_pi_listen(1).unwrap(); /// modbus.tcp_pi_accept(&mut socket).unwrap(); /// ``` fn tcp_pi_accept(&mut self, socket: &mut i32) -> Result<i32, Error> { unsafe { match ffi::modbus_tcp_pi_accept(self.ctx, socket) { -1 => bail!(::std::io::Error::last_os_error()), socket => Ok(socket), } } } /// `tcp_pi_listen` - create and listen a TCP PI Modbus socket (IPv6) /// /// The [`tcp_pi_listen()`](#method.tcp_pi_listen) function shall create a socket and listen to maximum /// `num_connection` incoming connections on the specifieded node. /// /// # Parameters /// /// * `num_connection` - maximum number of incoming connections on the specified IP address /// /// If node is set to `""` or `0.0.0.0`, any addresses will be listen. /// /// # Examples /// /// For detailed examples, look at the examples directory of this crate. /// /// * unit-test-server.rs - simple but handle only one connection /// * bandwidth-server-many-up.rs - handles several connection at once /// /// ```rust,no_run /// use libmodbus_rs::{Modbus, ModbusMapping, ModbusServer, ModbusTCPPI}; /// /// let mut modbus = Modbus::new_tcp_pi("::0", "1502").unwrap(); /// let mut socket = modbus.tcp_pi_listen(1).unwrap(); /// /// modbus.tcp_pi_accept(&mut socket); /// /// let modbus_mapping = ModbusMapping::new(500, 500, 500, 500).unwrap(); /// let mut query = vec![0u8; Modbus::MAX_ADU_LENGTH as usize]; /// /// loop { /// let request_len = modbus.receive(&mut query).unwrap(); /// modbus.reply(&query, request_len, &modbus_mapping); /// } /// ``` fn tcp_pi_listen(&mut self, num_connection: i32) -> Result<i32, Error> { unsafe { match ffi::modbus_tcp_pi_listen(self.ctx, num_connection) { -1 => bail!(::std::io::Error::last_os_error()), socket => Ok(socket), } } } }