| author | |
| committer | |
| log | 79313d844f96f9f661cd2621a33890cefa8fb859 |
| tree | b215bc2e0e3e5d8dfe3c5270186f3858a9d77079 |
| parent | 05cff8a558fda0e974ea7d00f26f8f4ff6e1195f |
socketpair is something like a pipe2() for sockets, and generally
only works for AF_UNIX sockets for most platforms. Winsock2
explicitly does not support this call, even though it does have
AF_UNIX sockets.2 files changed, 47 insertions(+), 1 deletions(-)
lib/std/c.zig+7-1| ... | ... | @@ -10599,6 +10599,12 @@ pub const socket = switch (native_os) { |
| 10599 | 10599 | else => private.socket, |
| 10600 | 10600 | }; |
| 10601 | 10601 | |
| 10602 | pub const socketpair = switch (native_os) { | |
| 10603 | // https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/#unsupported\unavailable: | |
| 10604 | .windows => void, | |
| 10605 | else => private.socketpair, | |
| 10606 | }; | |
| 10607 | ||
| 10602 | 10608 | pub const stat = switch (native_os) { |
| 10603 | 10609 | .macos => switch (native_arch) { |
| 10604 | 10610 | .x86_64 => private.@"stat$INODE64", |
| ... | ... | @@ -10740,7 +10746,6 @@ pub extern "c" fn uname(buf: *utsname) c_int; |
| 10740 | 10746 | pub extern "c" fn gethostname(name: [*]u8, len: usize) c_int; |
| 10741 | 10747 | pub extern "c" fn shutdown(socket: fd_t, how: c_int) c_int; |
| 10742 | 10748 | pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: socklen_t) c_int; |
| 10743 | pub extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint, sv: *[2]fd_t) c_int; | |
| 10744 | 10749 | pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int; |
| 10745 | 10750 | pub extern "c" fn getsockname(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int; |
| 10746 | 10751 | pub extern "c" fn getpeername(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int; |
| ... | ... | @@ -11429,6 +11434,7 @@ const private = struct { |
| 11429 | 11434 | extern "c" fn sigismember(set: ?*const sigset_t, signo: c_int) c_int; |
| 11430 | 11435 | extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; |
| 11431 | 11436 | extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; |
| 11437 | extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint, sv: *[2]fd_t) c_int; | |
| 11432 | 11438 | extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *Stat) c_int; |
| 11433 | 11439 | extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; |
| 11434 | 11440 | extern "c" fn sysconf(sc: c_int) c_long; |
lib/std/posix.zig+40| ... | ... | @@ -3671,6 +3671,46 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t |
| 3671 | 3671 | } |
| 3672 | 3672 | } |
| 3673 | 3673 | |
| 3674 | pub fn socketpair(domain: u32, socket_type: u32, protocol: u32) SocketError![2]socket_t { | |
| 3675 | // Note to the future: we could provide a shim here for e.g. windows which | |
| 3676 | // creates a listening socket, then creates a second socket and connects it | |
| 3677 | // to the listening socket, and then returns the two. | |
| 3678 | if (@TypeOf(system.socketpair) == void) | |
| 3679 | @compileError("socketpair() not supported by this OS"); | |
| 3680 | ||
| 3681 | // I'm not really sure if haiku supports flags here. I'm following the | |
| 3682 | // existing filter here from pipe2(), because it sure seems like it | |
| 3683 | // supports flags there too, but haiku can be hard to understand. | |
| 3684 | const have_sock_flags = !builtin.target.os.tag.isDarwin() and native_os != .haiku; | |
| 3685 | const filtered_sock_type = if (!have_sock_flags) | |
| 3686 | socket_type & ~@as(u32, SOCK.NONBLOCK | SOCK.CLOEXEC) | |
| 3687 | else | |
| 3688 | socket_type; | |
| 3689 | var socks: [2]socket_t = undefined; | |
| 3690 | const rc = system.socketpair(domain, filtered_sock_type, protocol, &socks); | |
| 3691 | switch (errno(rc)) { | |
| 3692 | .SUCCESS => { | |
| 3693 | errdefer close(socks[0]); | |
| 3694 | errdefer close(socks[1]); | |
| 3695 | if (!have_sock_flags) { | |
| 3696 | try setSockFlags(socks[0], socket_type); | |
| 3697 | try setSockFlags(socks[1], socket_type); | |
| 3698 | } | |
| 3699 | return socks; | |
| 3700 | }, | |
| 3701 | .ACCES => return error.AccessDenied, | |
| 3702 | .AFNOSUPPORT => return error.AddressFamilyNotSupported, | |
| 3703 | .INVAL => return error.ProtocolFamilyNotAvailable, | |
| 3704 | .MFILE => return error.ProcessFdQuotaExceeded, | |
| 3705 | .NFILE => return error.SystemFdQuotaExceeded, | |
| 3706 | .NOBUFS => return error.SystemResources, | |
| 3707 | .NOMEM => return error.SystemResources, | |
| 3708 | .PROTONOSUPPORT => return error.ProtocolNotSupported, | |
| 3709 | .PROTOTYPE => return error.SocketTypeNotSupported, | |
| 3710 | else => |err| return unexpectedErrno(err), | |
| 3711 | } | |
| 3712 | } | |
| 3713 | ||
| 3674 | 3714 | pub const ShutdownError = error{ |
| 3675 | 3715 | ConnectionAborted, |
| 3676 | 3716 |