Port internal handshake API to make use of async/await
The handshake code was written for non-blocking synchronous API and hence it's a bit hairy. Now that we don't need that, this code can be made much simpler through the use of async/await and async-io.