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:
Przemyslaw Czerpak
2010-01-06 16:16:22 +00:00
parent 53f0ff2643
commit 0d4b626818
6 changed files with 381 additions and 24 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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 )

View File

@@ -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;

View File

@@ -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

View File

@@ -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;