Fix #233: Refactor server logic for websockets and sync

This patch does a number of things, mostly aimed at being more careful about error states, and not causing, or avoiding, crashes.

A few things to note:
* I've moved away from `on('event')` to `onevent` so that I can safely manage a single listener at all times.  This makes it easier to reason about what is going to get triggered when.
* I've moved to always using `data.data` for `onmessage(data, flags)` since node also requires it.  We should confirm this works OK when the client is a browser.
* I've added more cases where we send back error SyncMessages to the client when things go wrong (e.g., invalid data)
* I've stopped using `socket.send` everywhere, and instead introduced `sync.sendMessage` which manages access to the ws instance, and makes sure we don't throw.  If we do, I emit an error so that we can deal with it (i.e., we shutdown the client cleanly now vs. crashing)
* I've added logic for dealing with the wss (server) erroring, where we now try to restart it, and if we can't, we bring down the server safely.
* I've added some new Sync states to reflect errors and the sync being terminated.
* I've streamlined a few users of `updateLastContact` since we were calling it multiple times in the same code path, which isn't necessary.

I've made various other code improvements as well, but the diff will show those better.  I spent a bunch of time reading https://github.com/einaros/ws/blob/master/lib/WebSocket.js and https://github.com/einaros/ws/blob/master/lib/WebSocketServer.js closely to make sure we are following what it actually does in terms of errors, states, events, etc.