<commit_before># 
# Copyright 2019 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

package gorgone::modules::core::proxy::hooks;

use warnings;
use strict;
use JSON::XS;
use gorgone::standard::misc;
use gorgone::class::core;
use gorgone::standard::library;
use gorgone::modules::core::proxy::class;
use File::Basename;
use MIME::Base64;
use Digest::MD5::File qw(file_md5_hex);
use Fcntl;

use constant NAMESPACE => 'core';
use constant NAME => 'proxy';
use constant EVENTS => [
    { event => 'PROXYREADY' },
    { event => 'REMOTECOPY', uri => '/remotecopy', method => 'POST' },
    { event => 'SETLOGS' }, # internal. Shouldn't be used by third party clients
    { event => 'PONG' }, # internal. Shouldn't be used by third party clients
    { event => 'REGISTERNODES' }, # internal. Shouldn't be used by third party clients
    { event => 'UNREGISTERNODES' }, # internal. Shouldn't be used by third party clients
    { event => 'PROXYADDNODE' }, # internal. Shouldn't be used by third party clients
    { event => 'PROXYDELNODE' }, # internal. Shouldn't be used by third party clients
    { event => 'PROXYADDSUBNODE' }, # internal. Shouldn't be used by third party clients
    { event => 'PONGRESET' }, # internal. Shouldn't be used by third party clients
];

my $config_core;
my $config;

my $synctime_error = 0;
my $synctime_nodes = {}; # get last time retrieved
my $synctime_lasttime;
my $synctime_option;
my $synctimeout_option;
my $ping_option;
my $ping_time = 0;

my $last_pong = {}; 
my $register_nodes = {};
# With static routes we have a pathscore. Dynamic no pathscore.
# algo is: we use static routes first. after we use dynamic routes
#  {
#     subnode_id => {
#         static => {
#              parent_id1 => 1,
#              parent_id2 => 2,
#         },
#         dynamic => {
#              parent_id3 => 1,
#              parent_id5 => 1,
#         },
#     }
#  }
#
my $register_subnodes = {};
my $constatus_ping = {};
my $parent_ping = {};
my $pools = {};
my $pools_pid = {};
my $nodes_pool = {};
my $rr_current = 0;
my $stop = 0;
my ($external_socket, $internal_socket, $core_id);

sub register {
    my (%options) = @_;
    
    $config = $options{config};
    $config_core = $options{config_core};

    $synctime_option = defined($config->{synchistory_time}) ? $config->{synchistory_time} : 60;
    $synctimeout_option = defined($config->{synchistory_timeout}) ? $config->{synchistory_timeout} : 30;
    $ping_option = defined($config->{ping}) ? $config->{ping} : 60;
    $config->{pong_discard_timeout} = defined($config->{pong_discard_timeout}) ? $config->{pong_discard_timeout} : 300;
    $config->{pool} = defined($config->{pool}) && $config->{pool} =~ /(\d+)/ ? $1 : 5;
    return (1, NAMESPACE, NAME, EVENTS);
}

sub init {
    my (%options) = @_;

    $synctime_lasttime = time();
    $core_id = $options{id};
    $external_socket = $options{external_socket};
    $internal_socket = $options{internal_socket};
    for my $pool_id (1..$config->{pool}) {
        create_child(dbh => $options{dbh}, pool_id => $pool_id, logger => $options{logger});
    }
}

