What is the best way to use coroutines for asynchronous messaging?


I am currently moving some of my Java libraries for slow control of devices to Kotlin and I wonder, how can I use coroutines for that?
I have some class, say PortController which have a method acceptMessage which is fired asynchronously when something drops into the port. This class could be attached to different kind of ports and works as a listener. Also I can send messages to the port. Now I have two separate yet similar use cases:

  1. I want to be able to perform synchronous operations like send message, wait at most for some duration and return the response if it is present and throw an exception if it is not.
  2. I want a lazy sequence of all responses to use it in a reactive way.

Previously, I was doing all of that via creating new CompletableFuture for each response request. If I understand correctly, coroutines use CompletableFutures under the hood and there probably is a solution which will do the same but in much more compact way. Any suggestions?