Current section
Files
Jump to
Current section
Files
README.md
# glquic
[](https://trev.zip/llc/glquic/actions?workflow=check.yaml)
[](https://trev.zip/llc/glquic/actions?workflow=vulnerable.yaml)
[](https://nixos.org/)
[](https://gleam.run/)
QUIC for Gleam, built on [quicer](https://hex.pm/packages/quicer) and [msquic](https://github.com/microsoft/msquic)
## using
```sh
gleam add glquic
```
quicer compiles msquic into a NIF the first time it is built, which needs:
- Linux or macOS
- `cmake`, `make`, `perl`, `git` and a C compiler
- `libatomic` and `libnuma` on Linux
each listener, connection and stream sends its events as messages to the process that owns it: the one that accepted, connected or opened it
### client
```gleam
import glquic
pub fn main() {
let options = glquic.client_options(alpn: ["echo"])
let assert Ok(connection) =
glquic.connect(to: "localhost", on: 4433, with: options, timeout: 5000)
let assert Ok(stream) = glquic.open_stream(connection)
let assert Ok(Nil) = glquic.send_and_finish(stream, <<"Hello, Joe!">>)
case glquic.receive(within: 5000) {
Ok(glquic.Data(data:, ..)) -> echo data
_ -> panic as "no reply"
}
}
```
### server
```gleam
import gleam/erlang/process
import glquic
pub fn main() {
let options =
glquic.server_options(
alpn: ["echo"],
certificate: "cert.pem",
private_key: "key.pem",
)
let assert Ok(listener) = glquic.listen(on: 4433, with: options)
accept_loop(listener)
}
fn accept_loop(listener: glquic.Listener) -> Nil {
case glquic.accept(listener, 60_000) {
Ok(connection) -> {
let handler = process.spawn(fn() { handle(connection) })
let assert Ok(Nil) = glquic.transfer_connection(connection, handler)
Nil
}
Error(_) -> Nil
}
accept_loop(listener)
}
fn handle(connection: glquic.Connection) -> Nil {
case glquic.accept_stream(connection, 60_000) {
Ok(_stream) -> echo_loop()
Error(_) -> Nil
}
}
fn echo_loop() -> Nil {
case glquic.receive(within: 60_000) {
Ok(glquic.Data(stream:, data:, fin: True)) -> {
let _ = glquic.send_and_finish(stream, data)
echo_loop()
}
Ok(glquic.Data(stream:, data:, fin: False)) -> {
let _ = glquic.send(stream, data)
echo_loop()
}
Ok(glquic.ConnectionClosed(..)) | Error(Nil) -> Nil
Ok(_) -> echo_loop()
}
}
```
events can also be added to a selector with `glquic.select`, for use in actors
## contributing
see [CONTRIBUTING.md](CONTRIBUTING.md) for requirements and getting started