aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2013-01-16 21:39:40 +0100
committerMax Kellermann <max@duempel.org>2013-01-16 21:51:08 +0100
commitb0bbb8b693d846c2710ec84bfa79dcaa3a21729a (patch)
tree43cba39160446e9379c188ebb23eae5633de4ea7
parentcab84af72e373acca0e88d9b407aa97796c083e0 (diff)
downloadmpd-b0bbb8b693d846c2710ec84bfa79dcaa3a21729a.tar.gz
mpd-b0bbb8b693d846c2710ec84bfa79dcaa3a21729a.tar.xz
mpd-b0bbb8b693d846c2710ec84bfa79dcaa3a21729a.zip
Client: use TimeoutMonitor to track connection timeout
Don't use a global loop over the whole client list.
-rw-r--r--src/ClientExpire.cxx53
-rw-r--r--src/ClientGlobal.cxx2
-rw-r--r--src/ClientIdle.cxx8
-rw-r--r--src/ClientInternal.hxx25
-rw-r--r--src/ClientNew.cxx8
-rw-r--r--src/ClientRead.cxx4
6 files changed, 22 insertions, 78 deletions
diff --git a/src/ClientExpire.cxx b/src/ClientExpire.cxx
index 56b003df8..8f57f5b3e 100644
--- a/src/ClientExpire.cxx
+++ b/src/ClientExpire.cxx
@@ -19,9 +19,6 @@
#include "config.h"
#include "ClientInternal.hxx"
-#include "ClientList.hxx"
-
-static guint expire_source_id;
void
Client::SetExpired()
@@ -29,54 +26,18 @@ Client::SetExpired()
if (IsExpired())
return;
- client_schedule_expire();
BufferedSocket::Close();
+ TimeoutMonitor::Schedule(0);
}
-static void
-client_check_expired_callback(Client *client, G_GNUC_UNUSED gpointer user_data)
+bool
+Client::OnTimeout()
{
- if (client->IsExpired()) {
- g_debug("[%u] expired", client->num);
- client->Close();
- } else if (!client->idle_waiting && /* idle clients
- never expire */
- (int)g_timer_elapsed(client->last_activity, NULL) >
- client_timeout) {
- g_debug("[%u] timeout", client->num);
- client->Close();
+ if (!IsExpired()) {
+ assert(!idle_waiting);
+ g_debug("[%u] timeout", num);
}
-}
-
-static void
-client_manager_expire(void)
-{
- client_list_foreach(client_check_expired_callback, NULL);
-}
-/**
- * An idle event which calls client_manager_expire().
- */
-static gboolean
-client_manager_expire_event(G_GNUC_UNUSED gpointer data)
-{
- expire_source_id = 0;
- client_manager_expire();
+ Close();
return false;
}
-
-void
-client_schedule_expire(void)
-{
- if (expire_source_id == 0)
- /* delayed deletion */
- expire_source_id = g_idle_add(client_manager_expire_event,
- NULL);
-}
-
-void
-client_deinit_expire(void)
-{
- if (expire_source_id != 0)
- g_source_remove(expire_source_id);
-}
diff --git a/src/ClientGlobal.cxx b/src/ClientGlobal.cxx
index 1aa82b435..47179b53d 100644
--- a/src/ClientGlobal.cxx
+++ b/src/ClientGlobal.cxx
@@ -69,6 +69,4 @@ void client_manager_deinit(void)
client_close_all();
client_max_connections = 0;
-
- client_deinit_expire();
}
diff --git a/src/ClientIdle.cxx b/src/ClientIdle.cxx
index b440a8260..89cb10aa1 100644
--- a/src/ClientIdle.cxx
+++ b/src/ClientIdle.cxx
@@ -43,7 +43,8 @@ Client::IdleNotify()
}
client_puts(this, "OK\n");
- g_timer_start(last_activity);
+
+ TimeoutMonitor::ScheduleSeconds(client_timeout);
}
void
@@ -83,6 +84,9 @@ Client::IdleWait(unsigned flags)
if (idle_flags & idle_subscriptions) {
IdleNotify();
return true;
- } else
+ } else {
+ /* disable timeouts while in "idle" */
+ TimeoutMonitor::Cancel();
return false;
+ }
}
diff --git a/src/ClientInternal.hxx b/src/ClientInternal.hxx
index 9384b84ee..097029f0b 100644
--- a/src/ClientInternal.hxx
+++ b/src/ClientInternal.hxx
@@ -25,6 +25,7 @@
#include "ClientMessage.hxx"
#include "CommandListBuilder.hxx"
#include "event/BufferedSocket.hxx"
+#include "event/TimeoutMonitor.hxx"
#include "command.h"
#include <set>
@@ -43,7 +44,7 @@ enum {
struct Partition;
-class Client final : private BufferedSocket {
+class Client final : private BufferedSocket, TimeoutMonitor {
public:
Partition &partition;
struct playlist &playlist;
@@ -54,11 +55,6 @@ public:
/** the uid of the client process, or -1 if unknown */
int uid;
- /**
- * How long since the last activity from this client?
- */
- GTimer *last_activity;
-
CommandListBuilder cmd_list;
unsigned int num; /* client number */
@@ -91,7 +87,6 @@ public:
Client(EventLoop &loop, Partition &partition,
int fd, int uid, int num);
- ~Client();
bool IsConnected() const {
return BufferedSocket::IsDefined();
@@ -125,6 +120,9 @@ private:
size_t length) override;
virtual void OnSocketError(GError *error) override;
virtual void OnSocketClosed() override;
+
+ /* virtual methods from class TimeoutMonitor */
+ virtual bool OnTimeout() override;
};
extern unsigned int client_max_connections;
@@ -132,19 +130,6 @@ extern int client_timeout;
extern size_t client_max_command_list_size;
extern size_t client_max_output_buffer_size;
-/**
- * Schedule an "expired" check for all clients: permanently delete
- * clients which have been set "expired" with client_set_expired().
- */
-void
-client_schedule_expire(void);
-
-/**
- * Removes a scheduled "expired" check.
- */
-void
-client_deinit_expire(void);
-
enum command_return
client_read(Client *client);
diff --git a/src/ClientNew.cxx b/src/ClientNew.cxx
index 42cc3470d..2a4774c55 100644
--- a/src/ClientNew.cxx
+++ b/src/ClientNew.cxx
@@ -49,20 +49,16 @@ static const char GREETING[] = "OK MPD " PROTOCOL_VERSION "\n";
Client::Client(EventLoop &_loop, Partition &_partition,
int _fd, int _uid, int _num)
:BufferedSocket(_fd, _loop, 16384, client_max_output_buffer_size),
+ TimeoutMonitor(_loop),
partition(_partition),
playlist(partition.playlist), player_control(&partition.pc),
permission(getDefaultPermissions()),
uid(_uid),
- last_activity(g_timer_new()),
num(_num),
idle_waiting(false), idle_flags(0),
num_subscriptions(0)
{
-}
-
-Client::~Client()
-{
- g_timer_destroy(last_activity);
+ TimeoutMonitor::ScheduleSeconds(client_timeout);
}
void
diff --git a/src/ClientRead.cxx b/src/ClientRead.cxx
index 363363d1f..49c698bc1 100644
--- a/src/ClientRead.cxx
+++ b/src/ClientRead.cxx
@@ -28,13 +28,13 @@
BufferedSocket::InputResult
Client::OnSocketInput(const void *data, size_t length)
{
- g_timer_start(last_activity);
-
const char *p = (const char *)data;
const char *newline = (const char *)memchr(p, '\n', length);
if (newline == NULL)
return InputResult::MORE;
+ TimeoutMonitor::ScheduleSeconds(client_timeout);
+
char *line = g_strndup(p, newline - p);
BufferedSocket::ConsumeInput(newline + 1 - p);