made more generic so that users can specify handshake protocol and specify their own state machines for handling responses