2016-05-12 22:45:40 +02:00
/** @file
* @ author Edouard DUPIN
* @ copyright 2016 , Edouard DUPIN , all right reserved
2017-01-05 21:28:23 +01:00
* @ license MPL v2 .0 ( see license file )
2016-05-12 22:45:40 +02:00
*/
2016-11-23 22:03:04 +01:00
# include <appl/Router.hpp>
2016-10-02 17:01:22 +02:00
# include <appl/debug.hpp>
# include <enet/TcpServer.hpp>
2017-01-04 21:58:34 +01:00
# include <etk/os/FSNode.hpp>
2016-05-23 21:18:37 +02:00
2017-01-04 00:02:22 +01:00
static std : : string g_pathDBName = " USERDATA:router-database.json " ;
class UserAvaillable {
public :
std : : string m_name ;
std : : string m_basePath ;
bool m_accessMediaCenter ;
2017-01-04 21:58:34 +01:00
FILE * m_subProcess ;
2017-01-04 00:02:22 +01:00
} ;
std : : vector < UserAvaillable > g_listUserAvaillable ;
bool g_needToStore = false ;
static void store_db ( ) {
if ( g_needToStore = = false ) {
return ;
}
APPL_ERROR ( " Store database [START] " ) ;
ejson : : Document database ;
ejson : : Array listUserArray ;
database . add ( " users " , listUserArray ) ;
for ( auto & it : g_listUserAvaillable ) {
ejson : : Object propObject ;
listUserArray . add ( propObject ) ;
propObject . add ( " name " , ejson : : String ( it . m_name ) ) ;
propObject . add ( " path " , ejson : : String ( it . m_basePath ) ) ;
propObject . add ( " access-media-center " , ejson : : Boolean ( it . m_accessMediaCenter ) ) ;
}
bool retGenerate = database . storeSafe ( g_pathDBName ) ;
APPL_ERROR ( " Store database [STOP] : " < < g_pathDBName < < " ret = " < < retGenerate ) ;
g_needToStore = false ;
}
static void load_db ( ) {
ejson : : Document database ;
bool ret = database . load ( g_pathDBName ) ;
if ( ret = = false ) {
APPL_WARNING ( " ==> LOAD error " ) ;
}
g_listUserAvaillable . clear ( ) ;
ejson : : Array listUserArray = database [ " users " ] . toArray ( ) ;
for ( const auto itArray : listUserArray ) {
ejson : : Object userElement = itArray . toObject ( ) ;
UserAvaillable userProperty ;
userProperty . m_name = userElement [ " name " ] . toString ( ) . get ( ) ;
userProperty . m_basePath = userElement [ " path " ] . toString ( ) . get ( ) ;
userProperty . m_accessMediaCenter = userElement [ " access-media-center " ] . toBoolean ( ) . get ( ) ;
APPL_INFO ( " find USER: ' " < < userProperty . m_name < < " ' " ) ;
g_listUserAvaillable . push_back ( userProperty ) ;
}
g_needToStore = false ;
}
2016-05-23 21:18:37 +02:00
2016-06-23 22:08:11 +02:00
namespace appl {
2016-05-23 21:18:37 +02:00
class TcpServerInput {
private :
enet : : TcpServer m_interface ;
std : : thread * m_thread ;
bool m_threadRunning ;
2016-11-23 22:03:04 +01:00
appl : : Router * m_router ;
2016-05-23 21:18:37 +02:00
bool m_service ;
public :
2016-11-23 22:03:04 +01:00
TcpServerInput ( appl : : Router * _router , bool _service ) :
2016-05-23 21:18:37 +02:00
m_thread ( nullptr ) ,
m_threadRunning ( false ) ,
2016-11-23 22:03:04 +01:00
m_router ( _router ) ,
2016-05-23 21:18:37 +02:00
m_service ( _service ) {
}
virtual ~ TcpServerInput ( ) { }
void start ( const std : : string & _host , uint16_t _port ) {
m_interface . setHostNane ( _host ) ;
m_interface . setPort ( _port ) ;
m_interface . link ( ) ;
m_threadRunning = true ;
m_thread = new std : : thread ( [ & ] ( void * ) { this - > threadCallback ( ) ; } , nullptr ) ;
if ( m_thread = = nullptr ) {
m_threadRunning = false ;
2016-06-20 23:07:25 +02:00
ZEUS_ERROR ( " creating callback thread! " ) ;
2016-05-23 21:18:37 +02:00
return ;
}
}
void stop ( ) {
if ( m_thread ! = nullptr ) {
m_threadRunning = false ;
}
m_interface . unlink ( ) ;
if ( m_thread ! = nullptr ) {
m_thread - > join ( ) ;
delete m_thread ;
m_thread = nullptr ;
}
}
void threadCallback ( ) {
// get datas:
while ( m_threadRunning = = true ) {
// READ section data:
enet : : Tcp data = std : : move ( m_interface . waitNext ( ) ) ;
2016-06-20 23:07:25 +02:00
ZEUS_VERBOSE ( " New connection " ) ;
2016-05-23 21:18:37 +02:00
if ( m_service = = true ) {
2016-11-23 22:03:04 +01:00
m_router - > newClientGateWay ( std : : move ( data ) ) ;
2016-05-23 21:18:37 +02:00
} else {
2016-11-23 22:03:04 +01:00
m_router - > newClient ( std : : move ( data ) ) ;
2016-05-23 21:18:37 +02:00
}
}
}
} ;
}
2016-05-12 22:45:40 +02:00
2016-11-23 22:03:04 +01:00
void appl : : Router : : newClientGateWay ( enet : : Tcp _connection ) {
2016-06-20 23:07:25 +02:00
ZEUS_WARNING ( " New TCP connection (service) " ) ;
2016-11-21 22:15:46 +01:00
ememory : : SharedPtr < appl : : GateWayInterface > tmp = ememory : : makeShared < appl : : GateWayInterface > ( std : : move ( _connection ) , this ) ;
2016-05-23 21:18:37 +02:00
tmp - > start ( ) ;
2016-11-23 22:03:04 +01:00
m_GateWayList . push_back ( tmp ) ;
2016-05-23 21:18:37 +02:00
}
2016-05-12 22:45:40 +02:00
2016-11-23 22:03:04 +01:00
void appl : : Router : : newClient ( enet : : Tcp _connection ) {
2016-06-20 23:07:25 +02:00
ZEUS_WARNING ( " New TCP connection (client) " ) ;
2016-07-15 21:22:11 +02:00
ememory : : SharedPtr < appl : : ClientInterface > tmp = ememory : : makeShared < appl : : ClientInterface > ( std : : move ( _connection ) , this ) ;
2016-11-29 21:39:39 +01:00
tmp - > start ( ) ;
2016-05-23 21:18:37 +02:00
m_clientList . push_back ( tmp ) ;
}
2016-05-12 22:45:40 +02:00
2016-11-23 22:03:04 +01:00
appl : : Router : : Router ( ) :
2016-11-22 21:19:00 +01:00
m_clientUID ( 2 ) ,
2017-04-16 16:26:21 +02:00
propertyStdOut ( this , " stdout " , false , " Set the Log of the output " ) ,
2016-11-23 22:03:04 +01:00
propertyClientIp ( this , " client-ip " , " 127.0.0.1 " , " Ip to listen client " , & appl : : Router : : onPropertyChangeClientIp ) ,
propertyClientPort ( this , " client-port " , 1983 , " Port to listen client " , & appl : : Router : : onPropertyChangeClientPort ) ,
2016-11-30 22:09:16 +01:00
propertyClientMax ( this , " client-max " , 8000 , " Maximum of client at the same time " , & appl : : Router : : onPropertyChangeClientMax ) ,
propertyGateWayIp ( this , " gw-ip " , " 127.0.0.1 " , " Ip to listen Gateway " , & appl : : Router : : onPropertyChangeGateWayIp ) ,
propertyGateWayPort ( this , " gw-port " , 1984 , " Port to listen Gateway " , & appl : : Router : : onPropertyChangeGateWayPort ) ,
2017-02-21 21:46:51 +01:00
propertyGateWayMax ( this , " gw-max " , 8000 , " Maximum of Gateway at the same time " , & appl : : Router : : onPropertyChangeGateWayMax ) ,
propertyDelayToStop ( this , " delay-to-stop " , 0 , " Delay before the client stop the connection in second (default: 0=automatic set by the gateway; -1=never disconnect; other the time ) " ) {
2016-07-15 21:22:11 +02:00
m_interfaceClientServer = ememory : : makeShared < appl : : TcpServerInput > ( this , false ) ;
2016-11-23 22:03:04 +01:00
m_interfaceGateWayServer = ememory : : makeShared < appl : : TcpServerInput > ( this , true ) ;
2017-01-04 00:02:22 +01:00
load_db ( ) ;
2016-05-12 22:45:40 +02:00
}
2016-11-23 22:03:04 +01:00
appl : : Router : : ~ Router ( ) {
2016-05-12 22:45:40 +02:00
}
2016-11-23 22:03:04 +01:00
void appl : : Router : : start ( ) {
2016-05-23 21:18:37 +02:00
m_interfaceClientServer - > start ( * propertyClientIp , * propertyClientPort ) ;
2016-11-23 22:03:04 +01:00
m_interfaceGateWayServer - > start ( * propertyGateWayIp , * propertyGateWayPort ) ;
2016-05-12 22:45:40 +02:00
}
2016-11-23 22:03:04 +01:00
void appl : : Router : : stop ( ) {
2016-11-21 22:15:46 +01:00
// TODO : Stop all server ...
2016-05-12 22:45:40 +02:00
}
2017-01-04 00:02:22 +01:00
bool appl : : Router : : userIsConnected ( const std : : string & _userName ) {
for ( auto & it : m_GateWayList ) {
if ( it = = nullptr ) {
continue ;
}
if ( it - > getName ( ) ! = _userName ) {
continue ;
}
return true ;
}
return false ;
}
# include <iomanip>
# include <iostream>
2017-01-04 21:58:34 +01:00
# include <cstdio>
# include <unistd.h>
2017-01-04 00:02:22 +01:00
2016-11-23 22:03:04 +01:00
ememory : : SharedPtr < appl : : GateWayInterface > appl : : Router : : get ( const std : : string & _userName ) {
2016-11-21 22:15:46 +01:00
// TODO : Start USer only when needed, not get it all time started...
2016-11-23 22:03:04 +01:00
for ( auto & it : m_GateWayList ) {
2016-05-22 22:40:42 +02:00
if ( it = = nullptr ) {
continue ;
}
2016-11-21 22:15:46 +01:00
if ( it - > getName ( ) ! = _userName ) {
2016-05-22 22:40:42 +02:00
continue ;
}
return it ;
}
2017-01-04 00:02:22 +01:00
// we not find the user ==> check if it is availlable ...
for ( auto & it : g_listUserAvaillable ) {
if ( it . m_name = = _userName ) {
2017-01-04 21:58:34 +01:00
#if 0
// start interface:
std : : string cmd = " ~/dev/perso/out/Linux_x86_64/debug/staging/clang/zeus-package-base/zeus-package-base.app/bin/zeus-gateway " ;
cmd + = " --user= " + it . m_name + " " ;
cmd + = " --srv=user " ;
cmd + = " --srv=picture " ;
cmd + = " --srv=video " ;
cmd + = " --base-path= " + it . m_basePath ;
cmd + = " --elog-file= \" /tmp/zeus.gateway. " + it . m_name + " .log \" " ;
cmd + = " & " ;
APPL_ERROR ( " Start " < < cmd ) ;
it . m_subProcess = popen ( cmd . c_str ( ) , " r " ) ;
if ( it . m_subProcess = = nullptr ) {
perror ( " popen " ) ;
return nullptr ;
}
// just trash IO ...
//pclose(it.m_subProcess);
# else
if ( fork ( ) ) {
// We're in the parent here.
// nothing to do ...
APPL_ERROR ( " Parent Execution ... " ) ;
} else {
// We're in the child here.
APPL_ERROR ( " Child Execution ... " ) ;
2017-03-22 21:08:15 +01:00
std : : string binary = etk : : FSNodeGetApplicationPath ( ) + " /zeus-gateway " ;
2017-01-04 21:58:34 +01:00
std : : string userConf = " --user= " + it . m_name ;
std : : string basePath = " --base-path= " + it . m_basePath ;
2017-04-16 16:26:21 +02:00
std : : string logFile ;
if ( * propertyStdOut = = false ) {
logFile = it . m_basePath + " /log/gateway.log " ;
2017-01-04 21:58:34 +01:00
if ( logFile . size ( ) ! = 0
& & logFile [ 0 ] = = ' ~ ' ) {
logFile = etk : : FSNodeGetHomePath ( ) + & logFile [ 1 ] ;
}
logFile = " --elog-file= " + logFile ;
//std::string logFile = "--elog-file=/home/heero/.local/share/zeus-DATA/SDFGHTHBSDFGSQDHZSRDFGSDFGSDFGSDFG/log/gateway.log";
//std::string logFile = " ";
APPL_INFO ( " New Child log in = " < < logFile ) ;
2017-04-16 16:26:21 +02:00
}
2017-02-21 21:46:51 +01:00
std : : string delay = " --router-delay= " + etk : : to_string ( * propertyDelayToStop ) ;
2017-04-16 23:24:07 +02:00
APPL_INFO ( " execute: " < < binary < < " " < < userConf < < " --srv=all " < < delay < < " " < < basePath < < " " < < logFile ) ;
2017-01-04 21:58:34 +01:00
int ret = execlp ( binary . c_str ( ) ,
binary . c_str ( ) , // must repeate the binary name to have the name as first argument ...
userConf . c_str ( ) ,
2017-03-26 23:16:21 +02:00
" --srv=all " ,
2017-04-25 21:47:45 +02:00
" --service-extern=false " ,
2017-02-21 21:46:51 +01:00
delay . c_str ( ) ,
2017-01-04 21:58:34 +01:00
basePath . c_str ( ) ,
logFile . c_str ( ) ,
NULL ) ;
APPL_ERROR ( " Child Execution ret = " < < ret ) ;
exit ( - 1 ) ;
APPL_ERROR ( " Must never appear ... child of fork killed ... " ) ;
}
# endif
2017-02-15 21:04:13 +01:00
int32_t nbCheckDelayMax = 24 ;
while ( nbCheckDelayMax - - > 0 ) {
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 25 ) ) ;
for ( auto & it : m_GateWayList ) {
if ( it = = nullptr ) {
continue ;
}
if ( it - > getName ( ) ! = _userName ) {
continue ;
}
return it ;
2017-01-04 21:58:34 +01:00
}
}
2017-02-15 21:04:13 +01:00
APPL_ERROR ( " must be connected ==> and it is not ... " ) ;
2017-01-04 00:02:22 +01:00
break ;
}
}
2016-05-22 22:40:42 +02:00
return nullptr ;
}
2016-11-21 22:15:46 +01:00
2016-11-23 22:03:04 +01:00
std : : vector < std : : string > appl : : Router : : getAllUserName ( ) {
2016-05-27 22:21:32 +02:00
std : : vector < std : : string > out ;
2016-11-21 22:15:46 +01:00
/*
2016-11-23 22:03:04 +01:00
for ( auto & it : m_GateWayList ) {
2016-05-27 22:21:32 +02:00
if ( it = = nullptr ) {
continue ;
}
out . push_back ( it - > getName ( ) ) ;
}
2016-11-21 22:15:46 +01:00
*/
2016-05-27 22:21:32 +02:00
return out ;
}
2016-05-23 21:18:37 +02:00
2016-11-23 22:03:04 +01:00
void appl : : Router : : cleanIO ( ) {
2017-01-04 00:02:22 +01:00
store_db ( ) ;
2016-11-23 22:03:04 +01:00
auto it = m_GateWayList . begin ( ) ;
while ( it ! = m_GateWayList . end ( ) ) {
2016-05-24 22:29:03 +02:00
if ( * it ! = nullptr ) {
if ( ( * it ) - > isAlive ( ) = = false ) {
2016-11-23 22:03:04 +01:00
it = m_GateWayList . erase ( it ) ;
2016-05-24 22:29:03 +02:00
continue ;
}
} else {
2016-11-23 22:03:04 +01:00
it = m_GateWayList . erase ( it ) ;
2016-05-24 22:29:03 +02:00
continue ;
}
+ + it ;
}
auto it2 = m_clientList . begin ( ) ;
while ( it2 ! = m_clientList . end ( ) ) {
if ( * it2 ! = nullptr ) {
if ( ( * it2 ) - > isAlive ( ) = = false ) {
2016-12-08 22:13:16 +01:00
( * it2 ) - > stop ( ) ;
2016-05-24 22:29:03 +02:00
it2 = m_clientList . erase ( it2 ) ;
2016-12-08 22:13:16 +01:00
APPL_INFO ( " remove DONE ... " ) ;
2016-05-24 22:29:03 +02:00
continue ;
}
} else {
it2 = m_clientList . erase ( it2 ) ;
continue ;
}
+ + it2 ;
}
}
2016-11-23 22:03:04 +01:00
void appl : : Router : : onClientConnect ( const bool & _value ) {
2016-06-20 23:07:25 +02:00
ZEUS_TODO ( " Client connection: " < < _value ) ;
2016-05-22 22:40:42 +02:00
}
2016-11-23 22:03:04 +01:00
void appl : : Router : : onServiceConnect ( const bool & _value ) {
2016-06-20 23:07:25 +02:00
ZEUS_TODO ( " Service connection: " < < _value ) ;
2016-05-12 22:45:40 +02:00
}
2016-11-23 22:03:04 +01:00
void appl : : Router : : onPropertyChangeClientIp ( ) {
2016-05-12 22:45:40 +02:00
}
2016-11-23 22:03:04 +01:00
void appl : : Router : : onPropertyChangeClientPort ( ) {
2016-05-12 22:45:40 +02:00
}
2016-11-23 22:03:04 +01:00
void appl : : Router : : onPropertyChangeClientMax ( ) {
2016-05-12 22:45:40 +02:00
}
2016-11-23 22:03:04 +01:00
void appl : : Router : : onPropertyChangeGateWayIp ( ) {
2016-05-12 22:45:40 +02:00
}
2016-11-23 22:03:04 +01:00
void appl : : Router : : onPropertyChangeGateWayPort ( ) {
2016-05-12 22:45:40 +02:00
}
2016-11-23 22:03:04 +01:00
void appl : : Router : : onPropertyChangeGateWayMax ( ) {
2016-05-12 22:45:40 +02:00
}