| ... | ... | @@ -2159,9 +2159,20 @@ pub const SocketError = error{ |
| 2159 | 2159 | } || UnexpectedError; |
| 2160 | 2160 | |
| 2161 | 2161 | pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!fd_t { |
| 2162 | const have_sock_flags = comptime !std.Target.current.isDarwin(); |
| 2163 | const filtered_sock_type = if (!have_sock_flags) |
| 2164 | socket_type & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC) |
| 2165 | else |
| 2166 | socket_type; |
| 2162 | 2167 | const rc = system.socket(domain, socket_type, protocol); |
| 2163 | 2168 | switch (errno(rc)) { |
| 2164 | | 0 => return @intCast(fd_t, rc), |
| 2169 | 0 => { |
| 2170 | const fd = @intCast(fd_t, rc); |
| 2171 | if (!have_sock_flags and filtered_sock_type != socket_type) { |
| 2172 | try setSockFlags(fd, socket_type); |
| 2173 | } |
| 2174 | return fd; |
| 2175 | }, |
| 2165 | 2176 | EACCES => return error.PermissionDenied, |
| 2166 | 2177 | EAFNOSUPPORT => return error.AddressFamilyNotSupported, |
| 2167 | 2178 | EINVAL => return error.ProtocolFamilyNotAvailable, |
| ... | ... | @@ -2284,7 +2295,7 @@ pub const AcceptError = error{ |
| 2284 | 2295 | /// Accept a connection on a socket. |
| 2285 | 2296 | /// If the application has a global event loop enabled, EAGAIN is handled |
| 2286 | 2297 | /// via the event loop. Otherwise EAGAIN results in error.WouldBlock. |
| 2287 | | pub fn accept4( |
| 2298 | pub fn accept( |
| 2288 | 2299 | /// This argument is a socket that has been created with `socket`, bound to a local address |
| 2289 | 2300 | /// with `bind`, and is listening for connections after a `listen`. |
| 2290 | 2301 | sockfd: fd_t, |
| ... | ... | @@ -2300,8 +2311,7 @@ pub fn accept4( |
| 2300 | 2311 | /// The returned address is truncated if the buffer provided is too small; in this case, `addr_size` |
| 2301 | 2312 | /// will return a value greater than was supplied to the call. |
| 2302 | 2313 | addr_size: *socklen_t, |
| 2303 | | /// If flags is 0, then `accept4` is the same as `accept`. The following values can be bitwise |
| 2304 | | /// ORed in flags to obtain different behavior: |
| 2314 | /// The following values can be bitwise ORed in flags to obtain different behavior: |
| 2305 | 2315 | /// * `SOCK_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the open file description (see `open`) |
| 2306 | 2316 | /// referred to by the new file descriptor. Using this flag saves extra calls to `fcntl` to achieve |
| 2307 | 2317 | /// the same result. |
| ... | ... | @@ -2309,12 +2319,24 @@ pub fn accept4( |
| 2309 | 2319 | /// description of the `O_CLOEXEC` flag in `open` for reasons why this may be useful. |
| 2310 | 2320 | flags: u32, |
| 2311 | 2321 | ) AcceptError!fd_t { |
| 2322 | const have_accept4 = comptime !std.Target.current.isDarwin(); |
| 2323 | assert(0 == (flags & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC))); // Unsupported flag(s) |
| 2324 | |
| 2312 | 2325 | while (true) { |
| 2313 | | const rc = system.accept4(sockfd, addr, addr_size, flags); |
| 2326 | const rc = if (have_accept4) |
| 2327 | system.accept4(sockfd, addr, addr_size, flags) |
| 2328 | else |
| 2329 | system.accept(sockfd, addr, addr_size); |
| 2330 | |
| 2314 | 2331 | switch (errno(rc)) { |
| 2315 | | 0 => return @intCast(fd_t, rc), |
| 2332 | 0 => { |
| 2333 | const fd = @intCast(fd_t, rc); |
| 2334 | if (!have_accept4 and flags != 0) { |
| 2335 | try setSockFlags(fd, flags); |
| 2336 | } |
| 2337 | return fd; |
| 2338 | }, |
| 2316 | 2339 | EINTR => continue, |
| 2317 | | |
| 2318 | 2340 | EAGAIN => if (std.event.Loop.instance) |loop| { |
| 2319 | 2341 | loop.waitUntilFdReadable(sockfd); |
| 2320 | 2342 | continue; |
| ... | ... | @@ -2333,7 +2355,6 @@ pub fn accept4( |
| 2333 | 2355 | EOPNOTSUPP => unreachable, |
| 2334 | 2356 | EPROTO => return error.ProtocolFailure, |
| 2335 | 2357 | EPERM => return error.BlockedByFirewall, |
| 2336 | | |
| 2337 | 2358 | else => |err| return unexpectedErrno(err), |
| 2338 | 2359 | } |
| 2339 | 2360 | } |
| ... | ... | @@ -3245,6 +3266,35 @@ pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize { |
| 3245 | 3266 | } |
| 3246 | 3267 | } |
| 3247 | 3268 | |
| 3269 | fn setSockFlags(fd: fd_t, flags: u32) !void { |
| 3270 | { |
| 3271 | var fd_flags = fcntl(fd, F_GETFD, 0) catch |err| switch (err) { |
| 3272 | error.FileBusy => unreachable, |
| 3273 | error.Locked => unreachable, |
| 3274 | else => |e| return e, |
| 3275 | }; |
| 3276 | if ((flags & SOCK_NONBLOCK) != 0) fd_flags |= FD_CLOEXEC; |
| 3277 | _ = fcntl(fd, F_SETFD, fd_flags) catch |err| switch (err) { |
| 3278 | error.FileBusy => unreachable, |
| 3279 | error.Locked => unreachable, |
| 3280 | else => |e| return e, |
| 3281 | }; |
| 3282 | } |
| 3283 | { |
| 3284 | var fl_flags = fcntl(fd, F_GETFL, 0) catch |err| switch (err) { |
| 3285 | error.FileBusy => unreachable, |
| 3286 | error.Locked => unreachable, |
| 3287 | else => |e| return e, |
| 3288 | }; |
| 3289 | if ((flags & SOCK_CLOEXEC) != 0) fl_flags |= O_NONBLOCK; |
| 3290 | _ = fcntl(fd, F_SETFL, fl_flags) catch |err| switch (err) { |
| 3291 | error.FileBusy => unreachable, |
| 3292 | error.Locked => unreachable, |
| 3293 | else => |e| return e, |
| 3294 | }; |
| 3295 | } |
| 3296 | } |
| 3297 | |
| 3248 | 3298 | pub const FlockError = error{ |
| 3249 | 3299 | WouldBlock, |
| 3250 | 3300 | |