ActionResponse Service::onAction(const std::string& action, const xml::Document& doc)
{
    try
    {
        ActionResponse response(action, ServiceType::ConnectionManager);
        auto request = doc.getFirstChild();
    
        switch (actionFromString(action))
        {
        case Action::GetProtocolInfo:
            response.addArgument("Source",               getVariable(Variable::SourceProtocolInfo).getValue());
            response.addArgument("Sink",                 getVariable(Variable::SinkProtocolInfo).getValue());
            break;
        case Action::PrepareForConnection:
        {
            ConnectionInfo connInfo;
            connInfo.peerConnectionManager  = request.getChildNodeValue("PeerConnectionManager");
            connInfo.peerConnectionId       = std::stoi(request.getChildNodeValue("PeerConnectionID"));
            connInfo.direction              = directionFromString(request.getChildNodeValue("Direction"));
            
            ProtocolInfo protoInfo(request.getChildNodeValue("RemoteProtocolInfo"));;
            m_connectionManager.prepareForConnection(protoInfo, connInfo);
        
            response.addArgument("ConnectionID",         std::to_string(connInfo.connectionId));
            response.addArgument("AVTransportID",        std::to_string(connInfo.avTransportId));
            response.addArgument("RcsID",                std::to_string(connInfo.renderingControlServiceId));
            break;
        }
        case Action::ConnectionComplete:
            m_connectionManager.connectionComplete(std::stoi(request.getChildNodeValue("ConnectionID")));
            break;
        case Action::GetCurrentConnectionIDs:
            response.addArgument("ConnectionIDs",        getVariable(Variable::CurrentConnectionIds).getValue());
            break;
        case Action::GetCurrentConnectionInfo:
        {
            auto connInfo = m_connectionManager.getCurrentConnectionInfo(std::stoi(request.getChildNodeValue("ConnectionID")));
            response.addArgument("RcsID",                   std::to_string(connInfo.renderingControlServiceId));
            response.addArgument("AVTransportID",           std::to_string(connInfo.avTransportId));
            response.addArgument("ProtocolInfo",            connInfo.protocolInfo.toString());
            response.addArgument("PeerConnectionManager",   connInfo.peerConnectionManager);
            response.addArgument("PeerConnectionID",        std::to_string(connInfo.peerConnectionId));
            response.addArgument("Direction",               toString(connInfo.direction));
            response.addArgument("Status",                  toString(connInfo.connectionStatus));
            break;
        }
        default:
            throw InvalidActionException();
        }
        
        return response;
    }
    catch (std::exception& e)
    {
        log::error("Error processing ConnectionManager request: %s", e.what());
        throw InvalidActionException();
    }
}