2020-03-04 18:05:57 +03:00
/* -------------------------------------------------------------------------- */
2024-07-29 15:25:20 +03:00
/* Copyright 2002-2024, OpenNebula Project, OpenNebula Systems */
2020-03-04 18:05:57 +03:00
/* */
/* 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. */
/* -------------------------------------------------------------------------- */
2020-06-29 13:14:00 +03:00
# ifndef DRIVER_MESSAGE_H
# define DRIVER_MESSAGE_H
2020-03-04 18:05:57 +03:00
# include <unistd.h>
# include <string>
# include <iostream>
# include <sstream>
# include "EnumString.h"
2020-06-29 13:14:00 +03:00
# include "SSLUtil.h"
2020-03-04 18:05:57 +03:00
/**
* This class represents a generic message used by the Monitoring Protocol .
* The structure of the message is :
*
2020-06-05 13:03:15 +03:00
* + - - - - - - + - - - - - + - - - - - - - - + - - - - - + - - - - - + - - - - - + - - - - + - - - - - + - - - - - - - - - + - - - - - - +
* | TYPE | ' ' | STATUS | ' ' | OID | ' ' | TS | ' ' | PAYLOAD | ' \n ' |
* + - - - - - - + - - - - - + - - - - - - - - + - - - - - + - - - - - + - - - - - + - - - - + - - - - - + - - - - - - - - - + - - - - - - +
2020-03-04 18:05:57 +03:00
*
* TYPE String ( non - blanks ) identifying the message type
* ' ' A single white space to separate fields
* STATUS String ( non - blanks ) , status of the message depends on message
* type , could contain result of operation ( " SUCCESS " or " FAILURE " )
* OID Number , id of affected object , - 1 if not object related
2020-06-05 13:03:15 +03:00
* TS timestamp for the message in epoch .
2020-03-04 18:05:57 +03:00
* PAYLOAD of the message XML base64 encoded
* ' \n ' End of message delimiter
*
*/
2020-06-29 13:14:00 +03:00
template < typename E , //Enum class for the message types
bool encode = false , //Payload is base64 encoded
bool compress = false , //Payload is compressed
bool encrypt = false , //Payload is encrypted
bool has_timestamp = false > //Message includes timestamp
2020-03-04 18:05:57 +03:00
class Message
{
public :
2020-06-29 13:14:00 +03:00
using msg_enum = E ;
Message ( ) = default ;
Message ( E type , std : : string & & status , int oid , const std : : string & msg_payload ) ;
2020-03-04 18:05:57 +03:00
/**
* Parse the Message from an input string
* @ param input string with the message
*/
2020-06-29 13:14:00 +03:00
int parse_from ( const std : : string & input ) ;
2020-03-04 18:05:57 +03:00
/**
* Writes this object to the given string
*/
2020-06-29 13:14:00 +03:00
int write_to ( std : : string & out ) const ;
2020-03-04 18:05:57 +03:00
/**
* Writes this object to the given file descriptor
*/
2020-06-29 13:14:00 +03:00
int write_to ( int fd ) const ;
2020-03-04 18:05:57 +03:00
/**
* Writes this object to the given output stream
*/
2020-06-29 13:14:00 +03:00
int write_to ( std : : ostream & oss ) const ;
2020-03-04 18:05:57 +03:00
/**
*
*/
E type ( ) const
{
return _type ;
}
void type ( E t )
{
_type = t ;
}
/**
* Returns type of the message as string
*/
const std : : string & type_str ( ) const
{
return _type_str . _to_str ( _type ) ;
}
2020-04-25 19:42:13 +03:00
static const std : : string & type_str ( E t )
{
return _type_str . _to_str ( t ) ;
}
2020-03-04 18:05:57 +03:00
/**
* Status of the message , can ' t contain blanks .
* Depends on message type , could contain result of
* operation ( " SUCCESS " or " FAILURE " )
* Default value is " - "
*/
const std : : string & status ( ) const
{
return _status ;
}
void status ( const std : : string & status )
{
_status = status ;
}
/**
* Object ID , - 1 if not object related
*/
int oid ( ) const
{
return _oid ;
}
void oid ( int oid )
{
_oid = oid ;
}
/**
* Message data , could be empty
*/
const std : : string & payload ( ) const
{
return _payload ;
}
2022-04-09 15:48:15 +03:00
std : : string payload64 ( ) const
{
std : : string buffer ;
ssl_util : : base64_decode ( _payload , buffer ) ;
return buffer ;
}
2020-03-04 18:05:57 +03:00
void payload ( const std : : string & p )
{
_payload = p ;
}
2020-06-05 13:03:15 +03:00
/**
* Message timestamp , optional
*/
time_t timestamp ( ) const
{
2020-06-29 13:14:00 +03:00
static_assert ( has_timestamp = = true , " Timestamp disabled " ) ;
2020-06-05 13:03:15 +03:00
return _timestamp ;
}
void timestamp ( time_t ts )
{
2020-06-29 13:14:00 +03:00
static_assert ( has_timestamp = = true , " Timestamp disabled " ) ;
2020-06-05 13:03:15 +03:00
_timestamp = ts ;
}
2020-03-04 18:05:57 +03:00
private :
/**
* Message fields
*/
2023-02-13 19:31:51 +03:00
E _type = E : : UNDEFINED ;
2020-03-04 18:05:57 +03:00
std : : string _status = std : : string ( " - " ) ;
int _oid = - 1 ;
std : : string _payload ;
2020-06-05 13:03:15 +03:00
time_t _timestamp = 0 ;
2020-03-04 18:05:57 +03:00
static const EString < E > _type_str ;
} ;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
2020-06-29 13:14:00 +03:00
/* Message Template Implementation */
2020-03-04 18:05:57 +03:00
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
2020-06-29 13:14:00 +03:00
template < typename E , bool compress , bool encode , bool encrypt , bool has_timestamp >
Message < E , compress , encode , encrypt , has_timestamp >
2024-06-03 12:40:24 +03:00
: : Message ( E type , std : : string & & status , int oid , const std : : string & payload )
: _type ( type )
, _status ( std : : move ( status ) )
, _oid ( oid )
, _payload ( payload )
2020-06-29 13:14:00 +03:00
{
}
template < typename E , bool compress , bool encode , bool encrypt , bool has_timestamp >
int Message < E , compress , encode , encrypt , has_timestamp >
2024-06-03 12:40:24 +03:00
: : parse_from ( const std : : string & input )
2020-03-04 18:05:57 +03:00
{
std : : istringstream is ( input ) ;
2020-06-29 13:14:00 +03:00
std : : string buffer ;
2020-03-04 18:05:57 +03:00
if ( ! is . good ( ) )
{
goto error ;
}
is > > buffer ;
2023-01-31 15:46:09 +03:00
_type = _type_str . _from_str ( buffer ) ;
2020-03-04 18:05:57 +03:00
if ( ! is . good ( ) | | _type = = E : : UNDEFINED )
{
goto error ;
}
buffer . clear ( ) ;
is > > _status ;
2020-06-29 13:14:00 +03:00
is > > _oid > > std : : ws ;
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
if ( has_timestamp )
{
is > > _timestamp > > std : : ws ;
}
2020-06-05 13:03:15 +03:00
2020-06-29 13:14:00 +03:00
getline ( is , buffer ) ;
2020-03-04 18:05:57 +03:00
if ( buffer . empty ( ) )
{
_payload . clear ( ) ;
return 0 ;
}
2020-06-29 13:14:00 +03:00
if ( encode )
2020-03-04 18:05:57 +03:00
{
2020-06-29 13:14:00 +03:00
ssl_util : : base64_decode ( buffer , _payload ) ;
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
if ( compress & & ssl_util : : zlib_decompress ( _payload , _payload ) = = - 1 )
2020-03-04 18:05:57 +03:00
{
goto error ;
}
2020-06-29 13:14:00 +03:00
if ( encrypt & & ssl_util : : is_rsa_set ( ) )
{
if ( ssl_util : : rsa_private_decrypt ( _payload , _payload ) = = - 1 )
{
// Accept also not encrypted messages
}
}
}
else
{
_payload = buffer ;
2020-03-04 18:05:57 +03:00
}
return 0 ;
error :
_type = E : : UNDEFINED ;
_payload = input ;
return - 1 ;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
2020-06-29 13:14:00 +03:00
template < typename E , bool compress , bool encode , bool encrypt , bool has_timestamp >
int Message < E , compress , encode , encrypt , has_timestamp >
2024-06-03 12:40:24 +03:00
: : write_to ( std : : string & out ) const
2020-03-04 18:05:57 +03:00
{
out . clear ( ) ;
2020-06-29 13:14:00 +03:00
out = _type_str . _to_str ( _type ) ;
out + = ' ' ;
out + = _status ;
out + = ' ' ;
out + = std : : to_string ( _oid ) ;
out + = ' ' ;
if ( has_timestamp )
{
out + = std : : to_string ( _timestamp ) ;
out + = ' ' ;
}
2020-03-04 18:05:57 +03:00
if ( ! _payload . empty ( ) )
{
2020-06-29 13:14:00 +03:00
if ( encode )
2020-03-04 18:05:57 +03:00
{
2020-06-29 13:14:00 +03:00
std : : string msg ;
msg = _payload ;
if ( compress & & ssl_util : : zlib_compress ( msg , msg ) = = - 1 )
2020-03-04 18:05:57 +03:00
{
return - 1 ;
}
2020-06-29 13:14:00 +03:00
if ( ssl_util : : base64_encode ( msg , msg ) = = - 1 )
{
return - 1 ;
}
2020-03-04 18:05:57 +03:00
2020-06-29 13:14:00 +03:00
out + = msg ;
}
else
2020-03-04 18:05:57 +03:00
{
2020-06-29 13:14:00 +03:00
out + = _payload ;
2020-03-04 18:05:57 +03:00
}
}
out + = ' \n ' ;
return 0 ;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
2020-06-29 13:14:00 +03:00
template < typename E , bool compress , bool encode , bool encrypt , bool has_timestamp >
int Message < E , compress , encode , encrypt , has_timestamp >
2024-06-03 12:40:24 +03:00
: : write_to ( int fd ) const
2020-03-04 18:05:57 +03:00
{
std : : string out ;
2020-06-29 13:14:00 +03:00
if ( write_to ( out ) = = - 1 )
2020-03-04 18:05:57 +03:00
{
return - 1 ;
}
: : write ( fd , ( const void * ) out . c_str ( ) , out . size ( ) ) ;
return 0 ;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
2020-06-29 13:14:00 +03:00
template < typename E , bool compress , bool encode , bool encrypt , bool has_timestamp >
int Message < E , compress , encode , encrypt , has_timestamp >
2024-06-03 12:40:24 +03:00
: : write_to ( std : : ostream & oss ) const
2020-03-04 18:05:57 +03:00
{
std : : string out ;
2020-06-29 13:14:00 +03:00
if ( write_to ( out ) = = - 1 )
2020-03-04 18:05:57 +03:00
{
return - 1 ;
}
oss < < out ;
return 0 ;
}
2020-06-29 13:14:00 +03:00
# endif /*DRIVER_MESSAGE_H_*/