##! Internal functions and types used by the analyzer framework.

module Analyzer;

%%{
#include "zeek/NetVar.h"
#include "zeek/analyzer/Manager.h"
%%}

function Analyzer::__enable_analyzer%(id: Analyzer::Tag%) : bool
	%{
	bool result = zeek::analyzer_mgr->EnableAnalyzer(id->AsEnumVal());
	return zeek::val_mgr->Bool(result);
	%}

function Analyzer::__disable_analyzer%(id: Analyzer::Tag%) : bool
	%{
	bool result = zeek::analyzer_mgr->DisableAnalyzer(id->AsEnumVal());
	return zeek::val_mgr->Bool(result);
	%}

function Analyzer::__disable_all_analyzers%(%) : any
	%{
	zeek::analyzer_mgr->DisableAllAnalyzers();
	return nullptr;
	%}

function Analyzer::__register_for_port%(id: Analyzer::Tag, p: port%) : bool
	%{
	bool result = zeek::analyzer_mgr->RegisterAnalyzerForPort(id->AsEnumVal(), p);
	return zeek::val_mgr->Bool(result);
	%}

function Analyzer::__schedule_analyzer%(orig: addr, resp: addr, resp_p: port,
					analyzer: Analyzer::Tag, tout: interval%) : bool
	%{
	zeek::analyzer_mgr->ScheduleAnalyzer(orig->AsAddr(), resp->AsAddr(), resp_p, analyzer->AsEnumVal(), tout);
	return zeek::val_mgr->True();
	%}

function __name%(atype: AllAnalyzers::Tag%) : string
	%{
	auto val = atype->AsEnumVal();

	// Note that we don't want to follow mappings here, we want the name of
	// whatever the user passes in.
	plugin::Component* component = zeek::analyzer_mgr->Lookup(val, false);
	if ( ! component )
		component = zeek::packet_mgr->Lookup(val, false);
	if ( ! component )
		component = zeek::file_mgr->Lookup(val, false);
	if ( ! component )
		return zeek::make_intrusive<zeek::StringVal>("<error>");

	return component->CanonicalNameVal();
	%}

%%{
static zeek::plugin::Component* component_for_name(const char* name)
	{
	// Note that we don't want to follow mappings here, we want the name of
	// whatever the user passes in.
	zeek::plugin::Component* component = zeek::analyzer_mgr->Lookup(name);
	if ( ! component )
		component = zeek::packet_mgr->Lookup(name, false);
	if ( ! component )
		component = zeek::file_mgr->Lookup(name, false);

	return component;
	}
%%}

function __tag%(name: string%) : AllAnalyzers::Tag
	%{
	plugin::Component* component = component_for_name(name->CheckString());
	zeek::Tag t = component ? component->Tag() : zeek::Tag();
	return t.AsVal();
	%}

function __has_tag%(name: string%) : bool
	%{
	plugin::Component* component = component_for_name(name->CheckString());
	return zeek::val_mgr->Bool(component != nullptr);
	%}
