authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-07 03:55:52-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-08 18:26:24-04:00
log0d22a00f6fde79f851a7d19c2096c07f541ed0be
tree600beb890e8be09168d10849119ef55bb9fe8ffe
parent292d0cbdadd453874af6e2065638a88d4dda8a10

*WIP* async/await TCP server


17 files changed, 885 insertions(+), 801 deletions(-)

CMakeLists.txt-2
......@@ -432,7 +432,6 @@ set(ZIG_STD_FILES
432432 "dwarf.zig"
433433 "elf.zig"
434434 "empty.zig"
435 "endian.zig"
436435 "fmt/errol/enum3.zig"
437436 "fmt/errol/index.zig"
438437 "fmt/errol/lookup.zig"
......@@ -503,7 +502,6 @@ set(ZIG_STD_FILES
503502 "os/get_user_id.zig"
504503 "os/index.zig"
505504 "os/linux/errno.zig"
506 "os/linux/i386.zig"
507505 "os/linux/index.zig"
508506 "os/linux/x86_64.zig"
509507 "os/path.zig"
src/all_types.hpp+1-11
......@@ -359,7 +359,6 @@ enum NodeType {
359359 NodeTypeRoot,
360360 NodeTypeFnProto,
361361 NodeTypeFnDef,
362 NodeTypeFnDecl,
363362 NodeTypeParamDecl,
364363 NodeTypeBlock,
365364 NodeTypeGroupedExpr,
......@@ -453,10 +452,6 @@ struct AstNodeFnDef {
453452 AstNode *body;
454453};
455454
456struct AstNodeFnDecl {
457 AstNode *fn_proto;
458};
459
460455struct AstNodeParamDecl {
461456 Buf *name;
462457 AstNode *type;
......@@ -713,10 +708,6 @@ struct AstNodeSwitchRange {
713708 AstNode *end;
714709};
715710
716struct AstNodeLabel {
717 Buf *name;
718};
719
720711struct AstNodeCompTime {
721712 AstNode *expr;
722713};
......@@ -892,7 +883,6 @@ struct AstNode {
892883 union {
893884 AstNodeRoot root;
894885 AstNodeFnDef fn_def;
895 AstNodeFnDecl fn_decl;
896886 AstNodeFnProto fn_proto;
897887 AstNodeParamDecl param_decl;
898888 AstNodeBlock block;
......@@ -917,7 +907,6 @@ struct AstNode {
917907 AstNodeSwitchExpr switch_expr;
918908 AstNodeSwitchProng switch_prong;
919909 AstNodeSwitchRange switch_range;
920 AstNodeLabel label;
921910 AstNodeCompTime comptime_expr;
922911 AstNodeAsmExpr asm_expr;
923912 AstNodeFieldAccessExpr field_access_expr;
......@@ -2702,6 +2691,7 @@ struct IrInstructionFnProto {
27022691
27032692 IrInstruction **param_types;
27042693 IrInstruction *align_value;
2694 IrInstruction *async_allocator_type_value;
27052695 IrInstruction *return_type;
27062696 IrInstruction *async_allocator_type_value;
27072697 bool is_var_args;
src/analyze.cpp-1
......@@ -3236,7 +3236,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
32363236 break;
32373237 case NodeTypeContainerDecl:
32383238 case NodeTypeParamDecl:
3239 case NodeTypeFnDecl:
32403239 case NodeTypeReturnExpr:
32413240 case NodeTypeDefer:
32423241 case NodeTypeBlock:
src/ast_render.cpp-3
......@@ -148,8 +148,6 @@ static const char *node_type_str(NodeType node_type) {
148148 return "Root";
149149 case NodeTypeFnDef:
150150 return "FnDef";
151 case NodeTypeFnDecl:
152 return "FnDecl";
153151 case NodeTypeFnProto:
154152 return "FnProto";
155153 case NodeTypeParamDecl:
......@@ -1098,7 +1096,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
10981096 }
10991097 break;
11001098 }
1101 case NodeTypeFnDecl:
11021099 case NodeTypeParamDecl:
11031100 case NodeTypeTestDecl:
11041101 case NodeTypeStructField:
src/ir.cpp+16-5
......@@ -2153,12 +2153,12 @@ static IrInstruction *ir_build_unwrap_err_payload_from(IrBuilder *irb, IrInstruc
21532153}
21542154
21552155static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *source_node,
2156 IrInstruction **param_types, IrInstruction *align_value, IrInstruction *return_type,
2157 IrInstruction *async_allocator_type_value, bool is_var_args)
2156 IrInstruction **param_types, IrInstruction *align_value, IrInstruction *return_type, IrInstruction *async_allocator_type_value, bool is_var_args)
21582157{
21592158 IrInstructionFnProto *instruction = ir_build_instruction<IrInstructionFnProto>(irb, scope, source_node);
21602159 instruction->param_types = param_types;
21612160 instruction->align_value = align_value;
2161 instruction->async_allocator_type_value = async_allocator_type_value;
21622162 instruction->return_type = return_type;
21632163 instruction->async_allocator_type_value = async_allocator_type_value;
21642164 instruction->is_var_args = is_var_args;
......@@ -6041,6 +6041,13 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo
60416041 return irb->codegen->invalid_instruction;
60426042 }
60436043
6044 IrInstruction *async_allocator_type_value = nullptr;
6045 if (node->data.fn_proto.async_allocator_type != nullptr) {
6046 async_allocator_type_value = ir_gen_node(irb, node->data.fn_proto.async_allocator_type, parent_scope);
6047 if (async_allocator_type_value == irb->codegen->invalid_instruction)
6048 return irb->codegen->invalid_instruction;
6049 }
6050
60446051 IrInstruction *return_type;
60456052 if (node->data.fn_proto.return_var_token == nullptr) {
60466053 if (node->data.fn_proto.return_type == nullptr) {
......@@ -6061,8 +6068,7 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo
60616068 return irb->codegen->invalid_instruction;
60626069 }
60636070
6064 return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type,
6065 async_allocator_type_value, is_var_args);
6071 return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, async_allocator_type_value, is_var_args);
60666072}
60676073
60686074static IrInstruction *ir_gen_cancel(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
......@@ -6273,7 +6279,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
62736279 case NodeTypeSwitchRange:
62746280 case NodeTypeStructField:
62756281 case NodeTypeFnDef:
6276 case NodeTypeFnDecl:
62776282 case NodeTypeTestDecl:
62786283 zig_unreachable();
62796284 case NodeTypeBlock:
......@@ -16741,6 +16746,12 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc
1674116746 return ira->codegen->builtin_types.entry_invalid;
1674216747 }
1674316748
16749 if (instruction->async_allocator_type_value != nullptr) {
16750 fn_type_id.async_allocator_type = ir_resolve_type(ira, instruction->async_allocator_type_value->other);
16751 if (type_is_invalid(fn_type_id.async_allocator_type))
16752 return ira->codegen->builtin_types.entry_invalid;
16753 }
16754
1674416755 IrInstruction *return_type_value = instruction->return_type->other;
1674516756 fn_type_id.return_type = ir_resolve_type(ira, return_type_value);
1674616757 if (type_is_invalid(fn_type_id.return_type))
src/parser.cpp+1-3
......@@ -1037,6 +1037,7 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
10371037
10381038 Token *async_token = &pc->tokens->at(*token_index);
10391039 if (async_token->id == TokenIdKeywordAsync) {
1040 size_t token_index_of_async = *token_index;
10401041 *token_index += 1;
10411042
10421043 AstNode *allocator_expr_node = nullptr;
......@@ -2923,9 +2924,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
29232924 visit_field(&node->data.fn_def.fn_proto, visit, context);
29242925 visit_field(&node->data.fn_def.body, visit, context);
29252926 break;
2926 case NodeTypeFnDecl:
2927 visit_field(&node->data.fn_decl.fn_proto, visit, context);
2928 break;
29292927 case NodeTypeParamDecl:
29302928 visit_field(&node->data.param_decl.type, visit, context);
29312929 break;
std/endian.zig deleted-25
......@@ -1,25 +0,0 @@
1const mem = @import("mem.zig");
2const builtin = @import("builtin");
3
4pub fn swapIfLe(comptime T: type, x: T) T {
5 return swapIf(builtin.Endian.Little, T, x);
6}
7
8pub fn swapIfBe(comptime T: type, x: T) T {
9 return swapIf(builtin.Endian.Big, T, x);
10}
11
12pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) T {
13 return if (builtin.endian == endian) swap(T, x) else x;
14}
15
16pub fn swap(comptime T: type, x: T) T {
17 var buf: [@sizeOf(T)]u8 = undefined;
18 mem.writeInt(buf[0..], x, builtin.Endian.Little);
19 return mem.readInt(buf, T, builtin.Endian.Big);
20}
21
22test "swap" {
23 const debug = @import("debug/index.zig");
24 debug.assert(swap(u32, 0xDEADBEEF) == 0xEFBEADDE);
25}
std/event.zig created+202
......@@ -0,0 +1,202 @@
1const std = @import("index.zig");
2const assert = std.debug.assert;
3const event = this;
4const mem = std.mem;
5const posix = std.os.posix;
6
7pub const TcpServer = struct {
8 handleRequestFn: async(&mem.Allocator) fn (&TcpServer, &const std.net.Address, &const std.os.File) void,
9
10 loop: &Loop,
11 sockfd: i32,
12 accept_coro: ?promise,
13
14 waiting_for_emfile_node: PromiseNode,
15
16 const PromiseNode = std.LinkedList(promise).Node;
17
18 pub fn init(loop: &Loop) !TcpServer {
19 const sockfd = try std.os.posixSocket(posix.AF_INET,
20 posix.SOCK_STREAM|posix.SOCK_CLOEXEC|posix.SOCK_NONBLOCK,
21 posix.PROTO_tcp);
22 errdefer std.os.close(sockfd);
23
24 // TODO can't initialize handler coroutine here because we need well defined copy elision
25 return TcpServer {
26 .loop = loop,
27 .sockfd = sockfd,
28 .accept_coro = null,
29 .handleRequestFn = undefined,
30 .waiting_for_emfile_node = undefined,
31 };
32 }
33
34 pub fn listen(self: &TcpServer, address: &const std.net.Address,
35 handleRequestFn: async(&mem.Allocator) fn (&TcpServer, &const std.net.Address, &const std.os.File)void) !void
36 {
37 self.handleRequestFn = handleRequestFn;
38
39 try std.os.posixBind(self.sockfd, &address.sockaddr);
40 try std.os.posixListen(self.sockfd, posix.SOMAXCONN);
41
42 self.accept_coro = try async(self.loop.allocator) (TcpServer.handler)(self); // TODO #817
43 errdefer cancel ??self.accept_coro;
44
45 try self.loop.addFd(self.sockfd, ??self.accept_coro);
46 errdefer self.loop.removeFd(self.sockfd);
47
48 }
49
50 pub fn deinit(self: &TcpServer) void {
51 self.loop.removeFd(self.sockfd);
52 if (self.accept_coro) |accept_coro| cancel accept_coro;
53 std.os.close(self.sockfd);
54 }
55
56 pub async fn handler(self: &TcpServer) void {
57 while (true) {
58 var accepted_addr: std.net.Address = undefined;
59 if (std.os.posixAccept(self.sockfd, &accepted_addr.sockaddr,
60 posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd|
61 {
62 var socket = std.os.File.openHandle(accepted_fd);
63 // TODO #817
64 _ = async(self.loop.allocator) (self.handleRequestFn)(self, accepted_addr,
65 socket) catch |err| switch (err)
66 {
67 error.OutOfMemory => {
68 socket.close();
69 continue;
70 },
71 };
72 } else |err| switch (err) {
73 error.WouldBlock => {
74 suspend; // we will get resumed by epoll_wait in the event loop
75 continue;
76 },
77 error.ProcessFdQuotaExceeded => {
78 errdefer std.os.emfile_promise_queue.remove(&self.waiting_for_emfile_node);
79 suspend |p| {
80 self.waiting_for_emfile_node = PromiseNode.init(p);
81 std.os.emfile_promise_queue.append(&self.waiting_for_emfile_node);
82 }
83 continue;
84 },
85 error.ConnectionAborted,
86 error.FileDescriptorClosed => continue,
87
88 error.PageFault => unreachable,
89 error.InvalidSyscall => unreachable,
90 error.FileDescriptorNotASocket => unreachable,
91 error.OperationNotSupported => unreachable,
92
93 error.SystemFdQuotaExceeded,
94 error.SystemResources,
95 error.ProtocolFailure,
96 error.BlockedByFirewall,
97 error.Unexpected => {
98 @panic("TODO handle this error");
99 },
100 }
101 }
102 }
103};
104
105pub const Loop = struct {
106 allocator: &mem.Allocator,
107 epollfd: i32,
108 keep_running: bool,
109
110 fn init(allocator: &mem.Allocator) !Loop {
111 const epollfd = try std.os.linuxEpollCreate(std.os.linux.EPOLL_CLOEXEC);
112 return Loop {
113 .keep_running = true,
114 .allocator = allocator,
115 .epollfd = epollfd,
116 };
117 }
118
119 pub fn addFd(self: &Loop, fd: i32, prom: promise) !void {
120 var ev = std.os.linux.epoll_event {
121 .events = std.os.linux.EPOLLIN|std.os.linux.EPOLLET,
122 .data = std.os.linux.epoll_data {
123 .ptr = @ptrToInt(prom),
124 },
125 };
126 try std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_ADD, fd, &ev);
127 }
128
129 pub fn removeFd(self: &Loop, fd: i32) void {
130 std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_DEL, fd, undefined) catch {};
131 }
132
133 async fn waitFd(self: &Loop, fd: i32) !void {
134 defer self.removeFd(fd);
135 suspend |p| {
136 try self.addFd(fd, p);
137 }
138 }
139
140 pub fn stop(self: &Loop) void {
141 // TODO make atomic
142 self.keep_running = false;
143 // TODO activate an fd in the epoll set
144 }
145
146 pub fn run(self: &Loop) void {
147 while (self.keep_running) {
148 var events: [16]std.os.linux.epoll_event = undefined;
149 const count = std.os.linuxEpollWait(self.epollfd, events[0..], -1);
150 for (events[0..count]) |ev| {
151 const p = @intToPtr(promise, ev.data.ptr);
152 resume p;
153 }
154 }
155 }
156};
157
158test "listen on a port, send bytes, receive bytes" {
159 const MyServer = struct {
160 tcp_server: TcpServer,
161
162 const Self = this;
163
164 async(&mem.Allocator) fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address,
165 _socket: &const std.os.File) void
166 {
167 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
168 var socket = *_socket; // TODO https://github.com/zig-lang/zig/issues/733
169 defer socket.close();
170 const next_handler = async errorableHandler(self, _addr, socket) catch |err| switch (err) {
171 error.OutOfMemory => return,
172 };
173 (await next_handler) catch |err| switch (err) {
174
175 };
176 suspend |p| { cancel p; }
177 }
178
179 async fn errorableHandler(self: &Self, _addr: &const std.net.Address,
180 _socket: &const std.os.File) !void
181 {
182 const addr = *_addr; // TODO https://github.com/zig-lang/zig/issues/733
183 var socket = *_socket; // TODO https://github.com/zig-lang/zig/issues/733
184
185 var adapter = std.io.FileOutStream.init(&socket);
186 var stream = &adapter.stream;
187 try stream.print("hello from server\n") catch unreachable;
188 }
189 };
190
191 const ip4addr = std.net.parseIp4("127.0.0.1") catch unreachable;
192 const addr = std.net.Address.initIp4(ip4addr, 0);
193
194 var loop = try Loop.init(std.debug.global_allocator);
195 var server = MyServer {
196 .tcp_server = try TcpServer.init(&loop),
197 };
198 defer server.tcp_server.deinit();
199 try server.tcp_server.listen(addr, MyServer.handler);
200
201 loop.run();
202}
std/fmt/index.zig+1-1
......@@ -465,7 +465,7 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
465465 return x;
466466}
467467
468fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
468pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
469469 const value = switch (c) {
470470 '0' ... '9' => c - '0',
471471 'A' ... 'Z' => c - 'A' + 10,
std/index.zig+2-2
......@@ -17,7 +17,7 @@ pub const debug = @import("debug/index.zig");
1717pub const dwarf = @import("dwarf.zig");
1818pub const elf = @import("elf.zig");
1919pub const empty_import = @import("empty.zig");
20pub const endian = @import("endian.zig");
20pub const event = @import("event.zig");
2121pub const fmt = @import("fmt/index.zig");
2222pub const hash = @import("hash/index.zig");
2323pub const heap = @import("heap.zig");
......@@ -50,13 +50,13 @@ test "std" {
5050 _ = @import("dwarf.zig");
5151 _ = @import("elf.zig");
5252 _ = @import("empty.zig");
53 _ = @import("endian.zig");
5453 _ = @import("fmt/index.zig");
5554 _ = @import("hash/index.zig");
5655 _ = @import("io.zig");
5756 _ = @import("macho.zig");
5857 _ = @import("math/index.zig");
5958 _ = @import("mem.zig");
59 _ = @import("net.zig");
6060 _ = @import("heap.zig");
6161 _ = @import("net.zig");
6262 _ = @import("os/index.zig");
std/linked_list.zig+1
......@@ -161,6 +161,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
161161 }
162162
163163 list.len -= 1;
164 assert(list.len == 0 or (list.first != null and list.last != null));
164165 }
165166
166167 /// Remove and return the last node in the list.
std/mem.zig+26
......@@ -3,6 +3,7 @@ const debug = std.debug;
33const assert = debug.assert;
44const math = std.math;
55const builtin = @import("builtin");
6const mem = this;
67
78pub const Allocator = struct {
89 const Error = error {OutOfMemory};
......@@ -550,3 +551,28 @@ test "std.mem.rotate" {
550551
551552 assert(eql(i32, arr, []i32{ 1, 2, 4, 5, 3 }));
552553}
554
555// TODO: When https://github.com/zig-lang/zig/issues/649 is solved these can be done by
556// endian-casting the pointer and then dereferencing
557
558pub fn endianSwapIfLe(comptime T: type, x: T) T {
559 return endianSwapIf(builtin.Endian.Little, T, x);
560}
561
562pub fn endianSwapIfBe(comptime T: type, x: T) T {
563 return endianSwapIf(builtin.Endian.Big, T, x);
564}
565
566pub fn endianSwapIf(endian: builtin.Endian, comptime T: type, x: T) T {
567 return if (builtin.endian == endian) endianSwap(T, x) else x;
568}
569
570pub fn endianSwap(comptime T: type, x: T) T {
571 var buf: [@sizeOf(T)]u8 = undefined;
572 mem.writeInt(buf[0..], x, builtin.Endian.Little);
573 return mem.readInt(buf, T, builtin.Endian.Big);
574}
575
576test "std.mem.endianSwap" {
577 assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE);
578}
std/net.zig+108-166
......@@ -1,143 +1,103 @@
11const std = @import("index.zig");
2const linux = std.os.linux;
32const assert = std.debug.assert;
4const endian = std.endian;
5
6// TODO don't trust this file, it bit rotted. start over
7
8const Connection = struct {
9 socket_fd: i32,
10
11 pub fn send(c: Connection, buf: []const u8) !usize {
12 const send_ret = linux.sendto(c.socket_fd, buf.ptr, buf.len, 0, null, 0);
13 const send_err = linux.getErrno(send_ret);
14 switch (send_err) {
15 0 => return send_ret,
16 linux.EINVAL => unreachable,
17 linux.EFAULT => unreachable,
18 linux.ECONNRESET => return error.ConnectionReset,
19 linux.EINTR => return error.SigInterrupt,
20 // TODO there are more possible errors
21 else => return error.Unexpected,
22 }
3const net = this;
4const posix = std.os.posix;
5const mem = std.mem;
6
7pub const Address = struct {
8 sockaddr: posix.sockaddr,
9
10 pub fn initIp4(ip4: u32, port: u16) Address {
11 return Address {
12 .sockaddr = posix.sockaddr {
13 .in = posix.sockaddr_in {
14 .family = posix.AF_INET,
15 .port = std.mem.endianSwapIfLe(u16, port),
16 .addr = ip4,
17 .zero = []u8{0} ** 8,
18 },
19 },
20 };
2321 }
2422
25 pub fn recv(c: Connection, buf: []u8) ![]u8 {
26 const recv_ret = linux.recvfrom(c.socket_fd, buf.ptr, buf.len, 0, null, null);
27 const recv_err = linux.getErrno(recv_ret);
28 switch (recv_err) {
29 0 => return buf[0..recv_ret],
30 linux.EINVAL => unreachable,
31 linux.EFAULT => unreachable,
32 linux.ENOTSOCK => return error.NotSocket,
33 linux.EINTR => return error.SigInterrupt,
34 linux.ENOMEM => return error.OutOfMemory,
35 linux.ECONNREFUSED => return error.ConnectionRefused,
36 linux.EBADF => return error.BadFd,
37 // TODO more error values
38 else => return error.Unexpected,
39 }
23 pub fn initIp6(ip6: &const Ip6Addr, port: u16) Address {
24 return Address {
25 .family = posix.AF_INET6,
26 .sockaddr = posix.sockaddr {
27 .in6 = posix.sockaddr_in6 {
28 .family = posix.AF_INET6,
29 .port = std.mem.endianSwapIfLe(u16, port),
30 .flowinfo = 0,
31 .addr = ip6.addr,
32 .scope_id = ip6.scope_id,
33 },
34 },
35 };
4036 }
4137
42 pub fn close(c: Connection) !void {
43 switch (linux.getErrno(linux.close(c.socket_fd))) {
44 0 => return,
45 linux.EBADF => unreachable,
46 linux.EINTR => return error.SigInterrupt,
47 linux.EIO => return error.Io,
48 else => return error.Unexpected,
38 pub fn format(self: &const Address, out_stream: var) !void {
39 switch (self.sockaddr.in.family) {
40 posix.AF_INET => {
41 const native_endian_port = std.mem.endianSwapIfLe(u16, self.sockaddr.in.port);
42 const bytes = ([]const u8)((&self.sockaddr.in.addr)[0..1]);
43 try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
44 },
45 posix.AF_INET6 => {
46 const native_endian_port = std.mem.endianSwapIfLe(u16, self.sockaddr.in6.port);
47 try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
48 },
49 else => try out_stream.write("(unrecognized address family)"),
4950 }
5051 }
5152};
5253
53const Address = struct {
54 family: u16,
55 scope_id: u32,
56 addr: [16]u8,
57 sort_key: i32,
58};
59
60pub fn lookup(hostname: []const u8, out_addrs: []Address) ![]Address {
61 if (hostname.len == 0) {
62
63 unreachable; // TODO
64 }
65
66 unreachable; // TODO
67}
54pub fn parseIp4(buf: []const u8) !u32 {
55 var result: u32 = undefined;
56 const out_ptr = ([]u8)((&result)[0..1]);
6857
69pub fn connectAddr(addr: &Address, port: u16) !Connection {
70 const socket_ret = linux.socket(addr.family, linux.SOCK_STREAM, linux.PROTO_tcp);
71 const socket_err = linux.getErrno(socket_ret);
72 if (socket_err > 0) {
73 // TODO figure out possible errors from socket()
74 return error.Unexpected;
58 var x: u8 = 0;
59 var index: u8 = 0;
60 var saw_any_digits = false;
61 for (buf) |c| {
62 if (c == '.') {
63 if (!saw_any_digits) {
64 return error.InvalidCharacter;
65 }
66 if (index == 3) {
67 return error.InvalidEnd;
68 }
69 out_ptr[index] = x;
70 index += 1;
71 x = 0;
72 saw_any_digits = false;
73 } else if (c >= '0' and c <= '9') {
74 saw_any_digits = true;
75 const digit = c - '0';
76 if (@mulWithOverflow(u8, x, 10, &x)) {
77 return error.Overflow;
78 }
79 if (@addWithOverflow(u8, x, digit, &x)) {
80 return error.Overflow;
81 }
82 } else {
83 return error.InvalidCharacter;
84 }
7585 }
76 const socket_fd = i32(socket_ret);
77
78 const connect_ret = if (addr.family == linux.AF_INET) x: {
79 var os_addr: linux.sockaddr_in = undefined;
80 os_addr.family = addr.family;
81 os_addr.port = endian.swapIfLe(u16, port);
82 @memcpy((&u8)(&os_addr.addr), &addr.addr[0], 4);
83 @memset(&os_addr.zero[0], 0, @sizeOf(@typeOf(os_addr.zero)));
84 break :x linux.connect(socket_fd, (&linux.sockaddr)(&os_addr), @sizeOf(linux.sockaddr_in));
85 } else if (addr.family == linux.AF_INET6) x: {
86 var os_addr: linux.sockaddr_in6 = undefined;
87 os_addr.family = addr.family;
88 os_addr.port = endian.swapIfLe(u16, port);
89 os_addr.flowinfo = 0;
90 os_addr.scope_id = addr.scope_id;
91 @memcpy(&os_addr.addr[0], &addr.addr[0], 16);
92 break :x linux.connect(socket_fd, (&linux.sockaddr)(&os_addr), @sizeOf(linux.sockaddr_in6));
93 } else {
94 unreachable;
95 };
96 const connect_err = linux.getErrno(connect_ret);
97 if (connect_err > 0) {
98 switch (connect_err) {
99 linux.ETIMEDOUT => return error.TimedOut,
100 else => {
101 // TODO figure out possible errors from connect()
102 return error.Unexpected;
103 },
104 }
86 if (index == 3 and saw_any_digits) {
87 out_ptr[index] = x;
88 return result;
10589 }
10690
107 return Connection {
108 .socket_fd = socket_fd,
109 };
110}
111
112pub fn connect(hostname: []const u8, port: u16) !Connection {
113 var addrs_buf: [1]Address = undefined;
114 const addrs_slice = try lookup(hostname, addrs_buf[0..]);
115 const main_addr = &addrs_slice[0];
116
117 return connectAddr(main_addr, port);
118}
119
120pub fn parseIpLiteral(buf: []const u8) !Address {
121
122 return error.InvalidIpLiteral;
91 return error.Incomplete;
12392}
12493
125fn hexDigit(c: u8) u8 {
126 // TODO use switch with range
127 if ('0' <= c and c <= '9') {
128 return c - '0';
129 } else if ('A' <= c and c <= 'Z') {
130 return c - 'A' + 10;
131 } else if ('a' <= c and c <= 'z') {
132 return c - 'a' + 10;
133 } else {
134 return @maxValue(u8);
135 }
136}
94pub const Ip6Addr = struct {
95 scope_id: u32,
96 addr: [16]u8,
97};
13798
138fn parseIp6(buf: []const u8) !Address {
139 var result: Address = undefined;
140 result.family = linux.AF_INET6;
99pub fn parseIp6(buf: []const u8) !Ip6Addr {
100 var result: Ip6Addr = undefined;
141101 result.scope_id = 0;
142102 const ip_slice = result.addr[0..];
143103
......@@ -156,14 +116,14 @@ fn parseIp6(buf: []const u8) !Address {
156116 return error.Overflow;
157117 }
158118 } else {
159 return error.InvalidChar;
119 return error.InvalidCharacter;
160120 }
161121 } else if (c == ':') {
162122 if (!saw_any_digits) {
163 return error.InvalidChar;
123 return error.InvalidCharacter;
164124 }
165125 if (index == 14) {
166 return error.JunkAtEnd;
126 return error.InvalidEnd;
167127 }
168128 ip_slice[index] = @truncate(u8, x >> 8);
169129 index += 1;
......@@ -174,7 +134,7 @@ fn parseIp6(buf: []const u8) !Address {
174134 saw_any_digits = false;
175135 } else if (c == '%') {
176136 if (!saw_any_digits) {
177 return error.InvalidChar;
137 return error.InvalidCharacter;
178138 }
179139 if (index == 14) {
180140 ip_slice[index] = @truncate(u8, x >> 8);
......@@ -185,10 +145,7 @@ fn parseIp6(buf: []const u8) !Address {
185145 scope_id = true;
186146 saw_any_digits = false;
187147 } else {
188 const digit = hexDigit(c);
189 if (digit == @maxValue(u8)) {
190 return error.InvalidChar;
191 }
148 const digit = try std.fmt.charToDigit(c, 16);
192149 if (@mulWithOverflow(u16, x, 16, &x)) {
193150 return error.Overflow;
194151 }
......@@ -216,42 +173,27 @@ fn parseIp6(buf: []const u8) !Address {
216173 return error.Incomplete;
217174}
218175
219fn parseIp4(buf: []const u8) !u32 {
220 var result: u32 = undefined;
221 const out_ptr = ([]u8)((&result)[0..1]);
176test "std.net.parseIp4" {
177 assert((try parseIp4("127.0.0.1")) == std.mem.endianSwapIfLe(u32, 0x7f000001));
222178
223 var x: u8 = 0;
224 var index: u8 = 0;
225 var saw_any_digits = false;
226 for (buf) |c| {
227 if (c == '.') {
228 if (!saw_any_digits) {
229 return error.InvalidChar;
230 }
231 if (index == 3) {
232 return error.JunkAtEnd;
233 }
234 out_ptr[index] = x;
235 index += 1;
236 x = 0;
237 saw_any_digits = false;
238 } else if (c >= '0' and c <= '9') {
239 saw_any_digits = true;
240 const digit = c - '0';
241 if (@mulWithOverflow(u8, x, 10, &x)) {
242 return error.Overflow;
243 }
244 if (@addWithOverflow(u8, x, digit, &x)) {
245 return error.Overflow;
246 }
247 } else {
248 return error.InvalidChar;
249 }
250 }
251 if (index == 3 and saw_any_digits) {
252 out_ptr[index] = x;
253 return result;
179 testParseIp4Fail("256.0.0.1", error.Overflow);
180 testParseIp4Fail("x.0.0.1", error.InvalidCharacter);
181 testParseIp4Fail("127.0.0.1.1", error.InvalidEnd);
182 testParseIp4Fail("127.0.0.", error.Incomplete);
183 testParseIp4Fail("100..0.1", error.InvalidCharacter);
184}
185
186fn testParseIp4Fail(buf: []const u8, expected_err: error) void {
187 if (parseIp4(buf)) |_| {
188 @panic("expected error");
189 } else |e| {
190 assert(e == expected_err);
254191 }
192}
255193
256 return error.Incomplete;
194test "std.net.parseIp6" {
195 const addr = try parseIp6("FF01:0:0:0:0:0:0:FB");
196 assert(addr.addr[0] == 0xff);
197 assert(addr.addr[1] == 0x01);
198 assert(addr.addr[2] == 0x00);
257199}
std/os/index.zig+352-21
......@@ -4,6 +4,19 @@ const Os = builtin.Os;
44const is_windows = builtin.os == Os.windows;
55const os = this;
66
7test "std.os" {
8 _ = @import("child_process.zig");
9 _ = @import("darwin.zig");
10 _ = @import("darwin_errno.zig");
11 _ = @import("get_user_id.zig");
12 _ = @import("linux/errno.zig");
13 _ = @import("linux/index.zig");
14 _ = @import("linux/x86_64.zig");
15 _ = @import("path.zig");
16 _ = @import("test.zig");
17 _ = @import("windows/index.zig");
18}
19
720pub const windows = @import("windows/index.zig");
821pub const darwin = @import("darwin.zig");
922pub const linux = @import("linux/index.zig");
......@@ -14,6 +27,7 @@ pub const posix = switch(builtin.os) {
1427 Os.zen => zen,
1528 else => @compileError("Unsupported OS"),
1629};
30pub const net = @import("net.zig");
1731
1832pub const ChildProcess = @import("child_process.zig").ChildProcess;
1933pub const path = @import("path.zig");
......@@ -173,6 +187,13 @@ pub fn exit(status: u8) noreturn {
173187 }
174188}
175189
190/// When a file descriptor is closed on linux, it pops the first
191/// node from this queue and resumes it.
192/// Async functions which get the EMFILE error code can suspend,
193/// putting their coroutine handle into this list.
194/// TODO make this an atomic linked list
195pub var emfile_promise_queue = std.LinkedList(promise).init();
196
176197/// Closes the file handle. Keeps trying if it gets interrupted by a signal.
177198pub fn close(handle: FileHandle) void {
178199 if (is_windows) {
......@@ -180,10 +201,12 @@ pub fn close(handle: FileHandle) void {
180201 } else {
181202 while (true) {
182203 const err = posix.getErrno(posix.close(handle));
183 if (err == posix.EINTR) {
184 continue;
185 } else {
186 return;
204 switch (err) {
205 posix.EINTR => continue,
206 else => {
207 if (emfile_promise_queue.popFirst()) |p| resume p.data;
208 return;
209 },
187210 }
188211 }
189212 }
......@@ -1753,27 +1776,16 @@ fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const
17531776 assert(it.next(debug.global_allocator) == null);
17541777}
17551778
1756test "std.os" {
1757 _ = @import("child_process.zig");
1758 _ = @import("darwin_errno.zig");
1759 _ = @import("darwin.zig");
1760 _ = @import("get_user_id.zig");
1761 _ = @import("linux/errno.zig");
1762 //_ = @import("linux_i386.zig");
1763 _ = @import("linux/x86_64.zig");
1764 _ = @import("linux/index.zig");
1765 _ = @import("path.zig");
1766 _ = @import("windows/index.zig");
1767 _ = @import("test.zig");
1768}
1769
1770
17711779// TODO make this a build variable that you can set
17721780const unexpected_error_tracing = false;
1781const UnexpectedError = error {
1782 /// The Operating System returned an undocumented error code.
1783 Unexpected,
1784};
17731785
17741786/// Call this when you made a syscall or something that sets errno
17751787/// and you get an unexpected error.
1776pub fn unexpectedErrorPosix(errno: usize) (error{Unexpected}) {
1788pub fn unexpectedErrorPosix(errno: usize) UnexpectedError {
17771789 if (unexpected_error_tracing) {
17781790 debug.warn("unexpected errno: {}\n", errno);
17791791 debug.dumpCurrentStackTrace(null);
......@@ -1783,7 +1795,7 @@ pub fn unexpectedErrorPosix(errno: usize) (error{Unexpected}) {
17831795
17841796/// Call this when you made a windows DLL call or something that does SetLastError
17851797/// and you get an unexpected error.
1786pub fn unexpectedErrorWindows(err: windows.DWORD) (error{Unexpected}) {
1798pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError {
17871799 if (unexpected_error_tracing) {
17881800 debug.warn("unexpected GetLastError(): {}\n", err);
17891801 debug.dumpCurrentStackTrace(null);
......@@ -1898,3 +1910,322 @@ pub fn isTty(handle: FileHandle) bool {
18981910 }
18991911 }
19001912}
1913
1914pub const PosixSocketError = error {
1915 /// Permission to create a socket of the specified type and/or
1916 /// pro‐tocol is denied.
1917 PermissionDenied,
1918
1919 /// The implementation does not support the specified address family.
1920 AddressFamilyNotSupported,
1921
1922 /// Unknown protocol, or protocol family not available.
1923 ProtocolFamilyNotAvailable,
1924
1925 /// The per-process limit on the number of open file descriptors has been reached.
1926 ProcessFdQuotaExceeded,
1927
1928 /// The system-wide limit on the total number of open files has been reached.
1929 SystemFdQuotaExceeded,
1930
1931 /// Insufficient memory is available. The socket cannot be created until sufficient
1932 /// resources are freed.
1933 SystemResources,
1934
1935 /// The protocol type or the specified protocol is not supported within this domain.
1936 ProtocolNotSupported,
1937};
1938
1939pub fn posixSocket(domain: u32, socket_type: u32, protocol: u32) !i32 {
1940 const rc = posix.socket(domain, socket_type, protocol);
1941 const err = posix.getErrno(rc);
1942 switch (err) {
1943 0 => return i32(rc),
1944 posix.EACCES => return PosixSocketError.PermissionDenied,
1945 posix.EAFNOSUPPORT => return PosixSocketError.AddressFamilyNotSupported,
1946 posix.EINVAL => return PosixSocketError.ProtocolFamilyNotAvailable,
1947 posix.EMFILE => return PosixSocketError.ProcessFdQuotaExceeded,
1948 posix.ENFILE => return PosixSocketError.SystemFdQuotaExceeded,
1949 posix.ENOBUFS, posix.ENOMEM => return PosixSocketError.SystemResources,
1950 posix.EPROTONOSUPPORT => return PosixSocketError.ProtocolNotSupported,
1951 else => return unexpectedErrorPosix(err),
1952 }
1953}
1954
1955pub const PosixBindError = error {
1956 /// The address is protected, and the user is not the superuser.
1957 /// For UNIX domain sockets: Search permission is denied on a component
1958 /// of the path prefix.
1959 AccessDenied,
1960
1961 /// The given address is already in use, or in the case of Internet domain sockets,
1962 /// The port number was specified as zero in the socket
1963 /// address structure, but, upon attempting to bind to an ephemeral port, it was
1964 /// determined that all port numbers in the ephemeral port range are currently in
1965 /// use. See the discussion of /proc/sys/net/ipv4/ip_local_port_range ip(7).
1966 AddressInUse,
1967
1968 /// sockfd is not a valid file descriptor.
1969 InvalidFileDescriptor,
1970
1971 /// The socket is already bound to an address, or addrlen is wrong, or addr is not
1972 /// a valid address for this socket's domain.
1973 InvalidSocketOrAddress,
1974
1975 /// The file descriptor sockfd does not refer to a socket.
1976 FileDescriptorNotASocket,
1977
1978 /// A nonexistent interface was requested or the requested address was not local.
1979 AddressNotAvailable,
1980
1981 /// addr points outside the user's accessible address space.
1982 PageFault,
1983
1984 /// Too many symbolic links were encountered in resolving addr.
1985 SymLinkLoop,
1986
1987 /// addr is too long.
1988 NameTooLong,
1989
1990 /// A component in the directory prefix of the socket pathname does not exist.
1991 FileNotFound,
1992
1993 /// Insufficient kernel memory was available.
1994 SystemResources,
1995
1996 /// A component of the path prefix is not a directory.
1997 NotDir,
1998
1999 /// The socket inode would reside on a read-only filesystem.
2000 ReadOnlyFileSystem,
2001
2002 Unexpected,
2003};
2004
2005/// addr is `&const T` where T is one of the sockaddr
2006pub fn posixBind(fd: i32, addr: &const posix.sockaddr) PosixBindError!void {
2007 const rc = posix.bind(fd, addr, @sizeOf(posix.sockaddr));
2008 const err = posix.getErrno(rc);
2009 switch (err) {
2010 0 => return,
2011 posix.EACCES => return PosixBindError.AccessDenied,
2012 posix.EADDRINUSE => return PosixBindError.AddressInUse,
2013 posix.EBADF => return PosixBindError.InvalidFileDescriptor,
2014 posix.EINVAL => return PosixBindError.InvalidSocketOrAddress,
2015 posix.ENOTSOCK => return PosixBindError.FileDescriptorNotASocket,
2016 posix.EADDRNOTAVAIL => return PosixBindError.AddressNotAvailable,
2017 posix.EFAULT => return PosixBindError.PageFault,
2018 posix.ELOOP => return PosixBindError.SymLinkLoop,
2019 posix.ENAMETOOLONG => return PosixBindError.NameTooLong,
2020 posix.ENOENT => return PosixBindError.FileNotFound,
2021 posix.ENOMEM => return PosixBindError.SystemResources,
2022 posix.ENOTDIR => return PosixBindError.NotDir,
2023 posix.EROFS => return PosixBindError.ReadOnlyFileSystem,
2024 else => return unexpectedErrorPosix(err),
2025 }
2026}
2027
2028const PosixListenError = error {
2029 /// Another socket is already listening on the same port.
2030 /// For Internet domain sockets, the socket referred to by sockfd had not previously
2031 /// been bound to an address and, upon attempting to bind it to an ephemeral port, it
2032 /// was determined that all port numbers in the ephemeral port range are currently in
2033 /// use. See the discussion of /proc/sys/net/ipv4/ip_local_port_range in ip(7).
2034 AddressInUse,
2035
2036 /// The argument sockfd is not a valid file descriptor.
2037 InvalidFileDescriptor,
2038
2039 /// The file descriptor sockfd does not refer to a socket.
2040 FileDescriptorNotASocket,
2041
2042 /// The socket is not of a type that supports the listen() operation.
2043 OperationNotSupported,
2044
2045 Unexpected,
2046};
2047
2048pub fn posixListen(sockfd: i32, backlog: u32) PosixListenError!void {
2049 const rc = posix.listen(sockfd, backlog);
2050 const err = posix.getErrno(rc);
2051 switch (err) {
2052 0 => return,
2053 posix.EADDRINUSE => return PosixListenError.AddressInUse,
2054 posix.EBADF => return PosixListenError.InvalidFileDescriptor,
2055 posix.ENOTSOCK => return PosixListenError.FileDescriptorNotASocket,
2056 posix.EOPNOTSUPP => return PosixListenError.OperationNotSupported,
2057 else => return unexpectedErrorPosix(err),
2058 }
2059}
2060
2061pub const PosixAcceptError = error {
2062 /// The socket is marked nonblocking and no connections are present to be accepted.
2063 WouldBlock,
2064
2065 /// sockfd is not an open file descriptor.
2066 FileDescriptorClosed,
2067
2068 ConnectionAborted,
2069
2070 /// The addr argument is not in a writable part of the user address space.
2071 PageFault,
2072
2073 /// Socket is not listening for connections, or addrlen is invalid (e.g., is negative),
2074 /// or invalid value in flags.
2075 InvalidSyscall,
2076
2077 /// The per-process limit on the number of open file descriptors has been reached.
2078 ProcessFdQuotaExceeded,
2079
2080 /// The system-wide limit on the total number of open files has been reached.
2081 SystemFdQuotaExceeded,
2082
2083 /// Not enough free memory. This often means that the memory allocation is limited
2084 /// by the socket buffer limits, not by the system memory.
2085 SystemResources,
2086
2087 /// The file descriptor sockfd does not refer to a socket.
2088 FileDescriptorNotASocket,
2089
2090 /// The referenced socket is not of type SOCK_STREAM.
2091 OperationNotSupported,
2092
2093 ProtocolFailure,
2094
2095 /// Firewall rules forbid connection.
2096 BlockedByFirewall,
2097
2098 Unexpected,
2099};
2100
2101pub fn posixAccept(fd: i32, addr: &posix.sockaddr, flags: u32) PosixAcceptError!i32 {
2102 while (true) {
2103 var sockaddr_size = u32(@sizeOf(posix.sockaddr));
2104 const rc = posix.accept4(fd, addr, &sockaddr_size, flags);
2105 const err = posix.getErrno(rc);
2106 switch (err) {
2107 0 => return i32(rc),
2108 posix.EINTR => continue,
2109 else => return unexpectedErrorPosix(err),
2110
2111 posix.EAGAIN => return PosixAcceptError.WouldBlock,
2112 posix.EBADF => return PosixAcceptError.FileDescriptorClosed,
2113 posix.ECONNABORTED => return PosixAcceptError.ConnectionAborted,
2114 posix.EFAULT => return PosixAcceptError.PageFault,
2115 posix.EINVAL => return PosixAcceptError.InvalidSyscall,
2116 posix.EMFILE => return PosixAcceptError.ProcessFdQuotaExceeded,
2117 posix.ENFILE => return PosixAcceptError.SystemFdQuotaExceeded,
2118 posix.ENOBUFS, posix.ENOMEM => return PosixAcceptError.SystemResources,
2119 posix.ENOTSOCK => return PosixAcceptError.FileDescriptorNotASocket,
2120 posix.EOPNOTSUPP => return PosixAcceptError.OperationNotSupported,
2121 posix.EPROTO => return PosixAcceptError.ProtocolFailure,
2122 posix.EPERM => return PosixAcceptError.BlockedByFirewall,
2123 }
2124 }
2125}
2126
2127pub const LinuxEpollCreateError = error {
2128 /// Invalid value specified in flags.
2129 InvalidSyscall,
2130
2131 /// The per-user limit on the number of epoll instances imposed by
2132 /// /proc/sys/fs/epoll/max_user_instances was encountered. See epoll(7) for further
2133 /// details.
2134 /// Or, The per-process limit on the number of open file descriptors has been reached.
2135 ProcessFdQuotaExceeded,
2136
2137 /// The system-wide limit on the total number of open files has been reached.
2138 SystemFdQuotaExceeded,
2139
2140 /// There was insufficient memory to create the kernel object.
2141 SystemResources,
2142
2143 Unexpected,
2144};
2145
2146pub fn linuxEpollCreate(flags: u32) LinuxEpollCreateError!i32 {
2147 const rc = posix.epoll_create1(flags);
2148 const err = posix.getErrno(rc);
2149 switch (err) {
2150 0 => return i32(rc),
2151 else => return unexpectedErrorPosix(err),
2152
2153 posix.EINVAL => return LinuxEpollCreateError.InvalidSyscall,
2154 posix.EMFILE => return LinuxEpollCreateError.ProcessFdQuotaExceeded,
2155 posix.ENFILE => return LinuxEpollCreateError.SystemFdQuotaExceeded,
2156 posix.ENOMEM => return LinuxEpollCreateError.SystemResources,
2157 }
2158}
2159
2160pub const LinuxEpollCtlError = error {
2161 /// epfd or fd is not a valid file descriptor.
2162 InvalidFileDescriptor,
2163
2164 /// op was EPOLL_CTL_ADD, and the supplied file descriptor fd is already registered
2165 /// with this epoll instance.
2166 FileDescriptorAlreadyPresentInSet,
2167
2168 /// epfd is not an epoll file descriptor, or fd is the same as epfd, or the requested
2169 /// operation op is not supported by this interface, or
2170 /// An invalid event type was specified along with EPOLLEXCLUSIVE in events, or
2171 /// op was EPOLL_CTL_MOD and events included EPOLLEXCLUSIVE, or
2172 /// op was EPOLL_CTL_MOD and the EPOLLEXCLUSIVE flag has previously been applied to
2173 /// this epfd, fd pair, or
2174 /// EPOLLEXCLUSIVE was specified in event and fd refers to an epoll instance.
2175 InvalidSyscall,
2176
2177 /// fd refers to an epoll instance and this EPOLL_CTL_ADD operation would result in a
2178 /// circular loop of epoll instances monitoring one another.
2179 OperationCausesCircularLoop,
2180
2181 /// op was EPOLL_CTL_MOD or EPOLL_CTL_DEL, and fd is not registered with this epoll
2182 /// instance.
2183 FileDescriptorNotRegistered,
2184
2185 /// There was insufficient memory to handle the requested op control operation.
2186 SystemResources,
2187
2188 /// The limit imposed by /proc/sys/fs/epoll/max_user_watches was encountered while
2189 /// trying to register (EPOLL_CTL_ADD) a new file descriptor on an epoll instance.
2190 /// See epoll(7) for further details.
2191 UserResourceLimitReached,
2192
2193 /// The target file fd does not support epoll. This error can occur if fd refers to,
2194 /// for example, a regular file or a directory.
2195 FileDescriptorIncompatibleWithEpoll,
2196
2197 Unexpected,
2198};
2199
2200pub fn linuxEpollCtl(epfd: i32, op: u32, fd: i32, event: &linux.epoll_event) LinuxEpollCtlError!void {
2201 const rc = posix.epoll_ctl(epfd, op, fd, event);
2202 const err = posix.getErrno(rc);
2203 switch (err) {
2204 0 => return,
2205 else => return unexpectedErrorPosix(err),
2206
2207 posix.EBADF => return LinuxEpollCtlError.InvalidFileDescriptor,
2208 posix.EEXIST => return LinuxEpollCtlError.FileDescriptorAlreadyPresentInSet,
2209 posix.EINVAL => return LinuxEpollCtlError.InvalidSyscall,
2210 posix.ELOOP => return LinuxEpollCtlError.OperationCausesCircularLoop,
2211 posix.ENOENT => return LinuxEpollCtlError.FileDescriptorNotRegistered,
2212 posix.ENOMEM => return LinuxEpollCtlError.SystemResources,
2213 posix.ENOSPC => return LinuxEpollCtlError.UserResourceLimitReached,
2214 posix.EPERM => return LinuxEpollCtlError.FileDescriptorIncompatibleWithEpoll,
2215 }
2216}
2217
2218pub fn linuxEpollWait(epfd: i32, events: []linux.epoll_event, timeout: i32) usize {
2219 while (true) {
2220 const rc = posix.epoll_wait(epfd, &events[0], u32(events.len), timeout);
2221 const err = posix.getErrno(rc);
2222 switch (err) {
2223 0 => return rc,
2224 posix.EINTR => continue,
2225 posix.EBADF => unreachable,
2226 posix.EFAULT => unreachable,
2227 posix.EINVAL => unreachable,
2228 else => unreachable,
2229 }
2230 }
2231}
std/os/linux/i386.zig deleted-505
......@@ -1,505 +0,0 @@
1const std = @import("../../index.zig");
2const linux = std.os.linux;
3const socklen_t = linux.socklen_t;
4const iovec = linux.iovec;
5
6pub const SYS_restart_syscall = 0;
7pub const SYS_exit = 1;
8pub const SYS_fork = 2;
9pub const SYS_read = 3;
10pub const SYS_write = 4;
11pub const SYS_open = 5;
12pub const SYS_close = 6;
13pub const SYS_waitpid = 7;
14pub const SYS_creat = 8;
15pub const SYS_link = 9;
16pub const SYS_unlink = 10;
17pub const SYS_execve = 11;
18pub const SYS_chdir = 12;
19pub const SYS_time = 13;
20pub const SYS_mknod = 14;
21pub const SYS_chmod = 15;
22pub const SYS_lchown = 16;
23pub const SYS_break = 17;
24pub const SYS_oldstat = 18;
25pub const SYS_lseek = 19;
26pub const SYS_getpid = 20;
27pub const SYS_mount = 21;
28pub const SYS_umount = 22;
29pub const SYS_setuid = 23;
30pub const SYS_getuid = 24;
31pub const SYS_stime = 25;
32pub const SYS_ptrace = 26;
33pub const SYS_alarm = 27;
34pub const SYS_oldfstat = 28;
35pub const SYS_pause = 29;
36pub const SYS_utime = 30;
37pub const SYS_stty = 31;
38pub const SYS_gtty = 32;
39pub const SYS_access = 33;
40pub const SYS_nice = 34;
41pub const SYS_ftime = 35;
42pub const SYS_sync = 36;
43pub const SYS_kill = 37;
44pub const SYS_rename = 38;
45pub const SYS_mkdir = 39;
46pub const SYS_rmdir = 40;
47pub const SYS_dup = 41;
48pub const SYS_pipe = 42;
49pub const SYS_times = 43;
50pub const SYS_prof = 44;
51pub const SYS_brk = 45;
52pub const SYS_setgid = 46;
53pub const SYS_getgid = 47;
54pub const SYS_signal = 48;
55pub const SYS_geteuid = 49;
56pub const SYS_getegid = 50;
57pub const SYS_acct = 51;
58pub const SYS_umount2 = 52;
59pub const SYS_lock = 53;
60pub const SYS_ioctl = 54;
61pub const SYS_fcntl = 55;
62pub const SYS_mpx = 56;
63pub const SYS_setpgid = 57;
64pub const SYS_ulimit = 58;
65pub const SYS_oldolduname = 59;
66pub const SYS_umask = 60;
67pub const SYS_chroot = 61;
68pub const SYS_ustat = 62;
69pub const SYS_dup2 = 63;
70pub const SYS_getppid = 64;
71pub const SYS_getpgrp = 65;
72pub const SYS_setsid = 66;
73pub const SYS_sigaction = 67;
74pub const SYS_sgetmask = 68;
75pub const SYS_ssetmask = 69;
76pub const SYS_setreuid = 70;
77pub const SYS_setregid = 71;
78pub const SYS_sigsuspend = 72;
79pub const SYS_sigpending = 73;
80pub const SYS_sethostname = 74;
81pub const SYS_setrlimit = 75;
82pub const SYS_getrlimit = 76;
83pub const SYS_getrusage = 77;
84pub const SYS_gettimeofday = 78;
85pub const SYS_settimeofday = 79;
86pub const SYS_getgroups = 80;
87pub const SYS_setgroups = 81;
88pub const SYS_select = 82;
89pub const SYS_symlink = 83;
90pub const SYS_oldlstat = 84;
91pub const SYS_readlink = 85;
92pub const SYS_uselib = 86;
93pub const SYS_swapon = 87;
94pub const SYS_reboot = 88;
95pub const SYS_readdir = 89;
96pub const SYS_mmap = 90;
97pub const SYS_munmap = 91;
98pub const SYS_truncate = 92;
99pub const SYS_ftruncate = 93;
100pub const SYS_fchmod = 94;
101pub const SYS_fchown = 95;
102pub const SYS_getpriority = 96;
103pub const SYS_setpriority = 97;
104pub const SYS_profil = 98;
105pub const SYS_statfs = 99;
106pub const SYS_fstatfs = 100;
107pub const SYS_ioperm = 101;
108pub const SYS_socketcall = 102;
109pub const SYS_syslog = 103;
110pub const SYS_setitimer = 104;
111pub const SYS_getitimer = 105;
112pub const SYS_stat = 106;
113pub const SYS_lstat = 107;
114pub const SYS_fstat = 108;
115pub const SYS_olduname = 109;
116pub const SYS_iopl = 110;
117pub const SYS_vhangup = 111;
118pub const SYS_idle = 112;
119pub const SYS_vm86old = 113;
120pub const SYS_wait4 = 114;
121pub const SYS_swapoff = 115;
122pub const SYS_sysinfo = 116;
123pub const SYS_ipc = 117;
124pub const SYS_fsync = 118;
125pub const SYS_sigreturn = 119;
126pub const SYS_clone = 120;
127pub const SYS_setdomainname = 121;
128pub const SYS_uname = 122;
129pub const SYS_modify_ldt = 123;
130pub const SYS_adjtimex = 124;
131pub const SYS_mprotect = 125;
132pub const SYS_sigprocmask = 126;
133pub const SYS_create_module = 127;
134pub const SYS_init_module = 128;
135pub const SYS_delete_module = 129;
136pub const SYS_get_kernel_syms = 130;
137pub const SYS_quotactl = 131;
138pub const SYS_getpgid = 132;
139pub const SYS_fchdir = 133;
140pub const SYS_bdflush = 134;
141pub const SYS_sysfs = 135;
142pub const SYS_personality = 136;
143pub const SYS_afs_syscall = 137;
144pub const SYS_setfsuid = 138;
145pub const SYS_setfsgid = 139;
146pub const SYS__llseek = 140;
147pub const SYS_getdents = 141;
148pub const SYS__newselect = 142;
149pub const SYS_flock = 143;
150pub const SYS_msync = 144;
151pub const SYS_readv = 145;
152pub const SYS_writev = 146;
153pub const SYS_getsid = 147;
154pub const SYS_fdatasync = 148;
155pub const SYS__sysctl = 149;
156pub const SYS_mlock = 150;
157pub const SYS_munlock = 151;
158pub const SYS_mlockall = 152;
159pub const SYS_munlockall = 153;
160pub const SYS_sched_setparam = 154;
161pub const SYS_sched_getparam = 155;
162pub const SYS_sched_setscheduler = 156;
163pub const SYS_sched_getscheduler = 157;
164pub const SYS_sched_yield = 158;
165pub const SYS_sched_get_priority_max = 159;
166pub const SYS_sched_get_priority_min = 160;
167pub const SYS_sched_rr_get_interval = 161;
168pub const SYS_nanosleep = 162;
169pub const SYS_mremap = 163;
170pub const SYS_setresuid = 164;
171pub const SYS_getresuid = 165;
172pub const SYS_vm86 = 166;
173pub const SYS_query_module = 167;
174pub const SYS_poll = 168;
175pub const SYS_nfsservctl = 169;
176pub const SYS_setresgid = 170;
177pub const SYS_getresgid = 171;
178pub const SYS_prctl = 172;
179pub const SYS_rt_sigreturn = 173;
180pub const SYS_rt_sigaction = 174;
181pub const SYS_rt_sigprocmask = 175;
182pub const SYS_rt_sigpending = 176;
183pub const SYS_rt_sigtimedwait = 177;
184pub const SYS_rt_sigqueueinfo = 178;
185pub const SYS_rt_sigsuspend = 179;
186pub const SYS_pread64 = 180;
187pub const SYS_pwrite64 = 181;
188pub const SYS_chown = 182;
189pub const SYS_getcwd = 183;
190pub const SYS_capget = 184;
191pub const SYS_capset = 185;
192pub const SYS_sigaltstack = 186;
193pub const SYS_sendfile = 187;
194pub const SYS_getpmsg = 188;
195pub const SYS_putpmsg = 189;
196pub const SYS_vfork = 190;
197pub const SYS_ugetrlimit = 191;
198pub const SYS_mmap2 = 192;
199pub const SYS_truncate64 = 193;
200pub const SYS_ftruncate64 = 194;
201pub const SYS_stat64 = 195;
202pub const SYS_lstat64 = 196;
203pub const SYS_fstat64 = 197;
204pub const SYS_lchown32 = 198;
205pub const SYS_getuid32 = 199;
206pub const SYS_getgid32 = 200;
207pub const SYS_geteuid32 = 201;
208pub const SYS_getegid32 = 202;
209pub const SYS_setreuid32 = 203;
210pub const SYS_setregid32 = 204;
211pub const SYS_getgroups32 = 205;
212pub const SYS_setgroups32 = 206;
213pub const SYS_fchown32 = 207;
214pub const SYS_setresuid32 = 208;
215pub const SYS_getresuid32 = 209;
216pub const SYS_setresgid32 = 210;
217pub const SYS_getresgid32 = 211;
218pub const SYS_chown32 = 212;
219pub const SYS_setuid32 = 213;
220pub const SYS_setgid32 = 214;
221pub const SYS_setfsuid32 = 215;
222pub const SYS_setfsgid32 = 216;
223pub const SYS_pivot_root = 217;
224pub const SYS_mincore = 218;
225pub const SYS_madvise = 219;
226pub const SYS_madvise1 = 219;
227pub const SYS_getdents64 = 220;
228pub const SYS_fcntl64 = 221;
229pub const SYS_gettid = 224;
230pub const SYS_readahead = 225;
231pub const SYS_setxattr = 226;
232pub const SYS_lsetxattr = 227;
233pub const SYS_fsetxattr = 228;
234pub const SYS_getxattr = 229;
235pub const SYS_lgetxattr = 230;
236pub const SYS_fgetxattr = 231;
237pub const SYS_listxattr = 232;
238pub const SYS_llistxattr = 233;
239pub const SYS_flistxattr = 234;
240pub const SYS_removexattr = 235;
241pub const SYS_lremovexattr = 236;
242pub const SYS_fremovexattr = 237;
243pub const SYS_tkill = 238;
244pub const SYS_sendfile64 = 239;
245pub const SYS_futex = 240;
246pub const SYS_sched_setaffinity = 241;
247pub const SYS_sched_getaffinity = 242;
248pub const SYS_set_thread_area = 243;
249pub const SYS_get_thread_area = 244;
250pub const SYS_io_setup = 245;
251pub const SYS_io_destroy = 246;
252pub const SYS_io_getevents = 247;
253pub const SYS_io_submit = 248;
254pub const SYS_io_cancel = 249;
255pub const SYS_fadvise64 = 250;
256pub const SYS_exit_group = 252;
257pub const SYS_lookup_dcookie = 253;
258pub const SYS_epoll_create = 254;
259pub const SYS_epoll_ctl = 255;
260pub const SYS_epoll_wait = 256;
261pub const SYS_remap_file_pages = 257;
262pub const SYS_set_tid_address = 258;
263pub const SYS_timer_create = 259;
264pub const SYS_timer_settime = SYS_timer_create+1;
265pub const SYS_timer_gettime = SYS_timer_create+2;
266pub const SYS_timer_getoverrun = SYS_timer_create+3;
267pub const SYS_timer_delete = SYS_timer_create+4;
268pub const SYS_clock_settime = SYS_timer_create+5;
269pub const SYS_clock_gettime = SYS_timer_create+6;
270pub const SYS_clock_getres = SYS_timer_create+7;
271pub const SYS_clock_nanosleep = SYS_timer_create+8;
272pub const SYS_statfs64 = 268;
273pub const SYS_fstatfs64 = 269;
274pub const SYS_tgkill = 270;
275pub const SYS_utimes = 271;
276pub const SYS_fadvise64_64 = 272;
277pub const SYS_vserver = 273;
278pub const SYS_mbind = 274;
279pub const SYS_get_mempolicy = 275;
280pub const SYS_set_mempolicy = 276;
281pub const SYS_mq_open = 277;
282pub const SYS_mq_unlink = SYS_mq_open+1;
283pub const SYS_mq_timedsend = SYS_mq_open+2;
284pub const SYS_mq_timedreceive = SYS_mq_open+3;
285pub const SYS_mq_notify = SYS_mq_open+4;
286pub const SYS_mq_getsetattr = SYS_mq_open+5;
287pub const SYS_kexec_load = 283;
288pub const SYS_waitid = 284;
289pub const SYS_add_key = 286;
290pub const SYS_request_key = 287;
291pub const SYS_keyctl = 288;
292pub const SYS_ioprio_set = 289;
293pub const SYS_ioprio_get = 290;
294pub const SYS_inotify_init = 291;
295pub const SYS_inotify_add_watch = 292;
296pub const SYS_inotify_rm_watch = 293;
297pub const SYS_migrate_pages = 294;
298pub const SYS_openat = 295;
299pub const SYS_mkdirat = 296;
300pub const SYS_mknodat = 297;
301pub const SYS_fchownat = 298;
302pub const SYS_futimesat = 299;
303pub const SYS_fstatat64 = 300;
304pub const SYS_unlinkat = 301;
305pub const SYS_renameat = 302;
306pub const SYS_linkat = 303;
307pub const SYS_symlinkat = 304;
308pub const SYS_readlinkat = 305;
309pub const SYS_fchmodat = 306;
310pub const SYS_faccessat = 307;
311pub const SYS_pselect6 = 308;
312pub const SYS_ppoll = 309;
313pub const SYS_unshare = 310;
314pub const SYS_set_robust_list = 311;
315pub const SYS_get_robust_list = 312;
316pub const SYS_splice = 313;
317pub const SYS_sync_file_range = 314;
318pub const SYS_tee = 315;
319pub const SYS_vmsplice = 316;
320pub const SYS_move_pages = 317;
321pub const SYS_getcpu = 318;
322pub const SYS_epoll_pwait = 319;
323pub const SYS_utimensat = 320;
324pub const SYS_signalfd = 321;
325pub const SYS_timerfd_create = 322;
326pub const SYS_eventfd = 323;
327pub const SYS_fallocate = 324;
328pub const SYS_timerfd_settime = 325;
329pub const SYS_timerfd_gettime = 326;
330pub const SYS_signalfd4 = 327;
331pub const SYS_eventfd2 = 328;
332pub const SYS_epoll_create1 = 329;
333pub const SYS_dup3 = 330;
334pub const SYS_pipe2 = 331;
335pub const SYS_inotify_init1 = 332;
336pub const SYS_preadv = 333;
337pub const SYS_pwritev = 334;
338pub const SYS_rt_tgsigqueueinfo = 335;
339pub const SYS_perf_event_open = 336;
340pub const SYS_recvmmsg = 337;
341pub const SYS_fanotify_init = 338;
342pub const SYS_fanotify_mark = 339;
343pub const SYS_prlimit64 = 340;
344pub const SYS_name_to_handle_at = 341;
345pub const SYS_open_by_handle_at = 342;
346pub const SYS_clock_adjtime = 343;
347pub const SYS_syncfs = 344;
348pub const SYS_sendmmsg = 345;
349pub const SYS_setns = 346;
350pub const SYS_process_vm_readv = 347;
351pub const SYS_process_vm_writev = 348;
352pub const SYS_kcmp = 349;
353pub const SYS_finit_module = 350;
354pub const SYS_sched_setattr = 351;
355pub const SYS_sched_getattr = 352;
356pub const SYS_renameat2 = 353;
357pub const SYS_seccomp = 354;
358pub const SYS_getrandom = 355;
359pub const SYS_memfd_create = 356;
360pub const SYS_bpf = 357;
361pub const SYS_execveat = 358;
362pub const SYS_socket = 359;
363pub const SYS_socketpair = 360;
364pub const SYS_bind = 361;
365pub const SYS_connect = 362;
366pub const SYS_listen = 363;
367pub const SYS_accept4 = 364;
368pub const SYS_getsockopt = 365;
369pub const SYS_setsockopt = 366;
370pub const SYS_getsockname = 367;
371pub const SYS_getpeername = 368;
372pub const SYS_sendto = 369;
373pub const SYS_sendmsg = 370;
374pub const SYS_recvfrom = 371;
375pub const SYS_recvmsg = 372;
376pub const SYS_shutdown = 373;
377pub const SYS_userfaultfd = 374;
378pub const SYS_membarrier = 375;
379pub const SYS_mlock2 = 376;
380
381
382pub const O_CREAT = 0o100;
383pub const O_EXCL = 0o200;
384pub const O_NOCTTY = 0o400;
385pub const O_TRUNC = 0o1000;
386pub const O_APPEND = 0o2000;
387pub const O_NONBLOCK = 0o4000;
388pub const O_DSYNC = 0o10000;
389pub const O_SYNC = 0o4010000;
390pub const O_RSYNC = 0o4010000;
391pub const O_DIRECTORY = 0o200000;
392pub const O_NOFOLLOW = 0o400000;
393pub const O_CLOEXEC = 0o2000000;
394
395pub const O_ASYNC = 0o20000;
396pub const O_DIRECT = 0o40000;
397pub const O_LARGEFILE = 0o100000;
398pub const O_NOATIME = 0o1000000;
399pub const O_PATH = 0o10000000;
400pub const O_TMPFILE = 0o20200000;
401pub const O_NDELAY = O_NONBLOCK;
402
403pub const F_DUPFD = 0;
404pub const F_GETFD = 1;
405pub const F_SETFD = 2;
406pub const F_GETFL = 3;
407pub const F_SETFL = 4;
408
409pub const F_SETOWN = 8;
410pub const F_GETOWN = 9;
411pub const F_SETSIG = 10;
412pub const F_GETSIG = 11;
413
414pub const F_GETLK = 12;
415pub const F_SETLK = 13;
416pub const F_SETLKW = 14;
417
418pub const F_SETOWN_EX = 15;
419pub const F_GETOWN_EX = 16;
420
421pub const F_GETOWNER_UIDS = 17;
422
423pub inline fn syscall0(number: usize) usize {
424 return asm volatile ("int $0x80"
425 : [ret] "={eax}" (-> usize)
426 : [number] "{eax}" (number));
427}
428
429pub inline fn syscall1(number: usize, arg1: usize) usize {
430 return asm volatile ("int $0x80"
431 : [ret] "={eax}" (-> usize)
432 : [number] "{eax}" (number),
433 [arg1] "{ebx}" (arg1));
434}
435
436pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) usize {
437 return asm volatile ("int $0x80"
438 : [ret] "={eax}" (-> usize)
439 : [number] "{eax}" (number),
440 [arg1] "{ebx}" (arg1),
441 [arg2] "{ecx}" (arg2));
442}
443
444pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize {
445 return asm volatile ("int $0x80"
446 : [ret] "={eax}" (-> usize)
447 : [number] "{eax}" (number),
448 [arg1] "{ebx}" (arg1),
449 [arg2] "{ecx}" (arg2),
450 [arg3] "{edx}" (arg3));
451}
452
453pub inline fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
454 return asm volatile ("int $0x80"
455 : [ret] "={eax}" (-> usize)
456 : [number] "{eax}" (number),
457 [arg1] "{ebx}" (arg1),
458 [arg2] "{ecx}" (arg2),
459 [arg3] "{edx}" (arg3),
460 [arg4] "{esi}" (arg4));
461}
462
463pub inline fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize,
464 arg4: usize, arg5: usize) usize
465{
466 return asm volatile ("int $0x80"
467 : [ret] "={eax}" (-> usize)
468 : [number] "{eax}" (number),
469 [arg1] "{ebx}" (arg1),
470 [arg2] "{ecx}" (arg2),
471 [arg3] "{edx}" (arg3),
472 [arg4] "{esi}" (arg4),
473 [arg5] "{edi}" (arg5));
474}
475
476pub inline fn syscall6(number: usize, arg1: usize, arg2: usize, arg3: usize,
477 arg4: usize, arg5: usize, arg6: usize) usize
478{
479 return asm volatile ("int $0x80"
480 : [ret] "={eax}" (-> usize)
481 : [number] "{eax}" (number),
482 [arg1] "{ebx}" (arg1),
483 [arg2] "{ecx}" (arg2),
484 [arg3] "{edx}" (arg3),
485 [arg4] "{esi}" (arg4),
486 [arg5] "{edi}" (arg5),
487 [arg6] "{ebp}" (arg6));
488}
489
490pub nakedcc fn restore() void {
491 asm volatile (
492 \\popl %%eax
493 \\movl $119, %%eax
494 \\int $0x80
495 :
496 :
497 : "rcx", "r11");
498}
499
500pub nakedcc fn restore_rt() void {
501 asm volatile ("int $0x80"
502 :
503 : [number] "{eax}" (usize(SYS_rt_sigreturn))
504 : "rcx", "r11");
505}
std/os/linux/index.zig+160-56
......@@ -101,17 +101,6 @@ pub const SIG_BLOCK = 0;
101101pub const SIG_UNBLOCK = 1;
102102pub const SIG_SETMASK = 2;
103103
104pub const SOCK_STREAM = 1;
105pub const SOCK_DGRAM = 2;
106pub const SOCK_RAW = 3;
107pub const SOCK_RDM = 4;
108pub const SOCK_SEQPACKET = 5;
109pub const SOCK_DCCP = 6;
110pub const SOCK_PACKET = 10;
111pub const SOCK_CLOEXEC = 0o2000000;
112pub const SOCK_NONBLOCK = 0o4000;
113
114
115104pub const PROTO_ip = 0o000;
116105pub const PROTO_icmp = 0o001;
117106pub const PROTO_igmp = 0o002;
......@@ -149,6 +138,20 @@ pub const PROTO_encap = 0o142;
149138pub const PROTO_pim = 0o147;
150139pub const PROTO_raw = 0o377;
151140
141pub const SHUT_RD = 0;
142pub const SHUT_WR = 1;
143pub const SHUT_RDWR = 2;
144
145pub const SOCK_STREAM = 1;
146pub const SOCK_DGRAM = 2;
147pub const SOCK_RAW = 3;
148pub const SOCK_RDM = 4;
149pub const SOCK_SEQPACKET = 5;
150pub const SOCK_DCCP = 6;
151pub const SOCK_PACKET = 10;
152pub const SOCK_CLOEXEC = 0o2000000;
153pub const SOCK_NONBLOCK = 0o4000;
154
152155pub const PF_UNSPEC = 0;
153156pub const PF_LOCAL = 1;
154157pub const PF_UNIX = PF_LOCAL;
......@@ -193,7 +196,10 @@ pub const PF_CAIF = 37;
193196pub const PF_ALG = 38;
194197pub const PF_NFC = 39;
195198pub const PF_VSOCK = 40;
196pub const PF_MAX = 41;
199pub const PF_KCM = 41;
200pub const PF_QIPCRTR = 42;
201pub const PF_SMC = 43;
202pub const PF_MAX = 44;
197203
198204pub const AF_UNSPEC = PF_UNSPEC;
199205pub const AF_LOCAL = PF_LOCAL;
......@@ -239,8 +245,137 @@ pub const AF_CAIF = PF_CAIF;
239245pub const AF_ALG = PF_ALG;
240246pub const AF_NFC = PF_NFC;
241247pub const AF_VSOCK = PF_VSOCK;
248pub const AF_KCM = PF_KCM;
249pub const AF_QIPCRTR = PF_QIPCRTR;
250pub const AF_SMC = PF_SMC;
242251pub const AF_MAX = PF_MAX;
243252
253pub const SO_DEBUG = 1;
254pub const SO_REUSEADDR = 2;
255pub const SO_TYPE = 3;
256pub const SO_ERROR = 4;
257pub const SO_DONTROUTE = 5;
258pub const SO_BROADCAST = 6;
259pub const SO_SNDBUF = 7;
260pub const SO_RCVBUF = 8;
261pub const SO_KEEPALIVE = 9;
262pub const SO_OOBINLINE = 10;
263pub const SO_NO_CHECK = 11;
264pub const SO_PRIORITY = 12;
265pub const SO_LINGER = 13;
266pub const SO_BSDCOMPAT = 14;
267pub const SO_REUSEPORT = 15;
268pub const SO_PASSCRED = 16;
269pub const SO_PEERCRED = 17;
270pub const SO_RCVLOWAT = 18;
271pub const SO_SNDLOWAT = 19;
272pub const SO_RCVTIMEO = 20;
273pub const SO_SNDTIMEO = 21;
274pub const SO_ACCEPTCONN = 30;
275pub const SO_SNDBUFFORCE = 32;
276pub const SO_RCVBUFFORCE = 33;
277pub const SO_PROTOCOL = 38;
278pub const SO_DOMAIN = 39;
279
280pub const SO_SECURITY_AUTHENTICATION = 22;
281pub const SO_SECURITY_ENCRYPTION_TRANSPORT = 23;
282pub const SO_SECURITY_ENCRYPTION_NETWORK = 24;
283
284pub const SO_BINDTODEVICE = 25;
285
286pub const SO_ATTACH_FILTER = 26;
287pub const SO_DETACH_FILTER = 27;
288pub const SO_GET_FILTER = SO_ATTACH_FILTER;
289
290pub const SO_PEERNAME = 28;
291pub const SO_TIMESTAMP = 29;
292pub const SCM_TIMESTAMP = SO_TIMESTAMP;
293
294pub const SO_PEERSEC = 31;
295pub const SO_PASSSEC = 34;
296pub const SO_TIMESTAMPNS = 35;
297pub const SCM_TIMESTAMPNS = SO_TIMESTAMPNS;
298pub const SO_MARK = 36;
299pub const SO_TIMESTAMPING = 37;
300pub const SCM_TIMESTAMPING = SO_TIMESTAMPING;
301pub const SO_RXQ_OVFL = 40;
302pub const SO_WIFI_STATUS = 41;
303pub const SCM_WIFI_STATUS = SO_WIFI_STATUS;
304pub const SO_PEEK_OFF = 42;
305pub const SO_NOFCS = 43;
306pub const SO_LOCK_FILTER = 44;
307pub const SO_SELECT_ERR_QUEUE = 45;
308pub const SO_BUSY_POLL = 46;
309pub const SO_MAX_PACING_RATE = 47;
310pub const SO_BPF_EXTENSIONS = 48;
311pub const SO_INCOMING_CPU = 49;
312pub const SO_ATTACH_BPF = 50;
313pub const SO_DETACH_BPF = SO_DETACH_FILTER;
314pub const SO_ATTACH_REUSEPORT_CBPF = 51;
315pub const SO_ATTACH_REUSEPORT_EBPF = 52;
316pub const SO_CNX_ADVICE = 53;
317pub const SCM_TIMESTAMPING_OPT_STATS = 54;
318pub const SO_MEMINFO = 55;
319pub const SO_INCOMING_NAPI_ID = 56;
320pub const SO_COOKIE = 57;
321pub const SCM_TIMESTAMPING_PKTINFO = 58;
322pub const SO_PEERGROUPS = 59;
323pub const SO_ZEROCOPY = 60;
324
325pub const SOL_SOCKET = 1;
326
327pub const SOL_IP = 0;
328pub const SOL_IPV6 = 41;
329pub const SOL_ICMPV6 = 58;
330
331pub const SOL_RAW = 255;
332pub const SOL_DECNET = 261;
333pub const SOL_X25 = 262;
334pub const SOL_PACKET = 263;
335pub const SOL_ATM = 264;
336pub const SOL_AAL = 265;
337pub const SOL_IRDA = 266;
338pub const SOL_NETBEUI = 267;
339pub const SOL_LLC = 268;
340pub const SOL_DCCP = 269;
341pub const SOL_NETLINK = 270;
342pub const SOL_TIPC = 271;
343pub const SOL_RXRPC = 272;
344pub const SOL_PPPOL2TP = 273;
345pub const SOL_BLUETOOTH = 274;
346pub const SOL_PNPIPE = 275;
347pub const SOL_RDS = 276;
348pub const SOL_IUCV = 277;
349pub const SOL_CAIF = 278;
350pub const SOL_ALG = 279;
351pub const SOL_NFC = 280;
352pub const SOL_KCM = 281;
353pub const SOL_TLS = 282;
354
355pub const SOMAXCONN = 128;
356
357pub const MSG_OOB = 0x0001;
358pub const MSG_PEEK = 0x0002;
359pub const MSG_DONTROUTE = 0x0004;
360pub const MSG_CTRUNC = 0x0008;
361pub const MSG_PROXY = 0x0010;
362pub const MSG_TRUNC = 0x0020;
363pub const MSG_DONTWAIT = 0x0040;
364pub const MSG_EOR = 0x0080;
365pub const MSG_WAITALL = 0x0100;
366pub const MSG_FIN = 0x0200;
367pub const MSG_SYN = 0x0400;
368pub const MSG_CONFIRM = 0x0800;
369pub const MSG_RST = 0x1000;
370pub const MSG_ERRQUEUE = 0x2000;
371pub const MSG_NOSIGNAL = 0x4000;
372pub const MSG_MORE = 0x8000;
373pub const MSG_WAITFORONE = 0x10000;
374pub const MSG_BATCH = 0x40000;
375pub const MSG_ZEROCOPY = 0x4000000;
376pub const MSG_FASTOPEN = 0x20000000;
377pub const MSG_CMSG_CLOEXEC = 0x40000000;
378
244379pub const DT_UNKNOWN = 0;
245380pub const DT_FIFO = 1;
246381pub const DT_CHR = 2;
......@@ -599,30 +734,27 @@ pub fn sigismember(set: &const sigset_t, sig: u6) bool {
599734 return ((*set)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0;
600735}
601736
602
737pub const in_port_t = u16;
603738pub const sa_family_t = u16;
604739pub const socklen_t = u32;
605pub const in_addr = u32;
606pub const in6_addr = [16]u8;
607740
608pub const sockaddr = extern struct {
609 family: sa_family_t,
610 port: u16,
611 data: [12]u8,
741pub const sockaddr = extern union {
742 in: sockaddr_in,
743 in6: sockaddr_in6,
612744};
613745
614746pub const sockaddr_in = extern struct {
615747 family: sa_family_t,
616 port: u16,
617 addr: in_addr,
748 port: in_port_t,
749 addr: u32,
618750 zero: [8]u8,
619751};
620752
621753pub const sockaddr_in6 = extern struct {
622754 family: sa_family_t,
623 port: u16,
755 port: in_port_t,
624756 flowinfo: u32,
625 addr: in6_addr,
757 addr: [16]u8,
626758 scope_id: u32,
627759};
628760
......@@ -639,8 +771,8 @@ pub fn getpeername(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) us
639771 return syscall3(SYS_getpeername, usize(fd), @ptrToInt(addr), @ptrToInt(len));
640772}
641773
642pub fn socket(domain: i32, socket_type: i32, protocol: i32) usize {
643 return syscall3(SYS_socket, usize(domain), usize(socket_type), usize(protocol));
774pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
775 return syscall3(SYS_socket, domain, socket_type, protocol);
644776}
645777
646778pub fn setsockopt(fd: i32, level: i32, optname: i32, optval: &const u8, optlen: socklen_t) usize {
......@@ -677,8 +809,8 @@ pub fn bind(fd: i32, addr: &const sockaddr, len: socklen_t) usize {
677809 return syscall3(SYS_bind, usize(fd), @ptrToInt(addr), usize(len));
678810}
679811
680pub fn listen(fd: i32, backlog: i32) usize {
681 return syscall2(SYS_listen, usize(fd), usize(backlog));
812pub fn listen(fd: i32, backlog: u32) usize {
813 return syscall2(SYS_listen, usize(fd), backlog);
682814}
683815
684816pub fn sendto(fd: i32, buf: &const u8, len: usize, flags: u32, addr: ?&const sockaddr, alen: socklen_t) usize {
......@@ -697,34 +829,6 @@ pub fn accept4(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t, flags:
697829 return syscall4(SYS_accept4, usize(fd), @ptrToInt(addr), @ptrToInt(len), flags);
698830}
699831
700// error NameTooLong;
701// error SystemResources;
702// error Io;
703//
704// pub fn if_nametoindex(name: []u8) !u32 {
705// var ifr: ifreq = undefined;
706//
707// if (name.len >= ifr.ifr_name.len) {
708// return error.NameTooLong;
709// }
710//
711// const socket_ret = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
712// const socket_err = getErrno(socket_ret);
713// if (socket_err > 0) {
714// return error.SystemResources;
715// }
716// const socket_fd = i32(socket_ret);
717// @memcpy(&ifr.ifr_name[0], &name[0], name.len);
718// ifr.ifr_name[name.len] = 0;
719// const ioctl_ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr);
720// close(socket_fd);
721// const ioctl_err = getErrno(ioctl_ret);
722// if (ioctl_err > 0) {
723// return error.Io;
724// }
725// return ifr.ifr_ifindex;
726// }
727
728832pub fn fstat(fd: i32, stat_buf: &Stat) usize {
729833 return syscall2(SYS_fstat, usize(fd), @ptrToInt(stat_buf));
730834}
......@@ -749,7 +853,7 @@ pub fn epoll_create1(flags: usize) usize {
749853 return syscall1(SYS_epoll_create1, flags);
750854}
751855
752pub fn epoll_ctl(epoll_fd: i32, op: i32, fd: i32, ev: &epoll_event) usize {
856pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: &epoll_event) usize {
753857 return syscall4(SYS_epoll_ctl, usize(epoll_fd), usize(op), usize(fd), @ptrToInt(ev));
754858}
755859
test/cases/coroutines.zig+15
......@@ -133,6 +133,7 @@ fn early_seq(c: u8) void {
133133 early_points[early_seq_index] = c;
134134 early_seq_index += 1;
135135}
136<<<<<<< HEAD
136137
137138test "coro allocation failure" {
138139 var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0);
......@@ -224,3 +225,17 @@ async fn printTrace(p: promise->error!void) void {
224225 }
225226 };
226227}
228
229test "coroutine in a struct field" {
230 const Foo = struct {
231 bar: async fn() void,
232 };
233 var foo = Foo {
234 .bar = simpleAsyncFn2,
235 };
236 cancel try async<std.debug.global_allocator> foo.bar();
237}
238
239async fn simpleAsyncFn2() void {
240 suspend;
241}