@shd101wyy/yo 0.0.26 → 0.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/out/cjs/index.cjs +558 -553
- package/out/cjs/yo-cli.cjs +479 -474
- package/out/esm/index.mjs +432 -427
- package/out/types/src/codegen/async/state-machine.d.ts +1 -1
- package/out/types/src/codegen/exprs/await.d.ts +1 -0
- package/out/types/src/codegen/exprs/return.d.ts +1 -0
- package/out/types/src/codegen/exprs/while.d.ts +1 -1
- package/out/types/src/codegen/functions/context.d.ts +6 -18
- package/out/types/src/codegen/functions/declarations.d.ts +10 -2
- package/out/types/src/evaluator/async/await-analysis.d.ts +1 -0
- package/out/types/src/evaluator/context.d.ts +1 -0
- package/out/types/src/expr.d.ts +1 -0
- package/out/types/src/function-value.d.ts +1 -0
- package/out/types/src/types/creators.d.ts +2 -1
- package/out/types/src/types/definitions.d.ts +2 -1
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/crypto/random.yo +25 -13
- package/std/encoding/base64.yo +24 -49
- package/std/encoding/hex.yo +25 -22
- package/std/encoding/json.yo +25 -3
- package/std/encoding/utf16.yo +6 -5
- package/std/fs/dir.yo +106 -103
- package/std/fs/file.yo +122 -158
- package/std/fs/metadata.yo +23 -22
- package/std/fs/temp.yo +41 -47
- package/std/fs/walker.yo +48 -55
- package/std/net/addr.yo +8 -7
- package/std/net/dns.yo +27 -33
- package/std/net/errors.yo +13 -8
- package/std/net/tcp.yo +92 -113
- package/std/net/udp.yo +50 -54
- package/std/os/signal.yo +13 -8
- package/std/prelude.yo +23 -2
- package/std/sys/errors.yo +45 -33
- package/std/url/url.yo +19 -32
- package/out/types/src/codegen/effects/effect-state-machine.d.ts +0 -34
package/std/net/tcp.yo
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
// std/net/tcp.yo - High-level TCP types
|
|
2
2
|
//
|
|
3
3
|
// Wraps std/sys/tcp with typed TcpListener and TcpStream objects.
|
|
4
|
+
// Uses the Exception effect for error handling.
|
|
4
5
|
//
|
|
5
6
|
// Example:
|
|
6
7
|
// { TcpListener, TcpStream } :: import "std/net/tcp";
|
|
7
8
|
// { SocketAddr, IpAddr } :: import "std/net/addr";
|
|
9
|
+
// { Exception } :: import "std/error";
|
|
8
10
|
//
|
|
9
11
|
// main :: (fn(using(io : IO)) -> unit)({
|
|
12
|
+
// given(exn) := Exception(throw : ((err) -> {
|
|
13
|
+
// println(err.message());
|
|
14
|
+
// escape ();
|
|
15
|
+
// }));
|
|
10
16
|
// addr := SocketAddr.new(IpAddr.any_v4(), u16(8080));
|
|
11
17
|
// listener := io.await(TcpListener.bind(addr));
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// stream := io.await(l.accept());
|
|
15
|
-
// // ...
|
|
16
|
-
// },
|
|
17
|
-
// .Err(e) => println(e.to_string())
|
|
18
|
-
// );
|
|
18
|
+
// stream := io.await(listener.accept());
|
|
19
|
+
// // ...
|
|
19
20
|
// });
|
|
20
21
|
|
|
21
22
|
{ GlobalAllocator } :: import "../allocator";
|
|
@@ -26,6 +27,7 @@ open import "../fmt";
|
|
|
26
27
|
{ NetError } :: import "./errors";
|
|
27
28
|
{ IOError } :: import "../sys/errors";
|
|
28
29
|
{ IpAddr, SocketAddr } :: import "./addr";
|
|
30
|
+
{ Error, AnyError, Exception } :: import "../error";
|
|
29
31
|
IO_tcp :: import "../sys/tcp";
|
|
30
32
|
{
|
|
31
33
|
AF_INET, AF_INET6, SOCK_STREAM,
|
|
@@ -53,6 +55,10 @@ _make_sockaddr :: (fn(addr: SocketAddr) -> IO_tcp.SockAddr)(
|
|
|
53
55
|
)
|
|
54
56
|
);
|
|
55
57
|
|
|
58
|
+
_throw_io :: (fn(errno_val: i32, using(exn : Exception)) -> unit)(
|
|
59
|
+
exn.throw(dyn NetError.from_io(IOError.from_errno(errno_val)))
|
|
60
|
+
);
|
|
61
|
+
|
|
56
62
|
// ============================================================================
|
|
57
63
|
// TcpStream (declared before TcpListener so accept can reference it)
|
|
58
64
|
// ============================================================================
|
|
@@ -75,21 +81,15 @@ TcpListener :: object(
|
|
|
75
81
|
|
|
76
82
|
impl(TcpListener,
|
|
77
83
|
// Bind to a socket address and start listening.
|
|
78
|
-
bind : (fn(addr: SocketAddr, using(io : IO)) -> Impl(Future(
|
|
79
|
-
io.async((using(io : IO)) => {
|
|
84
|
+
bind : (fn(addr: SocketAddr, using(io : IO)) -> Impl(Future(TcpListener, IO, Exception)))(
|
|
85
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
80
86
|
domain := cond(
|
|
81
87
|
addr.ip.is_v4() => AF_INET,
|
|
82
88
|
true => AF_INET6
|
|
83
89
|
);
|
|
84
90
|
// Create socket
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
(fd < i32(0)) => {
|
|
88
|
-
(ret : Result(TcpListener, NetError)) = .Err(NetError.from_io(IOError.from_errno((i32(0) - fd))));
|
|
89
|
-
return ret;
|
|
90
|
-
},
|
|
91
|
-
true => ()
|
|
92
|
-
);
|
|
91
|
+
raw_fd := io.await(IO_tcp.socket(domain, SOCK_STREAM, i32(0)));
|
|
92
|
+
fd := NetError.check(raw_fd);
|
|
93
93
|
// Set SO_REUSEADDR
|
|
94
94
|
reuse_val := i32(1);
|
|
95
95
|
reuse_ptr := &reuse_val;
|
|
@@ -101,8 +101,7 @@ impl(TcpListener,
|
|
|
101
101
|
cond(
|
|
102
102
|
(bind_result < i32(0)) => {
|
|
103
103
|
io.await(IO_tcp.close(fd));
|
|
104
|
-
(
|
|
105
|
-
return ret;
|
|
104
|
+
_throw_io((i32(0) - bind_result));
|
|
106
105
|
},
|
|
107
106
|
true => ()
|
|
108
107
|
);
|
|
@@ -111,21 +110,18 @@ impl(TcpListener,
|
|
|
111
110
|
cond(
|
|
112
111
|
(listen_result < i32(0)) => {
|
|
113
112
|
io.await(IO_tcp.close(fd));
|
|
114
|
-
(
|
|
115
|
-
return ret;
|
|
113
|
+
_throw_io((i32(0) - listen_result));
|
|
116
114
|
},
|
|
117
115
|
true => ()
|
|
118
116
|
);
|
|
119
|
-
|
|
120
|
-
return ret;
|
|
117
|
+
return TcpListener(_fd: fd, _local_addr: addr, _is_closed: false);
|
|
121
118
|
})
|
|
122
119
|
),
|
|
123
120
|
|
|
124
121
|
// Accept an incoming connection.
|
|
125
|
-
|
|
126
|
-
accept : (fn(self: Self, using(io : IO)) -> Impl(Future(Result(TcpStream, NetError), IO)))({
|
|
122
|
+
accept : (fn(self: Self, using(io : IO)) -> Impl(Future(TcpStream, IO, Exception)))({
|
|
127
123
|
fd := self._fd;
|
|
128
|
-
io.async((using(io : IO)) => {
|
|
124
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
129
125
|
// Allocate space for the peer address
|
|
130
126
|
addr_buf := *(u8)(malloc(usize(128)).unwrap());
|
|
131
127
|
addr_len := *(u32)(malloc(usize(4)).unwrap());
|
|
@@ -135,8 +131,7 @@ impl(TcpListener,
|
|
|
135
131
|
(client_fd < i32(0)) => {
|
|
136
132
|
free(.Some(*(void)(addr_buf)));
|
|
137
133
|
free(.Some(*(void)(addr_len)));
|
|
138
|
-
(
|
|
139
|
-
return ret;
|
|
134
|
+
_throw_io((i32(0) - client_fd));
|
|
140
135
|
},
|
|
141
136
|
true => ()
|
|
142
137
|
);
|
|
@@ -145,12 +140,11 @@ impl(TcpListener,
|
|
|
145
140
|
free(.Some(*(void)(addr_buf)));
|
|
146
141
|
free(.Some(*(void)(addr_len)));
|
|
147
142
|
peer_addr := SocketAddr.new(IpAddr.any_v4(), peer_port);
|
|
148
|
-
|
|
143
|
+
return TcpStream(
|
|
149
144
|
_fd: client_fd,
|
|
150
145
|
_peer_addr: peer_addr,
|
|
151
146
|
_is_closed: false
|
|
152
|
-
)
|
|
153
|
-
return ret;
|
|
147
|
+
);
|
|
154
148
|
})
|
|
155
149
|
}),
|
|
156
150
|
|
|
@@ -160,21 +154,20 @@ impl(TcpListener,
|
|
|
160
154
|
),
|
|
161
155
|
|
|
162
156
|
// Close the listener.
|
|
163
|
-
close : (fn(self: Self, using(io : IO)) -> Impl(Future(
|
|
157
|
+
close : (fn(self: Self, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
|
|
164
158
|
fd := self._fd;
|
|
165
|
-
io.async((using(io : IO)) => {
|
|
166
|
-
|
|
167
|
-
self._is_closed =>
|
|
159
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
160
|
+
cond(
|
|
161
|
+
self._is_closed => (),
|
|
168
162
|
true => {
|
|
169
|
-
|
|
163
|
+
r := io.await(IO_tcp.close(fd));
|
|
170
164
|
self._is_closed = true;
|
|
171
165
|
cond(
|
|
172
|
-
(
|
|
173
|
-
true =>
|
|
174
|
-
)
|
|
166
|
+
(r < i32(0)) => { _throw_io((i32(0) - r)); },
|
|
167
|
+
true => ()
|
|
168
|
+
);
|
|
175
169
|
}
|
|
176
170
|
);
|
|
177
|
-
ret
|
|
178
171
|
})
|
|
179
172
|
}),
|
|
180
173
|
|
|
@@ -205,148 +198,136 @@ export TcpListener;
|
|
|
205
198
|
|
|
206
199
|
impl(TcpStream,
|
|
207
200
|
// Connect to a remote address.
|
|
208
|
-
connect : (fn(addr: SocketAddr, using(io : IO)) -> Impl(Future(
|
|
209
|
-
io.async((using(io : IO)) => {
|
|
201
|
+
connect : (fn(addr: SocketAddr, using(io : IO)) -> Impl(Future(TcpStream, IO, Exception)))(
|
|
202
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
210
203
|
domain := cond(
|
|
211
204
|
addr.ip.is_v4() => AF_INET,
|
|
212
205
|
true => AF_INET6
|
|
213
206
|
);
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
(fd < i32(0)) => {
|
|
217
|
-
(ret : Result(TcpStream, NetError)) = .Err(NetError.from_io(IOError.from_errno((i32(0) - fd))));
|
|
218
|
-
return ret;
|
|
219
|
-
},
|
|
220
|
-
true => ()
|
|
221
|
-
);
|
|
207
|
+
raw_fd := io.await(IO_tcp.socket(domain, SOCK_STREAM, i32(0)));
|
|
208
|
+
fd := NetError.check(raw_fd);
|
|
222
209
|
saddr := _make_sockaddr(addr);
|
|
223
210
|
conn_result := io.await(IO_tcp.connect(fd, saddr.buf, saddr.len));
|
|
224
211
|
IO_tcp.free_sockaddr(saddr);
|
|
225
212
|
cond(
|
|
226
213
|
(conn_result < i32(0)) => {
|
|
227
214
|
io.await(IO_tcp.close(fd));
|
|
228
|
-
(
|
|
229
|
-
return ret;
|
|
215
|
+
_throw_io((i32(0) - conn_result));
|
|
230
216
|
},
|
|
231
217
|
true => ()
|
|
232
218
|
);
|
|
233
|
-
|
|
219
|
+
return TcpStream(
|
|
234
220
|
_fd: fd,
|
|
235
221
|
_peer_addr: addr,
|
|
236
222
|
_is_closed: false
|
|
237
|
-
)
|
|
238
|
-
return ret;
|
|
223
|
+
);
|
|
239
224
|
})
|
|
240
225
|
),
|
|
241
226
|
|
|
242
227
|
// Read bytes from the stream.
|
|
243
228
|
// Returns the number of bytes read (0 means peer closed).
|
|
244
|
-
read : (fn(self: Self, buf: *(u8), size: usize, using(io : IO)) -> Impl(Future(
|
|
229
|
+
read : (fn(self: Self, buf: *(u8), size: usize, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
|
|
245
230
|
fd := self._fd;
|
|
246
|
-
io.async((using(io : IO)) => {
|
|
247
|
-
|
|
248
|
-
NetError.
|
|
231
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
232
|
+
r := io.await(IO_tcp.recv(fd, buf, size, i32(0)));
|
|
233
|
+
NetError.check(r)
|
|
249
234
|
})
|
|
250
235
|
}),
|
|
251
236
|
|
|
252
237
|
// Write a str to the stream.
|
|
253
238
|
// Returns the number of bytes written.
|
|
254
|
-
write_str : (fn(self: Self, data: str, using(io : IO)) -> Impl(Future(
|
|
239
|
+
write_str : (fn(self: Self, data: str, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
|
|
255
240
|
fd := self._fd;
|
|
256
241
|
s := String.from(data);
|
|
257
242
|
s_bytes := s.as_bytes();
|
|
258
|
-
io.async((using(io : IO)) => {
|
|
259
|
-
|
|
260
|
-
NetError.
|
|
243
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
244
|
+
r := io.await(IO_tcp.send(fd, s_bytes.ptr().unwrap(), s_bytes.len(), i32(0)));
|
|
245
|
+
NetError.check(r)
|
|
261
246
|
})
|
|
262
247
|
}),
|
|
263
248
|
|
|
264
249
|
// Write a String to the stream.
|
|
265
250
|
// Returns the number of bytes written.
|
|
266
|
-
|
|
251
|
+
write_string : (fn(self: Self, data: String, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
|
|
267
252
|
fd := self._fd;
|
|
268
253
|
data_bytes := data.as_bytes();
|
|
269
|
-
io.async((using(io : IO)) => {
|
|
270
|
-
|
|
271
|
-
NetError.
|
|
254
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
255
|
+
r := io.await(IO_tcp.send(fd, data_bytes.ptr().unwrap(), data_bytes.len(), i32(0)));
|
|
256
|
+
NetError.check(r)
|
|
272
257
|
})
|
|
273
258
|
}),
|
|
274
259
|
|
|
275
260
|
// Write bytes to the stream.
|
|
276
261
|
// Returns the number of bytes written.
|
|
277
|
-
write_bytes : (fn(self: Self, data: ArrayList(u8), using(io : IO)) -> Impl(Future(
|
|
262
|
+
write_bytes : (fn(self: Self, data: ArrayList(u8), using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
|
|
278
263
|
fd := self._fd;
|
|
279
|
-
io.async((using(io : IO)) => {
|
|
280
|
-
|
|
281
|
-
NetError.
|
|
264
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
265
|
+
r := io.await(IO_tcp.send(fd, data.ptr().unwrap(), data.len(), i32(0)));
|
|
266
|
+
NetError.check(r)
|
|
282
267
|
})
|
|
283
268
|
}),
|
|
284
269
|
|
|
285
270
|
// Read all available data into a byte list.
|
|
286
|
-
read_all : (fn(self: Self, using(io : IO)) -> Impl(Future(
|
|
271
|
+
read_all : (fn(self: Self, using(io : IO)) -> Impl(Future(ArrayList(u8), IO, Exception)))({
|
|
287
272
|
fd := self._fd;
|
|
288
|
-
io.async((using(io : IO)) => {
|
|
273
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
289
274
|
buf_size := usize(4096);
|
|
290
275
|
buf := *(u8)(malloc(buf_size).unwrap());
|
|
291
|
-
|
|
292
|
-
|
|
276
|
+
acc := ArrayList(u8).new();
|
|
277
|
+
done := false;
|
|
278
|
+
while runtime(!(done)), {
|
|
293
279
|
n := io.await(IO_tcp.recv(fd, buf, buf_size, i32(0)));
|
|
294
280
|
cond(
|
|
295
281
|
(n < i32(0)) => {
|
|
296
282
|
free(.Some(*(void)(buf)));
|
|
297
|
-
|
|
298
|
-
|
|
283
|
+
done = true;
|
|
284
|
+
_throw_io((i32(0) - n));
|
|
299
285
|
},
|
|
300
286
|
(n == i32(0)) => {
|
|
301
|
-
|
|
302
|
-
(ret : Result(ArrayList(u8), NetError)) = .Ok(result);
|
|
303
|
-
return ret;
|
|
287
|
+
done = true;
|
|
304
288
|
},
|
|
305
289
|
true => {
|
|
306
290
|
i := usize(0);
|
|
307
291
|
while runtime((i < usize(n))), {
|
|
308
|
-
|
|
292
|
+
acc.push((buf &+ i).*);
|
|
309
293
|
i = (i + usize(1));
|
|
310
294
|
};
|
|
311
295
|
}
|
|
312
296
|
);
|
|
313
297
|
};
|
|
314
298
|
free(.Some(*(void)(buf)));
|
|
315
|
-
|
|
316
|
-
return ret;
|
|
299
|
+
return acc;
|
|
317
300
|
})
|
|
318
301
|
}),
|
|
319
302
|
|
|
320
303
|
// Shut down the connection.
|
|
321
304
|
// how: 0 = read, 1 = write, 2 = both
|
|
322
|
-
shutdown : (fn(self: Self, how: i32, using(io : IO)) -> Impl(Future(
|
|
305
|
+
shutdown : (fn(self: Self, how: i32, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
|
|
323
306
|
fd := self._fd;
|
|
324
|
-
io.async((using(io : IO)) => {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
(
|
|
328
|
-
true =>
|
|
307
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
308
|
+
r := io.await(IO_tcp.shutdown(fd, how));
|
|
309
|
+
cond(
|
|
310
|
+
(r < i32(0)) => { _throw_io((i32(0) - r)); },
|
|
311
|
+
true => ()
|
|
329
312
|
);
|
|
330
|
-
ret
|
|
331
313
|
})
|
|
332
314
|
}),
|
|
333
315
|
|
|
334
316
|
// Close the stream.
|
|
335
|
-
close : (fn(self: Self, using(io : IO)) -> Impl(Future(
|
|
317
|
+
close : (fn(self: Self, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
|
|
336
318
|
fd := self._fd;
|
|
337
|
-
io.async((using(io : IO)) => {
|
|
338
|
-
|
|
339
|
-
self._is_closed =>
|
|
319
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
320
|
+
cond(
|
|
321
|
+
self._is_closed => (),
|
|
340
322
|
true => {
|
|
341
|
-
|
|
323
|
+
r := io.await(IO_tcp.close(fd));
|
|
342
324
|
self._is_closed = true;
|
|
343
325
|
cond(
|
|
344
|
-
(
|
|
345
|
-
true =>
|
|
346
|
-
)
|
|
326
|
+
(r < i32(0)) => { _throw_io((i32(0) - r)); },
|
|
327
|
+
true => ()
|
|
328
|
+
);
|
|
347
329
|
}
|
|
348
330
|
);
|
|
349
|
-
ret
|
|
350
331
|
})
|
|
351
332
|
}),
|
|
352
333
|
|
|
@@ -361,32 +342,30 @@ impl(TcpStream,
|
|
|
361
342
|
),
|
|
362
343
|
|
|
363
344
|
// Enable/disable TCP_NODELAY (Nagle's algorithm).
|
|
364
|
-
set_nodelay : (fn(self: Self, nodelay: bool, using(io : IO)) -> Impl(Future(
|
|
345
|
+
set_nodelay : (fn(self: Self, nodelay: bool, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
|
|
365
346
|
sock_fd := self._fd;
|
|
366
|
-
io.async((using(io : IO)) => {
|
|
347
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
367
348
|
val := cond(nodelay => i32(1), true => i32(0));
|
|
368
349
|
val_ptr := &val;
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
(
|
|
372
|
-
true =>
|
|
350
|
+
r := io.await(IO_tcp.setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, *(u8)(val_ptr), u32(4)));
|
|
351
|
+
cond(
|
|
352
|
+
(r < i32(0)) => { _throw_io((i32(0) - r)); },
|
|
353
|
+
true => ()
|
|
373
354
|
);
|
|
374
|
-
ret
|
|
375
355
|
})
|
|
376
356
|
}),
|
|
377
357
|
|
|
378
358
|
// Enable/disable SO_KEEPALIVE.
|
|
379
|
-
set_keepalive : (fn(self: Self, enabled: bool, using(io : IO)) -> Impl(Future(
|
|
359
|
+
set_keepalive : (fn(self: Self, enabled: bool, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
|
|
380
360
|
sock_fd := self._fd;
|
|
381
|
-
io.async((using(io : IO)) => {
|
|
361
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
382
362
|
val := cond(enabled => i32(1), true => i32(0));
|
|
383
363
|
val_ptr := &val;
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
(
|
|
387
|
-
true =>
|
|
364
|
+
r := io.await(IO_tcp.setsockopt(sock_fd, SOL_SOCKET, SO_KEEPALIVE, *(u8)(val_ptr), u32(4)));
|
|
365
|
+
cond(
|
|
366
|
+
(r < i32(0)) => { _throw_io((i32(0) - r)); },
|
|
367
|
+
true => ()
|
|
388
368
|
);
|
|
389
|
-
ret
|
|
390
369
|
})
|
|
391
370
|
})
|
|
392
371
|
);
|
package/std/net/udp.yo
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
// std/net/udp.yo - High-level UDP socket
|
|
2
2
|
//
|
|
3
3
|
// Wraps std/sys/udp with typed UdpSocket object.
|
|
4
|
+
// Uses the Exception effect for error handling.
|
|
4
5
|
//
|
|
5
6
|
// Example:
|
|
6
7
|
// { UdpSocket } :: import "std/net/udp";
|
|
7
8
|
// { SocketAddr, IpAddr } :: import "std/net/addr";
|
|
9
|
+
// { Exception } :: import "std/error";
|
|
8
10
|
//
|
|
9
11
|
// main :: (fn(using(io : IO)) -> unit)({
|
|
12
|
+
// given(exn) := Exception(throw : ((err) -> {
|
|
13
|
+
// println(err.message());
|
|
14
|
+
// escape ();
|
|
15
|
+
// }));
|
|
10
16
|
// addr := SocketAddr.new(IpAddr.loopback_v4(), u16(9999));
|
|
11
17
|
// sock := io.await(UdpSocket.bind(addr));
|
|
12
|
-
//
|
|
13
|
-
// .Ok(s) => {
|
|
14
|
-
// io.await(s.close());
|
|
15
|
-
// },
|
|
16
|
-
// .Err(e) => println(e.to_string())
|
|
17
|
-
// );
|
|
18
|
+
// io.await(sock.close());
|
|
18
19
|
// });
|
|
19
20
|
|
|
20
21
|
{ GlobalAllocator } :: import "../allocator";
|
|
@@ -25,6 +26,7 @@ open import "../fmt";
|
|
|
25
26
|
{ NetError } :: import "./errors";
|
|
26
27
|
{ IOError } :: import "../sys/errors";
|
|
27
28
|
{ IpAddr, SocketAddr } :: import "./addr";
|
|
29
|
+
{ Error, AnyError, Exception } :: import "../error";
|
|
28
30
|
IO_udp :: import "../sys/udp";
|
|
29
31
|
IO_tcp :: import "../sys/tcp";
|
|
30
32
|
{
|
|
@@ -49,6 +51,10 @@ _make_sockaddr :: (fn(addr: SocketAddr) -> IO_tcp.SockAddr)(
|
|
|
49
51
|
)
|
|
50
52
|
);
|
|
51
53
|
|
|
54
|
+
_throw_net_io :: (fn(errno_val: i32, using(exn : Exception)) -> unit)(
|
|
55
|
+
exn.throw(dyn NetError.from_io(IOError.from_errno(errno_val)))
|
|
56
|
+
);
|
|
57
|
+
|
|
52
58
|
// ============================================================================
|
|
53
59
|
// UdpSocket
|
|
54
60
|
// ============================================================================
|
|
@@ -61,108 +67,98 @@ UdpSocket :: object(
|
|
|
61
67
|
|
|
62
68
|
impl(UdpSocket,
|
|
63
69
|
// Create and bind a UDP socket to the given address.
|
|
64
|
-
bind : (fn(addr: SocketAddr, using(io : IO)) -> Impl(Future(
|
|
65
|
-
io.async((using(io : IO)) => {
|
|
70
|
+
bind : (fn(addr: SocketAddr, using(io : IO)) -> Impl(Future(UdpSocket, IO, Exception)))(
|
|
71
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
66
72
|
domain := cond(
|
|
67
73
|
addr.ip.is_v4() => AF_INET,
|
|
68
74
|
true => AF_INET6
|
|
69
75
|
);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
(fd < i32(0)) => {
|
|
73
|
-
(ret : Result(UdpSocket, NetError)) = .Err(NetError.from_io(IOError.from_errno((i32(0) - fd))));
|
|
74
|
-
return ret;
|
|
75
|
-
},
|
|
76
|
-
true => ()
|
|
77
|
-
);
|
|
76
|
+
raw_fd := io.await(IO_udp.socket(domain, i32(0)));
|
|
77
|
+
fd := NetError.check(raw_fd);
|
|
78
78
|
saddr := _make_sockaddr(addr);
|
|
79
|
-
|
|
79
|
+
bind_r := io.await(IO_udp.bind(fd, saddr.buf, saddr.len));
|
|
80
80
|
IO_tcp.free_sockaddr(saddr);
|
|
81
81
|
cond(
|
|
82
|
-
(
|
|
82
|
+
(bind_r < i32(0)) => {
|
|
83
83
|
io.await(IO_udp.close(fd));
|
|
84
|
-
(
|
|
85
|
-
return ret;
|
|
84
|
+
_throw_net_io((i32(0) - bind_r));
|
|
86
85
|
},
|
|
87
86
|
true => ()
|
|
88
87
|
);
|
|
89
|
-
|
|
90
|
-
return ret;
|
|
88
|
+
return UdpSocket(_fd: fd, _local_addr: addr, _is_closed: false);
|
|
91
89
|
})
|
|
92
90
|
),
|
|
93
91
|
|
|
94
92
|
// Send a datagram to a specific address.
|
|
95
93
|
// Returns the number of bytes sent.
|
|
96
|
-
send_to : (fn(self: Self, data: ArrayList(u8), addr: SocketAddr, using(io : IO)) -> Impl(Future(
|
|
94
|
+
send_to : (fn(self: Self, data: ArrayList(u8), addr: SocketAddr, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
|
|
97
95
|
fd := self._fd;
|
|
98
|
-
io.async((using(io : IO)) => {
|
|
96
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
99
97
|
saddr := _make_sockaddr(addr);
|
|
100
|
-
|
|
98
|
+
r := io.await(IO_udp.sendto(fd, data.ptr().unwrap(), data.len(), i32(0), saddr.buf, saddr.len));
|
|
101
99
|
IO_tcp.free_sockaddr(saddr);
|
|
102
|
-
NetError.
|
|
100
|
+
NetError.check(r)
|
|
103
101
|
})
|
|
104
102
|
}),
|
|
105
103
|
|
|
106
104
|
// Receive a datagram.
|
|
107
105
|
// Returns the number of bytes received.
|
|
108
|
-
recv : (fn(self: Self, buf: *(u8), size: usize, using(io : IO)) -> Impl(Future(
|
|
106
|
+
recv : (fn(self: Self, buf: *(u8), size: usize, using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
|
|
109
107
|
fd := self._fd;
|
|
110
|
-
io.async((using(io : IO)) => {
|
|
111
|
-
|
|
112
|
-
NetError.
|
|
108
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
109
|
+
r := io.await(IO_udp.recv(fd, buf, size, i32(0)));
|
|
110
|
+
NetError.check(r)
|
|
113
111
|
})
|
|
114
112
|
}),
|
|
115
113
|
|
|
116
114
|
// Receive a datagram and get the source address.
|
|
117
115
|
// Returns the number of bytes received.
|
|
118
|
-
recv_from : (fn(self: Self, buf: *(u8), size: usize, src_addr: *(u8), src_addr_len: *(u32), using(io : IO)) -> Impl(Future(
|
|
116
|
+
recv_from : (fn(self: Self, buf: *(u8), size: usize, src_addr: *(u8), src_addr_len: *(u32), using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
|
|
119
117
|
fd := self._fd;
|
|
120
|
-
io.async((using(io : IO)) => {
|
|
121
|
-
|
|
122
|
-
NetError.
|
|
118
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
119
|
+
r := io.await(IO_udp.recvfrom(fd, buf, size, i32(0), src_addr, src_addr_len));
|
|
120
|
+
NetError.check(r)
|
|
123
121
|
})
|
|
124
122
|
}),
|
|
125
123
|
|
|
126
124
|
// Send data on a connected socket (after connect()).
|
|
127
|
-
send : (fn(self: Self, data: ArrayList(u8), using(io : IO)) -> Impl(Future(
|
|
125
|
+
send : (fn(self: Self, data: ArrayList(u8), using(io : IO)) -> Impl(Future(i32, IO, Exception)))({
|
|
128
126
|
fd := self._fd;
|
|
129
|
-
io.async((using(io : IO)) => {
|
|
130
|
-
|
|
131
|
-
NetError.
|
|
127
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
128
|
+
r := io.await(IO_udp.send(fd, data.ptr().unwrap(), data.len(), i32(0)));
|
|
129
|
+
NetError.check(r)
|
|
132
130
|
})
|
|
133
131
|
}),
|
|
134
132
|
|
|
135
133
|
// Close the socket.
|
|
136
|
-
close : (fn(self: Self, using(io : IO)) -> Impl(Future(
|
|
134
|
+
close : (fn(self: Self, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
|
|
137
135
|
fd := self._fd;
|
|
138
|
-
io.async((using(io : IO)) => {
|
|
139
|
-
|
|
140
|
-
self._is_closed =>
|
|
136
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
137
|
+
cond(
|
|
138
|
+
self._is_closed => (),
|
|
141
139
|
true => {
|
|
142
|
-
|
|
140
|
+
r := io.await(IO_udp.close(fd));
|
|
143
141
|
self._is_closed = true;
|
|
144
142
|
cond(
|
|
145
|
-
(
|
|
146
|
-
true =>
|
|
147
|
-
)
|
|
143
|
+
(r < i32(0)) => { _throw_net_io((i32(0) - r)); },
|
|
144
|
+
true => ()
|
|
145
|
+
);
|
|
148
146
|
}
|
|
149
147
|
);
|
|
150
|
-
ret
|
|
151
148
|
})
|
|
152
149
|
}),
|
|
153
150
|
|
|
154
151
|
// Enable/disable SO_BROADCAST.
|
|
155
|
-
set_broadcast : (fn(self: Self, enabled: bool, using(io : IO)) -> Impl(Future(
|
|
152
|
+
set_broadcast : (fn(self: Self, enabled: bool, using(io : IO)) -> Impl(Future(unit, IO, Exception)))({
|
|
156
153
|
fd := self._fd;
|
|
157
|
-
io.async((using(io : IO)) => {
|
|
154
|
+
io.async((using(io : IO, exn : Exception)) => {
|
|
158
155
|
val := cond(enabled => i32(1), true => i32(0));
|
|
159
156
|
val_ptr := &val;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
(
|
|
163
|
-
true =>
|
|
157
|
+
r := io.await(IO_udp.setsockopt(fd, SOL_SOCKET, SO_BROADCAST, *(u8)(val_ptr), u32(4)));
|
|
158
|
+
cond(
|
|
159
|
+
(r < i32(0)) => { _throw_net_io((i32(0) - r)); },
|
|
160
|
+
true => ()
|
|
164
161
|
);
|
|
165
|
-
ret
|
|
166
162
|
})
|
|
167
163
|
}),
|
|
168
164
|
|
package/std/os/signal.yo
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
on_signal : _on_signal, off_signal : _off_signal, SignalHandler
|
|
14
14
|
} :: import "../sys/signal";
|
|
15
15
|
{ platform, Platform } :: import "../process";
|
|
16
|
+
{ Error, AnyError, Exception } :: import "../error";
|
|
16
17
|
|
|
17
18
|
// ============================================================================
|
|
18
19
|
// Signal enum
|
|
@@ -73,23 +74,27 @@ _signal_num :: (fn(sig: Signal) -> i32)(
|
|
|
73
74
|
// ============================================================================
|
|
74
75
|
|
|
75
76
|
// Register a handler for the given signal.
|
|
76
|
-
on_signal :: (fn(sig: Signal, handler: SignalHandler) ->
|
|
77
|
+
on_signal :: (fn(sig: Signal, handler: SignalHandler, using(exn : Exception)) -> unit)({
|
|
77
78
|
num := _signal_num(sig);
|
|
78
79
|
r := _on_signal(num, handler);
|
|
79
80
|
cond(
|
|
80
|
-
(r < i32(0)) =>
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
(r < i32(0)) => {
|
|
82
|
+
exn.throw(dyn IOError.from_errno((i32(0) - r)));
|
|
83
|
+
},
|
|
84
|
+
true => ()
|
|
85
|
+
);
|
|
83
86
|
});
|
|
84
87
|
|
|
85
88
|
// Remove the handler for the given signal.
|
|
86
|
-
off_signal :: (fn(sig: Signal) ->
|
|
89
|
+
off_signal :: (fn(sig: Signal, using(exn : Exception)) -> unit)({
|
|
87
90
|
num := _signal_num(sig);
|
|
88
91
|
r := _off_signal(num);
|
|
89
92
|
cond(
|
|
90
|
-
(r < i32(0)) =>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
+
(r < i32(0)) => {
|
|
94
|
+
exn.throw(dyn IOError.from_errno((i32(0) - r)));
|
|
95
|
+
},
|
|
96
|
+
true => ()
|
|
97
|
+
);
|
|
93
98
|
});
|
|
94
99
|
|
|
95
100
|
export SignalHandler, on_signal, off_signal;
|