websocket_demo: Re-work the client_state storage

Previously we had an array of n (10 in this case) struct client_state's.
This obviously puts a limit on the number of clients that can be handled
(true, probably not an issue for this demo, but we can do better without
too much effort) and increasing that number is likely to just lead to
memory wastage.

The other thing was that in handle_fd() we could end up looping through
this array three times.

What we do now is use a hash table to store the client_state structures
key'd of the socket file descriptor. We also have a hash table that
links client timer file descriptors to client socket file descriptors as
we can get both of those passed to handle_fd().

In handle_fd() we now do the following :-

    1) Lookup the client structure for the given fd, if we get a result
       we know we have a connected socket fd.
    2) If we didn't get a result, we lookup the fd in the
       timer_to_socket hash table, if we got a timer fd this should give
       the socket fd for that client which we lookup to get the
       client_state structure.
    3) If we still have no client_state structure, then we know we have
       a new client and can do the initial handshake and client_state
       initialisation.

While none of this really matters for this demo app, it is at least a
better way of doing things and provides a more solid base for doing
future work.

Signed-off-by: Andrew Clayton <andrew@digital-domain.net>
websocket_demo: Cleanup handle_fd()

handle_fd was starting to look a little chaotic. Split out the handling
of new clients, existing connections, timer expirations and connection
closing to their own functions.

Signed-off-by: Andrew Clayton <andrew@digital-domain.net>