This PR adds DNS functions to the standard library --------- Co-authored-by: Henrik Böving <hargonix@gmail.com> Co-authored-by: Markus Himmel <markus@himmel-villmar.de>
67 lines
2.1 KiB
Text
67 lines
2.1 KiB
Text
import Std.Internal.Async
|
||
import Std.Internal.UV
|
||
import Std.Net.Addr
|
||
|
||
open Std.Internal.IO Async
|
||
open Std.Net
|
||
|
||
open Std.Net
|
||
|
||
def assertBEq [BEq α] [ToString α] (actual expected : α) : IO Unit := do
|
||
unless actual == expected do
|
||
throw <| IO.userError <|
|
||
s!"expected '{expected}', got '{actual}'"
|
||
|
||
def baseSelector (asyncWaiter : AsyncTask α) : Selector α :=
|
||
{
|
||
tryFn := do
|
||
if ← IO.hasFinished asyncWaiter then
|
||
let result ← IO.ofExcept asyncWaiter.get
|
||
return some result
|
||
else
|
||
return none
|
||
registerFn waiter := do
|
||
discard <| AsyncTask.mapIO (x := asyncWaiter) fun data => do
|
||
let lose := return ()
|
||
let win promise := promise.resolve (.ok data)
|
||
waiter.race lose win
|
||
unregisterFn := pure ()
|
||
}
|
||
|
||
def race (a : AsyncTask α) (b : AsyncTask β) (map : Except α β → AsyncTask γ) : IO (AsyncTask γ) := do
|
||
Selectable.one #[
|
||
.case (baseSelector a) fun a => return map (.error a),
|
||
.case (baseSelector b) fun b => return map (.ok b),
|
||
]
|
||
|
||
def timeout (a : AsyncTask α) (time : Std.Time.Millisecond.Offset) : IO (AsyncTask α) := do
|
||
race (← sleep time) a fun
|
||
| .ok res => Task.pure (.ok res)
|
||
| .error _ => Task.pure (.error (IO.userError "Timeout."))
|
||
|
||
def runDNS : Async Unit := do
|
||
let infos ← await <| (← timeout (← DNS.getAddrInfo "google.com" "http") 10000)
|
||
|
||
unless infos.size > 0 do
|
||
(throw <| IO.userError <| "No DNS results for google.com" : IO _)
|
||
|
||
def runDNSNoAscii : Async Unit := do
|
||
let infos ← await <| (← timeout (← DNS.getAddrInfo "google.com▸" "http") 10000)
|
||
|
||
unless infos.size > 0 do
|
||
(throw <| IO.userError <| "No DNS results for google.com" : IO _)
|
||
|
||
def runReverseDNS : Async Unit := do
|
||
let result ← await (← DNS.getNameInfo (.v4 ⟨.ofParts 8 8 8 8, 53⟩))
|
||
assertBEq result.service "domain"
|
||
assertBEq result.host "dns.google"
|
||
|
||
#eval runDNS.toIO >>= AsyncTask.block
|
||
|
||
/--
|
||
error: invalid argument (error code: 22, invalid argument)
|
||
file: name is not ASCII.
|
||
-/
|
||
#guard_msgs in #eval runDNSNoAscii.toIO >>= AsyncTask.block
|
||
|
||
#eval runReverseDNS.toIO >>= AsyncTask.block
|