sub routing {
    my (%options) = @_;

    my $data;
    eval {
        $data = JSON::XS->new->utf8->decode($options{data});
    };
    if ($@) {
        $options{logger}->writeLogError("[proxy] Cannot decode json data: $@");
        gorgone::standard::library::add_history(
            dbh => $options{dbh},
            code => 20, token => $options{token},
            data => { message => 'proxy - cannot decode json' },
            json_encode => 1
        );
        return undef;
    }

    if ($options{action} eq 'PONG') {
        return undef if (!defined($data->{data}->{id}) || $data->{data}->{id} eq '');
        return undef if ($register_nodes->{$data->{data}->{id}}->{type} eq 'push_ssh');
        $synctime_nodes->{$data->{data}->{id}}->{in_progress_ping} = 0;
        $last_pong->{$data->{data}->{id}} = time();
        $constatus_ping->{$data->{data}->{id}}->{last_ping_recv} = time();
        $constatus_ping->{$data->{data}->{id}}->{nodes} = $data->{data}->{data};
        register_subnodes(%options, id => $data->{data}->{id}, subnodes => $data->{data}->{data});
        $options{logger}->writeLogInfo("[proxy] Pong received from '" . $data->{data}->{id} . "'");
        return undef;
    }
<commit_msg>fix(proxy): pong response for ssh client was rejected<commit_after># 
# Copyright 2019 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

package gorgone::modules::core::proxy::hooks;

use warnings;
use strict;
use JSON::XS;
use gorgone::standard::misc;
use gorgone::class::core;
use gorgone::standard::library;
use gorgone::modules::core::proxy::class;
use File::Basename;
use MIME::Base64;
use Digest::MD5::File qw(file_md5_hex);
use Fcntl;

use constant NAMESPACE => 'core';
use constant NAME => 'proxy';
use constant EVENTS => [
    { event => 'PROXYREADY' },
    { event => 'REMOTECOPY', uri => '/remotecopy', method => 'POST' },
    { event => 'SETLOGS' }, # internal. Shouldn't be used by third party clients
    { event => 'PONG' }, # internal. Shouldn't be used by third party clients
    { event => 'REGISTERNODES' }, # internal. Shouldn't be used by third party clients
    { event => 'UNREGISTERNODES' }, # internal. Shouldn't be used by third party clients
    { event => 'PROXYADDNODE' }, # internal. Shouldn't be used by third party clients
    { event => 'PROXYDELNODE' }, # internal. Shouldn't be used by third party clients
    { event => 'PROXYADDSUBNODE' }, # internal. Shouldn't be used by third party clients
    { event => 'PONGRESET' }, # internal. Shouldn't be used by third party clients
];

my $config_core;
my $config;

my $synctime_error = 0;
my $synctime_nodes = {}; # get last time retrieved
my $synctime_lasttime;
my $synctime_option;
my $synctimeout_option;
my $ping_option;
my $ping_time = 0;

my $last_pong = {}; 
my $register_nodes = {};
# With static routes we have a pathscore. Dynamic no pathscore.
# algo is: we use static routes first. after we use dynamic routes
#  {
#     subnode_id => {
#         static => {
#              parent_id1 => 1,
#              parent_id2 => 2,
#         },
#         dynamic => {
#              parent_id3 => 1,
#              parent_id5 => 1,
#         },
#     }
#  }
#
my $register_subnodes = {};
my $constatus_ping = {};
my $parent_ping = {};
my $pools = {};
my $pools_pid = {};
my $nodes_pool = {};
my $rr_current = 0;
my $stop = 0;
my ($external_socket, $internal_socket, $core_id);

sub register {
    my (%options) = @_;
    
    $config = $options{config};
    $config_core = $options{config_core};

    $synctime_option = defined($config->{synchistory_time}) ? $config->{synchistory_time} : 60;
    $synctimeout_option = defined($config->{synchistory_timeout}) ? $config->{synchistory_timeout} : 30;
    $ping_option = defined($config->{ping}) ? $config->{ping} : 60;
    $config->{pong_discard_timeout} = defined($config->{pong_discard_timeout}) ? $config->{pong_discard_timeout} : 300;
    $config->{pool} = defined($config->{pool}) && $config->{pool} =~ /(\d+)/ ? $1 : 5;
    return (1, NAMESPACE, NAME, EVENTS);
}

sub init {
    my (%options) = @_;

    $synctime_lasttime = time();
    $core_id = $options{id};
    $external_socket = $options{external_socket};
    $internal_socket = $options{internal_socket};
    for my $pool_id (1..$config->{pool}) {
        create_child(dbh => $options{dbh}, pool_id => $pool_id, logger => $options{logger});
    }
}

sub routing {
    my (%options) = @_;

    my $data;
    eval {
        $data = JSON::XS->new->utf8->decode($options{data});
    };
    if ($@) {
        $options{logger}->writeLogError("[proxy] Cannot decode json data: $@");
        gorgone::standard::library::add_history(
            dbh => $options{dbh},
            code => 20, token => $options{token},
            data => { message => 'proxy - cannot decode json' },
            json_encode => 1
        );
        return undef;
    }

    if ($options{action} eq 'PONG') {
        return undef if (!defined($data->{data}->{id}) || $data->{data}->{id} eq '');
        $synctime_nodes->{$data->{data}->{id}}->{in_progress_ping} = 0;
        $last_pong->{$data->{data}->{id}} = time();
        $constatus_ping->{$data->{data}->{id}}->{last_ping_recv} = time();
        $constatus_ping->{$data->{data}->{id}}->{nodes} = $data->{data}->{data};
        register_subnodes(%options, id => $data->{data}->{id}, subnodes => $data->{data}->{data});
        $options{logger}->writeLogInfo("[proxy] Pong received from '" . $data->{data}->{id} . "'");
        return undef;
    }

{'fraction_non_alphanumeric': 0.16573033707865167, 'fraction_numerical': 0.008426966292134831, 'mean_word_length': 3.4267317939609234, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 163, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3866166', 'n_tokens_mistral': 3359, 'n_tokens_neox': 3259, 'n_words': 873}