ClientList: convert to a class
This commit is contained in:
parent
1998633739
commit
601495fa0f
@ -222,7 +222,7 @@ src_mpd_SOURCES = \
|
|||||||
src/ClientEvent.cxx \
|
src/ClientEvent.cxx \
|
||||||
src/ClientExpire.cxx \
|
src/ClientExpire.cxx \
|
||||||
src/ClientGlobal.cxx \
|
src/ClientGlobal.cxx \
|
||||||
src/ClientIdle.cxx src/ClientIdle.hxx \
|
src/ClientIdle.cxx \
|
||||||
src/ClientList.cxx src/ClientList.hxx \
|
src/ClientList.cxx src/ClientList.hxx \
|
||||||
src/ClientNew.cxx \
|
src/ClientNew.cxx \
|
||||||
src/ClientProcess.cxx \
|
src/ClientProcess.cxx \
|
||||||
|
@ -31,7 +31,6 @@ struct Partition;
|
|||||||
class Client;
|
class Client;
|
||||||
|
|
||||||
void client_manager_init(void);
|
void client_manager_init(void);
|
||||||
void client_manager_deinit(void);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
client_new(EventLoop &loop, Partition &partition,
|
client_new(EventLoop &loop, Partition &partition,
|
||||||
|
@ -25,12 +25,9 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#define CLIENT_TIMEOUT_DEFAULT (60)
|
#define CLIENT_TIMEOUT_DEFAULT (60)
|
||||||
#define CLIENT_MAX_CONNECTIONS_DEFAULT (10)
|
|
||||||
#define CLIENT_MAX_COMMAND_LIST_DEFAULT (2048*1024)
|
#define CLIENT_MAX_COMMAND_LIST_DEFAULT (2048*1024)
|
||||||
#define CLIENT_MAX_OUTPUT_BUFFER_SIZE_DEFAULT (8192*1024)
|
#define CLIENT_MAX_OUTPUT_BUFFER_SIZE_DEFAULT (8192*1024)
|
||||||
|
|
||||||
/* set this to zero to indicate we have no possible clients */
|
|
||||||
unsigned int client_max_connections;
|
|
||||||
int client_timeout;
|
int client_timeout;
|
||||||
size_t client_max_command_list_size;
|
size_t client_max_command_list_size;
|
||||||
size_t client_max_output_buffer_size;
|
size_t client_max_output_buffer_size;
|
||||||
@ -39,9 +36,6 @@ void client_manager_init(void)
|
|||||||
{
|
{
|
||||||
client_timeout = config_get_positive(CONF_CONN_TIMEOUT,
|
client_timeout = config_get_positive(CONF_CONN_TIMEOUT,
|
||||||
CLIENT_TIMEOUT_DEFAULT);
|
CLIENT_TIMEOUT_DEFAULT);
|
||||||
client_max_connections =
|
|
||||||
config_get_positive(CONF_MAX_CONN,
|
|
||||||
CLIENT_MAX_CONNECTIONS_DEFAULT);
|
|
||||||
client_max_command_list_size =
|
client_max_command_list_size =
|
||||||
config_get_positive(CONF_MAX_COMMAND_LIST_SIZE,
|
config_get_positive(CONF_MAX_COMMAND_LIST_SIZE,
|
||||||
CLIENT_MAX_COMMAND_LIST_DEFAULT / 1024)
|
CLIENT_MAX_COMMAND_LIST_DEFAULT / 1024)
|
||||||
@ -52,10 +46,3 @@ void client_manager_init(void)
|
|||||||
CLIENT_MAX_OUTPUT_BUFFER_SIZE_DEFAULT / 1024)
|
CLIENT_MAX_OUTPUT_BUFFER_SIZE_DEFAULT / 1024)
|
||||||
* 1024;
|
* 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
void client_manager_deinit(void)
|
|
||||||
{
|
|
||||||
client_list_close_all();
|
|
||||||
|
|
||||||
client_max_connections = 0;
|
|
||||||
}
|
|
||||||
|
@ -18,9 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "ClientIdle.hxx"
|
|
||||||
#include "ClientInternal.hxx"
|
#include "ClientInternal.hxx"
|
||||||
#include "ClientList.hxx"
|
|
||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -58,21 +56,6 @@ Client::IdleAdd(unsigned flags)
|
|||||||
IdleNotify();
|
IdleNotify();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
client_idle_callback(Client *client, gpointer user_data)
|
|
||||||
{
|
|
||||||
unsigned flags = GPOINTER_TO_UINT(user_data);
|
|
||||||
|
|
||||||
client->IdleAdd(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
void client_manager_idle_add(unsigned flags)
|
|
||||||
{
|
|
||||||
assert(flags != 0);
|
|
||||||
|
|
||||||
client_list_foreach(client_idle_callback, GUINT_TO_POINTER(flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Client::IdleWait(unsigned flags)
|
Client::IdleWait(unsigned flags)
|
||||||
{
|
{
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2003-2013 The Music Player Daemon Project
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MPD_CLIENT_IDLE_HXX
|
|
||||||
#define MPD_CLIENT_IDLE_HXX
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the specified idle flags to all clients and immediately sends
|
|
||||||
* notifications to all waiting clients.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
client_manager_idle_add(unsigned flags);
|
|
||||||
|
|
||||||
#endif
|
|
@ -125,7 +125,6 @@ private:
|
|||||||
virtual bool OnTimeout() override;
|
virtual bool OnTimeout() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern unsigned int client_max_connections;
|
|
||||||
extern int client_timeout;
|
extern int client_timeout;
|
||||||
extern size_t client_max_command_list_size;
|
extern size_t client_max_command_list_size;
|
||||||
extern size_t client_max_output_buffer_size;
|
extern size_t client_max_output_buffer_size;
|
||||||
|
@ -21,51 +21,36 @@
|
|||||||
#include "ClientList.hxx"
|
#include "ClientList.hxx"
|
||||||
#include "ClientInternal.hxx"
|
#include "ClientInternal.hxx"
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
static std::list<Client *> clients;
|
void
|
||||||
static unsigned num_clients;
|
ClientList::Remove(Client &client)
|
||||||
|
|
||||||
bool
|
|
||||||
client_list_is_full(void)
|
|
||||||
{
|
{
|
||||||
return num_clients >= client_max_connections;
|
assert(size > 0);
|
||||||
|
assert(!list.empty());
|
||||||
|
|
||||||
|
auto i = std::find(list.begin(), list.end(), &client);
|
||||||
|
assert(i != list.end());
|
||||||
|
list.erase(i);
|
||||||
|
--size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
client_list_add(Client *client)
|
ClientList::CloseAll()
|
||||||
{
|
{
|
||||||
clients.push_front(client);
|
while (!list.empty())
|
||||||
++num_clients;
|
list.front()->Close();
|
||||||
|
|
||||||
|
assert(size == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
client_list_foreach(void (*callback)(Client *client, void *ctx), void *ctx)
|
ClientList::IdleAdd(unsigned flags)
|
||||||
{
|
{
|
||||||
for (Client *client : clients)
|
assert(flags != 0);
|
||||||
callback(client, ctx);
|
|
||||||
}
|
for (const auto &client : list)
|
||||||
|
client->IdleAdd(flags);
|
||||||
void
|
|
||||||
client_list_remove(Client *client)
|
|
||||||
{
|
|
||||||
assert(num_clients > 0);
|
|
||||||
assert(!clients.empty());
|
|
||||||
|
|
||||||
auto i = std::find(clients.begin(), clients.end(), client);
|
|
||||||
assert(i != clients.end());
|
|
||||||
clients.erase(i);
|
|
||||||
--num_clients;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
client_list_close_all()
|
|
||||||
{
|
|
||||||
while (!clients.empty())
|
|
||||||
clients.front()->Close();
|
|
||||||
|
|
||||||
assert(num_clients == 0);
|
|
||||||
}
|
}
|
||||||
|
@ -20,21 +20,42 @@
|
|||||||
#ifndef MPD_CLIENT_LIST_HXX
|
#ifndef MPD_CLIENT_LIST_HXX
|
||||||
#define MPD_CLIENT_LIST_HXX
|
#define MPD_CLIENT_LIST_HXX
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
class Client;
|
class Client;
|
||||||
|
|
||||||
bool
|
class ClientList {
|
||||||
client_list_is_full(void);
|
const unsigned max_size;
|
||||||
|
|
||||||
void
|
unsigned size;
|
||||||
client_list_add(Client *client);
|
std::list<Client *> list;
|
||||||
|
|
||||||
void
|
public:
|
||||||
client_list_foreach(void (*callback)(Client *client, void *ctx), void *ctx);
|
ClientList(unsigned _max_size)
|
||||||
|
:max_size(_max_size), size(0) {}
|
||||||
|
|
||||||
void
|
std::list<Client *>::iterator begin() {
|
||||||
client_list_remove(Client *client);
|
return list.begin();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
std::list<Client *>::iterator end() {
|
||||||
client_list_close_all();
|
return list.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFull() const {
|
||||||
|
return size >= max_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Add(Client &client) {
|
||||||
|
list.push_front(&client);
|
||||||
|
++size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Remove(Client &client);
|
||||||
|
|
||||||
|
void CloseAll();
|
||||||
|
|
||||||
|
void IdleAdd(unsigned flags);
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "ClientInternal.hxx"
|
#include "ClientInternal.hxx"
|
||||||
#include "ClientList.hxx"
|
#include "ClientList.hxx"
|
||||||
#include "Partition.hxx"
|
#include "Partition.hxx"
|
||||||
|
#include "Main.hxx"
|
||||||
#include "fd_util.h"
|
#include "fd_util.h"
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "resolver.h"
|
#include "resolver.h"
|
||||||
@ -95,7 +96,7 @@ client_new(EventLoop &loop, Partition &partition,
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_WRAP */
|
#endif /* HAVE_WRAP */
|
||||||
|
|
||||||
if (client_list_is_full()) {
|
if (client_list->IsFull()) {
|
||||||
g_warning("Max Connections Reached!");
|
g_warning("Max Connections Reached!");
|
||||||
close_socket(fd);
|
close_socket(fd);
|
||||||
return;
|
return;
|
||||||
@ -106,7 +107,7 @@ client_new(EventLoop &loop, Partition &partition,
|
|||||||
|
|
||||||
(void)send(fd, GREETING, sizeof(GREETING) - 1, 0);
|
(void)send(fd, GREETING, sizeof(GREETING) - 1, 0);
|
||||||
|
|
||||||
client_list_add(client);
|
client_list->Add(*client);
|
||||||
|
|
||||||
remote = sockaddr_to_string(sa, sa_length, NULL);
|
remote = sockaddr_to_string(sa, sa_length, NULL);
|
||||||
g_log(G_LOG_DOMAIN, LOG_LEVEL_SECURE,
|
g_log(G_LOG_DOMAIN, LOG_LEVEL_SECURE,
|
||||||
@ -117,7 +118,7 @@ client_new(EventLoop &loop, Partition &partition,
|
|||||||
void
|
void
|
||||||
Client::Close()
|
Client::Close()
|
||||||
{
|
{
|
||||||
client_list_remove(this);
|
client_list->Remove(*this);
|
||||||
|
|
||||||
SetExpired();
|
SetExpired();
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "ClientSubscribe.hxx"
|
#include "ClientSubscribe.hxx"
|
||||||
#include "ClientIdle.hxx"
|
|
||||||
#include "ClientInternal.hxx"
|
#include "ClientInternal.hxx"
|
||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
|
|
||||||
|
11
src/Main.cxx
11
src/Main.cxx
@ -31,8 +31,8 @@
|
|||||||
#include "DatabaseSimple.hxx"
|
#include "DatabaseSimple.hxx"
|
||||||
#include "Permission.hxx"
|
#include "Permission.hxx"
|
||||||
#include "Listen.hxx"
|
#include "Listen.hxx"
|
||||||
#include "ClientIdle.hxx"
|
|
||||||
#include "Client.hxx"
|
#include "Client.hxx"
|
||||||
|
#include "ClientList.hxx"
|
||||||
#include "AllCommands.hxx"
|
#include "AllCommands.hxx"
|
||||||
#include "Partition.hxx"
|
#include "Partition.hxx"
|
||||||
#include "Volume.hxx"
|
#include "Volume.hxx"
|
||||||
@ -99,6 +99,8 @@ enum {
|
|||||||
GThread *main_task;
|
GThread *main_task;
|
||||||
EventLoop *main_loop;
|
EventLoop *main_loop;
|
||||||
|
|
||||||
|
ClientList *client_list;
|
||||||
|
|
||||||
Partition *global_partition;
|
Partition *global_partition;
|
||||||
|
|
||||||
static StateFile *state_file;
|
static StateFile *state_file;
|
||||||
@ -330,7 +332,7 @@ idle_event_emitted(void)
|
|||||||
clients */
|
clients */
|
||||||
unsigned flags = idle_get();
|
unsigned flags = idle_get();
|
||||||
if (flags != 0)
|
if (flags != 0)
|
||||||
client_manager_idle_add(flags);
|
client_list->IdleAdd(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -401,6 +403,9 @@ int mpd_main(int argc, char *argv[])
|
|||||||
main_task = g_thread_self();
|
main_task = g_thread_self();
|
||||||
main_loop = new EventLoop(EventLoop::Default());
|
main_loop = new EventLoop(EventLoop::Default());
|
||||||
|
|
||||||
|
const unsigned max_clients = config_get_positive(CONF_MAX_CONN, 10);
|
||||||
|
client_list = new ClientList(max_clients);
|
||||||
|
|
||||||
success = listen_global_init(&error);
|
success = listen_global_init(&error);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
@ -532,8 +537,8 @@ int mpd_main(int argc, char *argv[])
|
|||||||
|
|
||||||
pc_kill(&global_partition->pc);
|
pc_kill(&global_partition->pc);
|
||||||
finishZeroconf();
|
finishZeroconf();
|
||||||
client_manager_deinit();
|
|
||||||
listen_global_finish();
|
listen_global_finish();
|
||||||
|
delete client_list;
|
||||||
|
|
||||||
start = clock();
|
start = clock();
|
||||||
DatabaseGlobalDeinit();
|
DatabaseGlobalDeinit();
|
||||||
|
@ -28,6 +28,8 @@ extern GThread *main_task;
|
|||||||
|
|
||||||
extern EventLoop *main_loop;
|
extern EventLoop *main_loop;
|
||||||
|
|
||||||
|
extern class ClientList *client_list;
|
||||||
|
|
||||||
extern struct Partition *global_partition;
|
extern struct Partition *global_partition;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "ClientSubscribe.hxx"
|
#include "ClientSubscribe.hxx"
|
||||||
#include "ClientInternal.hxx"
|
#include "ClientInternal.hxx"
|
||||||
#include "ClientList.hxx"
|
#include "ClientList.hxx"
|
||||||
|
#include "Main.hxx"
|
||||||
#include "protocol/Result.hxx"
|
#include "protocol/Result.hxx"
|
||||||
#include "protocol/ArgParser.hxx"
|
#include "protocol/ArgParser.hxx"
|
||||||
|
|
||||||
@ -73,31 +74,18 @@ handle_unsubscribe(Client *client, G_GNUC_UNUSED int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct channels_context {
|
|
||||||
std::set<std::string> channels;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
collect_channels(Client *client, gpointer user_data)
|
|
||||||
{
|
|
||||||
struct channels_context *context =
|
|
||||||
(struct channels_context *)user_data;
|
|
||||||
|
|
||||||
context->channels.insert(client->subscriptions.begin(),
|
|
||||||
client->subscriptions.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
enum command_return
|
enum command_return
|
||||||
handle_channels(Client *client,
|
handle_channels(Client *client,
|
||||||
G_GNUC_UNUSED int argc, G_GNUC_UNUSED char *argv[])
|
G_GNUC_UNUSED int argc, G_GNUC_UNUSED char *argv[])
|
||||||
{
|
{
|
||||||
assert(argc == 1);
|
assert(argc == 1);
|
||||||
|
|
||||||
struct channels_context context;
|
std::set<std::string> channels;
|
||||||
|
for (const auto &c : *client_list)
|
||||||
|
channels.insert(c->subscriptions.begin(),
|
||||||
|
c->subscriptions.end());
|
||||||
|
|
||||||
client_list_foreach(collect_channels, &context);
|
for (const auto &channel : channels)
|
||||||
|
|
||||||
for (const auto &channel : context.channels)
|
|
||||||
client_printf(client, "channel: %s\n", channel.c_str());
|
client_printf(client, "channel: %s\n", channel.c_str());
|
||||||
|
|
||||||
return COMMAND_RETURN_OK;
|
return COMMAND_RETURN_OK;
|
||||||
@ -120,27 +108,6 @@ handle_read_messages(Client *client,
|
|||||||
return COMMAND_RETURN_OK;
|
return COMMAND_RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct send_message_context {
|
|
||||||
ClientMessage msg;
|
|
||||||
|
|
||||||
bool sent;
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
send_message_context(T &&_channel, U &&_message)
|
|
||||||
:msg(std::forward<T>(_channel), std::forward<U>(_message)),
|
|
||||||
sent(false) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
send_message(Client *client, gpointer user_data)
|
|
||||||
{
|
|
||||||
struct send_message_context *context =
|
|
||||||
(struct send_message_context *)user_data;
|
|
||||||
|
|
||||||
if (client_push_message(client, context->msg))
|
|
||||||
context->sent = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum command_return
|
enum command_return
|
||||||
handle_send_message(Client *client,
|
handle_send_message(Client *client,
|
||||||
G_GNUC_UNUSED int argc, G_GNUC_UNUSED char *argv[])
|
G_GNUC_UNUSED int argc, G_GNUC_UNUSED char *argv[])
|
||||||
@ -153,11 +120,13 @@ handle_send_message(Client *client,
|
|||||||
return COMMAND_RETURN_ERROR;
|
return COMMAND_RETURN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct send_message_context context(argv[1], argv[2]);
|
bool sent = false;
|
||||||
|
const ClientMessage msg(argv[1], argv[2]);
|
||||||
|
for (const auto &c : *client_list)
|
||||||
|
if (client_push_message(c, msg))
|
||||||
|
sent = true;
|
||||||
|
|
||||||
client_list_foreach(send_message, &context);
|
if (sent)
|
||||||
|
|
||||||
if (context.sent)
|
|
||||||
return COMMAND_RETURN_OK;
|
return COMMAND_RETURN_OK;
|
||||||
else {
|
else {
|
||||||
command_error(client, ACK_ERROR_NO_EXIST,
|
command_error(client, ACK_ERROR_NO_EXIST,
|
||||||
|
Loading…
Reference in New Issue
Block a user