Make sure exceptions in connection open callback are thrown

This involves some ugliness to schedule the exception to be thrown so
it doesn't get swallowed by the promise machinery. (It may be worth
rewriting the connection handshake to use callbacks.)
Rewrite low-level API to use only callbacks

Because of the difficulty of raising exceptions from promises, it's
easier to base the promise API on a lower level that uses callbacks,
than vice versa.

A consequence is that only the promise API modules are dependent on a
promise library, which is cleaner.