nrfxlib/udp.rs
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 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
//! # UDP Sockets for nrfxlib
//!
//! UDP socket related code.
//!
//! Copyright (c) 42 Technology Ltd 2019
//!
//! Dual-licensed under MIT and Apache 2.0. See the [README](../README.md) for
//! more details.
//******************************************************************************
// Sub-Modules
//******************************************************************************
// None
//******************************************************************************
// Imports
//******************************************************************************
use super::{get_last_error, Error};
use crate::raw::*;
use log::debug;
use nrfxlib_sys as sys;
//******************************************************************************
// Types
//******************************************************************************
/// Represents a connection to a remote TCP/IP device using plain UDP
#[derive(Debug)]
pub struct UdpSocket {
socket: Socket,
}
//******************************************************************************
// Constants
//******************************************************************************
// None
//******************************************************************************
// Global Variables
//******************************************************************************
// None
//******************************************************************************
// Macros
//******************************************************************************
// None
//******************************************************************************
// Public Functions and Impl on Public Types
//******************************************************************************
// None
//******************************************************************************
// Private Functions and Impl on Private Types
//******************************************************************************
impl UdpSocket {
/// Create a new TCP socket.
pub fn new() -> Result<UdpSocket, Error> {
let socket = Socket::new(
SocketDomain::Inet,
SocketType::Datagram,
SocketProtocol::Udp,
)?;
// Now configure this socket
Ok(UdpSocket { socket })
}
/// Look up the hostname and for each result returned, try to connect to
/// it.
pub fn connect(&self, hostname: &str, port: u16) -> Result<(), Error> {
use core::fmt::Write;
debug!("Connecting via UDP to {}:{}", hostname, port);
// Now, make a null-terminated hostname
let mut hostname_smallstring: heapless::String<64> = heapless::String::new();
write!(hostname_smallstring, "{}\0", hostname).map_err(|_| Error::HostnameTooLong)?;
// Now call getaddrinfo with some hints
let hints = sys::nrf_addrinfo {
ai_flags: 0,
ai_family: sys::NRF_AF_INET as i32,
ai_socktype: sys::NRF_SOCK_DGRAM as i32,
ai_protocol: 0,
ai_addrlen: 0,
ai_addr: core::ptr::null_mut(),
ai_canonname: core::ptr::null_mut(),
ai_next: core::ptr::null_mut(),
};
let mut output_ptr: *mut sys::nrf_addrinfo = core::ptr::null_mut();
let mut result = unsafe {
sys::nrf_getaddrinfo(
// hostname
hostname_smallstring.as_ptr(),
// service
core::ptr::null(),
// hints
&hints,
// output pointer
&mut output_ptr,
)
};
if (result == 0) && (!output_ptr.is_null()) {
let mut record: &sys::nrf_addrinfo = unsafe { &*output_ptr };
loop {
let dns_addr: &sys::nrf_sockaddr_in =
unsafe { &*(record.ai_addr as *const sys::nrf_sockaddr_in) };
// Create a new sockaddr_in with the right port
let connect_addr = sys::nrf_sockaddr_in {
sin_len: core::mem::size_of::<sys::nrf_sockaddr_in>() as u8,
sin_family: sys::NRF_AF_INET as i32,
sin_port: htons(port),
sin_addr: dns_addr.sin_addr,
};
debug!("Trying IP address {}", &crate::NrfSockAddrIn(connect_addr));
// try and connect to this result
result = unsafe {
sys::nrf_connect(
self.socket.fd,
&connect_addr as *const sys::nrf_sockaddr_in as *const _,
connect_addr.sin_len as u32,
)
};
if result == 0 {
break;
}
if !record.ai_next.is_null() {
record = unsafe { &*record.ai_next };
} else {
break;
}
}
unsafe {
sys::nrf_freeaddrinfo(output_ptr);
}
}
if result != 0 {
Err(Error::Nordic("udp_connect", result, get_last_error()))
} else {
Ok(())
}
}
}
impl Pollable for UdpSocket {
/// Get the underlying socket ID for this socket.
fn get_fd(&self) -> i32 {
self.socket.fd
}
}
impl core::ops::DerefMut for UdpSocket {
fn deref_mut(&mut self) -> &mut Socket {
&mut self.socket
}
}
impl core::ops::Deref for UdpSocket {
type Target = Socket;
fn deref(&self) -> &Socket {
&self.socket
}
}
//******************************************************************************
// End of File
//******************************************************************************