From bb047ca3ba3e090588069e2e106b607b1d37f222 Mon Sep 17 00:00:00 2001 From: mefyl Date: Fri, 29 Dec 2023 11:04:17 +0100 Subject: [PATCH] Add Net.listening_addr. --- CHANGES.md | 172 +++++++++++++++++++------------------ lib_eio/mock/eio_mock.mli | 7 +- lib_eio/mock/net.ml | 10 ++- lib_eio/net.ml | 5 ++ lib_eio/net.mli | 5 ++ lib_eio_linux/eio_linux.ml | 5 ++ lib_eio_posix/net.ml | 5 ++ lib_eio_windows/net.ml | 5 ++ 8 files changed, 126 insertions(+), 88 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8c19e8265..ef3604e31 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +## v0.14 + +New features / API changes: + +- Add `Net.listening_addr` (@mefyl #555). + ## v0.13 New features / API changes: @@ -45,7 +51,7 @@ Build and test changes: New features / API changes: -- Replace objects with variants (@talex5 @patricoferris #553 #605 #608, reviewed by @avsm). +- Replace objects with variants (@talex5 @patricoferris #553 #605 #608, reviewed by @avsm). Some potential users found object types confusing, so we now use an alternative scheme for OS resources. For users of the resources, the only thing that changes is the types: @@ -57,27 +63,27 @@ New features / API changes: If you want to define your own interfaces, see the `Eio.Resource` module documentation. -- Add `Eio.Pool` (@talex5 @darrenldl #602, reviewed by @patricoferris). +- Add `Eio.Pool` (@talex5 @darrenldl #602, reviewed by @patricoferris). A lock-free pool of resources. This is similar to `Lwt_pool`. -- Add `Eio.Lazy` (@talex5 #609, reviewed by @SGrondin). +- Add `Eio.Lazy` (@talex5 #609, reviewed by @SGrondin). If one fiber tries to force a lazy value while another is already doing it, this will wait for the first one to finish rather than raising an exception (as `Stdlib.Lazy` does). -- Add `Eio.Path.native` (@talex5 #603, reviewed by @patricoferris). +- Add `Eio.Path.native` (@talex5 #603, reviewed by @patricoferris). This is useful when interacting with non-Eio libraries, for spawning sub-processes, and for displaying paths to users. - Add `Flow.single_write` (@talex5 #598). -- Add `Eio.Flow.Pi.simple_copy` (@talex5 #611). +- Add `Eio.Flow.Pi.simple_copy` (@talex5 #611). Provides an easy way to implement the `copy` operation when making your own sink. -- Eio_unix: add FD passing (@talex5 #522). +- Eio_unix: add FD passing (@talex5 #522). Allows opening a file and passing the handle over a Unix-domain socket. - Add `Process.run ?is_success` to control definition of success (@SGrondin #586, reviewed by @talex5). -- Add `Eio_mock.Domain_manager` (@talex5 #610). +- Add `Eio_mock.Domain_manager` (@talex5 #610). This mock domain manager runs everything in a single domain, allowing tests to remain deterministic. - Add `Eio.Debug.with_trace_prefix` (@talex5 #610). @@ -85,10 +91,10 @@ New features / API changes: Bug fixes: -- Fork actions must not allocate (@talex5 #593). +- Fork actions must not allocate (@talex5 #593). When using multiple domains, child processes could get stuck if they forked while another domain held the malloc lock. -- eio_posix: ignore some errors writing to the wake-up pipe (@talex5 #600). +- eio_posix: ignore some errors writing to the wake-up pipe (@talex5 #600). If the pipe is full or closed, the wake-up should simply be ignored. Build/test fixes: @@ -108,14 +114,14 @@ Build/test fixes: New features / API changes: -- Extend `Eio.Condition` API (@talex5 #563). +- Extend `Eio.Condition` API (@talex5 #563). - `loop_no_mutex` is a simpler and more efficient way to way for a condition. - `register_immediate` allows integration with other IO libraries. -- Expose `Eio.Stdenv.backend_id` (@bord-o #560, reviewed by @talex5). +- Expose `Eio.Stdenv.backend_id` (@bord-o #560, reviewed by @talex5). Useful in tests to report which backend is being used. -- Remove deprecated features (@talex5 #552, reviewed by @avsm). +- Remove deprecated features (@talex5 #552, reviewed by @avsm). These were all already marked as deprecated in v0.10 and are now gone completely: - `Fiber.fork_sub` - `Eio_unix.{FD,Ipaddr,socketpair,getnameinfo}` @@ -124,36 +130,36 @@ New features / API changes: - Allow calling `close` more than once (@talex5 #547, requested by @anmonteiro, reviewed by @patricoferris, @avsm). -- Add `close` to socket type (@talex5 #549). +- Add `close` to socket type (@talex5 #549). Simplifies the type signatures a bit by avoiding having to mention this everywhere. Bug fixes: -- Fix handling of empty path strings (@talex5 #569, reported by @SGrondin). +- Fix handling of empty path strings (@talex5 #569, reported by @SGrondin). Using "" instead of "." in some places resulted in an error. -- eio_posix: fix update to watched FDs on cancel (@talex5 #574, reported and reviewed by @quernd). +- eio_posix: fix update to watched FDs on cancel (@talex5 #574, reported and reviewed by @quernd). Cancelling the last watcher of an FD didn't remove it from the set passed to `poll`, which could result in constant wake-ups. -- eio_posix: fix `pread` at end-of-file (@talex5 #581, reported by @SGrondin). +- eio_posix: fix `pread` at end-of-file (@talex5 #581, reported by @SGrondin). It tried to return 0 instead of `End_of_file`, triggering an assertion. -- eio_posix: don't reap non-Eio child processes (@talex5 #562). +- eio_posix: don't reap non-Eio child processes (@talex5 #562). This allows spawning processes with e.g. the stdlib or Lwt (but see https://github.com/ocaml-multicore/lwt_eio/pull/19 for Lwt support). -- Preserve backtraces across `Domain_manager.run` (@talex5 #571). +- Preserve backtraces across `Domain_manager.run` (@talex5 #571). See https://github.com/ocaml/ocaml/issues/12362. -- Correct the backend selection for Cygwin (@dra27 #557). +- Correct the backend selection for Cygwin (@dra27 #557). Use `eio_posix`, not `eio_windows` in this case. Other changes: - Simplify dune files with dune 3.9's `build_if` (@talex5 #582). -- Remove `Waiters` from `Eio_core` (@talex5 #567). +- Remove `Waiters` from `Eio_core` (@talex5 #567). `Eio.Switch` no longer uses this so it can finally be removed. - Use `Fmt.Dump.signal` to format signals (@talex5, @MisterDA #543). @@ -168,33 +174,33 @@ New features / API changes: - Add `Eio.Process` for cross-platform subprocess support (@patricoferris @talex5 #499, reviewed by @anmonteiro @avsm @haesbaert). -- Add `Eio_unix.Net module` (@talex5 #516, reviewed by @avsm). +- Add `Eio_unix.Net module` (@talex5 #516, reviewed by @avsm). The Unix network APIs have been cleaned up and moved here, and some missing datagram operations have been added. `send` now takes an iovec, not just a single buffer. -- Add support for domain local await (@polytypic @talex5 #494 #503). +- Add support for domain local await (@polytypic @talex5 #494 #503). Allows sharing e.g. kcas data-structures across Eio and Domainslib domains. -- Add initial eio_windows backend (@patricoferris @talex5 #497 #530 #511 #523 #509, reviewed by @avsm @polytypic). +- Add initial eio_windows backend (@patricoferris @talex5 #497 #530 #511 #523 #509, reviewed by @avsm @polytypic). -- Remove eio_luv backend (@talex5 #485). +- Remove eio_luv backend (@talex5 #485). It was only used on Windows, and has been replaced by eio_windows. -- Unify `Eio_linux.FD` and `Eio_posix.Fd` as `Eio_unix.Fd` (@talex5 #491). +- Unify `Eio_linux.FD` and `Eio_posix.Fd` as `Eio_unix.Fd` (@talex5 #491). Now that eio_luv is gone, there is no need for different backends to have different types for wrapped file descriptors. -- Move `Eio.Stdenv.t` to `Eio_unix.Stdenv.base` (@talex5 #498). +- Move `Eio.Stdenv.t` to `Eio_unix.Stdenv.base` (@talex5 #498). Note that the rest of `Eio.Stdenv` is still there; only the definition of a full Unix-like environment has moved. -- Deprecation cleanups (@talex5 #508). +- Deprecation cleanups (@talex5 #508). Removed some APIs that were already marked as deprecated in Eio 0.8. Bug fixes: -- eio_linux: fall back to `fork` if `clone3` is unavailable (@talex5 #524, reported by @smondet, reviewed by @avsm). +- eio_linux: fall back to `fork` if `clone3` is unavailable (@talex5 #524, reported by @smondet, reviewed by @avsm). Docker's default security policy blocks `clone3`. -- Don't call `accept_fork`'s error handler on cancellation (@talex5 #520). +- Don't call `accept_fork`'s error handler on cancellation (@talex5 #520). This isn't an error and should not be reported. - Fix `eio_unix_is_blocking` C stub (@patricoferris #505, reviewed by @talex5). @@ -223,12 +229,12 @@ Other changes: - Fix MDX tests on OCaml 5.1 (@talex5 #526). -- Add stress test for spawning processes (@talex5 #519). +- Add stress test for spawning processes (@talex5 #519). This was an attempt to track down the https://github.com/ocaml/ocaml/issues/12253 signals bug. - `Eio.Process.pp_status` should be polymorphic (@talex5 #518). -- eio_posix: probe for existence of some flags (@talex5 #507, reported by @hannesm). +- eio_posix: probe for existence of some flags (@talex5 #507, reported by @hannesm). FreeBSD 12 didn't have `O_DSYNC`. Also, add `O_RESOLVE_BENEATH` and `O_PATH` if available. - Fix race in ctf tests (@talex5 #493). @@ -237,33 +243,33 @@ Other changes: New features: -- Add eio_posix backend (@talex5 @haesbaert #448 #477, reviewed by @avsm @patricoferris @polytypic). +- Add eio_posix backend (@talex5 @haesbaert #448 #477, reviewed by @avsm @patricoferris @polytypic). This replaces eio_luv on all platforms except Windows (which will later switch to its own backend). It is a lot faster, provides access to more modern features (such as `openat`), and can safely share OS resources between domains. -- Add subprocess support (@patricoferris @talex5 #461 #464 #472, reviewed by @haesbaert @avsm). +- Add subprocess support (@patricoferris @talex5 #461 #464 #472, reviewed by @haesbaert @avsm). This is the low-level API support for eio_linux and eio_posix. A high-level cross-platform API will be added in the next release. -- Add `Fiber.fork_seq` (@talex5 #460, reviewed by @avsm). +- Add `Fiber.fork_seq` (@talex5 #460, reviewed by @avsm). This is a light-weight alternative to using a single-producer, single-consumer, 0-capacity stream, similar to a Python generator function. Bug fixes: -- eio_linux: make it safe to share FDs across domains (@talex5 #440, reviewed by @haesbaert). +- eio_linux: make it safe to share FDs across domains (@talex5 #440, reviewed by @haesbaert). It was previously not safe to share file descriptors between domains because if one domain used an FD just as another was closing it, and the FD got reused, then the original operation could act on the wrong file. -- eio_linux: release uring if Linux is too old (@talex5 #476). +- eio_linux: release uring if Linux is too old (@talex5 #476). Avoids a small resource leak. -- eio_linux: improve error handling creating pipes and sockets (@talex5 #474, spotted by @avsm). +- eio_linux: improve error handling creating pipes and sockets (@talex5 #474, spotted by @avsm). If we get an error (e.g. too many FDs) then report it to the calling fiber, instead of exiting the event loop. -- eio_linux: wait for uring to finish before exiting (@talex5 #470, reviewed by @avsm). +- eio_linux: wait for uring to finish before exiting (@talex5 #470, reviewed by @avsm). If the main fiber raised an exception then it was possible to exit while a cancellation operation was still in progress. -- eio_main: make `EIO_BACKEND` handling more uniform (@talex5 #447). +- eio_main: make `EIO_BACKEND` handling more uniform (@talex5 #447). Previously this environment variable was only used on Linux. Now all platforms check it. -- Tell dune about `EIO_BACKEND` (@talex5 #442). +- Tell dune about `EIO_BACKEND` (@talex5 #442). If this changes, dune needs to re-run the tests. - eio_linux: add some missing close-on-execs (@talex5 #441). @@ -280,7 +286,7 @@ Documentation: - Improve worker pool example (@talex5 #454). -- Add more Conditions documentation (@talex5 #436, reviewed by @haesbaert). +- Add more Conditions documentation (@talex5 #436, reviewed by @haesbaert). This adds a discussion of conditions to the README and provides examples using them to handle signals. - Condition: fix the example in the docstring (@avsm #468). @@ -303,7 +309,7 @@ Other changes: - Use dune.3.7.0 (@patricoferris #457). -- Mint exclusive IDs across domains (@TheLortex #480, reported by @haesbaert, reviewed by @talex5). +- Mint exclusive IDs across domains (@TheLortex #480, reported by @haesbaert, reviewed by @talex5). The tracing currently only works with a single domain anyway, but this will change when OCaml 5.1 is released. @@ -321,18 +327,18 @@ Some build fixes: New features: -- Add `Eio.Net.run_server` (@bikallem @talex5 #408). +- Add `Eio.Net.run_server` (@bikallem @talex5 #408). Runs an accept loop in one or more domains, with cancellation and graceful shutdown, and an optional maximum number of concurrent connections. -- Add `Buf_read.BE` and `LE` parsers (@Cjen1 #399). +- Add `Buf_read.BE` and `LE` parsers (@Cjen1 #399). Parse numbers in various binary formats. - Add `Eio.Buf_read.uint8` (@talex5 #418). Performance: -- Make `Eio.Condition` lock-free (@talex5 #397 #381). +- Make `Eio.Condition` lock-free (@talex5 #397 #381). In addition to being faster, this allows using conditions in signal handlers. - Make `Eio.Semaphore` lock-free (@talex5 @polytypic #398). @@ -343,10 +349,10 @@ Performance: Bug fixes: -- eio_linux: call `Uring.submit` as needed (@talex5 @bikallem #428). +- eio_linux: call `Uring.submit` as needed (@talex5 @bikallem #428). Previously, we could fail to submit a job promptly because the SQE queue was full. -- Fix luv signals (@haesbaert #412). +- Fix luv signals (@haesbaert #412). `libuv` automatically retries polling if it gets `EINTR`, without giving OCaml signal handlers a chance to run. - eio_luv: fix some resource leaks (@talex5 @patricoferris #421). @@ -389,38 +395,38 @@ Other changes: API changes: -- Unify IO errors as `Eio.Io` (@talex5 #378). +- Unify IO errors as `Eio.Io` (@talex5 #378). This makes it easy to catch and log all IO errors if desired. The exception payload gives the type and can be used for matching specific errors. It also allows attaching extra information to exceptions, and various functions were updated to do this. -- Add `Time.Mono` for monotonic clocks (@bikallem @talex5 #338). +- Add `Time.Mono` for monotonic clocks (@bikallem @talex5 #338). Using the system clock for timeouts, etc can fail if the system time is changed during the wait. -- Allow datagram sockets to be created without a source address (@bikallem @haesbaert #360). +- Allow datagram sockets to be created without a source address (@bikallem @haesbaert #360). The kernel will allocate an address in this case. You can also now control the `reuse_addr` and `reuse_port` options. -- Add `File.stat` and improve `Path.load` (@haesbaert @talex5 #339). +- Add `File.stat` and improve `Path.load` (@haesbaert @talex5 #339). `Path.load` now uses the file size as the initial buffer size. -- Add `Eio_unix.pipe` (@patricoferris #350). +- Add `Eio_unix.pipe` (@patricoferris #350). This replaces `Eio_linux.pipe`. -- Avoid short reads from `getrandom(2)` (@haesbaert #344). +- Avoid short reads from `getrandom(2)` (@haesbaert #344). Guards against buggy user code that might not handle this correctly. -- Rename `Flow.read` to `Flow.single_read` (@talex5 #353). +- Rename `Flow.read` to `Flow.single_read` (@talex5 #353). This is a low-level function and it is easy to use it incorrectly by ignoring the possibility of short reads. Bug fixes: -- Eio_luv: Fix non-tail-recursive continue (@talex5 #378). +- Eio_luv: Fix non-tail-recursive continue (@talex5 #378). Affects the `Socket_of_fd` and `Socketpair` effects. - Eio_linux: UDP sockets were not created close-on-exec (@talex5 #360). -- Eio_linux: work around io_uring non-blocking bug (@haesbaert #327 #355). +- Eio_linux: work around io_uring non-blocking bug (@haesbaert #327 #355). The proper fix should be in Linux 6.1. - `Eio_mock.Backend`: preserve backtraces from `main` (@talex5 #349). @@ -439,15 +445,15 @@ Documentation: Backend-specific changes: -- Eio_luv: add low-level process support (@patricoferris #359). +- Eio_luv: add low-level process support (@patricoferris #359). A future release will add Eio_linux support and a cross-platform API for this. - Expose `Eio_luv.Low_level.Stream.write` (@patricoferris #359). -- Expose `Eio_luv.Low_level.get_loop` (@talex5 #371). +- Expose `Eio_luv.Low_level.get_loop` (@talex5 #371). This is needed if you want to create resources directly and then use them with Eio_luv. -- `Eio_linux.Low_level.openfile` is gone (@talex5 #378). +- `Eio_linux.Low_level.openfile` is gone (@talex5 #378). It was just left-over test code. @@ -459,33 +465,33 @@ Changes: - Add API for seekable read/writes (@nojb #307). -- Add `Flow.write` (@haesbaert #318). +- Add `Flow.write` (@haesbaert #318). This provides an optimised alternative to `copy` in the case where you are writing from a buffer. -- Add `Net.with_tcp_connect` (@bikallem #302). +- Add `Net.with_tcp_connect` (@bikallem #302). Convenience function for opening a TCP connection. -- Add `Eio.Time.Timeout` (@talex5 #320). +- Add `Eio.Time.Timeout` (@talex5 #320). Makes it easier to pass timeouts around. -- Add `Eio_mock.Clock` (@talex5 #328). +- Add `Eio_mock.Clock` (@talex5 #328). Control time in tests. -- Add `Buf_read.take_while1` and `skip_while1` (@bikallem #309). +- Add `Buf_read.take_while1` and `skip_while1` (@bikallem #309). These fail if no characters match. - Make the type parameter for `Promise.t` covariant (@anmonteiro #300). - Move list functions into a dedicated submodule (@raphael-proust #315). -- Direct implementation of `Flow.source_string` (@c-cube #317). +- Direct implementation of `Flow.source_string` (@c-cube #317). Slightly faster. Bug fixes: - `Condition.broadcast` must interlock as well (@haesbaert #324). -- Split the reads into no more than 2^32-1 for luv (@haesbaert @talex5 @EduardoRFS #343). +- Split the reads into no more than 2^32-1 for luv (@haesbaert @talex5 @EduardoRFS #343). Luv uses a 32 bit int for buffer sizes and wraps if the value passed is too big. - eio_luv: allow `Net.connect` to be cancelled (@talex5 @nojb #311). @@ -507,21 +513,21 @@ Documentation: New features: -- Add `Eio.Condition` (@TheLortex @talex5 #277). +- Add `Eio.Condition` (@TheLortex @talex5 #277). Allows a fiber to wait for some condition to become true. -- Add `Eio.Net.getaddrinfo` and `getnameinfo` (@bikallem @talex5 #278 #288 #291). +- Add `Eio.Net.getaddrinfo` and `getnameinfo` (@bikallem @talex5 #278 #288 #291). Convert between host names and addresses. -- Add `Eio.Debug` (@talex5 #276). +- Add `Eio.Debug` (@talex5 #276). Currently, this allows overriding the `traceln` function. -- `Buf_write.create`: make switch optional (@talex5 #283). +- `Buf_write.create`: make switch optional (@talex5 #283). This makes things easier for people porting code from Faraday. Bug fixes: -- Allow sharing of libuv poll handles (@patricoferris @talex5 #279). +- Allow sharing of libuv poll handles (@patricoferris @talex5 #279). Luv doesn't allow two callers to watch the same file handle, so we need to handle that in Eio. Other changes: @@ -542,20 +548,20 @@ API changes: New features: -- Fiber-local storage (@SquidDev #256). +- Fiber-local storage (@SquidDev #256). Attach key/value bindings to fibers. These are inherited across forks. - `Eio.Path.{unlink,rmdir,rename}` (@talex5 #264 #265). -- `Eio_main.run` can now return a value (@talex5 #263). +- `Eio_main.run` can now return a value (@talex5 #263). This is useful for e.g. cmdliner. - `Eio_unix.socketpair` (@talex5 #260). -- `Fiber.fork_daemon` (@talex5 #252). +- `Fiber.fork_daemon` (@talex5 #252). Create a helper fiber that does not prevent the switch from exiting. -- Add `Fiber.{iter,map,filter,fiter_map}` (@talex5 #248 #250). +- Add `Fiber.{iter,map,filter,fiter_map}` (@talex5 #248 #250). These are concurrent versions of the corresponding operations in `List`. Bug fixes: @@ -568,7 +574,7 @@ Bug fixes: - Use `Eio.Net.Connection_reset` exception in more places (@talex5 #257). -- Report use of closed FDs better (@talex5 #255). +- Report use of closed FDs better (@talex5 #255). Using a closed FD could previously cause the whole event loop to exit. - Some fixes for cancellation (@talex5 #254). @@ -581,16 +587,16 @@ Documentation: - Document integrations with Unix, Lwt and Async (@talex5 #247). -- Add a Dockerfile for easy testing (@talex5 #224). +- Add a Dockerfile for easy testing (@talex5 #224). ## v0.3 API changes: -- `Net.accept_sub` is deprecated in favour of `accept_fork` (@talex5 #240). +- `Net.accept_sub` is deprecated in favour of `accept_fork` (@talex5 #240). `Fiber.fork_on_accept`, which it used internally, has been removed. -- Allow short writes in `Read_source_buffer` (@talex5 #239). +- Allow short writes in `Read_source_buffer` (@talex5 #239). The reader is no longer required to consume all the data in one go. Also, add `Linux_eio.Low_level.writev_single` to expose this behaviour directly. @@ -600,13 +606,13 @@ New features: - Add `Eio.Mutex` (@TheLortex @talex5 #223). -- Add `Eio.Buf_write` (@talex5 #235). +- Add `Eio.Buf_write` (@talex5 #235). This is a buffered writer for Eio sinks, based on Faraday. -- Add `Eio_mock` library for testing (@talex5 #228). +- Add `Eio_mock` library for testing (@talex5 #228). At the moment it has mock flows and networks. -- Add `Eio_mock.Backend` (@talex5 #237 #238). +- Add `Eio_mock.Backend` (@talex5 #237 #238). Allows running tests without needing a dependency on eio_main. Also, as it is single-threaded, it can detect deadlocks in test code instead of just hanging. @@ -626,7 +632,7 @@ Bug fixes / minor changes: - Allow IO to happen even if a fiber keeps yielding (@TheLortex @talex5 #213). -- Fallback for `traceln` without an effect handler (@talex5 #226). +- Fallback for `traceln` without an effect handler (@talex5 #226). `traceln` now works outside of an event loop too. - Check for cancellation when creating a non-protected child context (@talex5 #222). diff --git a/lib_eio/mock/eio_mock.mli b/lib_eio/mock/eio_mock.mli index bcf181eaa..29e5e535d 100644 --- a/lib_eio/mock/eio_mock.mli +++ b/lib_eio/mock/eio_mock.mli @@ -132,8 +132,11 @@ module Net : sig val on_getnameinfo : t -> (string * string) Handler.actions -> unit - val listening_socket : string -> listening_socket - (** [listening_socket label] can be configured to provide mock connections. *) + val listening_socket : + ?listening_addr:Eio.Net.Sockaddr.stream -> string -> listening_socket + (** [listening_socket label] can be configured to provide mock connections. + + If [listening_addr] is not provided, a dummy value will be reported. *) val on_accept : listening_socket -> diff --git a/lib_eio/mock/net.ml b/lib_eio/mock/net.ml index 730f2f263..933791ef2 100644 --- a/lib_eio/mock/net.ml +++ b/lib_eio/mock/net.ml @@ -97,14 +97,16 @@ type listening_socket = listening_socket_ty r module Listening_socket = struct type t = { label : string; + listening_addr : Eio.Net.Sockaddr.stream; on_accept : (Flow.t * Eio.Net.Sockaddr.stream) Handler.t; } type tag = [`Generic] - let make label = + let make ?(listening_addr = `Tcp (Eio.Net.Ipaddr.V4.any, 0)) label = { label; + listening_addr; on_accept = Handler.make (`Raise (Failure "Mock accept handler not configured")) } @@ -119,6 +121,8 @@ module Listening_socket = struct let close t = traceln "%s: closed" t.label + let listening_addr { listening_addr; _ } = listening_addr + type (_, _, _) Eio.Resource.pi += Type : ('t, 't -> t, listening_socket_ty) Eio.Resource.pi let raw (Eio.Resource.T (t, ops)) = Eio.Resource.get ops Type t end @@ -129,8 +133,8 @@ let listening_socket_handler = H (Listening_socket.Type, Fun.id); ] -let listening_socket label : listening_socket = - Eio.Resource.T (Listening_socket.make label, listening_socket_handler) +let listening_socket ?listening_addr label : listening_socket = + Eio.Resource.T (Listening_socket.make ?listening_addr label, listening_socket_handler) let on_accept l actions = let r = Listening_socket.raw l in diff --git a/lib_eio/net.ml b/lib_eio/net.ml index fb9acb41d..3dffe2c4a 100644 --- a/lib_eio/net.ml +++ b/lib_eio/net.ml @@ -218,6 +218,7 @@ module Pi = struct val accept : t -> sw:Switch.t -> tag stream_socket_ty r * Sockaddr.stream val close : t -> unit + val listening_addr : t -> Sockaddr.stream end type (_, _, _) Resource.pi += @@ -277,6 +278,10 @@ let accept_fork ~sw (t : [> 'a listening_socket_ty] r) ~on_error handle = ) ) +let listening_addr (type tag) (Resource.T (t, ops) : [> tag listening_socket_ty] r) = + let module X = (val (Resource.get ops Pi.Listening_socket)) in + X.listening_addr t + let send (Resource.T (t, ops)) ?dst bufs = let module X = (val (Resource.get ops Pi.Datagram_socket)) in X.send t ?dst bufs diff --git a/lib_eio/net.mli b/lib_eio/net.mli index 86519633d..78761316f 100644 --- a/lib_eio/net.mli +++ b/lib_eio/net.mli @@ -167,6 +167,8 @@ val listen : The new socket will be closed when [sw] finishes, unless closed manually first. + On platforms that support this, passing port [0] will bind to a random port. + For (non-abstract) Unix domain sockets, the path will be removed afterwards. @param backlog The number of pending connections that can be queued up (see listen(2)). @@ -205,6 +207,8 @@ val accept_fork : [on_error] is not called for {!Cancel.Cancelled} exceptions, which do not need to be reported. *) +val listening_addr : [> 'tag listening_socket_ty] r -> Sockaddr.stream + (** {2 Running Servers} *) val run_server : @@ -327,6 +331,7 @@ module Pi : sig val accept : t -> sw:Switch.t -> tag stream_socket_ty r * Sockaddr.stream val close : t -> unit + val listening_addr : t -> Sockaddr.stream end val listening_socket : diff --git a/lib_eio_linux/eio_linux.ml b/lib_eio_linux/eio_linux.ml index b9018f010..3445da021 100644 --- a/lib_eio_linux/eio_linux.ml +++ b/lib_eio_linux/eio_linux.ml @@ -235,6 +235,11 @@ module Listening_socket = struct in let flow = (flow client :> _ Eio.Net.stream_socket) in flow, client_addr + + let listening_addr fd = + Eio_unix.Fd.use fd + (fun fd -> Eio_unix.Net.sockaddr_of_unix_stream (Unix.getsockname fd)) + ~if_closed:(fun () -> failwith "listening_addr: socket is closed") end let listening_handler = Eio_unix.Pi.listening_socket_handler (module Listening_socket) diff --git a/lib_eio_posix/net.ml b/lib_eio_posix/net.ml index 7fae5d19e..6b549accc 100644 --- a/lib_eio_posix/net.ml +++ b/lib_eio_posix/net.ml @@ -36,6 +36,11 @@ module Listening_socket = struct in let flow = (Flow.of_fd client :> _ Eio.Net.stream_socket) in flow, client_addr + + let listening_addr { fd; _ } = + Eio_unix.Fd.use fd + (fun fd -> Eio_unix.Net.sockaddr_of_unix_stream (Unix.getsockname fd)) + ~if_closed:(fun () -> failwith "listening_addr: socket is closed") end let listening_handler = Eio_unix.Pi.listening_socket_handler (module Listening_socket) diff --git a/lib_eio_windows/net.ml b/lib_eio_windows/net.ml index c2ce51e63..46171b094 100755 --- a/lib_eio_windows/net.ml +++ b/lib_eio_windows/net.ml @@ -36,6 +36,11 @@ module Listening_socket = struct in let flow = (Flow.of_fd client :> _ Eio.Net.stream_socket) in flow, client_addr + + let listening_addr fd = + Eio_unix.Fd.use fd + (fun fd -> Eio_unix.Net.sockaddr_of_unix_stream (Unix.getsockname fd)) + ~if_closed:(fun () -> failwith "listening_addr: socket is closed") end let listening_handler = Eio_unix.Pi.listening_socket_handler (module Listening_socket)