Add integration tests, decent amount of refactoring

Start doing some integration tests by spinning up an http server in the tests.

A bunch of refactoring/changes fell out of this:

- extracted error handling into a new file
- made cycling hostnames threadsafe
- make it possible to pass `nil` as additional info to many of the functions in `yeller.go`