aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/world/net/udp.jvm.lux
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))))))
  )