| ... | ... | @@ -206,34 +206,16 @@ pub fn connect( |
| 206 | 206 | port: u16, |
| 207 | 207 | options: IpAddress.ConnectOptions, |
| 208 | 208 | ) ConnectError!Stream { |
| 209 | | var canonical_name_buffer: [max_len]u8 = undefined; |
| 210 | | var results_buffer: [32]HostName.LookupResult = undefined; |
| 211 | | var results: Io.Queue(LookupResult) = .init(&results_buffer); |
| 212 | | |
| 213 | | var lookup_task = io.async(HostName.lookup, .{ host_name, io, &results, .{ |
| 214 | | .port = port, |
| 215 | | .canonical_name_buffer = &canonical_name_buffer, |
| 216 | | } }); |
| 217 | | defer lookup_task.cancel(io); |
| 218 | | |
| 219 | | const Result = union(enum) { connect_result: IpAddress.ConnectError!Stream }; |
| 220 | | var finished_task_buffer: [results_buffer.len]Result = undefined; |
| 221 | | var select: Io.Select(Result) = .init(io, &finished_task_buffer); |
| 222 | | defer select.cancel(); |
| 209 | var connect_many_buffer: [32]ConnectManyResult = undefined; |
| 210 | var connect_many_queue: Io.Queue(ConnectManyResult) = .init(&connect_many_buffer); |
| 223 | 211 | |
| 224 | | while (results.getOne(io)) |result| switch (result) { |
| 225 | | .address => |address| select.async(.connect_result, IpAddress.connect, .{ address, io, options }), |
| 226 | | .canonical_name => continue, |
| 227 | | .end => |lookup_result| { |
| 228 | | try lookup_result; |
| 229 | | break; |
| 230 | | }, |
| 231 | | } else |err| return err; |
| 212 | var connect_many = io.async(connectMany, .{ host_name, io, port, &connect_many_queue, options }); |
| 213 | defer connect_many.cancel(io); |
| 232 | 214 | |
| 233 | 215 | var aggregate_error: ConnectError = error.UnknownHostName; |
| 234 | 216 | |
| 235 | | while (select.outstanding != 0) switch (try select.wait()) { |
| 236 | | .connect_result => |connect_result| if (connect_result) |stream| return stream else |err| switch (err) { |
| 217 | while (connect_many_queue.getOne(io)) |result| switch (result) { |
| 218 | .connection => |connection| if (connection) |stream| return stream else |err| switch (err) { |
| 237 | 219 | error.SystemResources => |e| return e, |
| 238 | 220 | error.OptionUnsupported => |e| return e, |
| 239 | 221 | error.ProcessFdQuotaExceeded => |e| return e, |
| ... | ... | @@ -242,9 +224,59 @@ pub fn connect( |
| 242 | 224 | error.WouldBlock => return error.Unexpected, |
| 243 | 225 | else => |e| aggregate_error = e, |
| 244 | 226 | }, |
| 245 | | }; |
| 227 | .end => |end| { |
| 228 | try end; |
| 229 | return aggregate_error; |
| 230 | }, |
| 231 | } else |err| return err; |
| 232 | } |
| 233 | |
| 234 | pub const ConnectManyResult = union(enum) { |
| 235 | connection: IpAddress.ConnectError!Stream, |
| 236 | end: ConnectError!void, |
| 237 | }; |
| 238 | |
| 239 | /// Asynchronously establishes a connection to all IP addresses associated with |
| 240 | /// a host name, adding them to a results queue upon completion. |
| 241 | pub fn connectMany( |
| 242 | host_name: HostName, |
| 243 | io: Io, |
| 244 | port: u16, |
| 245 | results: *Io.Queue(ConnectManyResult), |
| 246 | options: IpAddress.ConnectOptions, |
| 247 | ) void { |
| 248 | var canonical_name_buffer: [max_len]u8 = undefined; |
| 249 | var lookup_buffer: [32]HostName.LookupResult = undefined; |
| 250 | var lookup_queue: Io.Queue(LookupResult) = .init(&lookup_buffer); |
| 251 | |
| 252 | host_name.lookup(io, &lookup_queue, .{ |
| 253 | .port = port, |
| 254 | .canonical_name_buffer = &canonical_name_buffer, |
| 255 | }); |
| 256 | |
| 257 | var group: Io.Group = .init; |
| 258 | defer group.cancel(io); |
| 259 | |
| 260 | while (lookup_queue.getOne(io)) |dns_result| switch (dns_result) { |
| 261 | .address => |address| group.async(io, enqueueConnection, .{ address, io, results, options }), |
| 262 | .canonical_name => continue, |
| 263 | .end => |lookup_result| { |
| 264 | group.wait(io); |
| 265 | results.putOneUncancelable(io, .{ .end = lookup_result }); |
| 266 | return; |
| 267 | }, |
| 268 | } else |err| switch (err) { |
| 269 | error.Canceled => |e| results.putOneUncancelable(io, .{ .end = e }), |
| 270 | } |
| 271 | } |
| 246 | 272 | |
| 247 | | return aggregate_error; |
| 273 | fn enqueueConnection( |
| 274 | address: IpAddress, |
| 275 | io: Io, |
| 276 | queue: *Io.Queue(ConnectManyResult), |
| 277 | options: IpAddress.ConnectOptions, |
| 278 | ) void { |
| 279 | queue.putOneUncancelable(io, .{ .connection = address.connect(io, options) }); |
| 248 | 280 | } |
| 249 | 281 | |
| 250 | 282 | pub const ResolvConf = struct { |