blob: 842f1c969e6f6734ef840c2de21de7342e66ad4c (
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
(.module:
[lux #*
[control
monad
["ex" exception (#+ exception:)]
[security
["." taint (#+ Dirty taint)]]]
[concurrency
["." promise (#+ Promise)]
[task (#+ Task)]]
[data
["." error (#+ Error)]
["." maybe]
[collection
["." array]]]
[world
["." binary (#+ Binary)]]
["." io (#+ IO)]
[host (#+ import:)]
[platform
[compiler
["." host]]]]
["." // (#+ Location)])
(import: java/lang/AutoCloseable
(close [] #io #try void))
(import: java/io/Flushable
(flush [] #io #try void))
(import: java/net/InetAddress
(#static getAllByName [String] #io #try (Array InetAddress))
(getHostAddress [] String))
(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))
(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 {address //.Address})
(ex.report ["Address" address]))
(exception: #export (multiple-candidate-addresses {address //.Address})
(ex.report ["Address" address]))
(signature: #export (UDP !)
(: (-> Nat (! (Error [Nat Location (Dirty Binary)])))
read)
(: (-> Location Binary (! (Error Any)))
write)
(: (-> Any (! (Error Any)))
close))
(def: #export (async udp)
(-> (UDP IO) (UDP Promise))
(`` (structure (def: read (|>> (:: udp read) promise.future))
(def: (write location data)
(promise.future (:: udp write location data)))
(def: close (|>> (:: udp close) promise.future)))))
(`` (for {(~~ (static host.jvm))
(as-is (def: (resolve address)
(-> //.Address (IO (Error InetAddress)))
(do io.Monad<Process>
[addresses (InetAddress::getAllByName address)]
(: (IO (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))))))
(def: (udp socket)
(-> DatagramSocket (UDP IO))
(structure (def: (read size)
(let [data (binary.create size)
packet (DatagramPacket::new|receive data +0 (.int size))]
(do io.Monad<Process>
[_ (DatagramSocket::receive packet socket)
#let [bytes-read (.nat (DatagramPacket::getLength packet))]]
(wrap [bytes-read
{#//.address (|> packet DatagramPacket::getAddress InetAddress::getHostAddress)
#//.port (.nat (DatagramPacket::getPort packet))}
(taint data)]))))
(def: (write location data)
(do io.Monad<Process>
[address (resolve (get@ #//.address location))]
(DatagramSocket::send (DatagramPacket::new|send data +0 (.int (binary.size data)) address (.int (get@ #//.port location)))
socket)))
(def: (close _)
(AutoCloseable::close socket))))
(def: #export client
(IO (Error (UDP IO)))
(|> (DatagramSocket::new|client)
(:: io.Monad<Process> map udp)))
(def: #export server
(-> //.Port (IO (Error (UDP IO))))
(|>> .int
DatagramSocket::new|server
(:: io.Monad<Process> map udp)))
)}))
|