File: %2Blinux.ha

package info (click to toggle)
hare 0.25.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,948 kB
  • sloc: asm: 1,264; makefile: 123; sh: 114; lisp: 101
file content (93 lines) | stat: -rw-r--r-- 2,852 bytes parent folder | download
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
// SPDX-License-Identifier: MPL-2.0
// (c) Hare authors <https://harelang.org>

use errors;
use io;
use rt;

// A network socket.
export type socket = io::file;

// Optional flags to [[accept]] to be set on the returned [[socket]].
// See the O_CLOEXEC and O_NONBLOCK sections of open(2) for details.
// Note that CLOEXEC is on by default, and NOCLOEXEC flag disables it.
export type sockflag = enum int {
	NOCLOEXEC = rt::SOCK_CLOEXEC,
	NONBLOCK = rt::SOCK_NONBLOCK,
	DGRAM = rt::SOCK_DGRAM,
};

// Accepts the next connection from a socket. Blocks until a new connection is
// available. Optionally accepts NOCLOEXEC and NONBLOCK flags. If flags are
// supplied, the [[io::file]] returned will have the supplied flags set.
export fn accept(sock: socket, flags: sockflag = 0) (socket | error) = {
	flags ^= rt::SOCK_CLOEXEC: sockflag; // invert CLOEXEC
	const fd = match (rt::accept4(sock, null, null, flags)) {
	case let err: rt::errno =>
		return errors::errno(err);
	case let fd: int =>
		yield fd;
	};
	return io::fdopen(fd);
};

fn msg_to_native(msg: *msghdr) *rt::msghdr = {
	let native = &msg.native;
	if (len(msg.vectors) != 0) {
		native.msg_iov = msg.vectors: *[*]rt::iovec;
		native.msg_iovlen = len(msg.vectors);
	};
	if (len(msg.control) != 0) {
		native.msg_control = msg.control: *[*]u8;
		native.msg_controllen = len(msg.control);
	};
	return native;
};

// Sends a message to a socket. See [[newmsg]] for details.
export fn sendmsg(sock: socket, msg: *msghdr) (size | error) = {
	// TODO: Flags
	match (rt::sendmsg(sock, msg_to_native(msg), 0)) {
	case let n: int =>
		return n: size;
	case let err: rt::errno =>
		return errors::errno(err);
	};
};

// Receives a message from a socket. See [[newmsg]] for details.
export fn recvmsg(sock: socket, msg: *msghdr) (size | error) = {
	// TODO: Flags
	match (rt::recvmsg(sock, msg_to_native(msg), 0)) {
	case let n: int =>
		return n: size;
	case let err: rt::errno =>
		return errors::errno(err);
	};
};

// Closes a [[socket]]. No further operations against this socket are permitted
// after calling this function. Closing a socket can fail only under certain
// conditions (for example, closing a socket twice, or an interrupted syscall).
// However, the user should not attempt to close the file again on failure - at
// best the user should print a diagnostic message and move on. See close(2) for
// details.
//
// On Linux, this function is an alias for [[io::close]].
export fn close(sock: socket) (void | error) = {
	match (io::close(sock)) {
	case void => void;
	case io::underread => abort();
	case let err: errors::error =>
		return err;
	};
};

// Shuts down part of a full-duplex connection.
export fn shutdown(sock: socket, how: shut) (void | error) = {
	match (rt::shutdown(sock, how)) {
	case void => void;
	case let err: rt::errno =>
		return errors::errno(err);
	};
};