Added maxconnsperip setting to controller. Only enforced if USER_NEW trigger is in use.
This commit is contained in:
parent
219e326048
commit
f641989991
4 changed files with 29 additions and 3 deletions
|
@ -322,7 +322,7 @@ bool Util::startInput(std::string streamname, std::string filename, bool forkFir
|
||||||
/// Attempt to start a push for streamname to target.
|
/// Attempt to start a push for streamname to target.
|
||||||
/// Both streamname and target may be changed by this function:
|
/// Both streamname and target may be changed by this function:
|
||||||
/// - streamname is sanitized to a permissible streamname
|
/// - streamname is sanitized to a permissible streamname
|
||||||
/// - target gets variables replaced and may be altered by the RECORDING_START trigger response.
|
/// - target gets variables replaced and may be altered by the PUSH_OUT_START trigger response.
|
||||||
/// Attempts to match the altered target to an output that can push to it.
|
/// Attempts to match the altered target to an output that can push to it.
|
||||||
pid_t Util::startPush(std::string & streamname, std::string & target) {
|
pid_t Util::startPush(std::string & streamname, std::string & target) {
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,7 @@ int main(int argc, char ** argv){
|
||||||
Controller::conf.addOption("port", stored_port);
|
Controller::conf.addOption("port", stored_port);
|
||||||
Controller::conf.addOption("interface", stored_interface);
|
Controller::conf.addOption("interface", stored_interface);
|
||||||
Controller::conf.addOption("username", stored_user);
|
Controller::conf.addOption("username", stored_user);
|
||||||
|
Controller::conf.addOption("maxconnsperip", JSON::fromString("{\"long\":\"maxconnsperip\", \"short\":\"M\", \"arg\":\"integer\" \"default\":0, \"help\":\"Max simultaneous sessions per unique IP address. Only enforced if the USER_NEW trigger is in use.\"}"));
|
||||||
Controller::conf.addOption("account", JSON::fromString("{\"long\":\"account\", \"short\":\"a\", \"arg\":\"string\" \"default\":\"\", \"help\":\"A username:password string to create a new account with.\"}"));
|
Controller::conf.addOption("account", JSON::fromString("{\"long\":\"account\", \"short\":\"a\", \"arg\":\"string\" \"default\":\"\", \"help\":\"A username:password string to create a new account with.\"}"));
|
||||||
Controller::conf.addOption("logfile", JSON::fromString("{\"long\":\"logfile\", \"short\":\"L\", \"arg\":\"string\" \"default\":\"\",\"help\":\"Redirect all standard output to a log file, provided with an argument\"}"));
|
Controller::conf.addOption("logfile", JSON::fromString("{\"long\":\"logfile\", \"short\":\"L\", \"arg\":\"string\" \"default\":\"\",\"help\":\"Redirect all standard output to a log file, provided with an argument\"}"));
|
||||||
Controller::conf.addOption("configFile", JSON::fromString("{\"long\":\"config\", \"short\":\"c\", \"arg\":\"string\" \"default\":\"config.json\", \"help\":\"Specify a config file other than default.\"}"));
|
Controller::conf.addOption("configFile", JSON::fromString("{\"long\":\"config\", \"short\":\"c\", \"arg\":\"string\" \"default\":\"config.json\", \"help\":\"Specify a config file other than default.\"}"));
|
||||||
|
@ -230,6 +231,7 @@ int main(int argc, char ** argv){
|
||||||
if (Controller::Storage["config"]["controller"]["prometheus"]){
|
if (Controller::Storage["config"]["controller"]["prometheus"]){
|
||||||
Controller::conf.getOption("prometheus", true)[0u] = Controller::Storage["config"]["controller"]["prometheus"];
|
Controller::conf.getOption("prometheus", true)[0u] = Controller::Storage["config"]["controller"]["prometheus"];
|
||||||
}
|
}
|
||||||
|
Controller::maxConnsPerIP = Controller::conf.getInteger("maxconnsperip");
|
||||||
Controller::Storage["config"]["controller"]["prometheus"] = Controller::conf.getString("prometheus");
|
Controller::Storage["config"]["controller"]["prometheus"] = Controller::conf.getString("prometheus");
|
||||||
{
|
{
|
||||||
IPC::semaphore configLock(SEM_CONF, O_CREAT | O_RDWR, ACCESSPERMS, 1);
|
IPC::semaphore configLock(SEM_CONF, O_CREAT | O_RDWR, ACCESSPERMS, 1);
|
||||||
|
|
|
@ -39,6 +39,7 @@ std::map<unsigned long, Controller::sessIndex> Controller::connToSession; ///< M
|
||||||
bool Controller::killOnExit = KILL_ON_EXIT;
|
bool Controller::killOnExit = KILL_ON_EXIT;
|
||||||
tthread::mutex Controller::statsMutex;
|
tthread::mutex Controller::statsMutex;
|
||||||
std::map<std::string, unsigned int> Controller::activeStreams;
|
std::map<std::string, unsigned int> Controller::activeStreams;
|
||||||
|
unsigned int Controller::maxConnsPerIP = 0;
|
||||||
|
|
||||||
//For server-wide totals. Local to this file only.
|
//For server-wide totals. Local to this file only.
|
||||||
struct streamTotals {
|
struct streamTotals {
|
||||||
|
@ -190,9 +191,31 @@ void Controller::SharedMemStats(void * config){
|
||||||
|
|
||||||
/// Updates the given active connection with new stats data.
|
/// Updates the given active connection with new stats data.
|
||||||
void Controller::statSession::update(unsigned long index, IPC::statExchange & data){
|
void Controller::statSession::update(unsigned long index, IPC::statExchange & data){
|
||||||
//update the sync byte: 0 = requesting fill, 1 = needs checking, > 1 = state known
|
//update the sync byte: 0 = requesting fill, 1 = needs checking, > 1 = state known (100=denied, 10=accepted)
|
||||||
if (!data.getSync()){
|
if (!data.getSync()){
|
||||||
data.setSync(sync);
|
//if we have a maximum connection count per IP, enforce it
|
||||||
|
if (maxConnsPerIP){
|
||||||
|
unsigned int currConns = 1;
|
||||||
|
long long shortly = Util::epoch();
|
||||||
|
std::string myHost;
|
||||||
|
{
|
||||||
|
sessIndex tmpidx(data);
|
||||||
|
myHost = tmpidx.host;
|
||||||
|
}
|
||||||
|
for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){
|
||||||
|
|
||||||
|
if (&it->second != this && it->first.host == myHost && (it->second.hasDataFor(shortly-STATS_DELAY) || it->second.hasDataFor(shortly) || it->second.hasDataFor(shortly-1) || it->second.hasDataFor(shortly-2) || it->second.hasDataFor(shortly-3) || it->second.hasDataFor(shortly-4) || it->second.hasDataFor(shortly-5)) && ++currConns > maxConnsPerIP){break;}
|
||||||
|
}
|
||||||
|
if (currConns > maxConnsPerIP){
|
||||||
|
WARN_MSG("Disconnecting session from %s: exceeds max connection count of %u", myHost.c_str(), maxConnsPerIP);
|
||||||
|
data.setSync(100);
|
||||||
|
}else{
|
||||||
|
data.setSync(sync);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//no maximum, just set the sync byte to its current value
|
||||||
|
data.setSync(sync);
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
if (sync < 2){
|
if (sync < 2){
|
||||||
sync = data.getSync();
|
sync = data.getSync();
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
namespace Controller {
|
namespace Controller {
|
||||||
|
|
||||||
extern bool killOnExit;
|
extern bool killOnExit;
|
||||||
|
extern unsigned int maxConnsPerIP;
|
||||||
|
|
||||||
//These functions keep track of which streams are currently active.
|
//These functions keep track of which streams are currently active.
|
||||||
extern std::map<std::string, unsigned int> activeStreams;
|
extern std::map<std::string, unsigned int> activeStreams;
|
||||||
|
|
Loading…
Add table
Reference in a new issue