Crate os_socketaddr

source ·
Expand description

This crate provides a type that can act as a platform-native socket address (i.e. libc::sockaddr)

Motivation

The std crate provides SocketAddr for managing socket addresses. However there is no easy way to convert SocketAddr from/into a libc::sockaddr because SocketAddr has a different internal layout.

This crate provides OsSocketAddr which holds a libc::sockaddr (containing an IPv4 or IPv6 address) and the conversion functions:

  • from/into SocketAddr
  • from (*const sockaddr, socklen_t)
  • into (*mut sockaddr, *mut socklen_t)

Example

extern crate libc;
extern crate os_socketaddr;

use std::net::{SocketAddr,UdpSocket};
use self::libc::{c_int, c_void, size_t, ssize_t, sockaddr};
#[cfg(target_family = "unix")]
use libc::socklen_t;
#[cfg(target_family = "windows")]
use winapi::um::ws2tcpip::socklen_t;

use self::os_socketaddr::OsSocketAddr;

////////// unix examples //////////

//
// calling C functions from Rust
//

#[cfg(target_family = "unix")]
fn sendto(socket: c_int, payload: &[u8], dst: SocketAddr) -> ssize_t
{
    let addr : OsSocketAddr = dst.into();
    unsafe {
        libc::sendto(socket, payload.as_ptr() as *const c_void, payload.len() as size_t, 0,
                     addr.as_ptr(), addr.len())
    }
}

#[cfg(target_family = "unix")]
fn recvfrom(socket: c_int, payload: &mut[u8]) -> (ssize_t, Option<SocketAddr>)
{
    let mut addr = OsSocketAddr::new();
    let mut addrlen = addr.capacity();
    let nb = unsafe {
        libc::recvfrom(socket, payload.as_mut_ptr() as *mut c_void, payload.len(), 0,
                       addr.as_mut_ptr(), &mut addrlen as *mut _)
    };
    (nb, addr.into())
}

//
// calling Rust functions from C
//

#[cfg(target_family = "unix")]
#[no_mangle]
pub unsafe extern "C" fn send_to(
        sock: *const UdpSocket, buf: *const u8, buflen: size_t,
        addr: *const sockaddr, addrlen: socklen_t) -> ssize_t
{
 
    let Some(dst) = OsSocketAddr::copy_from_raw(addr, addrlen).into_addr() else {
        // not an IPv4/IPv6 address
        return -1;
    };
    let slice = std::slice::from_raw_parts(buf, buflen);
    match (*sock).send_to(&slice, dst) {
        Ok(nb) => nb as ssize_t,
        Err(_) => -1,
    }
}

#[cfg(target_family = "unix")]
#[no_mangle]
pub unsafe extern "C" fn recv_from(
        sock: *const UdpSocket, buf: *mut u8, buflen: size_t,
        addr: *mut sockaddr, addrlen: *mut socklen_t) -> ssize_t
{
    let slice = std::slice::from_raw_parts_mut(buf, buflen);
    match (*sock).recv_from(slice) {
        Ok((nb, src)) => {
            OsSocketAddr::from(src).copy_to_raw(addr, addrlen);
            nb as ssize_t
        },
        Err(_) => -1,
    }
}

////////// windows examples //////////

//
// calling C functions from Rust
//

#[cfg(target_family = "windows")]
fn sendto(socket: winapi::um::winsock2::SOCKET,
          payload: &mut winapi::shared::ws2def::WSABUF,
          dst: SocketAddr) -> ssize_t
{
    let addr : OsSocketAddr = dst.into();
    let mut nb : u32 = 0;
    match unsafe {
        winapi::um::winsock2::WSASendTo(socket, payload, 1u32, &mut nb, 0u32,
                                        addr.as_ptr(), addr.len() as i32,
                                        std::ptr::null_mut::<winapi::um::minwinbase::OVERLAPPED>(), None)
    } {
        0 => nb as ssize_t,
        _ => -1,
    }
}

#[cfg(target_family = "windows")]
fn recvfrom(socket: winapi::um::winsock2::SOCKET,
            payload: &mut winapi::shared::ws2def::WSABUF) -> (ssize_t, Option<SocketAddr>)
{
    let mut addr = OsSocketAddr::new();
    let mut addrlen = addr.capacity();
    let mut nb : u32 = 0;
    let mut flags : u32 = 0;
    match unsafe {
        winapi::um::winsock2::WSARecvFrom(socket, payload, 1u32, &mut nb, &mut flags,
                                          addr.as_mut_ptr(), &mut addrlen as *mut _,
                                          std::ptr::null_mut::<winapi::um::minwinbase::OVERLAPPED>(), None)
    } {
        0 => (nb as ssize_t, addr.into()),
        _ => (-1, None),
    }
}

Structs

Type Definitions

Unions

  • A type for handling platform-native socket addresses (struct sockaddr)