blob: 9e61e55eb8b994bc9776c9b372db2f35ae212a9a (
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
|
(.module:
[lux #*
[control
monad
["ex" exception (#+ exception:)]]
[concurrency
["P" promise]
["T" task]]
[data
["e" error]
[maybe]
[collection [array]]]
[type abstract]
[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 {address //.Address})
address)
(exception: #export (multiple-candidate-addresses {address //.Address})
address)
(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))))))
(abstract: #export UDP {}
{#socket DatagramSocket}
(def: #export (read data offset length self)
(-> Blob Nat Nat UDP (T.Task [Nat //.Address //.Port]))
(let [(^open) (:representation self)
packet (DatagramPacket::new|receive [data (.int offset) (.int length)])]
(P.future
(do (e.ErrorT io.Monad<IO>)
[_ (DatagramSocket::receive [packet] socket)
#let [bytes-read (.nat (DatagramPacket::getLength [] packet))]]
(wrap [bytes-read
(|> packet (DatagramPacket::getAddress []) (InetAddress::getHostAddress []))
(.nat (DatagramPacket::getPort [] packet))])))))
(def: #export (write address port data offset length self)
(-> //.Address //.Port Blob Nat Nat UDP (T.Task Any))
(P.future
(do (e.ErrorT io.Monad<IO>)
[address (resolve address)
#let [(^open) (:representation self)]]
(DatagramSocket::send (DatagramPacket::new|send [data (.int offset) (.int length) address (.int port)])
socket))))
(def: #export (close self)
(-> UDP (T.Task Any))
(let [(^open) (:representation self)]
(P.future
(AutoCloseable::close [] socket))))
(def: #export (client _)
(-> Any (T.Task UDP))
(P.future
(do (e.ErrorT io.Monad<IO>)
[socket (DatagramSocket::new|client [])]
(wrap (:abstraction (#socket socket))))))
(def: #export (server port)
(-> //.Port (T.Task UDP))
(P.future
(do (e.ErrorT io.Monad<IO>)
[socket (DatagramSocket::new|server [(.int port)])]
(wrap (:abstraction (#socket socket))))))
)
|