Skip to content

Instantly share code, notes, and snippets.

@fdeantoni
Last active November 8, 2019 06:09
Show Gist options
  • Save fdeantoni/a1df96cdd0cc84f79e08a116aa184b71 to your computer and use it in GitHub Desktop.
Save fdeantoni/a1df96cdd0cc84f79e08a116aa184b71 to your computer and use it in GitHub Desktop.
A basic DTLS implementation, with help from https://github.com/TimonPost/udp-dtls.
[package]
name = "test-udp-dtls"
version = "0.1.0"
authors = ["fdeantoni <fdeantoni@gmail.com>"]
edition = "2018"
[dependencies]
tokio = "0.2.0-alpha.5"
futures-preview = { version = "=0.3.0-alpha.18", features = ["async-await", "nightly"] }
openssl = { version="0.10" }
use std::io;
use openssl::ssl::{SslAcceptor, SslConnector, SslMethod, SslVerifyMode, SslFiletype};
fn ssl_connector() -> Result<SslConnector, io::Error> {
let mut builder = SslConnector::builder(SslMethod::dtls())?;
builder.set_verify(SslVerifyMode::NONE);
let connector = builder.build();
Ok(connector)
}
fn ssl_acceptor(certificate: &str, key: &str) -> Result<SslAcceptor, io::Error> {
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::dtls())?;
builder
.set_private_key_file(key, SslFiletype::PEM)
.unwrap();
builder.set_certificate_chain_file(certificate).unwrap();
let acceptor = builder.build();
Ok(acceptor)
}
use std::net::UdpSocket;
use tokio::executor::spawn;
use std::io::{Read, Write};
use std::thread;
use std::time::Duration;
pub mod udp;
#[tokio::main]
async fn main() {
let certificate = String::from("test/cert.pem");
let key = String::from("test/key.pem");
let acceptor = ssl_acceptor(&certificate, &key).unwrap();
let server = UdpSocket::bind("127.0.0.1:0").unwrap();
let client = UdpSocket::bind("127.0.0.1:0").unwrap();
let server_addr = server.local_addr().unwrap();
let client_addr = client.local_addr().unwrap();
let server_channel = udp::UdpChannel::new(
server,
client_addr
);
let client_channel = udp::UdpChannel::new(
client,
server_addr
);
spawn(async move {
let mut server = acceptor.accept(server_channel).unwrap();
let mut count = 0;
loop {
let mut buf = [0; 5];
server.read_exact(&mut buf).expect("Could not read server buffer!");
let received = std::str::from_utf8(&buf).unwrap();
println!("{:?} {:?}", count, received);
count = count + 1;
thread::sleep(Duration::from_millis(2));
}
});
let connector = ssl_connector().unwrap();
let mut client = connector.connect("example.net", client_channel).unwrap();
loop {
let buf = b"hello";
client.write_all(buf).expect("Could not write client buffer!");
thread::sleep(Duration::from_millis(30));
}
}
use std::io::{Error, Read, Result, Write};
use std::net::{SocketAddr, UdpSocket};
use std::result;
#[derive(Debug)]
pub struct UdpChannel {
socket: UdpSocket,
remote_addr: SocketAddr,
}
impl Read for UdpChannel {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.socket.recv(buf)
}
}
impl Write for UdpChannel {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.socket.send_to(buf, self.remote_addr)
}
fn flush(&mut self) -> result::Result<(), Error> {
Ok(())
}
}
impl UdpChannel {
pub fn new(socket: UdpSocket, remote_addr: SocketAddr) -> UdpChannel {
UdpChannel {
socket,
remote_addr
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment