Code: Select all | Expand
#include "fileio.ch"#include "inkey.ch"#include "hbhrb.ch"#include "hbsocket.ch"#include "hbver.ch"#include "hbnetio.ch"#define _NETIOSRV_IPV4_DEF "0.0.0.0"#define _NETIOSRV_PORT_DEF 2941#define _NETIOMGM_IPV4_DEF "127.0.0.1"#define _NETIOMGM_PORT_DEF 2940#define _RPC_FILTER "HBNETIOSRV_RPCMAIN"#ifdef HB_EXTERNREQUEST __HB_EXTERN__#endif#define _NETIOSRV_cName 1#define _NETIOSRV_nPort 2#define _NETIOSRV_cIFAddr 3#define _NETIOSRV_cRootDir 4#define _NETIOSRV_lRPC 5#define _NETIOSRV_cRPCFFileName 6#define _NETIOSRV_hRPCFHRB 7#define _NETIOSRV_lEncryption 8#define _NETIOSRV_lAcceptConn 9#define _NETIOSRV_lShowConn 10#define _NETIOSRV_lQuit 11#define _NETIOSRV_pListenSocket 12#define _NETIOSRV_hConnection 13#define _NETIOSRV_mtxConnection 14#define _NETIOSRV_hAllow 15#define _NETIOSRV_hBlock 16#define _NETIOSRV_mtxFilters 17#define _NETIOSRV_hNotifStream 18#define _NETIOSRV_mtxNotifStream 19#define _NETIOSRV_MAX_ 19#define _NETIOSRV_CONN_pConnection 1#define _NETIOSRV_CONN_nThreadID 2#define _NETIOSRV_CONN_tStart 3#define _NETIOSRV_CONN_hInfo 4#define _NETIOSRV_CONN_MAX_ 4PROCEDURE Main( ... ) netiosrv_Main( .T., ... ) RETURNPROCEDURE netiosrv_Main( lUI, ... ) LOCAL netiosrv[ _NETIOSRV_MAX_ ] LOCAL netiomgm[ _NETIOSRV_MAX_ ] LOCAL cParam LOCAL cPassword LOCAL cPasswordManagement LOCAL cExt LOCAL cFile IF ! hb_mtvm() QOut( "Multithread support required." ) RETURN ENDIF Set( _SET_DATEFORMAT, "yyyy-mm-dd" ) Set( _SET_TIMEFORMAT, "hh:mm:ss.fff" ) HB_Logo() netiosrv[ _NETIOSRV_cName ] := "Data" netiosrv[ _NETIOSRV_nPort ] := _NETIOSRV_PORT_DEF netiosrv[ _NETIOSRV_cIFAddr ] := _NETIOSRV_IPV4_DEF netiosrv[ _NETIOSRV_cRootDir ] := hb_DirBase() + "data" netiosrv[ _NETIOSRV_lRPC ] := .F. netiosrv[ _NETIOSRV_lEncryption ] := .F. netiosrv[ _NETIOSRV_lAcceptConn ] := .T. netiosrv[ _NETIOSRV_lShowConn ] := .F. netiosrv[ _NETIOSRV_lQuit ] := .F. netiosrv[ _NETIOSRV_hConnection ] := { => } netiosrv[ _NETIOSRV_mtxConnection ] := hb_mutexCreate() netiosrv[ _NETIOSRV_hAllow ] := { => } netiosrv[ _NETIOSRV_hBlock ] := { => } netiosrv[ _NETIOSRV_mtxFilters ] := hb_mutexCreate() netiomgm[ _NETIOSRV_cName ] := "Management" netiomgm[ _NETIOSRV_nPort ] := _NETIOMGM_PORT_DEF netiomgm[ _NETIOSRV_cIFAddr ] := _NETIOMGM_IPV4_DEF netiomgm[ _NETIOSRV_cRootDir ] := "*?:*?:" netiomgm[ _NETIOSRV_lAcceptConn ] := .T. netiomgm[ _NETIOSRV_lShowConn ] := .F. netiomgm[ _NETIOSRV_hConnection ] := { => } netiomgm[ _NETIOSRV_mtxConnection ] := hb_mutexCreate() netiomgm[ _NETIOSRV_hAllow ] := { "127.0.0.1" => NIL, "::1" => NIL } netiomgm[ _NETIOSRV_hBlock ] := { => } netiomgm[ _NETIOSRV_mtxFilters ] := hb_mutexCreate() netiomgm[ _NETIOSRV_hNotifStream ] := { => } netiomgm[ _NETIOSRV_mtxNotifStream ] := hb_mutexCreate() FOR EACH cParam IN { ... } DO CASE CASE Lower( cParam ) == "-a" CASE Lower( Left( cParam, 5 ) ) == "-noui" lUI := .F. CASE Lower( Left( cParam, 6 ) ) == "-port=" netiosrv[ _NETIOSRV_nPort ] := Val( SubStr( cParam, 7 ) ) CASE Lower( Left( cParam, 7 ) ) == "-iface=" netiosrv[ _NETIOSRV_cIFAddr ] := SubStr( cParam, 8 ) CASE Lower( Left( cParam, 9 ) ) == "-rootdir=" netiosrv[ _NETIOSRV_cRootDir ] := SubStr( cParam, 10 ) CASE Lower( Left( cParam, 6 ) ) == "-pass=" cPassword := SubStr( cParam, 7 ) hb_StrClear( @cParam ) CASE Lower( Left( cParam, 11 ) ) == "-adminport=" netiomgm[ _NETIOSRV_nPort ] := Val( SubStr( cParam, 12 ) ) CASE Lower( Left( cParam, 12 ) ) == "-adminiface=" netiomgm[ _NETIOSRV_cIFAddr ] := SubStr( cParam, 13 ) CASE Lower( Left( cParam, 11 ) ) == "-adminpass=" cPasswordManagement := SubStr( cParam, 12 ) hb_StrClear( @cParam ) CASE Lower( Left( cParam, 5 ) ) == "-rpc=" netiosrv[ _NETIOSRV_cRPCFFileName ] := SubStr( cParam, 6 ) hb_FNameSplit( netiosrv[ _NETIOSRV_cRPCFFileName ], NIL, NIL, @cExt ) cExt := Lower( cExt ) SWITCH cExt CASE ".prg" CASE ".hb" CASE ".hrb" EXIT OTHERWISE cExt := FileSig( cFile ) ENDSWITCH SWITCH cExt CASE ".prg" CASE ".hb" cFile := hb_compileBuf( hb_argv( 0 ), "-n2", "-w", "-es2", "-q0", ; "-D" + "__HBSCRIPT__HBNETIOSRV", netiosrv[ _NETIOSRV_cRPCFFileName ] ) IF cFile != NIL netiosrv[ _NETIOSRV_hRPCFHRB ] := hb_hrbLoad( HB_HRB_BIND_FORCELOCAL, cFile ) ENDIF EXIT OTHERWISE netiosrv[ _NETIOSRV_hRPCFHRB ] := hb_hrbLoad( HB_HRB_BIND_FORCELOCAL, netiosrv[ _NETIOSRV_cRPCFFileName ] ) EXIT ENDSWITCH netiosrv[ _NETIOSRV_lRPC ] := ! Empty( netiosrv[ _NETIOSRV_hRPCFHRB ] ) .AND. ! Empty( hb_hrbGetFunSym( netiosrv[ _NETIOSRV_hRPCFHRB ], _RPC_FILTER ) ) IF ! netiosrv[ _NETIOSRV_lRPC ] netiosrv[ _NETIOSRV_cRPCFFileName ] := NIL netiosrv[ _NETIOSRV_hRPCFHRB ] := NIL ENDIF CASE Lower( cParam ) == "-rpc" netiosrv[ _NETIOSRV_lRPC ] := .T. CASE Lower( cParam ) == "--version" RETURN CASE Lower( cParam ) == "-?" .OR. ; Lower( cParam ) == "-h" .OR. ; Lower( cParam ) == "-help" .OR. ; Lower( cParam ) == "--help" HB_Usage() RETURN OTHERWISE netiosrv_LogEvent( hb_StrFormat( "Warning: Unrecognized command-line parameter ignored: %1$s", cParam ) ) ENDCASE NEXT IF netiosrv_ConfLoad( netiosrv, netiomgm ) netiosrv_LogEvent( hb_StrFormat( "Configuration loaded: %1$s", netiosrv_ConfName() ) ) ENDIF hb_DirBuild( netiosrv[ _NETIOSRV_cRootDir ] ) netiosrv[ _NETIOSRV_pListenSocket ] := netio_MTServer( ; netiosrv[ _NETIOSRV_nPort ], ; netiosrv[ _NETIOSRV_cIFAddr ], ; netiosrv[ _NETIOSRV_cRootDir ], ; iif( Empty( netiosrv[ _NETIOSRV_hRPCFHRB ] ), netiosrv[ _NETIOSRV_lRPC ], hb_hrbGetFunSym( netiosrv[ _NETIOSRV_hRPCFHRB ], _RPC_FILTER ) ), ; cPassword, ; NIL, ; NIL, ; {| pConnectionSocket | netiosrv_callback( netiomgm, netiosrv, pConnectionSocket, .F. ) } ) netiosrv[ _NETIOSRV_lEncryption ] := ! Empty( cPassword ) cPassword := NIL IF Empty( netiosrv[ _NETIOSRV_pListenSocket ] ) netiosrv_LogEvent( "Cannot start server." ) ELSE netiosrv_LogEvent( "Ready to accept connections." ) IF ! Empty( cPasswordManagement ) netiomgm[ _NETIOSRV_pListenSocket ] := netio_MTServer( ; netiomgm[ _NETIOSRV_nPort ], ; netiomgm[ _NETIOSRV_cIFAddr ], ; netiomgm[ _NETIOSRV_cRootDir ], ; { ; "hbnetiomgm_ping" => {| ... | .T. }, ; "hbnetiomgm_setclientinfo" => {| ... | netiomgm_rpc_setclientinfo( netiomgm, ... ) }, ; "hbnetiomgm_sysinfo" => {| ... | netiomgm_rpc_sysinfo() }, ; "hbnetiomgm_serverconfig" => {| ... | netiomgm_rpc_serverconfig( netiosrv, netiomgm ) }, ; "hbnetiomgm_clientinfo" => {| ... | netiomgm_rpc_clientinfo( netiosrv, netiomgm, ... ) }, ; "hbnetiomgm_shutdown" => {| ... | netiomgm_rpc_shutdown( netiosrv, netiomgm ) }, ; "hbnetiomgm_conninfo" => {| ... | netiomgm_rpc_conninfo( netiosrv ) }, ; "hbnetiomgm_adminfo" => {| ... | netiomgm_rpc_conninfo( netiomgm ) }, ; "hbnetiomgm_allowadd" => {| ... | netiomgm_rpc_filtermod( netiosrv, netiosrv[ _NETIOSRV_hAllow ], .T., ... ) }, ; "hbnetiomgm_allowdel" => {| ... | netiomgm_rpc_filtermod( netiosrv, netiosrv[ _NETIOSRV_hAllow ], .F., ... ) }, ; "hbnetiomgm_blockadd" => {| ... | netiomgm_rpc_filtermod( netiosrv, netiosrv[ _NETIOSRV_hBlock ], .T., ... ) }, ; "hbnetiomgm_blockdel" => {| ... | netiomgm_rpc_filtermod( netiosrv, netiosrv[ _NETIOSRV_hBlock ], .F., ... ) }, ; "hbnetiomgm_allowaddadmin" => {| ... | netiomgm_rpc_filtermod( netiomgm, netiomgm[ _NETIOSRV_hAllow ], .T., ... ) }, ; "hbnetiomgm_allowdeladmin" => {| ... | netiomgm_rpc_filtermod( netiomgm, netiomgm[ _NETIOSRV_hAllow ], .F., ... ) }, ; "hbnetiomgm_blockaddadmin" => {| ... | netiomgm_rpc_filtermod( netiomgm, netiomgm[ _NETIOSRV_hBlock ], .T., ... ) }, ; "hbnetiomgm_blockdeladmin" => {| ... | netiomgm_rpc_filtermod( netiomgm, netiomgm[ _NETIOSRV_hBlock ], .F., ... ) }, ; "hbnetiomgm_filters" => {| ... | netiomgm_rpc_filters( netiosrv ) }, ; "hbnetiomgm_filtersadmin" => {| ... | netiomgm_rpc_filters( netiomgm ) }, ; "hbnetiomgm_filtersave" => {| ... | netiomgm_rpc_filtersave( netiosrv, netiomgm ) }, ; "hbnetiomgm_stop" => {| ... | netiomgm_rpc_stop( netiosrv, ... ) }, ; "hbnetiomgm_conn" => {| ... | netiomgm_rpc_conn( netiosrv, .T. ) }, ; "hbnetiomgm_noconn" => {| ... | netiomgm_rpc_conn( netiosrv, .F. ) }, ; "hbnetiomgm_logconn" => {| ... | netiomgm_rpc_logconn( netiosrv, .T. ) }, ; "hbnetiomgm_nologconn" => {| ... | netiomgm_rpc_logconn( netiosrv, .F. ) }, ; "hbnetiomgm_regnotif" => {| ... | netiomgm_rpc_regnotif( netiomgm, ... ) } }, ; cPasswordManagement, ; NIL, ; NIL, ; {| pConnectionSocket | netiosrv_callback( netiomgm, netiomgm, pConnectionSocket, .T. ) } ) IF Empty( netiomgm[ _NETIOSRV_pListenSocket ] ) netiosrv_LogEvent( "Warning: Cannot start server management." ) ELSE IF lUI hb_threadDetach( hb_threadStart( {|| hbnetiocon_cmdUI( netiomgm[ _NETIOSRV_cIFAddr ], netiomgm[ _NETIOSRV_nPort ], cPasswordManagement ) } ) ) ENDIF ENDIF ENDIF ShowConfig( netiosrv, netiomgm ) IF ! Empty( netiomgm[ _NETIOSRV_pListenSocket ] ) hb_idleSleep( 2 ) netiomgm[ _NETIOSRV_lShowConn ] := .T. ENDIF DO WHILE ! netiosrv[ _NETIOSRV_lQuit ] .AND. inkey() != 27 hb_idleSleep( 5 ) ENDDO netio_ServerStop( netiosrv[ _NETIOSRV_pListenSocket ] ) netiosrv[ _NETIOSRV_pListenSocket ] := NIL IF ! Empty( netiomgm[ _NETIOSRV_pListenSocket ] ) netio_ServerStop( netiomgm[ _NETIOSRV_pListenSocket ] ) netiomgm[ _NETIOSRV_pListenSocket ] := NIL ENDIF netiosrv_LogEvent( "Server stopped." ) ENDIF RETURNSTATIC PROCEDURE netiosrv_LogEvent( cText ) QQOut( hb_TToC( hb_DateTime() ) + " " + cText + hb_eol() ) RETURN#define _NETIOSRV_SIGNATURE "netiosrv"STATIC FUNCTION netiosrv_ConfName() RETURN hb_ProgName() + ".config"STATIC FUNCTION netiosrv_ConfSave( netiosrv, netiomgm ) LOCAL hConf := { => } hConf[ "__signature" ] := _NETIOSRV_SIGNATURE hConf[ "__version" ] := 1 hConf[ "srv.showconn" ] := netiosrv[ _NETIOSRV_lShowConn ] hConf[ "srv.allow" ] := netiosrv[ _NETIOSRV_hAllow ] hConf[ "srv.block" ] := netiosrv[ _NETIOSRV_hBlock ] hConf[ "mgm.showconn" ] := netiomgm[ _NETIOSRV_lShowConn ] hConf[ "mgm.allow" ] := netiomgm[ _NETIOSRV_hAllow ] hConf[ "mgm.block" ] := netiomgm[ _NETIOSRV_hBlock ] RETURN hb_MemoWrit( netiosrv_ConfName(), hb_Serialize( hConf ) )STATIC FUNCTION netiosrv_ConfLoad( netiosrv, netiomgm ) LOCAL hConf := hb_Deserialize( hb_MemoRead( netiosrv_ConfName() ) ) IF HB_ISHASH( hConf ) .AND. ; "__signature" $ hConf .AND. ; hConf[ "__signature" ] == _NETIOSRV_SIGNATURE IF "srv.showconn" $ hConf netiosrv[ _NETIOSRV_lShowConn ] := hConf[ "srv.showconn" ] ENDIF IF "srv.allow" $ hConf netiosrv[ _NETIOSRV_hAllow ] := hConf[ "srv.allow" ] ENDIF IF "srv.block" $ hConf netiosrv[ _NETIOSRV_hBlock ] := hConf[ "srv.block" ] ENDIF IF "mgm.showconn" $ hConf netiomgm[ _NETIOSRV_lShowConn ] := hConf[ "mgm.showconn" ] ENDIF IF "mgm.allow" $ hConf netiomgm[ _NETIOSRV_hAllow ] := hConf[ "mgm.allow" ] ENDIF IF "mgm.block" $ hConf netiomgm[ _NETIOSRV_hBlock ] := hConf[ "mgm.block" ] ENDIF RETURN .T. ENDIF RETURN .F.STATIC FUNCTION netiosrv_config( netiosrv, netiomgm ) LOCAL aArray := { ; hb_StrFormat( "Listening on: %1$s:%2$d", netiosrv[ _NETIOSRV_cIFAddr ], netiosrv[ _NETIOSRV_nPort ] ), ; hb_StrFormat( "Root filesystem: %1$s", netiosrv[ _NETIOSRV_cRootDir ] ), ; hb_StrFormat( "RPC support: %1$s", iif( netiosrv[ _NETIOSRV_lRPC ], "enabled", "disabled" ) ), ; hb_StrFormat( "Encryption: %1$s", iif( netiosrv[ _NETIOSRV_lEncryption ], "enabled", "disabled" ) ), ; hb_StrFormat( "RPC filter module: %1$s", iif( Empty( netiosrv[ _NETIOSRV_hRPCFHRB ] ), iif( netiosrv[ _NETIOSRV_lRPC ], "not set (WARNING: unsafe open server)", "not set" ), netiosrv[ _NETIOSRV_cRPCFFileName ] ) ) } IF ! Empty( netiomgm[ _NETIOSRV_pListenSocket ] ) AAdd( aArray, hb_StrFormat( "Management iface: %1$s:%2$d", netiomgm[ _NETIOSRV_cIFAddr ], netiomgm[ _NETIOSRV_nPort ] ) ) ENDIF RETURN aArray#define _CLI_pConnSock 1#define _CLI_nStreamID 2#define _CLI_lNotify 3#define _CLI_nSendErrors 4#define _CLI_MAX_ 4STATIC PROCEDURE netiosrv_notifyclients( netiomgm, cMsg ) LOCAL aClient hb_mutexLock( netiomgm[ _NETIOSRV_mtxNotifStream ] ) FOR EACH aClient IN netiomgm[ _NETIOSRV_hNotifStream ] IF aClient[ _CLI_lNotify ] IF ! netio_SrvSendItem( aClient[ _CLI_pConnSock ], aClient[ _CLI_nStreamID ], hb_TToS( hb_DateTime() ) + " " + cMsg ) ++aClient[ _CLI_nSendErrors ] ENDIF ENDIF NEXT FOR EACH aClient IN netiomgm[ _NETIOSRV_hNotifStream ] DESCEND IF aClient[ _CLI_nSendErrors ] > 5 hb_HDel( netiomgm[ _NETIOSRV_hNotifStream ], aClient:__enumKey() ) ENDIF NEXT hb_mutexUnlock( netiomgm[ _NETIOSRV_mtxNotifStream ] ) RETURNSTATIC FUNCTION netiosrv_callback( netiomgm, netiosrv, pConnectionSocket, lManagement ) LOCAL aAddressPeer LOCAL cAddressPeer LOCAL lBlocked IF netiosrv[ _NETIOSRV_lAcceptConn ] netio_SrvStatus( pConnectionSocket, NETIO_SRVINFO_PEERADDRESS, @aAddressPeer ) cAddressPeer := AddrToIPPort( aAddressPeer ) lBlocked := .F. IF ! Empty( netiosrv[ _NETIOSRV_hAllow ] ) hb_mutexLock( netiosrv[ _NETIOSRV_mtxFilters ] ) IF ! cAddressPeer $ netiosrv[ _NETIOSRV_hAllow ] IF hb_HScan( netiosrv[ _NETIOSRV_hAllow ], {| tmp | hb_WildMatch( tmp, cAddressPeer ) } ) == 0 lBlocked := .T. ENDIF ENDIF hb_mutexUnlock( netiosrv[ _NETIOSRV_mtxFilters ] ) IF lBlocked IF ! lManagement netiosrv_notifyclients( netiomgm, hb_StrFormat( "Connection denied: %1$s", cAddressPeer ) ) ENDIF RETURN NIL ENDIF ENDIF IF ! Empty( netiosrv[ _NETIOSRV_hBlock ] ) hb_mutexLock( netiosrv[ _NETIOSRV_mtxFilters ] ) IF cAddressPeer $ netiosrv[ _NETIOSRV_hBlock ] lBlocked := .T. ELSE IF hb_HScan( netiosrv[ _NETIOSRV_hBlock ], {| tmp | hb_WildMatch( tmp, cAddressPeer ) } ) > 0 lBlocked := .T. ENDIF ENDIF hb_mutexUnlock( netiosrv[ _NETIOSRV_mtxFilters ] ) IF lBlocked IF ! lManagement netiosrv_notifyclients( netiomgm, hb_StrFormat( "Connection denied: %1$s", cAddressPeer ) ) ENDIF RETURN NIL ENDIF ENDIF IF netiosrv[ _NETIOSRV_lShowConn ] netiosrv_LogEvent( hb_StrFormat( "Connecting (%1$s): %2$s", netiosrv[ _NETIOSRV_cName ], cAddressPeer ) ) ENDIF IF ! lManagement netiosrv_notifyclients( netiomgm, hb_StrFormat( "Connecting: %1$s", cAddressPeer ) ) ENDIF netiosrv_conn_register( netiosrv, pConnectionSocket ) BEGIN SEQUENCE netio_Server( pConnectionSocket ) END SEQUENCE netiosrv_conn_unregister( netiosrv, pConnectionSocket ) netio_SrvStatus( pConnectionSocket, NETIO_SRVINFO_PEERADDRESS, @aAddressPeer ) IF netiosrv[ _NETIOSRV_lShowConn ] netiosrv_LogEvent( hb_StrFormat( "Disconnected (%1$s): %2$s", netiosrv[ _NETIOSRV_cName ], AddrToIPPort( aAddressPeer ) ) ) ENDIF IF ! lManagement netiosrv_notifyclients( netiomgm, hb_StrFormat( "Diconnected: %1$s", cAddressPeer ) ) ENDIF ENDIF RETURN NILSTATIC PROCEDURE netiosrv_conn_register( netiosrv, pConnectionSocket ) LOCAL nconn[ _NETIOSRV_CONN_MAX_ ] nconn[ _NETIOSRV_CONN_pConnection ] := pConnectionSocket nconn[ _NETIOSRV_CONN_nThreadID ] := hb_threadID() nconn[ _NETIOSRV_CONN_tStart ] := hb_DateTime() hb_mutexLock( netiosrv[ _NETIOSRV_mtxConnection ] ) IF ! pConnectionSocket $ netiosrv[ _NETIOSRV_hConnection ] netiosrv[ _NETIOSRV_hConnection ][ pConnectionSocket ] := nconn ENDIF hb_mutexUnlock( netiosrv[ _NETIOSRV_mtxConnection ] ) RETURNSTATIC PROCEDURE netiosrv_conn_unregister( netiosrv, pConnectionSocket ) hb_mutexLock( netiosrv[ _NETIOSRV_mtxConnection ] ) IF pConnectionSocket $ netiosrv[ _NETIOSRV_hConnection ] hb_HDel( netiosrv[ _NETIOSRV_hConnection ], pConnectionSocket ) ENDIF hb_mutexUnlock( netiosrv[ _NETIOSRV_mtxConnection ] ) RETURNSTATIC FUNCTION netiomgm_rpc_regnotif( netiomgm, pConnSock, nStreamID, lRegister ) LOCAL cIndex := hb_ValToStr( pConnSock ) LOCAL cli SWITCH PCount()#if 0 CASE 2 RETURN iif( cIndex $ netiomgm[ _NETIOSRV_hNotifStream ], netiomgm[ _NETIOSRV_hNotifStream ][ cIndex ][ _CLI_xCargo ], NIL )#endif CASE 4 IF ! HB_ISLOGICAL( lRegister ) .OR. ! lRegister hb_mutexLock( netiomgm[ _NETIOSRV_mtxNotifStream ] ) IF cIndex $ netiomgm[ _NETIOSRV_hNotifStream ] hb_HDel( netiomgm[ _NETIOSRV_hNotifStream ], cIndex ) ENDIF hb_mutexUnlock( netiomgm[ _NETIOSRV_mtxNotifStream ] ) RETURN -1 ELSE cli := Array( _CLI_MAX_ ) cli[ _CLI_pConnSock ] := pConnSock cli[ _CLI_nStreamID ] := nStreamID cli[ _CLI_lNotify ] := .T. cli[ _CLI_nSendErrors ] := 0 hb_mutexLock( netiomgm[ _NETIOSRV_mtxNotifStream ] ) netiomgm[ _NETIOSRV_hNotifStream ][ cIndex ] := cli hb_mutexUnlock( netiomgm[ _NETIOSRV_mtxNotifStream ] ) RETURN nStreamID ENDIF ENDSWITCH RETURN NILSTATIC FUNCTION netiomgm_rpc_setclientinfo( netiosrv, hInfo ) LOCAL nconn IF HB_ISHASH( hInfo ) hb_mutexLock( netiosrv[ _NETIOSRV_mtxConnection ] ) FOR EACH nconn IN netiosrv[ _NETIOSRV_hConnection ] IF nconn[ _NETIOSRV_CONN_nThreadID ] == hb_threadID() nconn[ _NETIOSRV_CONN_hInfo ] := hInfo EXIT ENDIF NEXT hb_mutexUnlock( netiosrv[ _NETIOSRV_mtxConnection ] ) ENDIF RETURN NILSTATIC FUNCTION netiomgm_rpc_sysinfo() RETURN { ; hb_StrFormat( "OS: %1$s", OS() ), ; hb_StrFormat( "Harbour: %1$s", Version() ), ; hb_StrFormat( "C Compiler: %1$s", hb_Compiler() ), ; hb_StrFormat( "Memory (KB): %1$d", Memory( 0 ) ) }STATIC FUNCTION netiomgm_rpc_serverconfig( netiosrv, netiomgm ) RETURN netiosrv_config( netiosrv, netiomgm )STATIC FUNCTION netiomgm_rpc_logconn( netiosrv, lValue ) LOCAL lOldValue := netiosrv[ _NETIOSRV_lShowConn ] IF HB_ISLOGICAL( lValue ) netiosrv[ _NETIOSRV_lShowConn ] := lValue ENDIF RETURN lOldValueSTATIC FUNCTION netiomgm_rpc_conn( netiosrv, lValue ) LOCAL lOldValue := netiosrv[ _NETIOSRV_lAcceptConn ] IF HB_ISLOGICAL( lValue ) netiosrv[ _NETIOSRV_lAcceptConn ] := lValue ENDIF RETURN lOldValueSTATIC FUNCTION netiomgm_rpc_stop( netiosrv, cIPPort ) LOCAL nconn LOCAL aAddressPeer IF HB_ISSTRING( cIPPort ) cIPPort := Lower( cIPPort ) hb_mutexLock( netiosrv[ _NETIOSRV_mtxConnection ] ) FOR EACH nconn IN netiosrv[ _NETIOSRV_hConnection ] aAddressPeer := NIL netio_SrvStatus( nconn[ _NETIOSRV_CONN_pConnection ], NETIO_SRVINFO_PEERADDRESS, @aAddressPeer ) IF cIPPort == "all" .OR. cIPPort == AddrToIPPort( aAddressPeer ) netiosrv_LogEvent( hb_StrFormat( "Stopping connection on %1$s", AddrToIPPort( aAddressPeer ) ) ) netio_ServerStop( nconn[ _NETIOSRV_CONN_pConnection ], .T. ) ENDIF NEXT hb_mutexUnlock( netiosrv[ _NETIOSRV_mtxConnection ] ) RETURN .T. ENDIF RETURN .F.STATIC FUNCTION netiomgm_rpc_clientinfo( netiosrv, netiomgm, cIPPort ) LOCAL nconn LOCAL aAddressPeer LOCAL xCargo := NIL LOCAL lDone IF HB_ISSTRING( cIPPort ) cIPPort := Lower( cIPPort ) lDone := .F. IF ! lDone hb_mutexLock( netiosrv[ _NETIOSRV_mtxConnection ] ) FOR EACH nconn IN netiosrv[ _NETIOSRV_hConnection ] aAddressPeer := NIL netio_SrvStatus( nconn[ _NETIOSRV_CONN_pConnection ], NETIO_SRVINFO_PEERADDRESS, @aAddressPeer ) IF cIPPort == AddrToIPPort( aAddressPeer ) xCargo := nconn[ _NETIOSRV_CONN_hInfo ] lDone := .T. EXIT ENDIF NEXT hb_mutexUnlock( netiosrv[ _NETIOSRV_mtxConnection ] ) ENDIF IF ! lDone hb_mutexLock( netiomgm[ _NETIOSRV_mtxConnection ] ) FOR EACH nconn IN netiomgm[ _NETIOSRV_hConnection ] aAddressPeer := NIL netio_SrvStatus( nconn[ _NETIOSRV_CONN_pConnection ], NETIO_SRVINFO_PEERADDRESS, @aAddressPeer ) IF cIPPort == AddrToIPPort( aAddressPeer ) xCargo := nconn[ _NETIOSRV_CONN_hInfo ] EXIT ENDIF NEXT hb_mutexUnlock( netiomgm[ _NETIOSRV_mtxConnection ] ) ENDIF ENDIF RETURN xCargoSTATIC FUNCTION netiomgm_rpc_shutdown( netiosrv, netiomgm ) netiosrv_LogEvent( "Shutdown initiated..." ) netiosrv_notifyclients( netiomgm, "__SHUTDOWN__" ) netiosrv[ _NETIOSRV_lQuit ] := .T. RETURN .T.STATIC FUNCTION netiomgm_rpc_conninfo( netiosrv ) LOCAL nconn LOCAL nStatus LOCAL nFilesCount LOCAL nBytesSent LOCAL nBytesReceived LOCAL aAddressPeer LOCAL aArray := {} hb_mutexLock( netiosrv[ _NETIOSRV_mtxConnection ] ) FOR EACH nconn IN netiosrv[ _NETIOSRV_hConnection ] nFilesCount := 0 nBytesSent := 0 nBytesReceived := 0 aAddressPeer := NIL nStatus := ; netio_SrvStatus( nconn[ _NETIOSRV_CONN_pConnection ], NETIO_SRVINFO_FILESCOUNT, @nFilesCount ) netio_SrvStatus( nconn[ _NETIOSRV_CONN_pConnection ], NETIO_SRVINFO_BYTESSENT, @nBytesSent ) netio_SrvStatus( nconn[ _NETIOSRV_CONN_pConnection ], NETIO_SRVINFO_BYTESRECEIVED, @nBytesReceived ) netio_SrvStatus( nconn[ _NETIOSRV_CONN_pConnection ], NETIO_SRVINFO_PEERADDRESS, @aAddressPeer ) AAdd( aArray, { ; "nThreadID" => nconn[ _NETIOSRV_CONN_nThreadID ], ; "tStart" => nconn[ _NETIOSRV_CONN_tStart ], ; "cStatus" => ConnStatusStr( nStatus ), ; "nFilesCount" => nFilesCount, ; "nBytesSent" => nBytesSent, ; "nBytesReceived" => nBytesReceived, ; "cAddressPeer" => AddrToIPPort( aAddressPeer ), ; "xCargo" => nconn[ _NETIOSRV_CONN_hInfo ] } ) NEXT hb_mutexUnlock( netiosrv[ _NETIOSRV_mtxConnection ] ) RETURN aArraySTATIC FUNCTION netiomgm_rpc_filtermod( netiosrv, hList, lAdd, cAddress ) LOCAL lSuccess := .T. hb_mutexLock( netiosrv[ _NETIOSRV_mtxFilters ] ) IF lAdd IF ! cAddress $ hList hList[ cAddress ] := NIL ELSE lSuccess := .F. ENDIF ELSE IF cAddress $ hList hb_HDel( hList, cAddress ) ELSE lSuccess := .F. ENDIF ENDIF hb_mutexUnlock( netiosrv[ _NETIOSRV_mtxFilters ] ) RETURN lSuccessSTATIC FUNCTION netiomgm_rpc_filters( netiosrv ) LOCAL cType LOCAL hFilter LOCAL cAddress LOCAL aArray := {} hb_mutexLock( netiosrv[ _NETIOSRV_mtxFilters ] ) FOR EACH cType, hFilter IN { "allow", "block" }, { netiosrv[ _NETIOSRV_hAllow ], netiosrv[ _NETIOSRV_hBlock ] } FOR EACH cAddress IN hFilter AAdd( aArray, { ; "cType" => cType, ; "cAddress" => cAddress:__enumKey() } ) NEXT NEXT hb_mutexUnlock( netiosrv[ _NETIOSRV_mtxFilters ] ) RETURN aArraySTATIC FUNCTION netiomgm_rpc_filtersave( netiosrv, netiomgm ) RETURN netiosrv_ConfSave( netiosrv, netiomgm )STATIC FUNCTION ConnStatusStr( nStatus ) SWITCH nStatus CASE NETIO_SRVSTAT_RUNNING ; RETURN "RUNNING" CASE NETIO_SRVSTAT_WRONGHANDLE ; RETURN "WRONGHANDLE" CASE NETIO_SRVSTAT_CLOSED ; RETURN "CLOSED" CASE NETIO_SRVSTAT_STOPPED ; RETURN "STOPPED" CASE NETIO_SRVSTAT_DATASTREAM ; RETURN "DATASTREAM" CASE NETIO_SRVSTAT_ITEMSTREAM ; RETURN "ITEMSTREAM" ENDSWITCH RETURN "UNKNOWN:" + hb_ntos( nStatus )STATIC FUNCTION AddrToIPPort( aAddr ) LOCAL cIP IF HB_ISARRAY( aAddr ) .AND. ; ( aAddr[ HB_SOCKET_ADINFO_FAMILY ] == HB_SOCKET_AF_INET .OR. ; aAddr[ HB_SOCKET_ADINFO_FAMILY ] == HB_SOCKET_AF_INET6 ) cIP := aAddr[ HB_SOCKET_ADINFO_ADDRESS ] + ":" + hb_ntos( aAddr[ HB_SOCKET_ADINFO_PORT ] ) ELSE cIP := "(?)" ENDIF RETURN cIPSTATIC FUNCTION FileSig( cFile ) LOCAL hFile LOCAL cBuff, cSig, cExt cExt := ".prg" hFile := FOpen( cFile, FO_READ ) IF hFile != F_ERROR cSig := hb_hrbSignature() cBuff := Space( hb_BLen( cSig ) ) FRead( hFile, @cBuff, hb_BLen( cBuff ) ) FClose( hFile ) IF cBuff == cSig cExt := ".hrb" ENDIF ENDIF RETURN cExtSTATIC PROCEDURE ShowConfig( netiosrv, netiomgm ) AEval( netiosrv_config( netiosrv, netiomgm ), {| tmp | netiosrv_LogEvent( tmp ) } ) RETURNSTATIC PROCEDURE HB_Logo() OutStd( ; "Harbour NETIO Server " + StrTran( Version(), "Harbour " ) + hb_eol() + ; "Copyright (c) 2009-" + ; "2020" + ", " + ; "Przemyslaw Czerpak, Viktor Szakats" + hb_eol() + ; hb_Version( HB_VERSION_URL_BASE ) + hb_eol() + ; hb_eol() ) RETURNSTATIC PROCEDURE HB_Usage() OutStd( "Syntax:" , hb_eol() ) OutStd( hb_eol() ) OutStd( " netiosrv [options]" , hb_eol() ) OutStd( hb_eol() ) OutStd( "Options:" , hb_eol() ) OutStd( hb_eol() ) OutStd( " -port=<port> accept incoming connections on IP port <port>" , hb_eol() ) OutStd( hb_StrFormat( " Default: %1$d", _NETIOSRV_PORT_DEF ) , hb_eol() ) OutStd( " -iface=<ipaddr> accept incoming connections on IPv4 interface <ipaddress>" , hb_eol() ) OutStd( hb_StrFormat( " Default: %1$s", _NETIOSRV_IPV4_DEF ) , hb_eol() ) OutStd( " -rootdir=<rootdir> use <rootdir> as root directory for served file system" , hb_eol() ) OutStd( " -rpc accept RPC requests" , hb_eol() ) OutStd( " -rpc=<file.hrb> set RPC processor .hrb module to <file.hrb>" , hb_eol() ) OutStd( " file.hrb needs to have an entry function named" , hb_eol() ) OutStd( hb_StrFormat( " '%1$s()'", _RPC_FILTER ) , hb_eol() ) OutStd( " -pass=<passwd> set server password" , hb_eol() ) OutStd( hb_eol() ) OutStd( " -adminport=<port> accept management connections on IP port <port>" , hb_eol() ) OutStd( hb_StrFormat( " Default: %1$d", _NETIOMGM_PORT_DEF ) , hb_eol() ) OutStd( " -adminiface=<ipaddr> accept manegement connections on IPv4 interface <ipaddress>" , hb_eol() ) OutStd( hb_StrFormat( " Default: %1$s", _NETIOMGM_IPV4_DEF ) , hb_eol() ) OutStd( " -adminpass=<passwd> set remote management password and enable management server" , hb_eol() ) OutStd( hb_eol() ) OutStd( " -noui don't open interactive console" , hb_eol() ) OutStd( hb_eol() ) #if ! defined( __HBSCRIPT__HBSHELL ) .AND. defined( __PLATFORM__WINDOWS ) OutStd( " -i install as service (requires admin rights)" , hb_eol() ) OutStd( " -u uninstall service (requires admin rights)" , hb_eol() ) OutStd( hb_eol() ) #endif OutStd( " --version display version header only" , hb_eol() ) OutStd( " -?|-h|-help|--help this help" , hb_eol() ) RETURN#if defined( __HBSCRIPT__HBSHELL )SET PROCEDURE TO "_console.prg"SET PROCEDURE TO "netiomgm.hb"#endif*function ping()return 'hola desde el server hbnetio '