aboutsummaryrefslogtreecommitdiffstats
path: root/src/output/HttpdClient.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/output/HttpdClient.cxx71
1 files changed, 45 insertions, 26 deletions
diff --git a/src/output/HttpdClient.cxx b/src/output/HttpdClient.cxx
index 8e13fda38..102ce1ec3 100644
--- a/src/output/HttpdClient.cxx
+++ b/src/output/HttpdClient.cxx
@@ -37,24 +37,26 @@ HttpdClient::~HttpdClient()
if (current_page != nullptr)
current_page->Unref();
- for (auto page : pages)
- page->Unref();
+ ClearQueue();
}
if (metadata)
metadata->Unref();
+
+ if (IsDefined())
+ BufferedSocket::Close();
}
void
HttpdClient::Close()
{
- httpd->RemoveClient(*this);
+ httpd.RemoveClient(*this);
}
void
HttpdClient::LockClose()
{
- const ScopeLock protect(httpd->mutex);
+ const ScopeLock protect(httpd.mutex);
Close();
}
@@ -67,7 +69,7 @@ HttpdClient::BeginResponse()
current_page = nullptr;
if (!head_method)
- httpd->SendHeader(*this);
+ httpd.SendHeader(*this);
}
/**
@@ -155,13 +157,13 @@ HttpdClient::SendResponse()
"realTimeInfo.dlna.org: DLNA.ORG_TLAG=*\r\n"
"contentFeatures.dlna.org: DLNA.ORG_OP=01;DLNA.ORG_CI=0\r\n"
"\r\n",
- httpd->content_type);
+ httpd.content_type);
} else if (metadata_requested) {
char *metadata_header =
- icy_server_metadata_header(httpd->name, httpd->genre,
- httpd->website,
- httpd->content_type,
+ icy_server_metadata_header(httpd.name, httpd.genre,
+ httpd.website,
+ httpd.content_type,
metaint);
g_strlcpy(buffer, metadata_header, sizeof(buffer));
@@ -176,7 +178,7 @@ HttpdClient::SendResponse()
"Pragma: no-cache\r\n"
"Cache-Control: no-cache, no-store\r\n"
"\r\n",
- httpd->content_type);
+ httpd.content_type);
}
ssize_t nbytes = SocketMonitor::Write(buffer, strlen(buffer));
@@ -192,11 +194,12 @@ HttpdClient::SendResponse()
return true;
}
-HttpdClient::HttpdClient(HttpdOutput *_httpd, int _fd, EventLoop &_loop,
+HttpdClient::HttpdClient(HttpdOutput &_httpd, int _fd, EventLoop &_loop,
bool _metadata_supported)
:BufferedSocket(_fd, _loop),
httpd(_httpd),
state(REQUEST),
+ queue_size(0),
head_method(false),
dlna_streaming_requested(false),
metadata_supported(_metadata_supported),
@@ -207,16 +210,24 @@ HttpdClient::HttpdClient(HttpdOutput *_httpd, int _fd, EventLoop &_loop,
{
}
-size_t
-HttpdClient::GetQueueSize() const
+void
+HttpdClient::ClearQueue()
{
- if (state != RESPONSE)
- return 0;
+ assert(state == RESPONSE);
- size_t size = 0;
- for (auto page : pages)
- size += page->size;
- return size;
+ while (!pages.empty()) {
+ Page *page = pages.front();
+ pages.pop();
+
+#ifndef NDEBUG
+ assert(queue_size >= page->size);
+ queue_size -= page->size;
+#endif
+
+ page->Unref();
+ }
+
+ assert(queue_size == 0);
}
void
@@ -225,9 +236,7 @@ HttpdClient::CancelQueue()
if (state != RESPONSE)
return;
- for (auto page : pages)
- page->Unref();
- pages.clear();
+ ClearQueue();
if (current_page == nullptr)
CancelWrite();
@@ -262,7 +271,7 @@ HttpdClient::GetBytesTillMetaData() const
inline bool
HttpdClient::TryWrite()
{
- const ScopeLock protect(httpd->mutex);
+ const ScopeLock protect(httpd.mutex);
assert(state == RESPONSE);
@@ -270,14 +279,17 @@ HttpdClient::TryWrite()
if (pages.empty()) {
/* another thread has removed the event source
while this thread was waiting for
- httpd->mutex */
+ httpd.mutex */
CancelWrite();
return true;
}
current_page = pages.front();
- pages.pop_front();
+ pages.pop();
current_position = 0;
+
+ assert(queue_size >= current_page->size);
+ queue_size -= current_page->size;
}
const ssize_t bytes_to_write = GetBytesTillMetaData();
@@ -378,8 +390,15 @@ HttpdClient::PushPage(Page *page)
/* the client is still writing the HTTP request */
return;
+ if (queue_size > 256 * 1024) {
+ FormatDebug(httpd_output_domain,
+ "client is too slow, flushing its queue");
+ ClearQueue();
+ }
+
page->Ref();
- pages.push_back(page);
+ pages.push(page);
+ queue_size += page->size;
ScheduleWrite();
}