From 7a27c57f308115291912ff89057f0289767c6010 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 28 Sep 2023 10:43:10 +0200 Subject: [PATCH] ev::dial: implement dial_udp --- ev/dial/ip.ha | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++- diff --git a/ev/dial/ip.ha b/ev/dial/ip.ha index 36e28e8ec4429a6d5dc3e5e522de1be41ad94244..ce718e7948641eb3e1fb92c21e89480012b32992 100644 --- a/ev/dial/ip.ha +++ b/ev/dial/ip.ha @@ -104,6 +104,15 @@ free(state); cb(user, r); }; +type udp_dialer = struct { + loop: *ev::loop, + cb: *dialcb, + user: nullable *opaque, + req: ev::req, + ip: []ip::addr, + port: u16, +}; + fn dial_udp( loop: *ev::loop, addr: str, @@ -111,5 +120,61 @@ service: str, cb: *dialcb, user: nullable *opaque, ) (ev::req | error) = { - abort(); // TODO + let state = alloc(udp_dialer { + loop = loop, + cb = cb, + user = user, + ... + }); + + const req = resolve(loop, "udp", addr, + service, &dial_udp_resolvecb, state)?; + state.req = req; + return ev::mkreq(&dial_udp_cancel, state); +}; + +fn dial_udp_resolvecb( + user: nullable *opaque, + r: (([]ip::addr, u16) | error), +) void = { + let state = user: *udp_dialer; + state.req = ev::req { ... }; + const (ip, port) = match (r) { + case let r: ([]ip::addr, u16) => + yield r; + case let err: error => + dial_udp_complete(state, err); + return; + }; + + state.ip = ip; + state.port = port; + dial_udp_connect(state); +}; + +fn dial_udp_connect(state: *udp_dialer) void = { + match (ev::connect_udp(state.loop, + state.ip[0], state.port)) { + case let err: (net::error | errors::error) => + dial_udp_complete(state, err); + return; + case let sock: *ev::file => + dial_udp_complete(state, sock); + return; + }; +}; + +fn dial_udp_cancel(req: *ev::req) void = { + let state = req: *udp_dialer; + ev::cancel(&state.req); + free(state.ip); + free(state); +}; + +fn dial_udp_complete(state: *udp_dialer, r: (*ev::file | error)) void = { + const cb = state.cb; + const user = state.user; + free(state.ip); + free(state); + cb(user, r); }; -- 2.48.1