Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psp-net"
version = "0.5.4"
version = "0.6.1"
edition = "2021"
license-file = "LICENSE"
keywords = ["psp", "net", "networking", "embedded", "gamedev"]
Expand Down
90 changes: 84 additions & 6 deletions src/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use alloc::{
string::{String, ToString},
vec as a_vec,
};
use dns_protocol::{Flags, Question, ResourceRecord};
use dns_protocol::{Flags, Label, Question, ResourceRecord};
use embedded_io::{Read, Write};
use embedded_nal::{IpAddr, Ipv4Addr, SocketAddr};
use psp::sys::in_addr;
Expand All @@ -25,10 +25,17 @@ lazy_static::lazy_static! {
/// Create a DNS query for an A record
#[allow(unused)]
#[must_use]
pub fn create_a_type_query(domain: &str) -> Question {
fn create_a_type_query(domain: &str) -> Question {
Question::new(domain, dns_protocol::ResourceType::A, 1)
}

/// Create a DNS query for reverse lookup
#[allow(unused)]
#[must_use]
fn create_reverse_query<'a>(domain: impl Into<Label<'a>>) -> Question<'a> {
Question::new(domain, dns_protocol::ResourceType::Ptr, 1)
}

/// An error that can occur when using a DNS resolver
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DnsError {
Expand Down Expand Up @@ -94,7 +101,7 @@ impl DnsResolver {
/// - [`DnsError::HostnameResolutionFailed`]: The hostname could not be resolved.
/// This may happen if the connection of the socket fails, or if the DNS server
/// does not answer the query, or any other error occurs
pub fn resolve(&mut self, host: &str) -> Result<in_addr, DnsError> {
fn resolve(&mut self, host: &str) -> Result<in_addr, DnsError> {
// create a new query
let mut questions = [super::dns::create_a_type_query(host)];
let query = dns_protocol::Message::new(
Expand Down Expand Up @@ -166,6 +173,69 @@ impl DnsResolver {
}
}

fn resolve_hostname(&mut self, addr: &str) -> Result<String, DnsError> {
let mut questions = [create_reverse_query(addr)];
let query = dns_protocol::Message::new(
0x42,
Flags::standard_query(),
&mut questions,
&mut [],
&mut [],
&mut [],
);

// create a new buffer with the size of the message
let mut tx_buf = a_vec![0u8; query.space_needed()];
query.write(&mut tx_buf).map_err(|_| {
DnsError::AddressResolutionFailed("Could not serialize query".to_owned())
})?;

// send the message to the DNS server
let _ = self
.udp_socket
.write(&tx_buf)
.map_err(|e| DnsError::AddressResolutionFailed(e.to_string()))?;

let mut rx_buf = [0u8; 1024];

// receive the response from the DNS server
let data_len = self
.udp_socket
.read(&mut rx_buf)
.map_err(|e| DnsError::AddressResolutionFailed(e.to_string()))?;

if data_len == 0 {
return Err(DnsError::AddressResolutionFailed(
"No data received".to_owned(),
));
}

// parse the response
let mut answers = [ResourceRecord::default(); 16];
let mut authority = [ResourceRecord::default(); 16];
let mut additional = [ResourceRecord::default(); 16];
let message = dns_protocol::Message::read(
&rx_buf[..data_len],
&mut questions,
&mut answers,
&mut authority,
&mut additional,
)
.map_err(|_| DnsError::AddressResolutionFailed("Could not parse response".to_owned()))?;

if message.answers().is_empty() {
return Err(DnsError::AddressResolutionFailed(
"No answers received".to_owned(),
));
}
let answer = message.answers()[0];

match answer.data().len() {
0 => Err(DnsError::AddressResolutionFailed("Empty answer".to_owned())),
_ => Ok(String::from_utf8_lossy(answer.data()).to_string()),
}
}

/// Get the [`SocketAddr`] of the DNS server
#[must_use]
#[inline]
Expand All @@ -180,7 +250,7 @@ impl traits::dns::ResolveHostname for DnsResolver {
/// Resolve a hostname to an IP address
///
/// # Parameters
/// - `host`: The hostname to resolve
/// - `hostname`: The hostname to resolve
///
/// # Returns
/// - `Ok(SocketAddr)`: The IP address of the hostname
Expand All @@ -198,8 +268,16 @@ impl traits::dns::ResolveHostname for DnsResolver {
impl traits::dns::ResolveAddr for DnsResolver {
type Error = DnsError;

fn resolve_addr(&mut self, _addr: in_addr) -> Result<String, DnsError> {
todo!("resolve_addr")
fn resolve_addr(&mut self, addr: SocketAddr) -> Result<String, DnsError> {
if matches!(addr, SocketAddr::V6(_)) {
return Err(DnsError::HostnameResolutionFailed(
"IPv6 not supported".to_owned(),
));
}

let addr = addr.ip().to_string();

self.resolve_hostname(&addr)
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/socket/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ impl TcpSocket<Connected> {
/// "Low level" read function. Read data from the socket and store it in
/// the buffer. This should not be used if you want to use this socket
/// [`EasySocket`] style.
pub fn _read(&self, buf: &mut [u8]) -> Result<usize, SocketError> {
fn _read(&self, buf: &mut [u8]) -> Result<usize, SocketError> {
let result = unsafe {
sys::sceNetInetRecv(
*self.fd,
Expand All @@ -196,7 +196,7 @@ impl TcpSocket<Connected> {
///
/// # Errors
/// - A [`SocketError`] if the write was unsuccessful
pub fn _write(&mut self, buf: &[u8]) -> Result<usize, SocketError> {
fn _write(&mut self, buf: &[u8]) -> Result<usize, SocketError> {
self.buffer.append_buffer(buf);
self.send()
}
Expand Down Expand Up @@ -227,10 +227,12 @@ impl TcpSocket<Connected> {
}

impl<S: SocketState> ErrorType for TcpSocket<S> {
/// The error type of the socket
type Error = SocketError;
}

impl<S: SocketState> OptionType for TcpSocket<S> {
/// The options of the socket
type Options<'a> = SocketOptions;
}

Expand Down
13 changes: 6 additions & 7 deletions src/socket/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ impl UdpSocket<Bound> {
/// # Errors
/// - Any [`SocketError`] if the read was unsuccessful
#[allow(unused)]
pub fn _read_from(
pub fn read_from(
mut self,
buf: &mut [u8],
) -> Result<(usize, UdpSocket<Connected>), SocketError> {
Expand All @@ -250,7 +250,7 @@ impl UdpSocket<Bound> {
///
/// # Parameters
/// - `buf`: The buffer containing the data to send
///
/// - `to`: The address to send the data to
///
/// # Returns
/// - `Ok((usize, UdpSocket<Connected>))` if the send was successful. The number of bytes sent
Expand All @@ -259,10 +259,9 @@ impl UdpSocket<Bound> {
/// # Errors
/// - Any [`SocketError`] if the send was unsuccessful
#[allow(unused)]
pub fn _write_to(
pub fn write_to(
self,
buf: &[u8],
len: usize,
to: SocketAddr,
) -> Result<(usize, UdpSocket<Connected>), SocketError> {
let sockaddr = match to {
Expand All @@ -278,7 +277,7 @@ impl UdpSocket<Bound> {
sys::sceNetInetSendto(
*self.fd,
buf.as_ptr().cast::<c_void>(),
len,
buf.len(),
self.send_flags.as_i32(),
&sockaddr,
socklen,
Expand Down Expand Up @@ -306,7 +305,7 @@ impl UdpSocket<Connected> {
/// # Errors
/// - Any [`SocketError`] if the read was unsuccessful
#[allow(unused)]
pub fn _read(&mut self, buf: &mut [u8]) -> Result<usize, SocketError> {
fn _read(&mut self, buf: &mut [u8]) -> Result<usize, SocketError> {
let result = unsafe {
sys::sceNetInetRecv(
*self.fd,
Expand All @@ -331,7 +330,7 @@ impl UdpSocket<Connected> {
/// # Errors
/// - Any [`SocketError`] if the send was unsuccessful
#[allow(unused)]
pub fn _write(&mut self, buf: &[u8]) -> Result<usize, SocketError> {
fn _write(&mut self, buf: &[u8]) -> Result<usize, SocketError> {
self.buffer.append_buffer(buf);
self.send()
}
Expand Down
3 changes: 1 addition & 2 deletions src/traits/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use core::fmt::Debug;
use alloc::string::String;

use embedded_nal::SocketAddr;
use psp::sys::in_addr;

/// Trait for resolving hostnames
///
Expand All @@ -30,7 +29,7 @@ pub trait ResolveAddr {
///
/// # Errors
/// An error will be returned if the IP address could not be resolved.
fn resolve_addr(&mut self, addr: in_addr) -> Result<String, Self::Error>;
fn resolve_addr(&mut self, addr: SocketAddr) -> Result<String, Self::Error>;
}

/// Trait for resolving hostnames and IP addresses.
Expand Down