Skip to content

Commit

Permalink
ensure timer preallocation counts timers used by filters
Browse files Browse the repository at this point in the history
  • Loading branch information
jkarneges committed Feb 6, 2025
1 parent 3167ddb commit e3e0cf1
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 11 deletions.
2 changes: 2 additions & 0 deletions src/handler/filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,8 @@ Filter::Targets Filter::targets(const QString &name)

Filter::MessageFilterStack::MessageFilterStack(const QStringList &filterNames)
{
assert(filterNames.count() <= MESSAGEFILTERSTACK_SIZE_MAX);

foreach(const QString &name, filterNames)
{
MessageFilter *f = createMessageFilter(name);
Expand Down
5 changes: 5 additions & 0 deletions src/handler/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
#include <QUrl>
#include <boost/signals2.hpp>

#define MESSAGEFILTERSTACK_SIZE_MAX 5

// 2 timers per zhttprequest
#define TIMERS_PER_MESSAGEFILTERSTACK (2 * MESSAGEFILTERSTACK_SIZE_MAX)

class ZhttpManager;

class Filter
Expand Down
20 changes: 11 additions & 9 deletions src/handler/handlerengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,6 @@
#define INSPECT_WORKERS_MAX 10
#define ACCEPT_WORKERS_MAX 10

// each session can have a bunch of timers:
// 2 per incoming zhttprequest
// 2 per outgoing zhttprequest
// 2 per httpsession
#define TIMERS_PER_SESSION 10

using namespace VariantUtil;

static QList<PublishItem> parseItems(const QVariantList &vitems, bool *ok = 0, QString *errorMessage = 0)
Expand Down Expand Up @@ -1337,8 +1331,10 @@ class HandlerEngine::Private : public QObject
{
config = _config;

int timersPerSession = qMax(TIMERS_PER_HTTPSESSION, TIMERS_PER_WSSESSION);

// enough timers for sessions, plus an extra 100 for misc
RTimer::init((config.connectionsMax * TIMERS_PER_SESSION) + 100);
RTimer::init((config.connectionsMax * timersPerSession) + 100);

publishLimiter->setRate(config.messageRate);
publishLimiter->setHwm(config.messageHwm);
Expand Down Expand Up @@ -2666,7 +2662,7 @@ class HandlerEngine::Private : public QObject
if(e.error != QJsonParseError::NoError || (!doc.isObject() && !doc.isArray()))
{
log_debug("grip control message is not valid json");
return;
continue;
}

if(doc.isObject())
Expand All @@ -2679,13 +2675,19 @@ class HandlerEngine::Private : public QObject
if(!ok)
{
log_debug("failed to parse grip control message: %s", qPrintable(errorMessage));
return;
continue;
}

if(cm.type == WsControlMessage::Subscribe)
{
if(s->channels.count() < config.connectionSubscriptionMax)
{
if(cm.filters.count() > MESSAGEFILTERSTACK_SIZE_MAX)
{
s->sendCloseError(QString("too many filters for channel '%1'").arg(cm.channel));
continue;
}

QString channel = s->channelPrefix + cm.channel;
s->channels += channel;
s->channelFilters[channel] = cm.filters;
Expand Down
8 changes: 8 additions & 0 deletions src/handler/httpsession.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,16 @@
#include "inspectdata.h"
#include "zhttprequest.h"
#include "instruct.h"
#include "filter.h"
#include <boost/signals2.hpp>

// each session can have a bunch of timers:
// 2 per incoming zhttprequest
// 2 per outgoing zhttprequest
// 2 additional timers
// filter timers
#define TIMERS_PER_HTTPSESSION (10 + TIMERS_PER_MESSAGEFILTERSTACK)

using Connection = boost::signals2::scoped_connection;

class QTimer;
Expand Down
7 changes: 7 additions & 0 deletions src/handler/instruct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "qtcompat.h"
#include "variantutil.h"
#include "statusreasons.h"
#include "filter.h"

#define DEFAULT_RESPONSE_TIMEOUT 55
#define MINIMUM_RESPONSE_TIMEOUT 5
Expand Down Expand Up @@ -147,6 +148,12 @@ Instruct Instruct::fromResponse(const HttpResponseData &response, bool *ok, QStr
c.filters += QString::fromUtf8(param.second);
}

if(c.filters.count() > MESSAGEFILTERSTACK_SIZE_MAX)
{
setError(ok, errorMessage, QString("too many filters for channel '%1'").arg(c.name));
return Instruct();
}

channels += c;
}

Expand Down
4 changes: 3 additions & 1 deletion src/handler/wssession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,9 @@ void WsSession::sendCloseError(const QString &message)
i.cid = cid.toUtf8();
i.type = WsControlPacket::Item::Close;
i.code = 1011;
i.reason = message.toUtf8();

if(debug)
i.reason = message.toUtf8();

send(i);
}
Expand Down
6 changes: 5 additions & 1 deletion src/handler/wssession.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
#include "filter.h"
#include <boost/signals2.hpp>

// each session can have a bunch of timers:
// filter timers
#define TIMERS_PER_WSSESSION (0 + TIMERS_PER_MESSAGEFILTERSTACK)

using Signal = boost::signals2::signal<void()>;
using Connection = boost::signals2::scoped_connection;

Expand Down Expand Up @@ -84,6 +88,7 @@ class WsSession : public QObject
void sendDelayed(const QByteArray &type, const QByteArray &message, int timeout);
void ack(int reqId);
void publish(const PublishItem &item);
void sendCloseError(const QString &message);

boost::signals2::signal<void(const WsControlPacket::Item&)> send;
Signal expired;
Expand All @@ -93,7 +98,6 @@ class WsSession : public QObject
void processPublishQueue();
void filtersFinished(const Filter::MessageFilter::Result &result);
void afterFilters(const PublishItem &item, Filter::SendAction sendAction, const QByteArray &content);
void sendCloseError(const QString &message);
void setupRequestTimer();

private slots:
Expand Down

0 comments on commit e3e0cf1

Please sign in to comment.