socket9 0.1.0-alpha.1

Extended untilities for the networking/unix sockets and raw network sockets
Documentation
#![cfg(windows)]

mod common;

use std::
{
    io::{ErrorKind, IoSlice, IoSliceMut, Read, Write}, 
    net::{TcpListener, TcpStream, UdpSocket}, 
    os::windows::io::OwnedSocket,  
    time::Duration
};

use socket9::{address::{So9DomainInets}, socket::Socket9};

use uds_fork::{WindowsUnixListener, WindowsUnixStream};

use common::make_temp_dir;



#[test]
fn check_cloexec()
{
    let val = Socket9::<UdpSocket>::new_unbound(So9DomainInets::Inet).unwrap();

    val.set_cloexec_sock(false).unwrap();

    val.set_cloexec_sock(true).unwrap();
}

#[test]
fn check_nonblocking()
{
    let val = Socket9::<UdpSocket>::new_unbound(So9DomainInets::Inet).unwrap();

    val.set_nonblocking(true).unwrap();


    val.set_nonblocking(false).unwrap();
}

#[test]
fn test_tcp_bind_connect()
{
    let tcp_listen = Socket9::<TcpListener>::new_with_bind_listen(&"127.0.0.2:8888", 1).unwrap();

    let tcp_conn = Socket9::<TcpStream>::new_unbound(So9DomainInets::Inet).unwrap();

    tcp_conn.connect("127.0.0.2:8888").unwrap();

    let accepted_conn = tcp_listen.accept().unwrap();


    let data = [1,2,3, 9];
    accepted_conn.0.send(&data[..3]).unwrap();

    let mut rcv_data = [0_u8; 4];
    let rcv_n = tcp_conn.recv(&mut rcv_data).unwrap();

    assert_eq!(rcv_n, 3);
    assert_eq!(&data[0..rcv_n], &rcv_data[0..rcv_n]);

    drop(accepted_conn);
    drop(tcp_conn);
    drop(tcp_listen);
}

#[test]
fn test_tcp_bind_connect_with_timeout()
{
    let tcp_listen = Socket9::<TcpListener>::new_with_bind_listen(&"127.0.0.2:8889", 1).unwrap();

    let tcp_conn = Socket9::<TcpStream>::new_unbound(So9DomainInets::Inet).unwrap();

    tcp_conn.connect_timeout("127.0.0.2:8889", Duration::from_millis(200)).unwrap();

    let accepted_conn = tcp_listen.accept().unwrap();


    let data = [1,2,3, 9];
    accepted_conn.0.send(&data[..3]).unwrap();

    let mut rcv_data = [0_u8; 4];
    let rcv_n = tcp_conn.recv(&mut rcv_data).unwrap();

    assert_eq!(rcv_n, 3);
    assert_eq!(&data[0..rcv_n], &rcv_data[0..rcv_n]);

    drop(accepted_conn);
    drop(tcp_conn);
    drop(tcp_listen);
}


#[test]
fn test_tcp_bind_connect_timmeout()
{
    let tcp_conn = Socket9::<TcpStream>::new_unbound(So9DomainInets::Inet).unwrap();

    let res = tcp_conn.connect_timeout("10.255.255.1:80", Duration::from_secs(1));

    assert_eq!(res.is_err(), true);
    let err = res.err().as_ref().unwrap().kind();
    assert!(err == ErrorKind::HostUnreachable || err == ErrorKind::TimedOut);
}

#[test]
fn test_try_from_ownedfd_udpsock()
{
    let udp = UdpSocket::bind("127.0.0.1:0").unwrap();

    let val = Socket9::<UdpSocket>::try_from(OwnedSocket::from(udp)).unwrap();

    let _udp: UdpSocket = val.into();
}

#[test]
fn test_try_pair()
{
    let (a, b) = Socket9::<WindowsUnixStream>::pair().unwrap();

    let data = [1,2,3,4];

    let snd_n = a.send(&data[..3]).unwrap();

    let mut rcv_data = [0_u8; 4];

    let rcv_n = b.recv(&mut rcv_data).unwrap();

    assert_eq!(rcv_n, snd_n);
    assert_eq!(&data[0..snd_n], &rcv_data[0..rcv_n]);
}

#[test]
fn test_try_from_ownedsock_wus()
{
    let (test_path, _dir) = make_temp_dir("test_sock");

    let unix_dgram = WindowsUnixListener::bind(&test_path).unwrap();

    let val = Socket9::<WindowsUnixListener>::try_from(OwnedSocket::from(unix_dgram)).unwrap();

    let _unix_dgram: WindowsUnixListener = val.into();
}


#[test]
fn test_try_from_pair_ownedfd_unixdg()
{
    let (a, b) = Socket9::<WindowsUnixStream>::pair().unwrap();

    let a: WindowsUnixStream = a.into();

    let data = [1,2,3,4];

    let snd_n = a.send(&data[..3]).unwrap();

    let mut rcv_data = [0_u8; 4];

    let rcv_n = b.recv(&mut rcv_data).unwrap();

    assert_eq!(rcv_n, snd_n);
    assert_eq!(&data[0..snd_n], &rcv_data[0..rcv_n]);
}


#[test]
fn test_try_from_ownedfd_unixlistener()
{
    let (test_path, _dir) = make_temp_dir("test_sock_test1");

    let unix_stream = WindowsUnixListener::bind(&test_path).unwrap();

    let val = Socket9::<WindowsUnixListener>::try_from(OwnedSocket::from(unix_stream)).unwrap();

    let _unix_stream: WindowsUnixListener = val.into();
}

#[test]
fn test_try_from_ownedfd_unixlistener_conn()
{
    let (test_path, _dir) = make_temp_dir("test_sock_test1");

    let _unix_listen = WindowsUnixListener::bind(&test_path).unwrap();

    let unix_listen_conn = WindowsUnixStream::connect(&test_path).unwrap();

    let val = Socket9::<WindowsUnixStream>::try_from(OwnedSocket::from(unix_listen_conn)).unwrap();

    let _unix_stream: WindowsUnixStream = val.into();

}


#[test]
fn test_try_from_pair_ownedfd_unixstream()
{
    let (a, b) = Socket9::<WindowsUnixStream>::pair().unwrap();

    let mut a: WindowsUnixStream = a.into();

    let data = [1,2,3,4];

    let snd_n = a.write(&data[..3]).unwrap();

    let mut rcv_data = [0_u8; 4];

    let rcv_n = b.recv(&mut rcv_data).unwrap();

    assert_eq!(rcv_n, snd_n);
    assert_eq!(&data[0..snd_n], &rcv_data[0..rcv_n]);

    let snd_n = b.send(&data[1..4]).unwrap();

    let mut rcv_data = [0_u8; 4];

    let rcv_n = a.read(&mut rcv_data).unwrap();

    assert_eq!(rcv_n, snd_n);
    assert_eq!(&data[1..1+snd_n], &rcv_data[0..rcv_n]);
}



#[test]
fn test_try_from_ownedfd_tcp_listener()
{
    let tcp_listen = TcpListener::bind("127.0.0.1:0").unwrap();

    let val = Socket9::<TcpListener>::try_from(OwnedSocket::from(tcp_listen)).unwrap();

    let _tcp_listen: TcpListener = val.into();
}


#[test]
fn test_try_from_ownedfd_tcp_connection()
{
    let tcp_listen = TcpListener::bind("127.0.0.1:0").unwrap();

    let addr = tcp_listen.local_addr().unwrap();

    let tcp_stream = TcpStream::connect_timeout(&addr, Duration::from_secs(1)).unwrap();

    let accpt = tcp_listen.accept().unwrap();

    let val = Socket9::<TcpListener>::try_from(OwnedSocket::from(tcp_listen)).unwrap();

    let tcp_listen: TcpListener = val.into();

    drop(tcp_stream);
    drop(accpt);
    drop(tcp_listen);
}

/// This test fails because: 
/// code: 10057, kind: NotConnected, message: (when sending on a datagram socket using a sendto call) no address was supplied.
#[test]
#[should_panic]
fn test_unixdatagram_send_to()
{
    let (test_path, _dir) = make_temp_dir("test_sock_test2");

    let (test_path2, _dir3) = make_temp_dir("test_sock_test3");

    let rcv_part = Socket9::<WindowsUnixStream>::new_with_bind(&test_path).unwrap();

    let snd_part = Socket9::<WindowsUnixStream>::new_with_bind(&test_path2).unwrap();
    //new_unbound(So9DomainUnix::Unix).unwrap();

    let data = [1,2,3,4];
    
    let snt_n = snd_part.send_to(&data[..3], &test_path).unwrap();
    
    let mut rcv_data = [0_u8; 4];
    let rcv_n = rcv_part.recv(&mut rcv_data).unwrap();

    assert_eq!(snt_n, rcv_n);
    assert_eq!(&data[0..snt_n], &rcv_data[0..rcv_n]);

}


