Programming Language

Nocter

A self-contained systems language built around simplicity, encapsulation, and foolproof design.

/examples/async-udp/exchange.nct

exchange.nct

see ./index.nct

use std/net.{IpAddress, Ipv4Address, SocketAddress, UdpSocket}
use std/time.Duration
use std/vec.Vec

noalloc func loopback(): SocketAddress {
    return SocketAddress.new(IpAddress.from_ipv4(Ipv4Address.loopback()), 0)
}

async func run(): i32! {
    let timeout = Duration.from_seconds(1)
    var sender = UdpSocket.bind(loopback())?
    var receiver = UdpSocket.bind(loopback())?
    let sender_address = sender.local_address()?
    let receiver_address = receiver.local_address()?

    await sender.send_to_with_timeout("ping".bytes(), receiver_address, timeout)?
    var bytes: Vec<u8> = Vec [
        u8.truncate(0),
        u8.truncate(0),
        u8.truncate(0),
        u8.truncate(0),
    ]
    let received = await receiver.receive_with_timeout(&+bytes, timeout)?
    if received.source() != sender_address || received.copied_len() != 4
    || received.was_truncated() || bytes[0] != 112 || bytes[1] != 105
    || bytes[2] != 110 || bytes[3] != 103 {
        return error.new("async-udp.datagram", "UDP changed one message boundary")
    }

    sender.connect(receiver_address)?
    receiver.connect(sender_address)?
    await receiver.send("pong".bytes())?
    let reply = await sender.receive_with_timeout(&+bytes, timeout)?
    if reply.copied_len() != 4 || reply.was_truncated()
    || bytes[0] != 112 || bytes[1] != 111 || bytes[2] != 110 || bytes[3] != 103 {
        return error.new("async-udp.reply", "connected UDP changed one reply")
    }
    return 0
}