| author | |
| committer | |
| log | 86ba8c06bff84ac4865cef18080fa64fe946cb11 |
| tree | 0460754507f6112ee4dcb59d7dfd2d98c7a42d66 |
| parent | 73e535e1125d76bcd4e85123defea8b76412ab09 |
| parent | 99f6f8ead90d36eab9b50fc1f2792a2bdfab8867 |
| signature | Commit is signed but in an unrecognized format. |
Closes #38203 files changed, 47 insertions(+), 1 deletions(-)
lib/std/c.zig+2-1| ... | @@ -120,7 +120,8 @@ pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int; | ... | @@ -120,7 +120,8 @@ pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int; |
| 120 | pub extern "c" fn getsockname(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int; | 120 | pub extern "c" fn getsockname(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int; |
| 121 | pub extern "c" fn connect(sockfd: fd_t, sock_addr: *const sockaddr, addrlen: socklen_t) c_int; | 121 | pub extern "c" fn connect(sockfd: fd_t, sock_addr: *const sockaddr, addrlen: socklen_t) c_int; |
| 122 | pub extern "c" fn accept4(sockfd: fd_t, addr: *sockaddr, addrlen: *socklen_t, flags: c_uint) c_int; | 122 | pub extern "c" fn accept4(sockfd: fd_t, addr: *sockaddr, addrlen: *socklen_t, flags: c_uint) c_int; |
| 123 | pub extern "c" fn getsockopt(sockfd: fd_t, level: c_int, optname: c_int, optval: *c_void, optlen: *socklen_t) c_int; | 123 | pub extern "c" fn getsockopt(sockfd: fd_t, level: u32, optname: u32, optval: *c_void, optlen: *socklen_t) c_int; |
| 124 | pub extern "c" fn setsockopt(sockfd: fd_t, level: u32, optname: u32, optval: *c_void, optlen: socklen_t) c_int; | ||
| 124 | pub extern "c" fn send(sockfd: fd_t, buf: *const c_void, len: usize, flags: u32) isize; | 125 | pub extern "c" fn send(sockfd: fd_t, buf: *const c_void, len: usize, flags: u32) isize; |
| 125 | pub extern "c" fn sendto( | 126 | pub extern "c" fn sendto( |
| 126 | sockfd: fd_t, | 127 | sockfd: fd_t, |
lib/std/net.zig+14| ... | @@ -1279,6 +1279,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8) | ... | @@ -1279,6 +1279,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8) |
| 1279 | pub const StreamServer = struct { | 1279 | pub const StreamServer = struct { |
| 1280 | /// Copied from `Options` on `init`. | 1280 | /// Copied from `Options` on `init`. |
| 1281 | kernel_backlog: u32, | 1281 | kernel_backlog: u32, |
| 1282 | reuse_address: bool, | ||
| 1282 | 1283 | ||
| 1283 | /// `undefined` until `listen` returns successfully. | 1284 | /// `undefined` until `listen` returns successfully. |
| 1284 | listen_address: Address, | 1285 | listen_address: Address, |
| ... | @@ -1290,6 +1291,9 @@ pub const StreamServer = struct { | ... | @@ -1290,6 +1291,9 @@ pub const StreamServer = struct { |
| 1290 | /// If more than this many connections pool in the kernel, clients will start | 1291 | /// If more than this many connections pool in the kernel, clients will start |
| 1291 | /// seeing "Connection refused". | 1292 | /// seeing "Connection refused". |
| 1292 | kernel_backlog: u32 = 128, | 1293 | kernel_backlog: u32 = 128, |
| 1294 | |||
| 1295 | /// Enable SO_REUSEADDR on the socket. | ||
| 1296 | reuse_address: bool = false, | ||
| 1293 | }; | 1297 | }; |
| 1294 | 1298 | ||
| 1295 | /// After this call succeeds, resources have been acquired and must | 1299 | /// After this call succeeds, resources have been acquired and must |
| ... | @@ -1298,6 +1302,7 @@ pub const StreamServer = struct { | ... | @@ -1298,6 +1302,7 @@ pub const StreamServer = struct { |
| 1298 | return StreamServer{ | 1302 | return StreamServer{ |
| 1299 | .sockfd = null, | 1303 | .sockfd = null, |
| 1300 | .kernel_backlog = options.kernel_backlog, | 1304 | .kernel_backlog = options.kernel_backlog, |
| 1305 | .reuse_address = options.reuse_address, | ||
| 1301 | .listen_address = undefined, | 1306 | .listen_address = undefined, |
| 1302 | }; | 1307 | }; |
| 1303 | } | 1308 | } |
| ... | @@ -1320,6 +1325,15 @@ pub const StreamServer = struct { | ... | @@ -1320,6 +1325,15 @@ pub const StreamServer = struct { |
| 1320 | self.sockfd = null; | 1325 | self.sockfd = null; |
| 1321 | } | 1326 | } |
| 1322 | 1327 | ||
| 1328 | if (self.reuse_address) { | ||
| 1329 | try os.setsockopt( | ||
| 1330 | self.sockfd.?, | ||
| 1331 | os.SOL_SOCKET, | ||
| 1332 | os.SO_REUSEADDR, | ||
| 1333 | &mem.toBytes(@as(c_int, 1)), | ||
| 1334 | ); | ||
| 1335 | } | ||
| 1336 | |||
| 1323 | var socklen = address.getOsSockLen(); | 1337 | var socklen = address.getOsSockLen(); |
| 1324 | try os.bind(sockfd, &address.any, socklen); | 1338 | try os.bind(sockfd, &address.any, socklen); |
| 1325 | try os.listen(sockfd, self.kernel_backlog); | 1339 | try os.listen(sockfd, self.kernel_backlog); |
lib/std/os.zig+31| ... | @@ -3250,3 +3250,34 @@ pub fn sched_yield() SchedYieldError!void { | ... | @@ -3250,3 +3250,34 @@ pub fn sched_yield() SchedYieldError!void { |
| 3250 | else => return error.SystemCannotYield, | 3250 | else => return error.SystemCannotYield, |
| 3251 | } | 3251 | } |
| 3252 | } | 3252 | } |
| 3253 | |||
| 3254 | pub const SetSockOptError = error{ | ||
| 3255 | /// The socket is already connected, and a specified option cannot be set while the socket is connected. | ||
| 3256 | AlreadyConnected, | ||
| 3257 | |||
| 3258 | /// The option is not supported by the protocol. | ||
| 3259 | InvalidProtocolOption, | ||
| 3260 | |||
| 3261 | /// The send and receive timeout values are too big to fit into the timeout fields in the socket structure. | ||
| 3262 | TimeoutTooBig, | ||
| 3263 | |||
| 3264 | /// Insufficient resources are available in the system to complete the call. | ||
| 3265 | SystemResources, | ||
| 3266 | } || UnexpectedError; | ||
| 3267 | |||
| 3268 | /// Set a socket's options. | ||
| 3269 | pub fn setsockopt(fd: fd_t, level: u32, optname: u32, opt: []const u8) SetSockOptError!void { | ||
| 3270 | switch (errno(system.setsockopt(fd, level, optname, opt.ptr, @intCast(socklen_t, opt.len)))) { | ||
| 3271 | 0 => {}, | ||
| 3272 | EBADF => unreachable, // always a race condition | ||
| 3273 | ENOTSOCK => unreachable, // always a race condition | ||
| 3274 | EINVAL => unreachable, | ||
| 3275 | EFAULT => unreachable, | ||
| 3276 | EDOM => return error.TimeoutTooBig, | ||
| 3277 | EISCONN => return error.AlreadyConnected, | ||
| 3278 | ENOPROTOOPT => return error.InvalidProtocolOption, | ||
| 3279 | ENOMEM => return error.SystemResources, | ||
| 3280 | ENOBUFS => return error.SystemResources, | ||
| 3281 | else => |err| return unexpectedErrno(err), | ||
| 3282 | } | ||
| 3283 | } |