ClientProcess.cxx 3.9 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2013 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 * 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.
 */

20
#include "config.h"
Max Kellermann's avatar
Max Kellermann committed
21 22
#include "ClientInternal.hxx"
#include "protocol/Result.hxx"
23
#include "command/AllCommands.hxx"
24
#include "Log.hxx"
25 26 27 28 29 30 31

#include <string.h>

#define CLIENT_LIST_MODE_BEGIN "command_list_begin"
#define CLIENT_LIST_OK_MODE_BEGIN "command_list_ok_begin"
#define CLIENT_LIST_MODE_END "command_list_end"

32
static CommandResult
33
client_process_command_list(Client &client, bool list_ok,
34
			    std::list<std::string> &&list)
35
{
36
	CommandResult ret = CommandResult::OK;
37 38
	unsigned num = 0;

39 40
	for (auto &&i : list) {
		char *cmd = &*i.begin();
41

42
		FormatDebug(client_domain, "process command \"%s\"", cmd);
43
		ret = command_process(client, num++, cmd);
44
		FormatDebug(client_domain, "command returned %i", ret);
45
		if (ret != CommandResult::OK || client.IsExpired())
46 47 48 49 50 51 52 53
			break;
		else if (list_ok)
			client_puts(client, "list_OK\n");
	}

	return ret;
}

54
CommandResult
55
client_process_line(Client &client, char *line)
56
{
57
	CommandResult ret;
58 59

	if (strcmp(line, "noidle") == 0) {
60
		if (client.idle_waiting) {
61
			/* send empty idle response and leave idle mode */
62
			client.idle_waiting = false;
63 64 65 66 67 68 69
			command_success(client);
		}

		/* do nothing if the client wasn't idling: the client
		   has already received the full idle response from
		   client_idle_notify(), which he can now evaluate */

70
		return CommandResult::OK;
71
	} else if (client.idle_waiting) {
72 73
		/* during idle mode, clients must not send anything
		   except "noidle" */
74 75
		FormatWarning(client_domain,
			      "[%u] command \"%s\" during idle",
76
			      client.num, line);
77
		return CommandResult::CLOSE;
78 79
	}

80
	if (client.cmd_list.IsActive()) {
81
		if (strcmp(line, CLIENT_LIST_MODE_END) == 0) {
82 83
			FormatDebug(client_domain,
				    "[%u] process command list",
84
				    client.num);
85

86
			auto &&cmd_list = client.cmd_list.Commit();
87

88
			ret = client_process_command_list(client,
89
							  client.cmd_list.IsOKMode(),
90
							  std::move(cmd_list));
91 92
			FormatDebug(client_domain,
				    "[%u] process command "
93
				    "list returned %i", client.num, ret);
94

95
			if (ret == CommandResult::CLOSE ||
96
			    client.IsExpired())
97
				return CommandResult::CLOSE;
98

99
			if (ret == CommandResult::OK)
100 101
				command_success(client);

102
			client.cmd_list.Reset();
103
		} else {
104
			if (!client.cmd_list.Add(line)) {
105 106 107
				FormatWarning(client_domain,
					      "[%u] command list size "
					      "is larger than the max (%lu)",
108
					      client.num,
109
					      (unsigned long)client_max_command_list_size);
110
				return CommandResult::CLOSE;
111 112
			}

113
			ret = CommandResult::OK;
114 115 116
		}
	} else {
		if (strcmp(line, CLIENT_LIST_MODE_BEGIN) == 0) {
117
			client.cmd_list.Begin(false);
118
			ret = CommandResult::OK;
119
		} else if (strcmp(line, CLIENT_LIST_OK_MODE_BEGIN) == 0) {
120
			client.cmd_list.Begin(true);
121
			ret = CommandResult::OK;
122
		} else {
123 124
			FormatDebug(client_domain,
				    "[%u] process command \"%s\"",
125
				    client.num, line);
126
			ret = command_process(client, 0, line);
127 128
			FormatDebug(client_domain,
				    "[%u] command returned %i",
129
				    client.num, ret);
130

131
			if (ret == CommandResult::CLOSE ||
132
			    client.IsExpired())
133
				return CommandResult::CLOSE;
134

135
			if (ret == CommandResult::OK)
136 137 138 139 140 141
				command_success(client);
		}
	}

	return ret;
}