Skip to content

Commit

Permalink
refactor: refactoring of the transport module (#13)
Browse files Browse the repository at this point in the history
* Code refactoring

Instead of having separate structures for each transport mode which have
the same data field refactor everything into single CoapEndpoint structure.
Remove unused methods.

* Further refactoring.

Encapsulate unsafe in CoapEndpoint::new.
Instead of every endpoint function making unsafe calls with these
changes they utilize CoapEndpoint::new with the protocol that they
require.
Document safety for CaopEndpoint::new.

* Fix module ordering in lib.

* Code clean up

Safety comments are not needed any more.
No need to cast the endpoint since everything is a common structure now.

* Refactoring

Further simplify the creation of endpoints.
  • Loading branch information
petardimitrijevic authored Jul 14, 2023
1 parent 0e17941 commit 287c26c
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 414 deletions.
38 changes: 15 additions & 23 deletions libcoap/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use libcoap_sys::{
coap_context_set_csm_timeout, coap_context_set_keepalive, coap_context_set_max_handshake_sessions,
coap_context_set_max_idle_sessions, coap_context_set_psk2, coap_context_set_session_timeout, coap_context_t,
coap_dtls_spsk_info_t, coap_dtls_spsk_t, coap_event_t, coap_free_context, coap_get_app_data, coap_io_process,
coap_new_context, coap_register_event_handler, coap_register_response_handler, coap_set_app_data,
coap_new_context, coap_proto_t, coap_register_event_handler, coap_register_response_handler, coap_set_app_data,
COAP_BLOCK_SINGLE_BODY, COAP_BLOCK_USE_LIBCOAP, COAP_DTLS_SPSK_SETUP_VERSION, COAP_IO_WAIT,
};

Expand All @@ -36,14 +36,14 @@ use crate::session::CoapSessionCommon;
use crate::session::CoapServerSession;
use crate::session::CoapSession;
#[cfg(feature = "dtls")]
use crate::transport::CoapDtlsEndpoint;
use crate::{
error::{ContextCreationError, EndpointCreationError, IoProcessError},
resource::{CoapResource, UntypedCoapResource},
session::session_response_handler,
transport::{CoapEndpoint, CoapUdpEndpoint, CoapTcpEndpoint},
};

use crate::transport::CoapEndpoint;

#[derive(Debug)]
struct CoapContextInner<'a> {
/// Reference to the raw context this context wraps around.
Expand Down Expand Up @@ -228,27 +228,24 @@ impl CoapContext<'_> {
Ok(())
}

