authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-09 00:53:16-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-09 00:53:16-04:00
log9ef1ba9d54e560ca384c95b74067674878aea019
tree70b94f7e1e5f761ad6fe95138ef9832cd0c32baf
parent292d0cbdadd453874af6e2065638a88d4dda8a10
parente85a10e9f5f6b17736babd321da8dceb72ea17af

Merge branch 'async-tcp-server'


19 files changed, 1097 insertions(+), 811 deletions(-)

CMakeLists.txt+1-2
...@@ -432,7 +432,7 @@ set(ZIG_STD_FILES...@@ -432,7 +432,7 @@ set(ZIG_STD_FILES
432 "dwarf.zig"432 "dwarf.zig"
433 "elf.zig"433 "elf.zig"
434 "empty.zig"434 "empty.zig"
435 "endian.zig"435 "event.zig"
436 "fmt/errol/enum3.zig"436 "fmt/errol/enum3.zig"
437 "fmt/errol/index.zig"437 "fmt/errol/index.zig"
438 "fmt/errol/lookup.zig"438 "fmt/errol/lookup.zig"
...@@ -503,7 +503,6 @@ set(ZIG_STD_FILES...@@ -503,7 +503,6 @@ set(ZIG_STD_FILES
503 "os/get_user_id.zig"503 "os/get_user_id.zig"
504 "os/index.zig"504 "os/index.zig"
505 "os/linux/errno.zig"505 "os/linux/errno.zig"
506 "os/linux/i386.zig"
507 "os/linux/index.zig"506 "os/linux/index.zig"
508 "os/linux/x86_64.zig"507 "os/linux/x86_64.zig"
509 "os/path.zig"508 "os/path.zig"
src/all_types.hpp-11
...@@ -359,7 +359,6 @@ enum NodeType {...@@ -359,7 +359,6 @@ enum NodeType {
359 NodeTypeRoot,359 NodeTypeRoot,
360 NodeTypeFnProto,360 NodeTypeFnProto,
361 NodeTypeFnDef,361 NodeTypeFnDef,
362 NodeTypeFnDecl,
363 NodeTypeParamDecl,362 NodeTypeParamDecl,
364 NodeTypeBlock,363 NodeTypeBlock,
365 NodeTypeGroupedExpr,364 NodeTypeGroupedExpr,
...@@ -453,10 +452,6 @@ struct AstNodeFnDef {...@@ -453,10 +452,6 @@ struct AstNodeFnDef {
453 AstNode *body;452 AstNode *body;
454};453};
455454
456struct AstNodeFnDecl {
457 AstNode *fn_proto;
458};
459
460struct AstNodeParamDecl {455struct AstNodeParamDecl {
461 Buf *name;456 Buf *name;
462 AstNode *type;457 AstNode *type;
...@@ -713,10 +708,6 @@ struct AstNodeSwitchRange {...@@ -713,10 +708,6 @@ struct AstNodeSwitchRange {
713 AstNode *end;708 AstNode *end;
714};709};
715710
716struct AstNodeLabel {
717 Buf *name;
718};
719
720struct AstNodeCompTime {711struct AstNodeCompTime {
721 AstNode *expr;712 AstNode *expr;
722};713};
...@@ -892,7 +883,6 @@ struct AstNode {...@@ -892,7 +883,6 @@ struct AstNode {
892 union {883 union {
893 AstNodeRoot root;884 AstNodeRoot root;
894 AstNodeFnDef fn_def;885 AstNodeFnDef fn_def;
895 AstNodeFnDecl fn_decl;
896 AstNodeFnProto fn_proto;886 AstNodeFnProto fn_proto;
897 AstNodeParamDecl param_decl;887 AstNodeParamDecl param_decl;
898 AstNodeBlock block;888 AstNodeBlock block;
...@@ -917,7 +907,6 @@ struct AstNode {...@@ -917,7 +907,6 @@ struct AstNode {
917 AstNodeSwitchExpr switch_expr;907 AstNodeSwitchExpr switch_expr;
918 AstNodeSwitchProng switch_prong;908 AstNodeSwitchProng switch_prong;
919 AstNodeSwitchRange switch_range;909 AstNodeSwitchRange switch_range;
920 AstNodeLabel label;
921 AstNodeCompTime comptime_expr;910 AstNodeCompTime comptime_expr;
922 AstNodeAsmExpr asm_expr;911 AstNodeAsmExpr asm_expr;
923 AstNodeFieldAccessExpr field_access_expr;912 AstNodeFieldAccessExpr field_access_expr;
src/analyze.cpp-1
...@@ -3236,7 +3236,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -3236,7 +3236,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
3236 break;3236 break;
3237 case NodeTypeContainerDecl:3237 case NodeTypeContainerDecl:
3238 case NodeTypeParamDecl:3238 case NodeTypeParamDecl:
3239 case NodeTypeFnDecl:
3240 case NodeTypeReturnExpr:3239 case NodeTypeReturnExpr:
3241 case NodeTypeDefer:3240 case NodeTypeDefer:
3242 case NodeTypeBlock:3241 case NodeTypeBlock:
src/ast_render.cpp-3
...@@ -148,8 +148,6 @@ static const char *node_type_str(NodeType node_type) {...@@ -148,8 +148,6 @@ static const char *node_type_str(NodeType node_type) {
148 return "Root";148 return "Root";
149 case NodeTypeFnDef:149 case NodeTypeFnDef:
150 return "FnDef";150 return "FnDef";
151 case NodeTypeFnDecl:
152 return "FnDecl";
153 case NodeTypeFnProto:151 case NodeTypeFnProto:
154 return "FnProto";152 return "FnProto";
155 case NodeTypeParamDecl:153 case NodeTypeParamDecl:
...@@ -1098,7 +1096,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -1098,7 +1096,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
1098 }1096 }
1099 break;1097 break;
1100 }1098 }
1101 case NodeTypeFnDecl:
1102 case NodeTypeParamDecl:1099 case NodeTypeParamDecl:
1103 case NodeTypeTestDecl:1100 case NodeTypeTestDecl:
1104 case NodeTypeStructField:1101 case NodeTypeStructField:
src/codegen.cpp+3
...@@ -408,6 +408,9 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e...@@ -408,6 +408,9 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e
408 if (!g->have_err_ret_tracing) {408 if (!g->have_err_ret_tracing) {
409 return UINT32_MAX;409 return UINT32_MAX;
410 }410 }
411 if (fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync) {
412 return 0;
413 }
411 TypeTableEntry *fn_type = fn_table_entry->type_entry;414 TypeTableEntry *fn_type = fn_table_entry->type_entry;
412 if (!fn_type_can_fail(&fn_type->data.fn.fn_type_id)) {415 if (!fn_type_can_fail(&fn_type->data.fn.fn_type_id)) {
413 return UINT32_MAX;416 return UINT32_MAX;
src/ir.cpp+22-12
...@@ -2755,9 +2755,10 @@ static IrInstruction *ir_mark_gen(IrInstruction *instruction) {...@@ -2755,9 +2755,10 @@ static IrInstruction *ir_mark_gen(IrInstruction *instruction) {
27552755
2756static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, bool gen_error_defers) {2756static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, bool gen_error_defers) {
2757 Scope *scope = inner_scope;2757 Scope *scope = inner_scope;
2758 bool is_noreturn = false;
2758 while (scope != outer_scope) {2759 while (scope != outer_scope) {
2759 if (!scope)2760 if (!scope)
2760 return false;2761 return is_noreturn;
27612762
2762 if (scope->id == ScopeIdDefer) {2763 if (scope->id == ScopeIdDefer) {
2763 AstNode *defer_node = scope->source_node;2764 AstNode *defer_node = scope->source_node;
...@@ -2770,14 +2771,18 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o...@@ -2770,14 +2771,18 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
2770 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;2771 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
2771 IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);2772 IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
2772 if (defer_expr_value != irb->codegen->invalid_instruction) {2773 if (defer_expr_value != irb->codegen->invalid_instruction) {
2773 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value));2774 if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == TypeTableEntryIdUnreachable) {
2775 is_noreturn = true;
2776 } else {
2777 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value));
2778 }
2774 }2779 }
2775 }2780 }
27762781
2777 }2782 }
2778 scope = scope->parent;2783 scope = scope->parent;
2779 }2784 }
2780 return true;2785 return is_noreturn;
2781}2786}
27822787
2783static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {2788static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {
...@@ -2936,12 +2941,13 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -2936,12 +2941,13 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
2936 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));2941 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));
29372942
2938 ir_set_cursor_at_end_and_append_block(irb, return_block);2943 ir_set_cursor_at_end_and_append_block(irb, return_block);
2939 ir_gen_defers_for_block(irb, scope, outer_scope, true);2944 if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) {
2940 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);2945 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
2941 if (irb->codegen->have_err_ret_tracing && !should_inline) {2946 if (irb->codegen->have_err_ret_tracing && !should_inline) {
2942 ir_build_save_err_ret_addr(irb, scope, node);2947 ir_build_save_err_ret_addr(irb, scope, node);
2948 }
2949 ir_gen_async_return(irb, scope, node, err_val, false);
2943 }2950 }
2944 ir_gen_async_return(irb, scope, node, err_val, false);
29452951
2946 ir_set_cursor_at_end_and_append_block(irb, continue_block);2952 ir_set_cursor_at_end_and_append_block(irb, continue_block);
2947 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false);2953 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false);
...@@ -5695,7 +5701,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast...@@ -5695,7 +5701,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast
56955701
5696 IrBasicBlock *dest_block = loop_scope->continue_block;5702 IrBasicBlock *dest_block = loop_scope->continue_block;
5697 ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, false);5703 ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, false);
5698 return ir_build_br(irb, continue_scope, node, dest_block, is_comptime);5704 return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime));
5699}5705}
57005706
5701static IrInstruction *ir_gen_error_type(IrBuilder *irb, Scope *scope, AstNode *node) {5707static IrInstruction *ir_gen_error_type(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -6178,7 +6184,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast...@@ -6178,7 +6184,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
61786184
6179 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);6185 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
6180 ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);6186 ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);
6181 ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false);6187 ir_mark_gen(ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false));
61826188
6183 ir_set_cursor_at_end_and_append_block(irb, resume_block);6189 ir_set_cursor_at_end_and_append_block(irb, resume_block);
6184 IrInstruction *yes_suspend_result = ir_build_load_ptr(irb, parent_scope, node, my_result_var_ptr);6190 IrInstruction *yes_suspend_result = ir_build_load_ptr(irb, parent_scope, node, my_result_var_ptr);
...@@ -6254,7 +6260,7 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod...@@ -6254,7 +6260,7 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
62546260
6255 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);6261 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
6256 ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);6262 ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);
6257 ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false);6263 ir_mark_gen(ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false));
62586264
6259 ir_set_cursor_at_end_and_append_block(irb, resume_block);6265 ir_set_cursor_at_end_and_append_block(irb, resume_block);
6260 return ir_build_const_void(irb, parent_scope, node);6266 return ir_build_const_void(irb, parent_scope, node);
...@@ -6273,7 +6279,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -6273,7 +6279,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
6273 case NodeTypeSwitchRange:6279 case NodeTypeSwitchRange:
6274 case NodeTypeStructField:6280 case NodeTypeStructField:
6275 case NodeTypeFnDef:6281 case NodeTypeFnDef:
6276 case NodeTypeFnDecl:
6277 case NodeTypeTestDecl:6282 case NodeTypeTestDecl:
6278 zig_unreachable();6283 zig_unreachable();
6279 case NodeTypeBlock:6284 case NodeTypeBlock:
...@@ -16747,6 +16752,11 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc...@@ -16747,6 +16752,11 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc
16747 return ira->codegen->builtin_types.entry_invalid;16752 return ira->codegen->builtin_types.entry_invalid;
1674816753
16749 if (fn_type_id.cc == CallingConventionAsync) {16754 if (fn_type_id.cc == CallingConventionAsync) {
16755 if (instruction->async_allocator_type_value == nullptr) {
16756 ir_add_error(ira, &instruction->base,
16757 buf_sprintf("async fn proto missing allocator type"));
16758 return ira->codegen->builtin_types.entry_invalid;
16759 }
16750 IrInstruction *async_allocator_type_value = instruction->async_allocator_type_value->other;16760 IrInstruction *async_allocator_type_value = instruction->async_allocator_type_value->other;
16751 fn_type_id.async_allocator_type = ir_resolve_type(ira, async_allocator_type_value);16761 fn_type_id.async_allocator_type = ir_resolve_type(ira, async_allocator_type_value);
16752 if (type_is_invalid(fn_type_id.async_allocator_type))16762 if (type_is_invalid(fn_type_id.async_allocator_type))
src/parser.cpp-3
...@@ -2923,9 +2923,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2923,9 +2923,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2923 visit_field(&node->data.fn_def.fn_proto, visit, context);2923 visit_field(&node->data.fn_def.fn_proto, visit, context);
2924 visit_field(&node->data.fn_def.body, visit, context);2924 visit_field(&node->data.fn_def.body, visit, context);
2925 break;2925 break;
2926 case NodeTypeFnDecl:
2927 visit_field(&node->data.fn_decl.fn_proto, visit, context);
2928 break;
2929 case NodeTypeParamDecl:2926 case NodeTypeParamDecl:
2930 visit_field(&node->data.param_decl.type, visit, context);2927 visit_field(&node->data.param_decl.type, visit, context);
2931 break;2928 break;
std/c/darwin.zig+8
...@@ -55,3 +55,11 @@ pub const dirent = extern struct {...@@ -55,3 +55,11 @@ pub const dirent = extern struct {
55 d_type: u8,55 d_type: u8,
56 d_name: u8, // field address is address of first byte of name56 d_name: u8, // field address is address of first byte of name
57};57};
58
59pub const sockaddr = extern struct {
60 sa_len: u8,
61 sa_family: sa_family_t,
62 sa_data: [14]u8,
63};
64
65pub const sa_family_t = u8;
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+235
...@@ -0,0 +1,235 @@
1const std = @import("index.zig");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4const event = this;
5const mem = std.mem;
6const posix = std.os.posix;
7
8pub const TcpServer = struct {
9 handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File) void,
10
11 loop: &Loop,
12 sockfd: i32,
13 accept_coro: ?promise,
14 listen_address: std.net.Address,
15
16 waiting_for_emfile_node: PromiseNode,
17
18 const PromiseNode = std.LinkedList(promise).Node;
19
20 pub fn init(loop: &Loop) !TcpServer {
21 const sockfd = try std.os.posixSocket(posix.AF_INET,
22 posix.SOCK_STREAM|posix.SOCK_CLOEXEC|posix.SOCK_NONBLOCK,
23 posix.PROTO_tcp);
24 errdefer std.os.close(sockfd);
25
26 // TODO can't initialize handler coroutine here because we need well defined copy elision
27 return TcpServer {
28 .loop = loop,
29 .sockfd = sockfd,
30 .accept_coro = null,
31 .handleRequestFn = undefined,
32 .waiting_for_emfile_node = undefined,
33 .listen_address = undefined,
34 };
35 }
36
37 pub fn listen(self: &TcpServer, address: &const std.net.Address,
38 handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File)void) !void
39 {
40 self.handleRequestFn = handleRequestFn;
41
42 try std.os.posixBind(self.sockfd, &address.os_addr);
43 try std.os.posixListen(self.sockfd, posix.SOMAXCONN);
44 self.listen_address = std.net.Address.initPosix(try std.os.posixGetSockName(self.sockfd));
45
46 self.accept_coro = try async<self.loop.allocator> TcpServer.handler(self);
47 errdefer cancel ??self.accept_coro;
48
49 try self.loop.addFd(self.sockfd, ??self.accept_coro);
50 errdefer self.loop.removeFd(self.sockfd);
51
52 }
53
54 pub fn deinit(self: &TcpServer) void {
55 self.loop.removeFd(self.sockfd);
56 if (self.accept_coro) |accept_coro| cancel accept_coro;
57 std.os.close(self.sockfd);
58 }
59
60 pub async fn handler(self: &TcpServer) void {
61 while (true) {
62 var accepted_addr: std.net.Address = undefined;
63 if (std.os.posixAccept(self.sockfd, &accepted_addr.os_addr,
64 posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd|
65 {
66 var socket = std.os.File.openHandle(accepted_fd);
67 _ = async<self.loop.allocator> self.handleRequestFn(self, accepted_addr, socket) catch |err| switch (err) {
68 error.OutOfMemory => {
69 socket.close();
70 continue;
71 },
72 };
73 } else |err| switch (err) {
74 error.WouldBlock => {
75 suspend; // we will get resumed by epoll_wait in the event loop
76 continue;
77 },
78 error.ProcessFdQuotaExceeded => {
79 errdefer std.os.emfile_promise_queue.remove(&self.waiting_for_emfile_node);
80 suspend |p| {
81 self.waiting_for_emfile_node = PromiseNode.init(p);
82 std.os.emfile_promise_queue.append(&self.waiting_for_emfile_node);
83 }
84 continue;
85 },
86 error.ConnectionAborted,
87 error.FileDescriptorClosed => continue,
88
89 error.PageFault => unreachable,
90 error.InvalidSyscall => unreachable,
91 error.FileDescriptorNotASocket => unreachable,
92 error.OperationNotSupported => unreachable,
93
94 error.SystemFdQuotaExceeded,
95 error.SystemResources,
96 error.ProtocolFailure,
97 error.BlockedByFirewall,
98 error.Unexpected => {
99 @panic("TODO handle this error");
100 },
101 }
102 }
103 }
104};
105
106pub const Loop = struct {
107 allocator: &mem.Allocator,
108 epollfd: i32,
109 keep_running: bool,
110
111 fn init(allocator: &mem.Allocator) !Loop {
112 const epollfd = try std.os.linuxEpollCreate(std.os.linux.EPOLL_CLOEXEC);
113 return Loop {
114 .keep_running = true,
115 .allocator = allocator,
116 .epollfd = epollfd,
117 };
118 }
119
120 pub fn addFd(self: &Loop, fd: i32, prom: promise) !void {
121 var ev = std.os.linux.epoll_event {
122 .events = std.os.linux.EPOLLIN|std.os.linux.EPOLLOUT|std.os.linux.EPOLLET,
123 .data = std.os.linux.epoll_data {
124 .ptr = @ptrToInt(prom),
125 },
126 };
127 try std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_ADD, fd, &ev);
128 }
129
130 pub fn removeFd(self: &Loop, fd: i32) void {
131 std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_DEL, fd, undefined) catch {};
132 }
133
134 async fn waitFd(self: &Loop, fd: i32) !void {
135 defer self.removeFd(fd);
136 suspend |p| {
137 try self.addFd(fd, p);
138 }
139 }
140
141 pub fn stop(self: &Loop) void {
142 // TODO make atomic
143 self.keep_running = false;
144 // TODO activate an fd in the epoll set
145 }
146
147 pub fn run(self: &Loop) void {
148 while (self.keep_running) {
149 var events: [16]std.os.linux.epoll_event = undefined;
150 const count = std.os.linuxEpollWait(self.epollfd, events[0..], -1);
151 for (events[0..count]) |ev| {
152 const p = @intToPtr(promise, ev.data.ptr);
153 resume p;
154 }
155 }
156 }
157};
158
159pub async fn connect(loop: &Loop, _address: &const std.net.Address) !std.os.File {
160 var address = *_address; // TODO https://github.com/zig-lang/zig/issues/733
161
162 const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM|posix.SOCK_CLOEXEC|posix.SOCK_NONBLOCK, posix.PROTO_tcp);
163 errdefer std.os.close(sockfd);
164
165 try std.os.posixConnectAsync(sockfd, &address.os_addr);
166 try await try async loop.waitFd(sockfd);
167 try std.os.posixGetSockOptConnectError(sockfd);
168
169 return std.os.File.openHandle(sockfd);
170}
171
172test "listen on a port, send bytes, receive bytes" {
173 if (builtin.os != builtin.Os.linux) {
174 // TODO build abstractions for other operating systems
175 return;
176 }
177 const MyServer = struct {
178 tcp_server: TcpServer,
179
180 const Self = this;
181
182 async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address,
183 _socket: &const std.os.File) void
184 {
185 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
186 var socket = *_socket; // TODO https://github.com/zig-lang/zig/issues/733
187 defer socket.close();
188 const next_handler = async errorableHandler(self, _addr, socket) catch |err| switch (err) {
189 error.OutOfMemory => @panic("unable to handle connection: out of memory"),
190 };
191 (await next_handler) catch |err| {
192 std.debug.panic("unable to handle connection: {}\n", err);
193 };
194 suspend |p| { cancel p; }
195 }
196
197 async fn errorableHandler(self: &Self, _addr: &const std.net.Address,
198 _socket: &const std.os.File) !void
199 {
200 const addr = *_addr; // TODO https://github.com/zig-lang/zig/issues/733
201 var socket = *_socket; // TODO https://github.com/zig-lang/zig/issues/733
202
203 var adapter = std.io.FileOutStream.init(&socket);
204 var stream = &adapter.stream;
205 try stream.print("hello from server\n");
206 }
207 };
208
209 const ip4addr = std.net.parseIp4("127.0.0.1") catch unreachable;
210 const addr = std.net.Address.initIp4(ip4addr, 0);
211
212 var loop = try Loop.init(std.debug.global_allocator);
213 var server = MyServer {
214 .tcp_server = try TcpServer.init(&loop),
215 };
216 defer server.tcp_server.deinit();
217 try server.tcp_server.listen(addr, MyServer.handler);
218
219 const p = try async<std.debug.global_allocator> doAsyncTest(&loop, server.tcp_server.listen_address);
220 defer cancel p;
221 loop.run();
222}
223
224async fn doAsyncTest(loop: &Loop, address: &const std.net.Address) void {
225 errdefer @panic("test failure");
226
227 var socket_file = try await try async event.connect(loop, address);
228 defer socket_file.close();
229
230 var buf: [512]u8 = undefined;
231 const amt_read = try socket_file.read(buf[0..]);
232 const msg = buf[0..amt_read];
233 assert(mem.eql(u8, msg, "hello from server\n"));
234 loop.stop();
235}
std/fmt/index.zig+1-1
...@@ -465,7 +465,7 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned...@@ -465,7 +465,7 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
465 return x;465 return x;
466}466}
467467
468fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {468pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
469 const value = switch (c) {469 const value = switch (c) {
470 '0' ... '9' => c - '0',470 '0' ... '9' => c - '0',
471 'A' ... 'Z' => c - 'A' + 10,471 'A' ... 'Z' => c - 'A' + 10,
std/index.zig+3-3
...@@ -17,7 +17,7 @@ pub const debug = @import("debug/index.zig");...@@ -17,7 +17,7 @@ pub const debug = @import("debug/index.zig");
17pub const dwarf = @import("dwarf.zig");17pub const dwarf = @import("dwarf.zig");
18pub const elf = @import("elf.zig");18pub const elf = @import("elf.zig");
19pub const empty_import = @import("empty.zig");19pub const empty_import = @import("empty.zig");
20pub const endian = @import("endian.zig");20pub const event = @import("event.zig");
21pub const fmt = @import("fmt/index.zig");21pub const fmt = @import("fmt/index.zig");
22pub const hash = @import("hash/index.zig");22pub const hash = @import("hash/index.zig");
23pub const heap = @import("heap.zig");23pub const heap = @import("heap.zig");
...@@ -50,15 +50,15 @@ test "std" {...@@ -50,15 +50,15 @@ test "std" {
50 _ = @import("dwarf.zig");50 _ = @import("dwarf.zig");
51 _ = @import("elf.zig");51 _ = @import("elf.zig");
52 _ = @import("empty.zig");52 _ = @import("empty.zig");
53 _ = @import("endian.zig");53 _ = @import("event.zig");
54 _ = @import("fmt/index.zig");54 _ = @import("fmt/index.zig");
55 _ = @import("hash/index.zig");55 _ = @import("hash/index.zig");
56 _ = @import("io.zig");56 _ = @import("io.zig");
57 _ = @import("macho.zig");57 _ = @import("macho.zig");
58 _ = @import("math/index.zig");58 _ = @import("math/index.zig");
59 _ = @import("mem.zig");59 _ = @import("mem.zig");
60 _ = @import("heap.zig");
61 _ = @import("net.zig");60 _ = @import("net.zig");
61 _ = @import("heap.zig");
62 _ = @import("os/index.zig");62 _ = @import("os/index.zig");
63 _ = @import("rand/index.zig");63 _ = @import("rand/index.zig");
64 _ = @import("sort.zig");64 _ = @import("sort.zig");
std/linked_list.zig+1
...@@ -161,6 +161,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na...@@ -161,6 +161,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
161 }161 }
162162
163 list.len -= 1;163 list.len -= 1;
164 assert(list.len == 0 or (list.first != null and list.last != null));
164 }165 }
165166
166 /// Remove and return the last node in the list.167 /// Remove and return the last node in the list.
std/mem.zig+26
...@@ -3,6 +3,7 @@ const debug = std.debug;...@@ -3,6 +3,7 @@ const debug = std.debug;
3const assert = debug.assert;3const assert = debug.assert;
4const math = std.math;4const math = std.math;
5const builtin = @import("builtin");5const builtin = @import("builtin");
6const mem = this;
67
7pub const Allocator = struct {8pub const Allocator = struct {
8 const Error = error {OutOfMemory};9 const Error = error {OutOfMemory};
...@@ -550,3 +551,28 @@ test "std.mem.rotate" {...@@ -550,3 +551,28 @@ test "std.mem.rotate" {
550551
551 assert(eql(i32, arr, []i32{ 1, 2, 4, 5, 3 }));552 assert(eql(i32, arr, []i32{ 1, 2, 4, 5, 3 }));
552}553}
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+121-162
...@@ -1,143 +1,120 @@...@@ -1,143 +1,120 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const linux = std.os.linux;2const builtin = @import("builtin");
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const endian = std.endian;4const net = this;
5const posix = std.os.posix;
6const mem = std.mem;
57
6// TODO don't trust this file, it bit rotted. start over8pub const TmpWinAddr = struct {
79 family: u8,
8const Connection = struct {10 data: [14]u8,
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 }
23 }
24
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 }
40 }
41
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,
49 }
50 }
51};11};
5212
53const Address = struct {13pub const OsAddress = switch (builtin.os) {
54 family: u16,14 builtin.Os.windows => TmpWinAddr,
55 scope_id: u32,15 else => posix.sockaddr,
56 addr: [16]u8,
57 sort_key: i32,
58};16};
5917
60pub fn lookup(hostname: []const u8, out_addrs: []Address) ![]Address {18pub const Address = struct {
61 if (hostname.len == 0) {19 os_addr: OsAddress,
6220
63 unreachable; // TODO21 pub fn initIp4(ip4: u32, port: u16) Address {
22 return Address {
23 .os_addr = posix.sockaddr {
24 .in = posix.sockaddr_in {
25 .family = posix.AF_INET,
26 .port = std.mem.endianSwapIfLe(u16, port),
27 .addr = ip4,
28 .zero = []u8{0} ** 8,
29 },
30 },
31 };
64 }32 }
6533
66 unreachable; // TODO34 pub fn initIp6(ip6: &const Ip6Addr, port: u16) Address {
67}35 return Address {
36 .family = posix.AF_INET6,
37 .os_addr = posix.sockaddr {
38 .in6 = posix.sockaddr_in6 {
39 .family = posix.AF_INET6,
40 .port = std.mem.endianSwapIfLe(u16, port),
41 .flowinfo = 0,
42 .addr = ip6.addr,
43 .scope_id = ip6.scope_id,
44 },
45 },
46 };
47 }
6848
69pub fn connectAddr(addr: &Address, port: u16) !Connection {49 pub fn initPosix(addr: &const posix.sockaddr) Address {
70 const socket_ret = linux.socket(addr.family, linux.SOCK_STREAM, linux.PROTO_tcp);50 return Address {
71 const socket_err = linux.getErrno(socket_ret);51 .os_addr = *addr,
72 if (socket_err > 0) {52 };
73 // TODO figure out possible errors from socket()
74 return error.Unexpected;
75 }53 }
76 const socket_fd = i32(socket_ret);
7754
78 const connect_ret = if (addr.family == linux.AF_INET) x: {55 pub fn format(self: &const Address, out_stream: var) !void {
79 var os_addr: linux.sockaddr_in = undefined;56 switch (self.os_addr.in.family) {
80 os_addr.family = addr.family;57 posix.AF_INET => {
81 os_addr.port = endian.swapIfLe(u16, port);58 const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in.port);
82 @memcpy((&u8)(&os_addr.addr), &addr.addr[0], 4);59 const bytes = ([]const u8)((&self.os_addr.in.addr)[0..1]);
83 @memset(&os_addr.zero[0], 0, @sizeOf(@typeOf(os_addr.zero)));60 try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
84 break :x linux.connect(socket_fd, (&linux.sockaddr)(&os_addr), @sizeOf(linux.sockaddr_in));61 },
85 } else if (addr.family == linux.AF_INET6) x: {62 posix.AF_INET6 => {
86 var os_addr: linux.sockaddr_in6 = undefined;63 const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in6.port);
87 os_addr.family = addr.family;64 try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
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 },65 },
66 else => try out_stream.write("(unrecognized address family)"),
104 }67 }
105 }68 }
69};
10670
107 return Connection {71pub fn parseIp4(buf: []const u8) !u32 {
108 .socket_fd = socket_fd,72 var result: u32 = undefined;
109 };73 const out_ptr = ([]u8)((&result)[0..1]);
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}
11974
120pub fn parseIpLiteral(buf: []const u8) !Address {75 var x: u8 = 0;
76 var index: u8 = 0;
77 var saw_any_digits = false;
78 for (buf) |c| {
79 if (c == '.') {
80 if (!saw_any_digits) {
81 return error.InvalidCharacter;
82 }
83 if (index == 3) {
84 return error.InvalidEnd;
85 }
86 out_ptr[index] = x;
87 index += 1;
88 x = 0;
89 saw_any_digits = false;
90 } else if (c >= '0' and c <= '9') {
91 saw_any_digits = true;
92 const digit = c - '0';
93 if (@mulWithOverflow(u8, x, 10, &x)) {
94 return error.Overflow;
95 }
96 if (@addWithOverflow(u8, x, digit, &x)) {
97 return error.Overflow;
98 }
99 } else {
100 return error.InvalidCharacter;
101 }
102 }
103 if (index == 3 and saw_any_digits) {
104 out_ptr[index] = x;
105 return result;
106 }
121107
122 return error.InvalidIpLiteral;108 return error.Incomplete;
123}109}
124110
125fn hexDigit(c: u8) u8 {111pub const Ip6Addr = struct {
126 // TODO use switch with range112 scope_id: u32,
127 if ('0' <= c and c <= '9') {113 addr: [16]u8,
128 return c - '0';114};
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}
137115
138fn parseIp6(buf: []const u8) !Address {116pub fn parseIp6(buf: []const u8) !Ip6Addr {
139 var result: Address = undefined;117 var result: Ip6Addr = undefined;
140 result.family = linux.AF_INET6;
141 result.scope_id = 0;118 result.scope_id = 0;
142 const ip_slice = result.addr[0..];119 const ip_slice = result.addr[0..];
143120
...@@ -156,14 +133,14 @@ fn parseIp6(buf: []const u8) !Address {...@@ -156,14 +133,14 @@ fn parseIp6(buf: []const u8) !Address {
156 return error.Overflow;133 return error.Overflow;
157 }134 }
158 } else {135 } else {
159 return error.InvalidChar;136 return error.InvalidCharacter;
160 }137 }
161 } else if (c == ':') {138 } else if (c == ':') {
162 if (!saw_any_digits) {139 if (!saw_any_digits) {
163 return error.InvalidChar;140 return error.InvalidCharacter;
164 }141 }
165 if (index == 14) {142 if (index == 14) {
166 return error.JunkAtEnd;143 return error.InvalidEnd;
167 }144 }
168 ip_slice[index] = @truncate(u8, x >> 8);145 ip_slice[index] = @truncate(u8, x >> 8);
169 index += 1;146 index += 1;
...@@ -174,7 +151,7 @@ fn parseIp6(buf: []const u8) !Address {...@@ -174,7 +151,7 @@ fn parseIp6(buf: []const u8) !Address {
174 saw_any_digits = false;151 saw_any_digits = false;
175 } else if (c == '%') {152 } else if (c == '%') {
176 if (!saw_any_digits) {153 if (!saw_any_digits) {
177 return error.InvalidChar;154 return error.InvalidCharacter;
178 }155 }
179 if (index == 14) {156 if (index == 14) {
180 ip_slice[index] = @truncate(u8, x >> 8);157 ip_slice[index] = @truncate(u8, x >> 8);
...@@ -185,10 +162,7 @@ fn parseIp6(buf: []const u8) !Address {...@@ -185,10 +162,7 @@ fn parseIp6(buf: []const u8) !Address {
185 scope_id = true;162 scope_id = true;
186 saw_any_digits = false;163 saw_any_digits = false;
187 } else {164 } else {
188 const digit = hexDigit(c);165 const digit = try std.fmt.charToDigit(c, 16);
189 if (digit == @maxValue(u8)) {
190 return error.InvalidChar;
191 }
192 if (@mulWithOverflow(u16, x, 16, &x)) {166 if (@mulWithOverflow(u16, x, 16, &x)) {
193 return error.Overflow;167 return error.Overflow;
194 }168 }
...@@ -216,42 +190,27 @@ fn parseIp6(buf: []const u8) !Address {...@@ -216,42 +190,27 @@ fn parseIp6(buf: []const u8) !Address {
216 return error.Incomplete;190 return error.Incomplete;
217}191}
218192
219fn parseIp4(buf: []const u8) !u32 {193test "std.net.parseIp4" {
220 var result: u32 = undefined;194 assert((try parseIp4("127.0.0.1")) == std.mem.endianSwapIfLe(u32, 0x7f000001));
221 const out_ptr = ([]u8)((&result)[0..1]);
222195
223 var x: u8 = 0;196 testParseIp4Fail("256.0.0.1", error.Overflow);
224 var index: u8 = 0;197 testParseIp4Fail("x.0.0.1", error.InvalidCharacter);
225 var saw_any_digits = false;198 testParseIp4Fail("127.0.0.1.1", error.InvalidEnd);
226 for (buf) |c| {199 testParseIp4Fail("127.0.0.", error.Incomplete);
227 if (c == '.') {200 testParseIp4Fail("100..0.1", error.InvalidCharacter);
228 if (!saw_any_digits) {201}
229 return error.InvalidChar;202
230 }203fn testParseIp4Fail(buf: []const u8, expected_err: error) void {
231 if (index == 3) {204 if (parseIp4(buf)) |_| {
232 return error.JunkAtEnd;205 @panic("expected error");
233 }206 } else |e| {
234 out_ptr[index] = x;207 assert(e == expected_err);
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;
254 }208 }
209}
255210
256 return error.Incomplete;211test "std.net.parseIp6" {
212 const addr = try parseIp6("FF01:0:0:0:0:0:0:FB");
213 assert(addr.addr[0] == 0xff);
214 assert(addr.addr[1] == 0x01);
215 assert(addr.addr[2] == 0x00);
257}216}
std/os/darwin.zig+3
...@@ -301,6 +301,9 @@ pub const timespec = c.timespec;...@@ -301,6 +301,9 @@ pub const timespec = c.timespec;
301pub const Stat = c.Stat;301pub const Stat = c.Stat;
302pub const dirent = c.dirent;302pub const dirent = c.dirent;
303303
304pub const sa_family_t = c.sa_family_t;
305pub const sockaddr = c.sockaddr;
306
304/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.307/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
305pub const Sigaction = struct {308pub const Sigaction = struct {
306 handler: extern fn(i32)void,309 handler: extern fn(i32)void,
std/os/index.zig+507-21
...@@ -4,6 +4,19 @@ const Os = builtin.Os;...@@ -4,6 +4,19 @@ const Os = builtin.Os;
4const is_windows = builtin.os == Os.windows;4const is_windows = builtin.os == Os.windows;
5const os = this;5const 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
7pub const windows = @import("windows/index.zig");20pub const windows = @import("windows/index.zig");
8pub const darwin = @import("darwin.zig");21pub const darwin = @import("darwin.zig");
9pub const linux = @import("linux/index.zig");22pub const linux = @import("linux/index.zig");
...@@ -14,6 +27,7 @@ pub const posix = switch(builtin.os) {...@@ -14,6 +27,7 @@ pub const posix = switch(builtin.os) {
14 Os.zen => zen,27 Os.zen => zen,
15 else => @compileError("Unsupported OS"),28 else => @compileError("Unsupported OS"),
16};29};
30pub const net = @import("net.zig");
1731
18pub const ChildProcess = @import("child_process.zig").ChildProcess;32pub const ChildProcess = @import("child_process.zig").ChildProcess;
19pub const path = @import("path.zig");33pub const path = @import("path.zig");
...@@ -173,6 +187,13 @@ pub fn exit(status: u8) noreturn {...@@ -173,6 +187,13 @@ pub fn exit(status: u8) noreturn {
173 }187 }
174}188}
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
176/// Closes the file handle. Keeps trying if it gets interrupted by a signal.197/// Closes the file handle. Keeps trying if it gets interrupted by a signal.
177pub fn close(handle: FileHandle) void {198pub fn close(handle: FileHandle) void {
178 if (is_windows) {199 if (is_windows) {
...@@ -180,10 +201,12 @@ pub fn close(handle: FileHandle) void {...@@ -180,10 +201,12 @@ pub fn close(handle: FileHandle) void {
180 } else {201 } else {
181 while (true) {202 while (true) {
182 const err = posix.getErrno(posix.close(handle));203 const err = posix.getErrno(posix.close(handle));
183 if (err == posix.EINTR) {204 switch (err) {
184 continue;205 posix.EINTR => continue,
185 } else {206 else => {
186 return;207 if (emfile_promise_queue.popFirst()) |p| resume p.data;
208 return;
209 },
187 }210 }
188 }211 }
189 }212 }
...@@ -1753,27 +1776,16 @@ fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const...@@ -1753,27 +1776,16 @@ fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const
1753 assert(it.next(debug.global_allocator) == null);1776 assert(it.next(debug.global_allocator) == null);
1754}1777}
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
1771// TODO make this a build variable that you can set1779// TODO make this a build variable that you can set
1772const unexpected_error_tracing = false;1780const unexpected_error_tracing = false;
1781const UnexpectedError = error {
1782 /// The Operating System returned an undocumented error code.
1783 Unexpected,
1784};
17731785
1774/// Call this when you made a syscall or something that sets errno1786/// Call this when you made a syscall or something that sets errno
1775/// and you get an unexpected error.1787/// and you get an unexpected error.
1776pub fn unexpectedErrorPosix(errno: usize) (error{Unexpected}) {1788pub fn unexpectedErrorPosix(errno: usize) UnexpectedError {
1777 if (unexpected_error_tracing) {1789 if (unexpected_error_tracing) {
1778 debug.warn("unexpected errno: {}\n", errno);1790 debug.warn("unexpected errno: {}\n", errno);
1779 debug.dumpCurrentStackTrace(null);1791 debug.dumpCurrentStackTrace(null);
...@@ -1783,7 +1795,7 @@ pub fn unexpectedErrorPosix(errno: usize) (error{Unexpected}) {...@@ -1783,7 +1795,7 @@ pub fn unexpectedErrorPosix(errno: usize) (error{Unexpected}) {
17831795
1784/// Call this when you made a windows DLL call or something that does SetLastError1796/// Call this when you made a windows DLL call or something that does SetLastError
1785/// and you get an unexpected error.1797/// and you get an unexpected error.
1786pub fn unexpectedErrorWindows(err: windows.DWORD) (error{Unexpected}) {1798pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError {
1787 if (unexpected_error_tracing) {1799 if (unexpected_error_tracing) {
1788 debug.warn("unexpected GetLastError(): {}\n", err);1800 debug.warn("unexpected GetLastError(): {}\n", err);
1789 debug.dumpCurrentStackTrace(null);1801 debug.dumpCurrentStackTrace(null);
...@@ -1898,3 +1910,477 @@ pub fn isTty(handle: FileHandle) bool {...@@ -1898,3 +1910,477 @@ pub fn isTty(handle: FileHandle) bool {
1898 }1910 }
1899 }1911 }
1900}1912}
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.ptr, 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}
2232
2233pub const PosixGetSockNameError = error {
2234 /// Insufficient resources were available in the system to perform the operation.
2235 SystemResources,
2236
2237 Unexpected,
2238};
2239
2240pub fn posixGetSockName(sockfd: i32) PosixGetSockNameError!posix.sockaddr {
2241 var addr: posix.sockaddr = undefined;
2242 var addrlen: posix.socklen_t = @sizeOf(posix.sockaddr);
2243 const rc = posix.getsockname(sockfd, &addr, &addrlen);
2244 const err = posix.getErrno(rc);
2245 switch (err) {
2246 0 => return addr,
2247 else => return unexpectedErrorPosix(err),
2248
2249 posix.EBADF => unreachable,
2250 posix.EFAULT => unreachable,
2251 posix.EINVAL => unreachable,
2252 posix.ENOTSOCK => unreachable,
2253 posix.ENOBUFS => return PosixGetSockNameError.SystemResources,
2254 }
2255}
2256
2257pub const PosixConnectError = error {
2258 /// For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket
2259 /// file, or search permission is denied for one of the directories in the path prefix.
2260 /// or
2261 /// The user tried to connect to a broadcast address without having the socket broadcast flag enabled or
2262 /// the connection request failed because of a local firewall rule.
2263 PermissionDenied,
2264
2265 /// Local address is already in use.
2266 AddressInUse,
2267
2268 /// (Internet domain sockets) The socket referred to by sockfd had not previously been bound to an
2269 /// address and, upon attempting to bind it to an ephemeral port, it was determined that all port numbers
2270 /// in the ephemeral port range are currently in use. See the discussion of
2271 /// /proc/sys/net/ipv4/ip_local_port_range in ip(7).
2272 AddressNotAvailable,
2273
2274 /// The passed address didn't have the correct address family in its sa_family field.
2275 AddressFamilyNotSupported,
2276
2277 /// Insufficient entries in the routing cache.
2278 SystemResources,
2279
2280 /// A connect() on a stream socket found no one listening on the remote address.
2281 ConnectionRefused,
2282
2283 /// Network is unreachable.
2284 NetworkUnreachable,
2285
2286 /// Timeout while attempting connection. The server may be too busy to accept new connections. Note
2287 /// that for IP sockets the timeout may be very long when syncookies are enabled on the server.
2288 ConnectionTimedOut,
2289
2290 Unexpected,
2291};
2292
2293pub fn posixConnect(sockfd: i32, sockaddr: &const posix.sockaddr) PosixConnectError!void {
2294 while (true) {
2295 const rc = posix.connect(sockfd, sockaddr, @sizeOf(posix.sockaddr));
2296 const err = posix.getErrno(rc);
2297 switch (err) {
2298 0 => return,
2299 else => return unexpectedErrorPosix(err),
2300
2301 posix.EACCES => return PosixConnectError.PermissionDenied,
2302 posix.EPERM => return PosixConnectError.PermissionDenied,
2303 posix.EADDRINUSE => return PosixConnectError.AddressInUse,
2304 posix.EADDRNOTAVAIL => return PosixConnectError.AddressNotAvailable,
2305 posix.EAFNOSUPPORT => return PosixConnectError.AddressFamilyNotSupported,
2306 posix.EAGAIN => return PosixConnectError.SystemResources,
2307 posix.EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed.
2308 posix.EBADF => unreachable, // sockfd is not a valid open file descriptor.
2309 posix.ECONNREFUSED => return PosixConnectError.ConnectionRefused,
2310 posix.EFAULT => unreachable, // The socket structure address is outside the user's address space.
2311 posix.EINPROGRESS => unreachable, // The socket is nonblocking and the connection cannot be completed immediately.
2312 posix.EINTR => continue,
2313 posix.EISCONN => unreachable, // The socket is already connected.
2314 posix.ENETUNREACH => return PosixConnectError.NetworkUnreachable,
2315 posix.ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
2316 posix.EPROTOTYPE => unreachable, // The socket type does not support the requested communications protocol.
2317 posix.ETIMEDOUT => return PosixConnectError.ConnectionTimedOut,
2318 }
2319 }
2320}
2321
2322/// Same as posixConnect except it is for blocking socket file descriptors.
2323/// It expects to receive EINPROGRESS.
2324pub fn posixConnectAsync(sockfd: i32, sockaddr: &const posix.sockaddr) PosixConnectError!void {
2325 while (true) {
2326 const rc = posix.connect(sockfd, sockaddr, @sizeOf(posix.sockaddr));
2327 const err = posix.getErrno(rc);
2328 switch (err) {
2329 0, posix.EINPROGRESS => return,
2330 else => return unexpectedErrorPosix(err),
2331
2332 posix.EACCES => return PosixConnectError.PermissionDenied,
2333 posix.EPERM => return PosixConnectError.PermissionDenied,
2334 posix.EADDRINUSE => return PosixConnectError.AddressInUse,
2335 posix.EADDRNOTAVAIL => return PosixConnectError.AddressNotAvailable,
2336 posix.EAFNOSUPPORT => return PosixConnectError.AddressFamilyNotSupported,
2337 posix.EAGAIN => return PosixConnectError.SystemResources,
2338 posix.EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed.
2339 posix.EBADF => unreachable, // sockfd is not a valid open file descriptor.
2340 posix.ECONNREFUSED => return PosixConnectError.ConnectionRefused,
2341 posix.EFAULT => unreachable, // The socket structure address is outside the user's address space.
2342 posix.EINTR => continue,
2343 posix.EISCONN => unreachable, // The socket is already connected.
2344 posix.ENETUNREACH => return PosixConnectError.NetworkUnreachable,
2345 posix.ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
2346 posix.EPROTOTYPE => unreachable, // The socket type does not support the requested communications protocol.
2347 posix.ETIMEDOUT => return PosixConnectError.ConnectionTimedOut,
2348 }
2349 }
2350}
2351
2352pub fn posixGetSockOptConnectError(sockfd: i32) PosixConnectError!void {
2353 var err_code: i32 = undefined;
2354 var size: u32 = @sizeOf(i32);
2355 const rc = posix.getsockopt(sockfd, posix.SOL_SOCKET, posix.SO_ERROR, @ptrCast(&u8, &err_code), &size);
2356 assert(size == 4);
2357 const err = posix.getErrno(rc);
2358 switch (err) {
2359 0 => switch (err_code) {
2360 0 => return,
2361 else => return unexpectedErrorPosix(err),
2362
2363 posix.EACCES => return PosixConnectError.PermissionDenied,
2364 posix.EPERM => return PosixConnectError.PermissionDenied,
2365 posix.EADDRINUSE => return PosixConnectError.AddressInUse,
2366 posix.EADDRNOTAVAIL => return PosixConnectError.AddressNotAvailable,
2367 posix.EAFNOSUPPORT => return PosixConnectError.AddressFamilyNotSupported,
2368 posix.EAGAIN => return PosixConnectError.SystemResources,
2369 posix.EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed.
2370 posix.EBADF => unreachable, // sockfd is not a valid open file descriptor.
2371 posix.ECONNREFUSED => return PosixConnectError.ConnectionRefused,
2372 posix.EFAULT => unreachable, // The socket structure address is outside the user's address space.
2373 posix.EISCONN => unreachable, // The socket is already connected.
2374 posix.ENETUNREACH => return PosixConnectError.NetworkUnreachable,
2375 posix.ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
2376 posix.EPROTOTYPE => unreachable, // The socket type does not support the requested communications protocol.
2377 posix.ETIMEDOUT => return PosixConnectError.ConnectionTimedOut,
2378 },
2379 else => return unexpectedErrorPosix(err),
2380 posix.EBADF => unreachable, // The argument sockfd is not a valid file descriptor.
2381 posix.EFAULT => unreachable, // The address pointed to by optval or optlen is not in a valid part of the process address space.
2382 posix.EINVAL => unreachable,
2383 posix.ENOPROTOOPT => unreachable, // The option is unknown at the level indicated.
2384 posix.ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
2385 }
2386}
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+166-62
...@@ -101,17 +101,6 @@ pub const SIG_BLOCK = 0;...@@ -101,17 +101,6 @@ pub const SIG_BLOCK = 0;
101pub const SIG_UNBLOCK = 1;101pub const SIG_UNBLOCK = 1;
102pub const SIG_SETMASK = 2;102pub 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
115pub const PROTO_ip = 0o000;104pub const PROTO_ip = 0o000;
116pub const PROTO_icmp = 0o001;105pub const PROTO_icmp = 0o001;
117pub const PROTO_igmp = 0o002;106pub const PROTO_igmp = 0o002;
...@@ -149,6 +138,20 @@ pub const PROTO_encap = 0o142;...@@ -149,6 +138,20 @@ pub const PROTO_encap = 0o142;
149pub const PROTO_pim = 0o147;138pub const PROTO_pim = 0o147;
150pub const PROTO_raw = 0o377;139pub 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
152pub const PF_UNSPEC = 0;155pub const PF_UNSPEC = 0;
153pub const PF_LOCAL = 1;156pub const PF_LOCAL = 1;
154pub const PF_UNIX = PF_LOCAL;157pub const PF_UNIX = PF_LOCAL;
...@@ -193,7 +196,10 @@ pub const PF_CAIF = 37;...@@ -193,7 +196,10 @@ pub const PF_CAIF = 37;
193pub const PF_ALG = 38;196pub const PF_ALG = 38;
194pub const PF_NFC = 39;197pub const PF_NFC = 39;
195pub const PF_VSOCK = 40;198pub 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
198pub const AF_UNSPEC = PF_UNSPEC;204pub const AF_UNSPEC = PF_UNSPEC;
199pub const AF_LOCAL = PF_LOCAL;205pub const AF_LOCAL = PF_LOCAL;
...@@ -239,8 +245,137 @@ pub const AF_CAIF = PF_CAIF;...@@ -239,8 +245,137 @@ pub const AF_CAIF = PF_CAIF;
239pub const AF_ALG = PF_ALG;245pub const AF_ALG = PF_ALG;
240pub const AF_NFC = PF_NFC;246pub const AF_NFC = PF_NFC;
241pub const AF_VSOCK = PF_VSOCK;247pub const AF_VSOCK = PF_VSOCK;
248pub const AF_KCM = PF_KCM;
249pub const AF_QIPCRTR = PF_QIPCRTR;
250pub const AF_SMC = PF_SMC;
242pub const AF_MAX = PF_MAX;251pub 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
244pub const DT_UNKNOWN = 0;379pub const DT_UNKNOWN = 0;
245pub const DT_FIFO = 1;380pub const DT_FIFO = 1;
246pub const DT_CHR = 2;381pub const DT_CHR = 2;
...@@ -599,30 +734,27 @@ pub fn sigismember(set: &const sigset_t, sig: u6) bool {...@@ -599,30 +734,27 @@ pub fn sigismember(set: &const sigset_t, sig: u6) bool {
599 return ((*set)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0;734 return ((*set)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0;
600}735}
601736
602737pub const in_port_t = u16;
603pub const sa_family_t = u16;738pub const sa_family_t = u16;
604pub const socklen_t = u32;739pub const socklen_t = u32;
605pub const in_addr = u32;
606pub const in6_addr = [16]u8;
607740
608pub const sockaddr = extern struct {741pub const sockaddr = extern union {
609 family: sa_family_t,742 in: sockaddr_in,
610 port: u16,743 in6: sockaddr_in6,
611 data: [12]u8,
612};744};
613745
614pub const sockaddr_in = extern struct {746pub const sockaddr_in = extern struct {
615 family: sa_family_t,747 family: sa_family_t,
616 port: u16,748 port: in_port_t,
617 addr: in_addr,749 addr: u32,
618 zero: [8]u8,750 zero: [8]u8,
619};751};
620752
621pub const sockaddr_in6 = extern struct {753pub const sockaddr_in6 = extern struct {
622 family: sa_family_t,754 family: sa_family_t,
623 port: u16,755 port: in_port_t,
624 flowinfo: u32,756 flowinfo: u32,
625 addr: in6_addr,757 addr: [16]u8,
626 scope_id: u32,758 scope_id: u32,
627};759};
628760
...@@ -639,16 +771,16 @@ pub fn getpeername(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) us...@@ -639,16 +771,16 @@ pub fn getpeername(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) us
639 return syscall3(SYS_getpeername, usize(fd), @ptrToInt(addr), @ptrToInt(len));771 return syscall3(SYS_getpeername, usize(fd), @ptrToInt(addr), @ptrToInt(len));
640}772}
641773
642pub fn socket(domain: i32, socket_type: i32, protocol: i32) usize {774pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
643 return syscall3(SYS_socket, usize(domain), usize(socket_type), usize(protocol));775 return syscall3(SYS_socket, domain, socket_type, protocol);
644}776}
645777
646pub fn setsockopt(fd: i32, level: i32, optname: i32, optval: &const u8, optlen: socklen_t) usize {778pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: &const u8, optlen: socklen_t) usize {
647 return syscall5(SYS_setsockopt, usize(fd), usize(level), usize(optname), usize(optval), @ptrToInt(optlen));779 return syscall5(SYS_setsockopt, usize(fd), level, optname, usize(optval), @ptrToInt(optlen));
648}780}
649781
650pub fn getsockopt(fd: i32, level: i32, optname: i32, noalias optval: &u8, noalias optlen: &socklen_t) usize {782pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: &u8, noalias optlen: &socklen_t) usize {
651 return syscall5(SYS_getsockopt, usize(fd), usize(level), usize(optname), @ptrToInt(optval), @ptrToInt(optlen));783 return syscall5(SYS_getsockopt, usize(fd), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
652}784}
653785
654pub fn sendmsg(fd: i32, msg: &const msghdr, flags: u32) usize {786pub fn sendmsg(fd: i32, msg: &const msghdr, flags: u32) usize {
...@@ -677,8 +809,8 @@ pub fn bind(fd: i32, addr: &const sockaddr, len: socklen_t) usize {...@@ -677,8 +809,8 @@ pub fn bind(fd: i32, addr: &const sockaddr, len: socklen_t) usize {
677 return syscall3(SYS_bind, usize(fd), @ptrToInt(addr), usize(len));809 return syscall3(SYS_bind, usize(fd), @ptrToInt(addr), usize(len));
678}810}
679811
680pub fn listen(fd: i32, backlog: i32) usize {812pub fn listen(fd: i32, backlog: u32) usize {
681 return syscall2(SYS_listen, usize(fd), usize(backlog));813 return syscall2(SYS_listen, usize(fd), backlog);
682}814}
683815
684pub fn sendto(fd: i32, buf: &const u8, len: usize, flags: u32, addr: ?&const sockaddr, alen: socklen_t) usize {816pub fn sendto(fd: i32, buf: &const u8, len: usize, flags: u32, addr: ?&const sockaddr, alen: socklen_t) usize {
...@@ -697,46 +829,18 @@ pub fn accept4(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t, flags:...@@ -697,46 +829,18 @@ pub fn accept4(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t, flags:
697 return syscall4(SYS_accept4, usize(fd), @ptrToInt(addr), @ptrToInt(len), flags);829 return syscall4(SYS_accept4, usize(fd), @ptrToInt(addr), @ptrToInt(len), flags);
698}830}
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
728pub fn fstat(fd: i32, stat_buf: &Stat) usize {832pub fn fstat(fd: i32, stat_buf: &Stat) usize {
729 return syscall2(SYS_fstat, usize(fd), @ptrToInt(stat_buf));833 return syscall2(SYS_fstat, usize(fd), @ptrToInt(stat_buf));
730}834}
731835
732pub const epoll_data = extern union {836pub const epoll_data = packed union {
733 ptr: usize,837 ptr: usize,
734 fd: i32,838 fd: i32,
735 @"u32": u32,839 @"u32": u32,
736 @"u64": u64,840 @"u64": u64,
737};841};
738842
739pub const epoll_event = extern struct {843pub const epoll_event = packed struct {
740 events: u32,844 events: u32,
741 data: epoll_data,845 data: epoll_data,
742};846};
...@@ -749,7 +853,7 @@ pub fn epoll_create1(flags: usize) usize {...@@ -749,7 +853,7 @@ pub fn epoll_create1(flags: usize) usize {
749 return syscall1(SYS_epoll_create1, flags);853 return syscall1(SYS_epoll_create1, flags);
750}854}
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 {
753 return syscall4(SYS_epoll_ctl, usize(epoll_fd), usize(op), usize(fd), @ptrToInt(ev));857 return syscall4(SYS_epoll_ctl, usize(epoll_fd), usize(op), usize(fd), @ptrToInt(ev));
754}858}
755859