1
// SPDX-License-Identifier: BSD-2-Clause
2
/*
3
 * Copyright © The libcoap-rs Contributors, all rights reserved.
4
 * This file is part of the libcoap-rs project, see the README file for
5
 * general information on this project and the NOTICE.md and LICENSE files
6
 * for information regarding copyright ownership and terms of use.
7
 *
8
 * tests/common/dtls.rs - common code for DTLS tests.
9
 */
10

            
11
use std::{ffi::CStr, path::PathBuf, time::Duration};
12

            
13
use libcoap_rs::{
14
    crypto::{
15
        pki_rpk::{KeyDef, KeyType, NonCertVerifying, PkiRpkContext, PkiRpkContextBuilder, ServerPkiRpkCryptoContext},
16
        ClientCryptoContext,
17
    },
18
    message::CoapMessageCommon,
19
    protocol::{CoapMessageCode, CoapResponseCode},
20
    session::{CoapClientSession, CoapSessionCommon},
21
    CoapContext,
22
};
23
use libcoap_sys::{
24
    coap_get_tls_library_version, coap_package_version, coap_tls_library_t_COAP_TLS_LIBRARY_GNUTLS,
25
    coap_tls_library_t_COAP_TLS_LIBRARY_MBEDTLS, coap_tls_library_t_COAP_TLS_LIBRARY_NOTLS,
26
    coap_tls_library_t_COAP_TLS_LIBRARY_OPENSSL, coap_tls_library_t_COAP_TLS_LIBRARY_TINYDTLS,
27
    coap_tls_library_t_COAP_TLS_LIBRARY_WOLFSSL,
28
};
29

            
30
use crate::common;
31

            
32
// Is used in some test cases, but not in others (causing a compiler warning)
33
#[allow(unused)]
34
13
pub fn dtls_client_server_request_common<KTY: KeyType, FC, FS>(
35
13
    client_key: impl KeyDef<KeyType = KTY> + 'static,
36
13
    server_key: impl KeyDef<KeyType = KTY> + 'static + Send,
37
13
    client_ctx_setup: FC,
38
13
    server_ctx_setup: FS,
39
13
) where
40
13
    FC: FnOnce(PkiRpkContextBuilder<'static, KTY, NonCertVerifying>) -> PkiRpkContext<'static, KTY> + 'static,
41
13
    FS: FnOnce(PkiRpkContextBuilder<'static, KTY, NonCertVerifying>) -> PkiRpkContext<'static, KTY> + Send + 'static,
42
13
    ServerPkiRpkCryptoContext<'static>: From<PkiRpkContext<'static, KTY>>,
43
13
    ClientCryptoContext<'static>: From<PkiRpkContext<'static, KTY>>,
44
13
{
45
    // Variant names are named by bindgen, we have no influence on this.
46
    // Ref: https://github.com/rust-lang/rust/issues/39371
47
    #[allow(non_upper_case_globals)]
48
13
    let tls_library = match unsafe { *coap_get_tls_library_version() }.type_ {
49
        coap_tls_library_t_COAP_TLS_LIBRARY_NOTLS => "notls",
50
1
        coap_tls_library_t_COAP_TLS_LIBRARY_TINYDTLS => "tinydtls",
51
4
        coap_tls_library_t_COAP_TLS_LIBRARY_OPENSSL => "openssl",
52
4
        coap_tls_library_t_COAP_TLS_LIBRARY_GNUTLS => "gnutls",
53
4
        coap_tls_library_t_COAP_TLS_LIBRARY_MBEDTLS => "mbedtls",
54
        coap_tls_library_t_COAP_TLS_LIBRARY_WOLFSSL => "wolfssl",
55
        _ => "unknown",
56
    };
57
13
    println!(
58
13
        "Libcoap-Version: {}, DTLS library: {}",
59
13
        unsafe { CStr::from_ptr(coap_package_version()) }.to_string_lossy(),
60
13
        tls_library
61
13
    );
62
13

            
63
13
    let server_address = common::get_unused_server_addr();
64
13
    let client_crypto_ctx = client_ctx_setup(PkiRpkContextBuilder::<'static, KTY, NonCertVerifying>::new(client_key));
65
13
    let server_handle = common::spawn_test_server(move |mut context: CoapContext| {
66
13
        let server_crypto_ctx =
67
13
            server_ctx_setup(PkiRpkContextBuilder::<'static, KTY, NonCertVerifying>::new(server_key));
68
13
        context.set_pki_rpk_context(server_crypto_ctx).unwrap();
69
13
        context.add_endpoint_dtls(server_address).unwrap();
70
13
        #[cfg(feature = "dtls-pki")]
71
13
        context.set_pki_root_ca_paths(Some("./resources/test-keys/ca/ca.crt.pem"), None::<PathBuf>);
72
13
        context
73
13
    });
74
13

            
75
13
    let mut context = CoapContext::new().unwrap();
76
13
    #[cfg(feature = "dtls-pki")]
77
13
    context.set_pki_root_ca_paths(Some("./resources/test-keys/ca/ca.crt.pem"), None::<PathBuf>);
78
13
    let session = CoapClientSession::connect_dtls(&mut context, server_address, client_crypto_ctx).unwrap();
79
13

            
80
13
    let request = common::gen_test_request();
81
13
    let req_handle = session.send_request(request).unwrap();
82
    loop {
83
80
        assert!(context.do_io(Some(Duration::from_secs(10))).expect("error during IO") <= Duration::from_secs(10));
84
80
        for response in session.poll_handle(&req_handle) {
85
13
            assert_eq!(response.code(), CoapMessageCode::Response(CoapResponseCode::Content));
86
13
            assert_eq!(response.data().unwrap().as_ref(), "Hello World!".as_bytes());
87
13
            server_handle.join().expect("Test server crashed with failure.");
88
13
            return;
89
13
        }
90
13
    }
91
13
}