2010-01-06 17:15 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/src/rtl/hbznet.c
! do not use DEF_MEM_LEVEL to avoid potential problems when <zutil.h>
is not available
* harbour/contrib/hbnetio/netio.h
* harbour/contrib/hbnetio/netiocli.c
* harbour/contrib/hbnetio/netiosrv.c
+ implemented RPC in HBNETIO protocol
+ added the following client functions:
check if function/procedure exists on the server side:
NETIO_PROCEXISTS( <cProcName> ) -> <lExists>
execute function/procedure on server the side,
do not wait for confirmation:
NETIO_PROCEXEC( <cProcName> [, <params,...>] ) -> <lSent>
execute function/procedure on the server side and wait for
confirmation:
NETIO_PROCEXECW( <cProcName> [, <params,...>] ) -> <lExecuted>
execute function on the server side and wait for its return value:
NETIO_FUNCEXEC( <cFuncName> [, <params,...>] ) -> <xFuncRetVal>
All above functions use default connection set by NETIO_CONNECT()
for RPCs but it's also possible to specify server address and port
in <cProcName>/<cFuncName> just like in <cFileName> parameter in RDD
functions, i.e.:
NETIO_PROCEXISTS( "192.168.0.1:10005:MYFUNC" )
+ added new server side functions to enable/disable/check RPC support:
NETIO_RPC( <pListenSocket> | <pConnectionSocket> [, <lEnable> ] )
-> <lEnabled>
if RPC is enabled for listen socket then connection sockets inherit
this setting.
+ added 4-th parameter <lRPC> to NETIO_LISTEN() function. .T. enable
RPC support in returned listen socket which is later inherited by
connection sockets
* changed protocol version ID - current NETIO clients and servers
cannot be used with old code
* harbour/contrib/hbnetio/utils/netiosrv.prg
* added option to enable RPC support in NETIO server
If you want to make some test then you can execute netiosrv with
non empty 4-th parameter as server, i.e.:
./netiosrv "" "" "" 1
and try this code as client:
proc main()
// pass server address to netio_connect() for non localhost tests
? "NETIO_CONNECT():", netio_connect()
?
? "DATE() function is supported:", netio_procexists( "DATE" )
? "QOUT() function is supported:", netio_procexists( "DATE" )
? "HB_DATETIME() function is supported:", ;
netio_procexists( "HB_DATETIME" )
?
? netio_procexec( "QOUT", repl( "=", 50 ) )
? netio_procexec( "QOUT", "This is RPC TEST", date(), hb_datetime() )
? netio_procexecw( "QOUT", repl( "=", 50 ) )
?
? "SERVER DATE:", netio_funcexec( "DATE" )
? "SERVER TIME:", netio_funcexec( "TIME" )
? "SERVER DATETIME:", netio_funcexec( "HB_DATETIME" )
?
? netio_funcexec( "upper", "hello world !!!" )
return
Please remember that only functions linked with server are available.
If you want to enabled all core functions in netiosrv then please
uncomment this line in netiosrv.prg:
REQUEST __HB_EXTERN__
Have a fun with a new toy. I hope that many Harbour user will find it
very interesting. Please only be careful !!!. This feature allows to
execute remotely _ANY_ code on the server side. _NEVER_ leave open ports
with RPC support for untrusted access.
This commit is contained in:
@@ -17,6 +17,81 @@
|
||||
past entries belonging to author(s): Viktor Szakats.
|
||||
*/
|
||||
|
||||
2010-01-06 17:15 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
|
||||
* harbour/src/rtl/hbznet.c
|
||||
! do not use DEF_MEM_LEVEL to avoid potential problems when <zutil.h>
|
||||
is not available
|
||||
|
||||
* harbour/contrib/hbnetio/netio.h
|
||||
* harbour/contrib/hbnetio/netiocli.c
|
||||
* harbour/contrib/hbnetio/netiosrv.c
|
||||
+ implemented RPC in HBNETIO protocol
|
||||
+ added the following client functions:
|
||||
check if function/procedure exists on the server side:
|
||||
NETIO_PROCEXISTS( <cProcName> ) -> <lExists>
|
||||
execute function/procedure on server the side,
|
||||
do not wait for confirmation:
|
||||
NETIO_PROCEXEC( <cProcName> [, <params,...>] ) -> <lSent>
|
||||
execute function/procedure on the server side and wait for
|
||||
confirmation:
|
||||
NETIO_PROCEXECW( <cProcName> [, <params,...>] ) -> <lExecuted>
|
||||
execute function on the server side and wait for its return value:
|
||||
NETIO_FUNCEXEC( <cFuncName> [, <params,...>] ) -> <xFuncRetVal>
|
||||
All above functions use default connection set by NETIO_CONNECT()
|
||||
for RPCs but it's also possible to specify server address and port
|
||||
in <cProcName>/<cFuncName> just like in <cFileName> parameter in RDD
|
||||
functions, i.e.:
|
||||
NETIO_PROCEXISTS( "192.168.0.1:10005:MYFUNC" )
|
||||
+ added new server side functions to enable/disable/check RPC support:
|
||||
NETIO_RPC( <pListenSocket> | <pConnectionSocket> [, <lEnable> ] )
|
||||
-> <lEnabled>
|
||||
if RPC is enabled for listen socket then connection sockets inherit
|
||||
this setting.
|
||||
+ added 4-th parameter <lRPC> to NETIO_LISTEN() function. .T. enable
|
||||
RPC support in returned listen socket which is later inherited by
|
||||
connection sockets
|
||||
* changed protocol version ID - current NETIO clients and servers
|
||||
cannot be used with old code
|
||||
|
||||
* harbour/contrib/hbnetio/utils/netiosrv.prg
|
||||
* added option to enable RPC support in NETIO server
|
||||
|
||||
If you want to make some test then you can execute netiosrv with
|
||||
non empty 4-th parameter as server, i.e.:
|
||||
./netiosrv "" "" "" 1
|
||||
and try this code as client:
|
||||
|
||||
proc main()
|
||||
// pass server address to netio_connect() for non localhost tests
|
||||
? "NETIO_CONNECT():", netio_connect()
|
||||
?
|
||||
? "DATE() function is supported:", netio_procexists( "DATE" )
|
||||
? "QOUT() function is supported:", netio_procexists( "DATE" )
|
||||
? "HB_DATETIME() function is supported:", ;
|
||||
netio_procexists( "HB_DATETIME" )
|
||||
?
|
||||
? netio_procexec( "QOUT", repl( "=", 50 ) )
|
||||
? netio_procexec( "QOUT", "This is RPC TEST", date(), hb_datetime() )
|
||||
? netio_procexecw( "QOUT", repl( "=", 50 ) )
|
||||
?
|
||||
? "SERVER DATE:", netio_funcexec( "DATE" )
|
||||
? "SERVER TIME:", netio_funcexec( "TIME" )
|
||||
? "SERVER DATETIME:", netio_funcexec( "HB_DATETIME" )
|
||||
?
|
||||
? netio_funcexec( "upper", "hello world !!!" )
|
||||
return
|
||||
|
||||
Please remember that only functions linked with server are available.
|
||||
If you want to enabled all core functions in netiosrv then please
|
||||
uncomment this line in netiosrv.prg:
|
||||
REQUEST __HB_EXTERN__
|
||||
|
||||
|
||||
Have a fun with a new toy. I hope that many Harbour user will find it
|
||||
very interesting. Please only be careful !!!. This feature allows to
|
||||
execute remotely _ANY_ code on the server side. _NEVER_ leave open ports
|
||||
with RPC support for untrusted access.
|
||||
|
||||
2010-01-06 00:21 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com)
|
||||
* contrib/hbide/hbide.prg
|
||||
* contrib/hbide/idedocks.prg
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
#define NETIO_SERVERNAME_MAX 256
|
||||
|
||||
/* login string */
|
||||
#define NETIO_LOGINSTRID "HarbourFileTcpIpServer\005"
|
||||
#define NETIO_LOGINSTRID "HarbourFileTcpIpServer\006"
|
||||
|
||||
/* messages */
|
||||
#define NETIO_LOGIN 1
|
||||
@@ -91,6 +91,10 @@
|
||||
#define NETIO_CLOSE 13
|
||||
#define NETIO_ERROR 14
|
||||
#define NETIO_SYNC 15
|
||||
#define NETIO_PROCIS 16
|
||||
#define NETIO_PROC 17
|
||||
#define NETIO_PROCW 18
|
||||
#define NETIO_FUNC 19
|
||||
#define NETIO_CONNECTED 0x4321DEAD
|
||||
|
||||
/* messages format */
|
||||
@@ -104,9 +108,13 @@
|
||||
/* { NETIO_LOCK, file_no[2], start[ 8 ], len[ 8 ], flags[ 2 ], ... } -> { NETIO_LOCK, ... } */
|
||||
/* { NETIO_TRUNC, file_no[2], offset[ 8 ], ... } -> { NETIO_TRUNC, ... } */
|
||||
/* { NETIO_SIZE, file_no[2], ... } -> { NETIO_SIZE, size[ 8 ], err[ 4 ], ... } */
|
||||
/* { NETIO_COMMIT, file_no[2], ... } -> { NETIO_SYNC, ... } */
|
||||
/* { NETIO_COMMIT, file_no[2], ... } -> { NETIO_SYNC, ... } | NULL */
|
||||
/* { NETIO_CLOSE, file_no[2], ... } -> { NETIO_CLOSE, ... } */
|
||||
/* { NETIO_UNLOCK, file_no[2], start[ 8 ], len[ 8 ], flags[ 2 ], ... } -> { NETIO_SYNC, ... } */
|
||||
/* { NETIO_UNLOCK, file_no[2], start[ 8 ], len[ 8 ], flags[ 2 ], ... } -> { NETIO_SYNC, ... } | NULL */
|
||||
/* { NETIO_PROCIS, size[ 4 ] } + (funcname + \0 + data)[ size ] -> { NETIO_PROCIS, ... } */
|
||||
/* { NETIO_PROC, size[ 4 ] } + (funcname + \0 + data)[ size ] -> { NETIO_SYNC, ... } | NULL */
|
||||
/* { NETIO_PROCW, size[ 4 ] } + (funcname + \0 + data)[ size ] -> { NETIO_PROC, ... } */
|
||||
/* { NETIO_FUNC, size[ 4 ] } + (funcname + \0 + data)[ size ] -> { NETIO_FUNC, size[ 4 ] } + data[ size ] */
|
||||
/* { NETIO_SYNC, ... } -> NULL */
|
||||
/* alternative answer for all messages: -> { NETIO_ERROR, err[ 4 ], ... } */
|
||||
|
||||
@@ -118,3 +126,5 @@
|
||||
#define NETIO_ERR_FILES_MAX 0xff05
|
||||
#define NETIO_ERR_READ 0xff06
|
||||
#define NETIO_ERR_FILE_IO 0xff07
|
||||
#define NETIO_ERR_NOT_EXISTS 0xff08
|
||||
#define NETIO_ERR_UNSUPPORTED 0xff09
|
||||
|
||||
@@ -468,6 +468,8 @@ static void s_netio_init( void )
|
||||
}
|
||||
}
|
||||
|
||||
/* NETIO_CONNECT( [<cServer>], [<cPort>], [<nTimeOut>] ) -> <lOK>
|
||||
*/
|
||||
HB_FUNC( NETIO_CONNECT )
|
||||
{
|
||||
const char * pszServer = hb_parc( 1 );
|
||||
@@ -491,6 +493,133 @@ HB_FUNC( NETIO_CONNECT )
|
||||
hb_retl( conn != NULL );
|
||||
}
|
||||
|
||||
static const char * s_netio_params( int iMsg, const char * pszName, UINT32 * pSize, char ** pFree )
|
||||
{
|
||||
int iPCount = iMsg == NETIO_PROCIS ? 0 : hb_pcount(), i;
|
||||
char * data = NULL, * itmData;
|
||||
ULONG size = 0, itmSize;
|
||||
|
||||
size = ( ULONG ) strlen( pszName ) + 1;
|
||||
|
||||
for( i = 2; i <= iPCount; ++i )
|
||||
{
|
||||
itmData = hb_itemSerialize( hb_param( i, HB_IT_ANY ), TRUE, &itmSize );
|
||||
if( data == NULL )
|
||||
data = ( char * ) memcpy( hb_xgrab( size + itmSize ), pszName, size );
|
||||
else
|
||||
data = ( char * ) hb_xrealloc( data, size + itmSize );
|
||||
memcpy( data + size, itmData, itmSize );
|
||||
size += itmSize;
|
||||
hb_xfree( itmData );
|
||||
}
|
||||
|
||||
*pFree = data;
|
||||
*pSize = ( UINT32 ) size;
|
||||
|
||||
return data ? data : pszName;
|
||||
}
|
||||
|
||||
static BOOL s_netio_procexec( const char * pszProcName, int iMsg )
|
||||
{
|
||||
BOOL fResult = FALSE;
|
||||
|
||||
if( pszProcName )
|
||||
{
|
||||
PHB_CONCLI conn = s_fileConnect( &pszProcName, NULL, 0, 0 );
|
||||
if( conn )
|
||||
{
|
||||
if( s_fileConLock( conn ) )
|
||||
{
|
||||
BYTE msgbuf[ NETIO_MSGLEN ];
|
||||
const char * data;
|
||||
char * buffer;
|
||||
UINT32 size;
|
||||
|
||||
data = s_netio_params( iMsg, pszProcName, &size, &buffer );
|
||||
HB_PUT_LE_UINT32( &msgbuf[ 0 ], iMsg );
|
||||
HB_PUT_LE_UINT32( &msgbuf[ 4 ], size );
|
||||
memset( msgbuf + 8, '\0', sizeof( msgbuf ) - 8 );
|
||||
fResult = s_fileSendMsg( conn, msgbuf, data, size, iMsg != NETIO_PROC );
|
||||
if( fResult && iMsg == NETIO_FUNC )
|
||||
{
|
||||
ULONG ulResult = HB_GET_LE_UINT32( &msgbuf[ 4 ] );
|
||||
|
||||
if( ulResult > 0 )
|
||||
{
|
||||
PHB_ITEM pItem;
|
||||
|
||||
if( ulResult > size && buffer )
|
||||
{
|
||||
hb_xfree( buffer );
|
||||
buffer = NULL;
|
||||
}
|
||||
if( buffer == NULL )
|
||||
buffer = ( char * ) hb_xgrab( ulResult );
|
||||
ulResult = s_fileRecvAll( conn, buffer, ulResult );
|
||||
data = buffer;
|
||||
pItem = hb_itemDeserialize( &data, &ulResult );
|
||||
if( pItem )
|
||||
hb_itemReturnRelease( pItem );
|
||||
/* else TODO: RTE */
|
||||
}
|
||||
}
|
||||
if( buffer )
|
||||
hb_xfree( buffer );
|
||||
s_fileConUnlock( conn );
|
||||
}
|
||||
s_fileConClose( conn );
|
||||
}
|
||||
}
|
||||
|
||||
return fResult;
|
||||
}
|
||||
|
||||
/* check if function/procedure exists on the server side:
|
||||
*
|
||||
* NETIO_PROCEXISTS( <cProcName> ) -> <lExists>
|
||||
*/
|
||||
HB_FUNC( NETIO_PROCEXISTS )
|
||||
{
|
||||
const char * pszProcName = hb_parc( 1 );
|
||||
|
||||
hb_retl( s_netio_procexec( pszProcName, NETIO_PROCIS ) );
|
||||
}
|
||||
|
||||
/* execute function/procedure on server the side,
|
||||
* do not wait for confirmation:
|
||||
*
|
||||
* NETIO_PROCEXEC( <cProcName> [, <params,...>] ) -> <lSent>
|
||||
*/
|
||||
HB_FUNC( NETIO_PROCEXEC )
|
||||
{
|
||||
const char * pszProcName = hb_parc( 1 );
|
||||
|
||||
hb_retl( s_netio_procexec( pszProcName, NETIO_PROC ) );
|
||||
}
|
||||
|
||||
/* execute function/procedure on the server side and wait for
|
||||
* confirmation:
|
||||
*
|
||||
* NETIO_PROCEXECW( <cProcName> [, <params,...>] ) -> <lExecuted>
|
||||
*/
|
||||
HB_FUNC( NETIO_PROCEXECW )
|
||||
{
|
||||
const char * pszProcName = hb_parc( 1 );
|
||||
|
||||
hb_retl( s_netio_procexec( pszProcName, NETIO_PROCW ) );
|
||||
}
|
||||
|
||||
/* execute function on the server side and wait for its return value:
|
||||
*
|
||||
* NETIO_FUNCEXEC( <cFuncName> [, <params,...>] ) -> <xFuncRetVal>
|
||||
*/
|
||||
HB_FUNC( NETIO_FUNCEXEC )
|
||||
{
|
||||
const char * pszProcName = hb_parc( 1 );
|
||||
|
||||
s_netio_procexec( pszProcName, NETIO_FUNC );
|
||||
}
|
||||
|
||||
/* Client methods
|
||||
*/
|
||||
static BOOL s_fileAccept( const char * pFilename )
|
||||
|
||||
@@ -61,11 +61,13 @@
|
||||
*/
|
||||
|
||||
#include "hbapi.h"
|
||||
#include "hbapiitm.h"
|
||||
#include "hbapifs.h"
|
||||
#include "hbapierr.h"
|
||||
#include "hbsocket.h"
|
||||
#include "hbinit.h"
|
||||
#include "hbvm.h"
|
||||
#include "hbstack.h"
|
||||
#include "hbthread.h"
|
||||
#include "netio.h"
|
||||
|
||||
@@ -81,6 +83,7 @@ typedef struct _HB_CONSRV
|
||||
int filesCount;
|
||||
int firstFree;
|
||||
BOOL stop;
|
||||
BOOL rpc;
|
||||
int rootPathLen;
|
||||
char rootPath[ HB_PATH_MAX ];
|
||||
}
|
||||
@@ -90,6 +93,7 @@ typedef struct _HB_LISTENSD
|
||||
{
|
||||
HB_SOCKET sd;
|
||||
BOOL stop;
|
||||
BOOL rpc;
|
||||
char rootPath[ HB_PATH_MAX ];
|
||||
}
|
||||
HB_LISTENSD, * PHB_LISTENSD;
|
||||
@@ -263,11 +267,12 @@ static void s_consrvRet( PHB_CONSRV conn )
|
||||
hb_ret();
|
||||
}
|
||||
|
||||
static PHB_CONSRV s_consrvNew( HB_SOCKET connsd, const char * szRootPath )
|
||||
static PHB_CONSRV s_consrvNew( HB_SOCKET connsd, const char * szRootPath, BOOL rpc )
|
||||
{
|
||||
PHB_CONSRV conn = ( PHB_CONSRV ) memset( hb_xgrab( sizeof( HB_CONSRV ) ),
|
||||
0, sizeof( HB_CONSRV ) );
|
||||
conn->sd = connsd;
|
||||
conn->rpc = rpc;
|
||||
if( szRootPath )
|
||||
{
|
||||
hb_strncpy( conn->rootPath, szRootPath, sizeof( conn->rootPath ) - 1 );
|
||||
@@ -355,7 +360,7 @@ static PHB_LISTENSD s_listenParam( int iParam, BOOL fError )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void s_listenRet( HB_SOCKET sd, const char * szRootPath )
|
||||
static void s_listenRet( HB_SOCKET sd, const char * szRootPath, BOOL rpc )
|
||||
{
|
||||
if( sd != HB_NO_SOCKET )
|
||||
{
|
||||
@@ -365,6 +370,7 @@ static void s_listenRet( HB_SOCKET sd, const char * szRootPath )
|
||||
lsd = ( PHB_LISTENSD ) memset( hb_xgrab( sizeof( HB_LISTENSD ) ),
|
||||
0, sizeof( HB_LISTENSD ) );
|
||||
lsd->sd = sd;
|
||||
lsd->rpc = rpc;
|
||||
if( szRootPath )
|
||||
hb_strncpy( lsd->rootPath, szRootPath, sizeof( lsd->rootPath ) - 1 );
|
||||
else
|
||||
@@ -389,6 +395,29 @@ static void s_listenRet( HB_SOCKET sd, const char * szRootPath )
|
||||
}
|
||||
|
||||
|
||||
HB_FUNC( NETIO_RPC )
|
||||
{
|
||||
PHB_LISTENSD lsd = s_listenParam( 1, FALSE );
|
||||
BOOL fRPC = FALSE;
|
||||
|
||||
if( lsd )
|
||||
{
|
||||
fRPC = lsd->rpc;
|
||||
if( HB_ISLOG( 2 ) )
|
||||
lsd->rpc = hb_parl( 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
PHB_CONSRV conn = s_consrvParam( 1 );
|
||||
if( conn )
|
||||
{
|
||||
fRPC = conn->rpc;
|
||||
if( HB_ISLOG( 2 ) )
|
||||
conn->rpc = hb_parl( 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HB_FUNC( NETIO_SERVERSTOP )
|
||||
{
|
||||
PHB_LISTENSD lsd = s_listenParam( 1, FALSE );
|
||||
@@ -400,7 +429,7 @@ HB_FUNC( NETIO_SERVERSTOP )
|
||||
{
|
||||
PHB_CONSRV conn = s_consrvParam( 1 );
|
||||
if( conn )
|
||||
lsd->stop = fStop;
|
||||
conn->stop = fStop;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,6 +440,7 @@ HB_FUNC( NETIO_LISTEN )
|
||||
int iPort = hb_parnidef( 1, NETIO_DEFAULT_PORT );
|
||||
const char * szAddress = hb_parc( 2 );
|
||||
const char * szRootPath = hb_parc( 3 );
|
||||
BOOL fRPC = hb_parl( 4 );
|
||||
void * pSockAddr;
|
||||
unsigned uiLen;
|
||||
HB_SOCKET sd = HB_NO_SOCKET;
|
||||
@@ -436,7 +466,7 @@ HB_FUNC( NETIO_LISTEN )
|
||||
hb_xfree( pSockAddr );
|
||||
}
|
||||
|
||||
s_listenRet( sd, szRootPath );
|
||||
s_listenRet( sd, szRootPath, fRPC );
|
||||
}
|
||||
|
||||
HB_FUNC( NETIO_ACCEPT )
|
||||
@@ -461,7 +491,7 @@ HB_FUNC( NETIO_ACCEPT )
|
||||
BYTE msgbuf[ NETIO_MSGLEN * 2 ];
|
||||
|
||||
hb_socketSetNoDelay( connsd, TRUE );
|
||||
conn = s_consrvNew( connsd, lsd->rootPath );
|
||||
conn = s_consrvNew( connsd, lsd->rootPath, lsd->rpc );
|
||||
|
||||
if( s_srvRecvAll( conn, msgbuf, NETIO_MSGLEN ) == NETIO_MSGLEN &&
|
||||
HB_GET_LE_INT32( msgbuf ) == NETIO_LOGIN )
|
||||
@@ -507,6 +537,7 @@ HB_FUNC( NETIO_SERVER )
|
||||
HB_ERRCODE errCode = 0, errFsCode;
|
||||
long len = 0, size, size2;
|
||||
int iFileNo;
|
||||
UINT32 uiMsg;
|
||||
USHORT uiFalgs;
|
||||
char * szExt;
|
||||
PHB_FILE pFile;
|
||||
@@ -517,7 +548,8 @@ HB_FUNC( NETIO_SERVER )
|
||||
if( s_srvRecvAll( conn, msgbuf, NETIO_MSGLEN ) != NETIO_MSGLEN )
|
||||
break;
|
||||
|
||||
switch( HB_GET_LE_UINT32( msgbuf ) )
|
||||
uiMsg = HB_GET_LE_UINT32( msgbuf );
|
||||
switch( uiMsg )
|
||||
{
|
||||
case NETIO_EXISTS:
|
||||
size = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
|
||||
@@ -737,7 +769,6 @@ HB_FUNC( NETIO_SERVER )
|
||||
errCode = s_srvFsError();
|
||||
else if( !fNoAnswer )
|
||||
{
|
||||
UINT32 uiMsg = HB_GET_LE_UINT32( msgbuf );
|
||||
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
|
||||
memset( msg + 4, '\0', NETIO_MSGLEN - 4 );
|
||||
}
|
||||
@@ -795,6 +826,95 @@ HB_FUNC( NETIO_SERVER )
|
||||
fNoAnswer = TRUE;
|
||||
break;
|
||||
|
||||
case NETIO_PROC:
|
||||
fNoAnswer = TRUE;
|
||||
case NETIO_PROCIS:
|
||||
case NETIO_PROCW:
|
||||
case NETIO_FUNC:
|
||||
if( !conn->rpc )
|
||||
{
|
||||
errCode = NETIO_ERR_UNSUPPORTED;
|
||||
break;
|
||||
}
|
||||
size = HB_GET_LE_UINT32( &msgbuf[ 4 ] );
|
||||
if( size < 2 )
|
||||
errCode = NETIO_ERR_WRONG_PARAM;
|
||||
else
|
||||
{
|
||||
if( size >= ( long ) sizeof( buffer ) )
|
||||
ptr = msg = ( BYTE * ) hb_xgrab( size );
|
||||
if( s_srvRecvAll( conn, msg, size ) != size )
|
||||
errCode = NETIO_ERR_READ;
|
||||
else
|
||||
{
|
||||
const char * data = ( const char * ) msg;
|
||||
size2 = ( long ) hb_strnlen( data, size ) + 1;
|
||||
if( size2 > size )
|
||||
errCode = NETIO_ERR_WRONG_PARAM;
|
||||
else
|
||||
{
|
||||
PHB_DYNS pDynSym = hb_dynsymFindName( data );
|
||||
if( !pDynSym || !hb_dynsymIsFunction( pDynSym ) )
|
||||
errCode = NETIO_ERR_NOT_EXISTS;
|
||||
else if( uiMsg != NETIO_PROCIS )
|
||||
{
|
||||
ULONG ulSize = size - size2;
|
||||
USHORT uiPCount = 0;
|
||||
|
||||
data += size2;
|
||||
|
||||
hb_vmPushDynSym( pDynSym );
|
||||
hb_vmPushNil();
|
||||
while( ulSize )
|
||||
{
|
||||
PHB_ITEM pItem = hb_itemDeserialize( &data, &ulSize );
|
||||
if( !pItem )
|
||||
{
|
||||
ulSize = 1;
|
||||
break;
|
||||
}
|
||||
++uiPCount;
|
||||
hb_vmPush( pItem );
|
||||
hb_itemRelease( pItem );
|
||||
}
|
||||
if( ulSize )
|
||||
{
|
||||
errCode = NETIO_ERR_WRONG_PARAM;
|
||||
uiPCount += 2;
|
||||
do
|
||||
hb_stackPop();
|
||||
while( --uiPCount );
|
||||
}
|
||||
else
|
||||
hb_vmProc( uiPCount );
|
||||
}
|
||||
}
|
||||
if( errCode == 0 && !fNoAnswer )
|
||||
{
|
||||
if( uiMsg == NETIO_FUNC )
|
||||
{
|
||||
ULONG itmSize;
|
||||
char * itmData = hb_itemSerialize( hb_stackReturnItem(), TRUE, &itmSize );
|
||||
if( itmSize <= sizeof( buffer ) - NETIO_MSGLEN )
|
||||
msg = buffer;
|
||||
else if( !ptr || itmSize > ( ULONG ) size - NETIO_MSGLEN )
|
||||
{
|
||||
if( ptr )
|
||||
hb_xfree( ptr );
|
||||
ptr = msg = ( BYTE * ) hb_xgrab( itmSize + NETIO_MSGLEN );
|
||||
}
|
||||
memcpy( msg + NETIO_MSGLEN, itmData, itmSize );
|
||||
hb_xfree( itmData );
|
||||
len = itmSize;
|
||||
}
|
||||
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
|
||||
HB_PUT_LE_UINT32( &msg[ 4 ], len );
|
||||
memset( msg + 8, '\0', NETIO_MSGLEN - 8 );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NETIO_SYNC:
|
||||
continue;
|
||||
|
||||
@@ -805,6 +925,7 @@ HB_FUNC( NETIO_SERVER )
|
||||
|
||||
if( fNoAnswer )
|
||||
{
|
||||
/* continue; */ /* do not send dummy record */
|
||||
HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_SYNC );
|
||||
memset( msg + 4, '\0', NETIO_MSGLEN - 4 );
|
||||
len = NETIO_MSGLEN;
|
||||
|
||||
@@ -15,24 +15,41 @@
|
||||
/* netio_mtserver() needs MT HVM version */
|
||||
REQUEST HB_MT
|
||||
|
||||
PROCEDURE Main( port, ifaddr, root )
|
||||
/* enable this if you need all core functions in RPC support */
|
||||
//REQUEST __HB_EXTERN__
|
||||
|
||||
PROCEDURE Main( port, ifaddr, rootdir, rpc )
|
||||
LOCAL pListenSocket
|
||||
|
||||
HB_Logo()
|
||||
|
||||
pListenSocket := netio_mtserver( iif( port != NIL, Val( port ), ), ifaddr, root )
|
||||
IF Empty( pListenSocket )
|
||||
OutStd( "Cannot start server." + hb_osNewLine() )
|
||||
port := IIF( Empty( port ), 2941, Val( port ) )
|
||||
IF Empty( ifaddr )
|
||||
ifaddr := "0.0.0.0"
|
||||
ENDIF
|
||||
IF Empty( rootdir )
|
||||
rootdir := hb_dirBase()
|
||||
ENDIF
|
||||
rpc := !Empty( rpc )
|
||||
|
||||
IF port == 0
|
||||
HB_Usage()
|
||||
ELSE
|
||||
OutStd( "Listening on: " + iif( ifaddr != NIL, ifaddr, "127.0.0.1" ) + ":" + iif( port != NIL, port, "2941" ) + hb_osNewLine() )
|
||||
OutStd( "Root filesystem: " + iif( root != NIL, root, hb_dirBase() ) + hb_osNewLine() )
|
||||
pListenSocket := netio_mtserver( port, ifaddr, rootdir, rpc )
|
||||
IF Empty( pListenSocket )
|
||||
OutStd( "Cannot start server." + hb_osNewLine() )
|
||||
ELSE
|
||||
OutStd( "Listening on: " + ifaddr + ":" + hb_ntos( port ) + hb_osNewLine() )
|
||||
OutStd( "Root filesystem: " + rootdir + hb_osNewLine() )
|
||||
OutStd( "RPC support: " + iif( rpc, "enabled", "disabled" ) + hb_osNewLine() )
|
||||
|
||||
OutStd( hb_osNewLine() )
|
||||
OutStd( "Press any key to stop NETIO server." + hb_osNewLine() )
|
||||
Inkey( 0 )
|
||||
OutStd( hb_osNewLine() )
|
||||
OutStd( "Press any key to stop NETIO server." + hb_osNewLine() )
|
||||
Inkey( 0 )
|
||||
|
||||
netio_serverstop( pListenSocket )
|
||||
pListenSocket := NIL
|
||||
netio_serverstop( pListenSocket )
|
||||
pListenSocket := NIL
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
RETURN
|
||||
@@ -48,7 +65,7 @@ STATIC PROCEDURE HB_Logo()
|
||||
|
||||
STATIC PROCEDURE HB_Usage()
|
||||
|
||||
OutStd( "Syntax: netiosrv <server> <port> <root>" + hb_osNewLine() )
|
||||
OutStd( "Syntax: netiosrv [<port>] [<inetaddr>] [<rootdir>] [<rpc>]" + hb_osNewLine() )
|
||||
|
||||
RETURN
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@
|
||||
#include "hbzlib.ch"
|
||||
|
||||
#include <zlib.h>
|
||||
#include <zutil.h>
|
||||
|
||||
typedef struct _HB_ZNETSTREAM
|
||||
{
|
||||
@@ -74,6 +73,12 @@ HB_ZNETSTREAM;
|
||||
|
||||
#define HB_ZNET_BUFSIZE 16384
|
||||
|
||||
#if MAX_MEM_LEVEL >= 8
|
||||
# define HB_ZNET_MEM_LEVEL 8
|
||||
#else
|
||||
# define HB_ZNET_MEM_LEVEL MAX_MEM_LEVEL
|
||||
#endif
|
||||
|
||||
/* return status of last compression/decompression operation */
|
||||
int hb_znetError( PHB_ZNETSTREAM pStream )
|
||||
{
|
||||
@@ -105,7 +110,7 @@ PHB_ZNETSTREAM hb_znetOpen( int level, int strategy )
|
||||
memset( pStream, 0, sizeof( HB_ZNETSTREAM ) );
|
||||
|
||||
if( deflateInit2( &pStream->wr, level,
|
||||
Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy ) == Z_OK )
|
||||
Z_DEFLATED, -MAX_WBITS, HB_ZNET_MEM_LEVEL, strategy ) == Z_OK )
|
||||
{
|
||||
pStream->wr.next_out = pStream->outbuf = ( Bytef * ) hb_xgrab( HB_ZNET_BUFSIZE );
|
||||
pStream->wr.avail_out = HB_ZNET_BUFSIZE;
|
||||
|
||||
Reference in New Issue
Block a user