/// Creates a new UDP endpoint that is bound to the given address.
pub fn add_endpoint_udp(&mut self, addr: SocketAddr) -> Result<(), EndpointCreationError> {
// SAFETY: Because we never return an owned reference to the endpoint, it cannot outlive the
// context it is bound to (i.e. this one).
let endpoint = unsafe { CoapUdpEndpoint::new(self, addr)? }.into();
/// Store reference to the endpoint
fn add_endpoint(&mut self, addr: SocketAddr, proto: coap_proto_t) -> Result<(), EndpointCreationError> {
let endpoint = CoapEndpoint::new_endpoint(self, addr, proto)?;

let mut inner_ref = self.inner.borrow_mut();
inner_ref.endpoints.push(endpoint);
// Cannot fail, we just pushed to the Vec.
Ok(())
}

/// Creates a new UDP endpoint that is bound to the given address.
pub fn add_endpoint_udp(&mut self, addr: SocketAddr) -> Result<(), EndpointCreationError> {
self.add_endpoint(addr, coap_proto_t::COAP_PROTO_UDP)
}

/// Creates a new TCP endpoint that is bound to the given address.
#[cfg(feature = "tcp")]
pub fn add_endpoint_tcp(&mut self, addr: SocketAddr) -> Result<(), EndpointCreationError> {
// SAFETY: Because we never return an owned reference to the endpoint, it cannot outlive the
// context it is bound to (i.e. this one).
let endpoint = unsafe { CoapTcpEndpoint::new(self, addr)? }.into();
let mut inner_ref = self.inner.borrow_mut();
inner_ref.endpoints.push(endpoint);
// Cannot fail, we just pushed to the Vec.
Ok(())
self.add_endpoint(addr, coap_proto_t::COAP_PROTO_TCP)
}

/// Creates a new DTLS endpoint that is bound to the given address.
Expand All @@ -257,19 +254,14 @@ impl CoapContext<'_> {
/// using [set_server_crypto_provider()](CoapContext::set_server_crypto_provider())
#[cfg(feature = "dtls")]
pub fn add_endpoint_dtls(&mut self, addr: SocketAddr) -> Result<(), EndpointCreationError> {
// SAFETY: Provided context (i.e., this instance) will not outlive the endpoint, as we will
// drop it alongside this context and never hand out copies of it.
let endpoint = unsafe { CoapDtlsEndpoint::new(self, addr)? }.into();
let mut inner_ref = self.inner.borrow_mut();
inner_ref.endpoints.push(endpoint);
// Cannot fail, we just pushed to the Vec.
Ok(())
self.add_endpoint(addr, coap_proto_t::COAP_PROTO_DTLS)
}

/// TODO
#[cfg(all(feature = "tcp", feature = "dtls"))]
pub fn add_endpoint_tls(&mut self, _addr: SocketAddr) -> Result<(), EndpointCreationError> {
todo!()
// TODO: self.add_endpoint(addr, coap_proto_t::COAP_PROTO_TLS)
}

/// Adds the given resource to the resource pool of this context.
Expand Down
2 changes: 1 addition & 1 deletion libcoap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
//! CoapRequestHandler, CoapResource,
//! session::{CoapSessionCommon, CoapServerSession},
//! };
//!
//!
//! // This will give us a SocketAddress with a port in the local port range automatically
//! // assigned by the operating system.
//! // Because the UdpSocket goes out of scope, the Port will be free for usage by libcoap.
Expand Down
66 changes: 66 additions & 0 deletions libcoap/src/transport.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* transport/mod.rs - Module file for CoAP transports.
* This file is part of the libcoap-rs crate, see the README and LICENSE files for
* more information and terms of use.
* Copyright © 2021-2023 The NAMIB Project Developers, all rights reserved.
* See the README as well as the LICENSE file for more information.
*/

use std::{net::SocketAddr, os::raw::c_uint};

use libcoap_sys::{
coap_endpoint_set_default_mtu, coap_endpoint_t, coap_free_endpoint, coap_new_endpoint, coap_proto_t,
};

use crate::{error::EndpointCreationError, types::CoapAddress, CoapContext};

pub type EndpointMtu = c_uint;

#[derive(Debug)]
pub struct CoapEndpoint {
raw_endpoint: *mut coap_endpoint_t,
}

/// Trait for functions common between all types of endpoints.
impl CoapEndpoint {
/// Sets the default MTU value of the endpoint.
pub fn set_default_mtu(&mut self, mtu: EndpointMtu) {
// SAFETY: as_mut_raw_endpoint cannot fail and will always return a valid reference.
// Modifying the state of the endpoint is also fine, because we have a mutable reference
// of the whole endpoint.
unsafe {
coap_endpoint_set_default_mtu(&mut *self.raw_endpoint, mtu);
}
}

/// Method utilized by transport protocol specific constructors to actually create the endpoint in libcoap
pub(crate) fn new_endpoint(
context: &mut CoapContext,
addr: SocketAddr,
proto: coap_proto_t,
) -> Result<Self, EndpointCreationError> {
let endpoint = unsafe {
// SAFETY: coap_new_endpoint will return null if it is unable to add new endpoint.
// These states are processed further in the code
coap_new_endpoint(
context.as_mut_raw_context(),
CoapAddress::from(addr).as_raw_address(),
proto,
)
};

if endpoint.is_null() {
Err(EndpointCreationError::Unknown)
} else {
Ok(Self { raw_endpoint: endpoint })
}
}
}

impl Drop for CoapEndpoint {
fn drop(&mut self) {
// SAFETY: Raw endpoint is guaranteed to exist for as long as the container exists.
unsafe { coap_free_endpoint(self.raw_endpoint) }
}
}
88 changes: 0 additions & 88 deletions libcoap/src/transport/dtls.rs

This file was deleted.

115 changes: 0 additions & 115 deletions libcoap/src/transport/mod.rs

This file was deleted.

Loading

0 comments on commit 287c26c

Please sign in to comment.