#[test]
fn test_tcp_io_listen()
{
    let tcp_listen = Socket9::<TcpListener>::new_with_bind_listen(&"0.0.0.0:0", 1).unwrap();

    let serv_addr = tcp_listen.local_addr().unwrap();

    assert_eq!(serv_addr.is_ipv4(), true);
    assert_eq!(serv_addr.ip().is_unspecified(), true);
}

#[test]
fn test_tcp_io()
{
    let tcp_listen = Socket9::<TcpListener>::new_with_bind_listen(&"127.0.0.1:0", 1).unwrap();

    let serv_addr = tcp_listen.local_addr().unwrap();

    let mut tcp_stream = Socket9::<TcpStream>::new_with_bind(&"127.0.0.1:0").unwrap();

    let client_addr = tcp_stream.local_addr().unwrap();

    tcp_stream.connect_timeout(&serv_addr, Duration::from_secs(1)).unwrap();

    let (rem_sock, rem_addr) = tcp_listen.accept().unwrap();

    println!("accepted connection from: {} exp: {}", rem_addr, client_addr);

    assert_eq!(client_addr, rem_addr);

    let test_str = "test!";

    write!(&rem_sock, "{}", test_str).unwrap();

    let mut buf = vec![0_u8; 20];

    let rcv_n = tcp_stream.read(&mut buf).unwrap();
    let rcv_str = str::from_utf8(&buf[..rcv_n]).unwrap();

    assert_eq!(rcv_n, test_str.as_bytes().len());
    assert_eq!(rcv_str, test_str);

    drop(tcp_stream);
    drop(rem_sock);
    drop(tcp_listen);
}

// max safe pkt len is 65507
#[test]
fn check_udp_vecotred_large()
{
    let p1 = "127.0.0.1:0";

    let sender = Socket9::<UdpSocket>::new_with_bind(&p1).unwrap();
    let receiver = Socket9::<UdpSocket>::new_with_bind(&p1).unwrap();

    let sock_addr_rcv = receiver.local_addr().unwrap();

    let buf0 = vec![1_u8; 65307];
    let buf1 = vec![2_u8; 200];

    let n = sender.send_to_vectored(&[IoSlice::new(&buf0), IoSlice::new(&buf1)], &sock_addr_rcv).unwrap();

    let mut rbuf0 = vec![0_u8; 65307];
    let mut rbuf1 = vec![0_u8; 1000];

    let rcv_io0 = IoSliceMut::new(&mut rbuf0);
    let rcv_io1 = IoSliceMut::new(&mut rbuf1);

    let rn = receiver.recv_from_vectored(&mut [rcv_io0, rcv_io1]).unwrap();

    println!("{} {}", n, rn.0);
    assert_eq!(n, rn.0);
    assert_eq!(rbuf0[0], 1);
    assert_eq!(rbuf1[0], 2);

}


#[test]
fn test_tcp_io_unbound()
{
    let tcp_listen = Socket9::<TcpListener>::new_with_bind_listen(&"127.0.0.1:0", 1).unwrap();

    let serv_addr = tcp_listen.local_addr().unwrap();

    let mut tcp_stream = Socket9::<TcpStream>::connect_unbound(&serv_addr).unwrap();

    let client_addr = tcp_stream.local_addr().unwrap();

    let (rem_sock, rem_addr) = tcp_listen.accept().unwrap();

    println!("accepted connection from: {} exp: {}", rem_addr, client_addr);

    assert_eq!(client_addr, rem_addr);

    let test_str = "test!";

    write!(&rem_sock, "{}", test_str).unwrap();

    let mut buf = vec![0_u8; 20];

    let rcv_n = tcp_stream.read(&mut buf).unwrap();
    let rcv_str = str::from_utf8(&buf[..rcv_n]).unwrap();

    assert_eq!(rcv_n, test_str.as_bytes().len());
    assert_eq!(rcv_str, test_str);

    drop(tcp_stream);
    drop(rem_sock);
    drop(tcp_listen);
}