CommandError.cxx 2.8 KB
Newer Older
1
/*
2
 * Copyright 2003-2018 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * http://www.musicpd.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "config.h"
21
#include "CommandError.hxx"
22
#include "PlaylistError.hxx"
Max Kellermann's avatar
Max Kellermann committed
23
#include "db/DatabaseError.hxx"
24
#include "client/Response.hxx"
25
#include "Log.hxx"
26
#include "util/Exception.hxx"
27

28 29
#include <system_error>

30 31
#include <assert.h>

32 33
gcc_const
static enum ack
34
ToAck(PlaylistResult result) noexcept
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
{
	switch (result) {
	case PlaylistResult::SUCCESS:
		break;

	case PlaylistResult::DENIED:
		return ACK_ERROR_PERMISSION;

	case PlaylistResult::NO_SUCH_SONG:
	case PlaylistResult::NO_SUCH_LIST:
		return ACK_ERROR_NO_EXIST;

	case PlaylistResult::LIST_EXISTS:
		return ACK_ERROR_EXIST;

	case PlaylistResult::BAD_NAME:
	case PlaylistResult::BAD_RANGE:
		return ACK_ERROR_ARG;

	case PlaylistResult::NOT_PLAYING:
		return ACK_ERROR_PLAYER_SYNC;

	case PlaylistResult::TOO_LARGE:
		return ACK_ERROR_PLAYLIST_MAX;

	case PlaylistResult::DISABLED:
		break;
	}

	return ACK_ERROR_UNKNOWN;
}

67 68 69
#ifdef ENABLE_DATABASE
gcc_const
static enum ack
70
ToAck(DatabaseErrorCode code) noexcept
71 72 73 74 75 76 77 78 79 80 81 82 83 84
{
	switch (code) {
	case DatabaseErrorCode::DISABLED:
	case DatabaseErrorCode::NOT_FOUND:
		return ACK_ERROR_NO_EXIST;

	case DatabaseErrorCode::CONFLICT:
		return ACK_ERROR_ARG;
	}

	return ACK_ERROR_UNKNOWN;
}
#endif

85 86
gcc_pure
static enum ack
87
ToAck(std::exception_ptr ep) noexcept
88 89 90 91 92 93 94
{
	try {
		std::rethrow_exception(ep);
	} catch (const ProtocolError &pe) {
		return pe.GetCode();
	} catch (const PlaylistError &pe) {
		return ToAck(pe.GetCode());
95 96 97 98
#ifdef ENABLE_DATABASE
	} catch (const DatabaseError &de) {
		return ToAck(de.GetCode());
#endif
99 100
	} catch (const std::system_error &e) {
		return ACK_ERROR_SYSTEM;
101 102
	} catch (const std::invalid_argument &e) {
		return ACK_ERROR_ARG;
103 104 105 106
	} catch (const std::length_error &e) {
		return ACK_ERROR_ARG;
	} catch (const std::out_of_range &e) {
		return ACK_ERROR_ARG;
107
	} catch (...) {
108 109 110 111 112 113
		try {
			std::rethrow_if_nested(ep);
			return ACK_ERROR_UNKNOWN;
		} catch (...) {
			return ToAck(std::current_exception());
		}
114 115 116
	}
}

117
void
118
PrintError(Response &r, std::exception_ptr ep)
119
{
120
	LogError(ep);
121
	r.Error(ToAck(ep), GetFullMessage(ep).c_str());
122
}