// Called when enough data was read into m_readbuf for a complete response message. 
    // Parse the response and forward it on to the response handler.
    void handle_tcp_response_received()
    {
        // No longer is there a pending read
        m_has_pending_tcp_read= false;

        // Parse the response buffer
        if (m_packed_response.unpack(m_response_read_buffer))
        {
            ResponsePtr response = m_packed_response.get_msg();

            if (response->request_id() != -1)
            {
                CLIENT_LOG_INFO("ClientNetworkManager::handle_tcp_response_received") 
                    << "Received response type " << response->type() << std::endl;
                m_response_listener->handle_response(response);
            }
            else
            {
                CLIENT_LOG_INFO("ClientNetworkManager::handle_tcp_response_received") 
                    << "Received notification type " << response->type() << std::endl;

                if (response->type() == PSMoveProtocol::Response_ResponseType_CONNECTION_INFO)
                {
                    // SPECIAL CASE: ConnectionInfo response sent at
                    handle_tcp_connection_info_notification(response);
                }
                else
                {
                    // Responses without a request ID are notifications
                    m_notification_listener->handle_notification(response);
                }
            }
        }
        else
        {
            CLIENT_LOG_ERROR("ClientNetworkManager::handle_tcp_response_received") 
                << "Error malformed response" << std::endl;
            stop();

            if (m_netEventListener)
            {
                //###bwalker $TODO pick a better error code that means "malformed data"
                m_netEventListener->handle_server_connection_socket_error(boost::asio::error::message_size);
            }
        }
    }
    void handle_tcp_connection_info_notification(ResponsePtr notification)
    {
        assert(notification->type() == PSMoveProtocol::Response_ResponseType_CONNECTION_INFO);

        // Remember the connection id
        m_tcp_connection_id= notification->result_connection_info().tcp_connection_id();
        
        CLIENT_LOG_INFO("ClientNetworkManager::handle_tcp_connection_info_notification") 
            << "Got connection_id: " << m_tcp_connection_id << std::endl;

        // Send the connection id back to the server over UDP
        // to establish a UDP connected and associate it with the TCP connection
        send_udp_connection_id();
    }