blob: a3124bdf2873e31806e9db7963fd67bffcf36326 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
(;module:
lux
(lux (control monad
["ex" exception #+ exception:])
(concurrency ["P" promise]
["T" task]
[frp])
(data ["e" error]
[maybe]
(coll [array]))
(type opaque)
(world [blob #+ Blob])
[io]
[host])
[..])
(host;import java.lang.AutoCloseable
(close [] #io #try void))
(host;import java.io.Flushable
(flush [] #io #try void))
(host;import java.net.InetAddress
(#static getAllByName [String] #io #try (Array InetAddress))
(getHostAddress [] String))
(host;import java.net.DatagramPacket
(new #as new|send [(Array byte) int int InetAddress int])
(new #as new|receive [(Array byte) int int])
(getAddress [] InetAddress)
(getPort [] int)
(getLength [] int))
(host;import java.net.DatagramSocket
(new #as new|client [] #io #try)
(new #as new|server [int] #io #try)
(receive [DatagramPacket] #io #try void)
(send [DatagramPacket] #io #try void))
############################################################
############################################################
############################################################
(exception: #export Cannot-Resolve-Address)
(exception: #export Multiple-Candidate-Addresses)
(def: (resolve address)
(-> ..;Address (io;IO (e;Error InetAddress)))
(do (e;ErrorT io;Monad<IO>)
[addresses (InetAddress.getAllByName [address])]
(: (io;IO (e;Error InetAddress))
(case (array;size addresses)
+0 (io;io (ex;throw Cannot-Resolve-Address address))
+1 (wrap (maybe;assume (array;read +0 addresses)))
_ (io;io (ex;throw Multiple-Candidate-Addresses address))))))
(opaque: #export UDP {}
{#socket DatagramSocket}
(def: #export (read data offset length self)
(-> Blob Nat Nat UDP (T;Task [Nat ..;Address ..;Port]))
(let [(^open) (@repr self)
packet (DatagramPacket.new|receive [data (nat-to-int offset) (nat-to-int length)])]
(P;future
(do (e;ErrorT io;Monad<IO>)
[_ (DatagramSocket.receive [packet] socket)
#let [bytes-read (int-to-nat (DatagramPacket.getLength [] packet))]]
(wrap [bytes-read
(|> packet (DatagramPacket.getAddress []) (InetAddress.getHostAddress []))
(int-to-nat (DatagramPacket.getPort [] packet))])))))
(def: #export (write address port data offset length self)
(-> ..;Address ..;Port Blob Nat Nat UDP (T;Task Unit))
(P;future
(do (e;ErrorT io;Monad<IO>)
[address (resolve address)
#let [(^open) (@repr self)]]
(DatagramSocket.send (DatagramPacket.new|send [data (nat-to-int offset) (nat-to-int length) address (nat-to-int port)])
socket))))
(def: #export (close self)
(-> UDP (T;Task Unit))
(let [(^open) (@repr self)]
(P;future
(AutoCloseable.close [] socket))))
(def: #export (client _)
(-> Unit (T;Task UDP))
(P;future
(do (e;ErrorT io;Monad<IO>)
[socket (DatagramSocket.new|client [])]
(wrap (@opaque (#socket socket))))))
(def: #export (server port)
(-> ..;Port (T;Task UDP))
(P;future
(do (e;ErrorT io;Monad<IO>)
[socket (DatagramSocket.new|server [(nat-to-int port)])]
(wrap (@opaque (#socket socket))))))
)
|