#include "listener.h"
#include "master_main.h"
#include <balancer/kernel/process/children/worker_process.h>

namespace NSrvKernel::NProcessCore {

    void TListener::OnAcceptFull(const TAcceptFull& acc) {
        WorkerProcess_->AddAccepted(TAddrDescr(*acc.Local));

        const auto& config = WorkerProcess_->MainConfig();
        if (config.MaxConnections) {
            //TODO - optimize

            while (WorkerConnectionCallback_.InProgr_ >= config.MaxConnections) {
                WorkerProcess_->Connections_.PopFront()->Cancel(); // TODO: check for use-after-free
            }
        }

        if (Y_LIKELY(acc.Remote) && WorkerProcess_->IsBanned(*acc.Remote)) {
            acc.S->Close();
            return;
        }

        if (config.SoSndbuf) {
            try {
                CheckedSetSockOpt((SOCKET)*acc.S, SOL_SOCKET, SO_SNDBUF, (int)config.SoSndbuf, "sndbuf");
            } catch (...) {
                // Can not do anything right now
            }
        }

        TCpuLimiter* cpuLimiter = nullptr;
        if (WorkerProcess_->CpuLimiter_) {
            if (!Y_LIKELY(acc.Remote) || !WorkerProcess_->CpuLimiter_->IsCheckerAddress(*acc.Remote)) {
                if (WorkerProcess_->CpuLimiter_->CheckConnRejected(*acc.S)) {
                    return;
                }
                cpuLimiter = WorkerProcess_->CpuLimiter_.Get();
            }
        }

        WorkerProcess_->Connections_.PushBack(new TConnection(&WorkerConnectionCallback_, Module, acc, cpuLimiter));

        // Pacing the accepts with processing
        RunningCont()->Yield();
    }

    void TListener::OnError()  {
        WorkerProcess_->Log_ << "on error: " << CurrentExceptionMessage() << Endl;
    }

    void TListener::OnStop(TSocketHolder* s)  {
        s->Close();
    }
}
