`Worker.Hello()`: Fix a `forceReset` regression.

As of #65, `{Emcee, No}Store.Exists()` correctly returns `false` if a
device ID has not previously registered with the push server. This
change caused `Worker.Hello()` to reset all client-specified IDs.

The client will now be assigned a new ID under the following
conditions:

* An explicit ID is not specified (i.e., the `"uaid"` field is `""` or
  omitted entirely).
* A client with the specified ID is already connected.
* The number of channels in the opening handshake exceeds the number of
  subscriptions allowed by the backing store.
* The client specifies existing channels for a nonexistent ID.
Replace `JsMap`s with structs where possible.
Handlers: Clean up client count checks.

* Use `app.ClientCount() >= max_connections` for all checks.
* Remove redundant type conversions.
* Fix a typo in `RealStatusHandler` that caused the handler to
  erroneously report the server as unhealthy.
Handlers: Clean up key validation.

* Replace the `filter` RegExp with `validPK()`.
* Consolidate map lookups and type assertions in
  `Handler.RouteHandler()` and `GCMPing.Register()`.
* Remove `proxyNotification()`.
`GCMPing`: Re-use `http.Client` instances.
Add a `CommandType` type.
Send the correct `Content-Type` for JSON replies.
Clean up conditionals.
Worker: Remove unused `wg` field.
Change the `Store.{Fetch, Put}Ping()` signatures.

`{Fetch, Put}Ping()` now accepts and returns byte slices instead of
strings. This allows proprietary ping plug-ins to define custom
serialization formats.
Config: Load proprietary pings after storage.
Refactor `GCMPing`.

* Change the `PropPinger.Register()` signature to `(uaid string,
  pingData []byte)`, where `pingData` contains opaque ping data sent by
  the client.
* Change the `PropPinger.Send()` signature to `(uaid string,
  vers int64)`. The proprietary ping plugin is now responsible for
  retrieving the ping data from the backing store. This simplifies the
  logic in `Handler.UpdateHandler()` and `Serv.Hello()`.
* `PropPinger.Send()` now returns `(ok bool, err error)`. The plugin
  should return `false, nil` if the request succeeded, but the device
  could not be woken up. `UpdateHandler()` will then send the message
  over the WebSocket.
* Fix `GCMPing.Register()` so that it no longer stores request-specific
  device and registration IDs in `GCMPing.config`. Since pingers are
  created per application (rather than per client), the previous
  behavior would cause GCM requests to stomp on one another.

The refactored `GCMPing` has been tested with GCM for Chrome, using the
"GCM Notifications" app to generate registration IDs.
Expand `TestHeloInvalidIds()`.
Use named struct fields. Add `make vet`.
`RouteHandler()`: Decode payloads into `Routable`.

Remove `Routable.DeviceID`; the device ID is specified in the URL.
Merge pull request #79 from mozilla-services/feature/nits

Miscellaneous nits
Merge pull request #80 from mozilla-services/bug/force-reset

Fix a `forceReset` regression
Merge pull request #81 from mozilla-services/feature/pinger

Refactor proprietary pingers
Merging #81.
Clarify log levels. Closes #39.

* Critical: Logs fatal errors that prevented the server from starting
  (e.g., missing or invalid configs), or caused the server to stop
  prematurely.
* Error: Logs errors that were fatal for a particular request, and may
  affect other requests (e.g., memcached connection errors, discovery
  service unavailable, bad data returned from database).
* Warning: Logs errors affecting individual requests (e.g., bad data
  sent by the client or app server). The push server can respond
  normally to other requests.
* Info: Normal service operation.
* Debug: Verbose debugging output.

Logger calls that may incur overhead (such as function calls) are now
wrapped in `Logger.ShouldLog()` checks. This check is omitted if the log
fields contain simple string values, since `Logger.Log()` calls
`Logger.ShouldLog()` internally.