Files
harbour-core/contrib/hbnetio/netiosrv.c
Viktor Szakats e00f50079e 2017-09-11 13:12 UTC Viktor Szakats (vszakats users.noreply.github.com)
* contrib/gtqtc/gtqtc1.cpp
  * contrib/gtwvg/gtwgud.c
  * contrib/gtwvw/wvwdraw.c
  * contrib/hbamf/amfdec.c
  * contrib/hbamf/amfstdio.c
  * contrib/hbbz2io/bz2io.c
  * contrib/hbgzio/gzio.c
  * contrib/hbhpdf/core.c
  * contrib/hbmemio/memio.c
  * contrib/hbmisc/irm.c
  * contrib/hbmisc/spd.c
  * contrib/hbnetio/netiosrv.c
  * contrib/hbssl/ssl_sock.c
  * contrib/hbwin/olecore.c
  * contrib/hbwin/wapi_commctrl.c
  * contrib/hbwin/wapi_winuser.c
  * contrib/hbwin/win_bmpd.c
  * contrib/hbwin/win_misc.c
  * contrib/hbzebra/qrcode.c
  * contrib/rddads/ads1.c
  * contrib/rddads/adsfunc.c
  * contrib/rddsql/sqlmix.c
  * contrib/sddfb/core.c
  * contrib/xhb/cstructc.c
  * contrib/xhb/hboutdbg.c
  * contrib/xhb/hbserv.c
  * include/hbdefs.h
  * include/hbexprb.c
  * include/hbrddcdx.h
  * include/hbthread.h
  * include/hbwmain.c
  * src/common/hbffind.c
  * src/compiler/complex.c
  * src/compiler/hbmain.c
  * src/compiler/hbopt.c
  * src/debug/dbgentry.c
  * src/rdd/dbf1.c
  * src/rdd/dbfcdx/dbfcdx1.c
  * src/rdd/dbffpt/dbffpt1.c
  * src/rdd/dbfnsx/dbfnsx1.c
  * src/rdd/dbfntx/dbfntx1.c
  * src/rdd/hbsix/sxcompr.c
  * src/rdd/wacore.c
  * src/rdd/workarea.c
  * src/rtl/cputime.c
  * src/rtl/dates.c
  * src/rtl/gtchrmap.c
  * src/rtl/gtcrs/gtcrs.c
  * src/rtl/gtpca/gtpca.c
  * src/rtl/gtsln/gtsln.c
  * src/rtl/gtsln/kbsln.c
  * src/rtl/gtsln/keytrans.c
  * src/rtl/gtstd/gtstd.c
  * src/rtl/gttrm/gttrm.c
  * src/rtl/gtwvt/gtwvt.c
  * src/rtl/gtxwc/gtxwc.c
  * src/rtl/hbcom.c
  * src/rtl/hbproces.c
  * src/rtl/itemseri.c
  * src/rtl/langapi.c
  * src/rtl/run.c
  * src/rtl/sha1.c
  * src/rtl/space.c
  * src/vm/classes.c
  * src/vm/hvm.c
  * src/vm/itemapi.c
  * src/vm/set.c
  * src/vm/thread.c
    * convert commented C code to #if 0 blocks, or clean them up in
      different ways
2017-09-11 13:27:12 +00:00

1820 lines
62 KiB
C

/*
* Demonstration code for alternative RDD IO API which uses own
* very simple TCP/IP file server with RPC support
* All files which names starts 'net:' are redirected to this API.
* This is server code giving the following .prg functions:
* netio_Listen( [<nPort>], [<cAddress>], [<cRootDir>], [<lRPC>] )
* --> <pListenSocket> | NIL
* netio_Accept( <pListenSocket>, [<nTimeOut>],
* [<cPass>], [<nCompressionLevel>], [<nStrategy>] )
* --> <pConnectionSocket> | NIL
* netio_Compress( <pConnectionSocket>,
* [<cPass>], [<nCompressionLevel>], [<nStrategy>] )
* --> NIL
* netio_Server( <pConnectionSocket> ) --> NIL
* netio_ServerStop( <pListenSocket> | <pConnectionSocket> [, <lStop>] )
* --> NIL
* netio_ServerTimeOut( <pConnectionSocket> [, <nTimeOut>] ) --> [<nTimeOut>]
* netio_RPC( <pListenSocket> | <pConnectionSocket> [, <lEnable>] )
* --> <lPrev>
* netio_RPCFilter( <pConnectionSocket>,
* <sFuncSym> | <hValue> | NIL ) --> NIL
*
* netio_SrvStatus( <pConnectionSocket> [, <nStreamID>] ) --> <nStatus>
* netio_SrvSendItem( <pConnectionSocket>, <nStreamID>, <xData> )
* --> <lSent>
* netio_SrvSendData( <pConnectionSocket>, <nStreamID>, <cData> )
* --> <lSent>
*
* Copyright 2009 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file LICENSE.txt. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA (or visit https://www.gnu.org/licenses/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
#include "hbapi.h"
#include "hbapiitm.h"
#include "hbapifs.h"
#include "hbapierr.h"
#include "hbsocket.h"
#include "hbznet.h"
#include "hbzlib.ch"
#include "hbinit.h"
#include "hbvm.h"
#include "hbstack.h"
#include "hbthread.h"
#include "hbdate.h"
#include "netio.h"
#include "hbserial.ch"
/*
* server code
*/
typedef struct _HB_CONSTREAM
{
int id;
int type;
struct _HB_CONSTREAM * next;
}
HB_CONSTREAM, * PHB_CONSTREAM;
typedef struct _HB_CONSRV
{
PHB_SOCKEX sock;
PHB_FILE fileTable[ NETIO_FILES_MAX ];
int filesCount;
int firstFree;
int timeout;
HB_BOOL stop;
HB_BOOL rpc;
HB_BOOL login;
PHB_SYMB rpcFunc;
PHB_ITEM rpcFilter;
PHB_ITEM mutex;
PHB_CONSTREAM streams;
HB_MAXUINT wr_count;
HB_MAXUINT rd_count;
int rootPathLen;
char rootPath[ HB_PATH_MAX ];
}
HB_CONSRV, * PHB_CONSRV;
typedef struct _HB_LISTENSD
{
HB_SOCKET sd;
HB_BOOL stop;
HB_BOOL rpc;
char rootPath[ HB_PATH_MAX ];
}
HB_LISTENSD, * PHB_LISTENSD;
static HB_BOOL s_isDirSep( char c )
{
/* intentionally used explicit values instead of Harbour macros
* because client can use different OS
*/
return c == '/' || c == '\\';
}
static const char * s_consrvFilePath( char * pszFileName, PHB_CONSRV conn, HB_BOOL fLink )
{
int iPos = 0, iLevel = 0;
char ch = HB_OS_PATH_DELIM_CHR;
if( conn->rootPathLen )
{
while( s_isDirSep( pszFileName[ 0 ] ) )
++pszFileName;
}
while( pszFileName[ iPos ] && iLevel >= 0 )
{
if( conn->rootPathLen && s_isDirSep( ch ) )
{
if( pszFileName[ iPos ] == '.' &&
pszFileName[ iPos + 1 ] == '.' &&
( pszFileName[ iPos + 2 ] == '\0' ||
s_isDirSep( pszFileName[ iPos + 2 ] ) ) )
--iLevel;
else if( pszFileName[ iPos ] &&
! s_isDirSep( pszFileName[ iPos ] ) &&
! ( pszFileName[ iPos ] == '.' &&
s_isDirSep( pszFileName[ iPos + 1 ] ) ) )
++iLevel;
}
ch = pszFileName[ iPos ];
if( s_isDirSep( ch ) )
pszFileName[ iPos ] = HB_OS_PATH_DELIM_CHR;
++iPos;
}
if( iLevel < 0 )
pszFileName = NULL;
else if( conn->rootPathLen && ! fLink )
{
memmove( pszFileName + conn->rootPathLen, pszFileName, iPos + 1 );
memcpy( pszFileName, conn->rootPath, conn->rootPathLen );
}
return pszFileName;
}
static HB_ERRCODE s_srvFsError( void )
{
HB_ERRCODE errCode = hb_fsError();
if( errCode == 0 )
errCode = NETIO_ERR_FILE_IO;
return errCode;
}
static int s_srvFileNew( PHB_CONSRV conn, PHB_FILE pFile )
{
if( conn->filesCount < NETIO_FILES_MAX )
{
while( conn->firstFree < NETIO_FILES_MAX )
{
if( conn->fileTable[ conn->firstFree ] == NULL )
{
conn->filesCount++;
conn->fileTable[ conn->firstFree ] = pFile;
return conn->firstFree++;
}
conn->firstFree++;
}
}
return -1;
}
static PHB_FILE s_srvFileFree( PHB_CONSRV conn, int iFile )
{
if( iFile < NETIO_FILES_MAX && conn->filesCount > 0 )
{
PHB_FILE pFile = conn->fileTable[ iFile ];
if( pFile )
{
conn->fileTable[ iFile ] = NULL;
conn->filesCount--;
if( conn->firstFree > iFile )
conn->firstFree = iFile;
return pFile;
}
}
return NULL;
}
static PHB_FILE s_srvFileGet( PHB_CONSRV conn, int iFile )
{
if( iFile < NETIO_FILES_MAX && conn->filesCount > 0 )
return conn->fileTable[ iFile ];
else
return NULL;
}
static void s_consrv_disconnect( PHB_CONSRV conn )
{
if( conn->sock )
{
hb_sockexClose( conn->sock, HB_TRUE );
conn->sock = NULL;
}
}
static void s_consrv_close( PHB_CONSRV conn )
{
int i = 0;
if( conn->rpcFilter )
hb_itemRelease( conn->rpcFilter );
while( conn->streams )
{
PHB_CONSTREAM stream = conn->streams;
conn->streams = stream->next;
hb_xfree( stream );
}
if( conn->mutex )
hb_itemRelease( conn->mutex );
if( conn->sock )
hb_sockexClose( conn->sock, HB_TRUE );
while( conn->filesCount > 0 )
{
if( i >= NETIO_FILES_MAX )
break; /* internal error, it should not happen */
if( conn->fileTable[ i ] )
{
hb_fileClose( conn->fileTable[ i ] );
conn->filesCount--;
}
++i;
}
hb_xfree( conn );
}
static HB_GARBAGE_FUNC( s_consrv_destructor )
{
PHB_CONSRV * conn_ptr = ( PHB_CONSRV * ) Cargo;
if( *conn_ptr )
{
PHB_CONSRV conn = *conn_ptr;
*conn_ptr = NULL;
s_consrv_close( conn );
}
}
static HB_GARBAGE_FUNC( s_consrv_mark )
{
PHB_CONSRV * conn_ptr = ( PHB_CONSRV * ) Cargo;
if( *conn_ptr && ( *conn_ptr )->rpcFilter )
hb_gcMark( ( *conn_ptr )->rpcFilter );
}
static const HB_GC_FUNCS s_gcConSrvFuncs =
{
s_consrv_destructor,
s_consrv_mark
};
static PHB_CONSRV s_consrvParam( int iParam )
{
PHB_CONSRV * conn_ptr = ( PHB_CONSRV * ) hb_parptrGC( &s_gcConSrvFuncs,
iParam );
if( conn_ptr && *conn_ptr )
return *conn_ptr;
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
return NULL;
}
static void s_consrvRet( PHB_CONSRV conn )
{
if( conn )
{
PHB_CONSRV * conn_ptr = ( PHB_CONSRV * ) hb_gcAllocate( sizeof( PHB_CONSRV ),
&s_gcConSrvFuncs );
*conn_ptr = conn;
hb_retptrGC( conn_ptr );
}
else
hb_ret();
}
static PHB_CONSRV s_consrvNew( PHB_SOCKEX sock, const char * szRootPath, HB_BOOL rpc )
{
PHB_CONSRV conn = ( PHB_CONSRV ) memset( hb_xgrab( sizeof( HB_CONSRV ) ),
0, sizeof( HB_CONSRV ) );
conn->sock = sock;
conn->rpc = rpc;
conn->timeout = -1;
if( szRootPath )
{
hb_strncpy( conn->rootPath, szRootPath, sizeof( conn->rootPath ) - 1 );
conn->rootPathLen = ( int ) strlen( conn->rootPath );
}
return conn;
}
static HB_BOOL s_srvRecvAll( PHB_CONSRV conn, void * buffer, long len )
{
HB_BYTE * ptr = ( HB_BYTE * ) buffer;
long lRead = 0, l;
HB_MAXINT timeout = conn->timeout;
HB_MAXUINT timer = hb_timerInit( timeout );
while( lRead < len && ! conn->stop )
{
l = hb_sockexRead( conn->sock, ptr + lRead, len - lRead, 1000 );
if( l > 0 )
{
lRead += l;
conn->rd_count += l;
}
else if( l == 0 ||
hb_socketGetError() != HB_SOCKET_ERR_TIMEOUT ||
( timeout = hb_timerTest( timeout, &timer ) ) == 0 ||
hb_vmRequestQuery() != 0 )
break;
}
return lRead == len;
}
static HB_BOOL s_srvSendAll( PHB_CONSRV conn, void * buffer, long len )
{
HB_BYTE * ptr = ( HB_BYTE * ) buffer;
long lSent = 0;
if( ! conn->mutex || hb_threadMutexLock( conn->mutex ) )
{
HB_MAXINT timeout = conn->timeout;
HB_MAXUINT timer = hb_timerInit( timeout );
while( lSent < len && ! conn->stop )
{
long l = hb_sockexWrite( conn->sock, ptr + lSent, len - lSent, 1000 );
if( l > 0 )
{
lSent += l;
conn->wr_count += l;
}
else if( hb_socketGetError() != HB_SOCKET_ERR_TIMEOUT ||
( timeout = hb_timerTest( timeout, &timer ) ) == 0 ||
hb_vmRequestQuery() != 0 )
break;
}
if( lSent == len && ! conn->stop )
{
if( hb_sockexFlush( conn->sock, conn->timeout > 0 ? conn->timeout : -1,
HB_FALSE ) != 0 )
lSent = -1;
}
if( conn->mutex )
hb_threadMutexUnlock( conn->mutex );
}
return lSent == len;
}
static HB_GARBAGE_FUNC( s_listensd_destructor )
{
PHB_LISTENSD * lsd_ptr = ( PHB_LISTENSD * ) Cargo;
if( *lsd_ptr )
{
PHB_LISTENSD lsd = *lsd_ptr;
*lsd_ptr = NULL;
if( lsd->sd != HB_NO_SOCKET )
{
hb_socketClose( lsd->sd );
lsd->sd = HB_NO_SOCKET;
}
hb_xfree( lsd );
}
}
static const HB_GC_FUNCS s_gcListensdFuncs =
{
s_listensd_destructor,
hb_gcDummyMark
};
static PHB_LISTENSD s_listenParam( int iParam, HB_BOOL fError )
{
PHB_LISTENSD * lsd_ptr = ( PHB_LISTENSD * )
hb_parptrGC( &s_gcListensdFuncs, iParam );
if( lsd_ptr && *lsd_ptr )
return *lsd_ptr;
if( fError )
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
return NULL;
}
static void s_listenRet( HB_SOCKET sd, const char * szRootPath, HB_BOOL rpc )
{
if( sd != HB_NO_SOCKET )
{
PHB_LISTENSD lsd, * lsd_ptr;
int iLen;
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
hb_fsBaseDirBuff( lsd->rootPath );
iLen = ( int ) strlen( lsd->rootPath );
if( iLen > 0 )
{
if( ! s_isDirSep( lsd->rootPath[ iLen - 1 ] ) )
{
if( iLen == ( int ) sizeof( lsd->rootPath ) - 1 )
--iLen;
lsd->rootPath[ iLen ] = HB_OS_PATH_DELIM_CHR;
}
}
lsd_ptr = ( PHB_LISTENSD * ) hb_gcAllocate( sizeof( PHB_LISTENSD ),
&s_gcListensdFuncs );
*lsd_ptr = lsd;
hb_retptrGC( lsd_ptr );
}
else
hb_ret();
}
/* netio_RPC( <pListenSocket> | <pConnectionSocket> [, <lEnable>] ) --> <lPrev>
*/
HB_FUNC( NETIO_RPC )
{
PHB_LISTENSD lsd = s_listenParam( 1, HB_FALSE );
HB_BOOL fRPC = HB_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_retl( fRPC );
}
/* netio_RPCFilter( <pConnectionSocket>,
* <sFuncSym> | <hValue> | NIL ) --> NIL
*/
HB_FUNC( NETIO_RPCFILTER )
{
PHB_CONSRV conn = s_consrvParam( 1 );
if( conn )
{
if( conn->rpcFilter )
{
hb_itemRelease( conn->rpcFilter );
conn->rpcFilter = NULL;
}
conn->rpcFunc = hb_itemGetSymbol( hb_param( 2, HB_IT_SYMBOL ) );
if( ! conn->rpcFunc )
{
PHB_ITEM pHash = hb_param( 2, HB_IT_HASH );
if( pHash )
{
conn->rpcFilter = hb_itemNew( pHash );
hb_gcUnlock( conn->rpcFilter );
}
}
}
}
/* netio_ServerStop( <pListenSocket> | <pConnectionSocket> [, <lStop>] ) --> NIL
*/
HB_FUNC( NETIO_SERVERSTOP )
{
PHB_LISTENSD lsd = s_listenParam( 1, HB_FALSE );
HB_BOOL fStop = hb_parldef( 2, HB_TRUE );
if( lsd )
lsd->stop = fStop;
else
{
PHB_CONSRV conn = s_consrvParam( 1 );
if( conn )
conn->stop = fStop;
}
}
/* netio_ServerTimeOut( <pConnectionSocket> [, <nTimeOut>] ) --> [<nTimeOut>]
*/
HB_FUNC( NETIO_SERVERTIMEOUT )
{
PHB_CONSRV conn = s_consrvParam( 1 );
if( conn )
{
hb_retni( conn->timeout );
if( HB_ISNUM( 2 ) )
conn->timeout = hb_parni( 2 );
}
}
/* netio_Listen( [<nPort>], [<cIfAddr>], [<cRootDir>], [<lRPC>] )
* --> <pListenSocket> | NIL
*/
HB_FUNC( NETIO_LISTEN )
{
static HB_BOOL s_fInit = HB_TRUE;
int iPort = hb_parnidef( 1, NETIO_DEFAULT_PORT );
const char * szAddress = hb_parc( 2 );
const char * szRootPath = hb_parc( 3 );
HB_BOOL fRPC = hb_parl( 4 );
void * pSockAddr;
unsigned uiLen;
HB_SOCKET sd = HB_NO_SOCKET;
if( s_fInit )
{
hb_socketInit();
s_fInit = HB_FALSE;
}
if( hb_socketInetAddr( &pSockAddr, &uiLen, szAddress, iPort ) )
{
sd = hb_socketOpen( HB_SOCKET_PF_INET, HB_SOCKET_PT_STREAM, 0 );
if( sd != HB_NO_SOCKET )
{
if( hb_socketBind( sd, pSockAddr, uiLen ) != 0 ||
hb_socketListen( sd, 10 ) != 0 )
{
hb_socketClose( sd );
sd = HB_NO_SOCKET;
}
}
hb_xfree( pSockAddr );
}
s_listenRet( sd, szRootPath, fRPC );
}
/* netio_Accept( <pListenSocket>, [<nTimeOut>],
* [<cPass>], [<nCompressionLevel>], [<nStrategy>] )
* --> <pConnectionSocket> | NIL
*/
HB_FUNC( NETIO_ACCEPT )
{
PHB_LISTENSD lsd = s_listenParam( 1, HB_TRUE );
PHB_CONSRV conn = NULL;
if( lsd && lsd->sd != HB_NO_SOCKET && ! lsd->stop )
{
HB_MAXINT timeout = hb_parnintdef( 2, -1 );
HB_SOCKET connsd;
int iLevel, iStrategy, keylen = ( int ) hb_parclen( 3 );
if( keylen > NETIO_PASSWD_MAX )
keylen = NETIO_PASSWD_MAX;
iLevel = hb_parnidef( 4, keylen ? HB_ZLIB_COMPRESSION_DEFAULT :
HB_ZLIB_COMPRESSION_DISABLE );
iStrategy = hb_parnidef( 5, HB_ZLIB_STRATEGY_DEFAULT );
do
{
connsd = hb_socketAccept( lsd->sd, NULL, NULL, timeout < 0 ? 1000 : timeout );
}
while( connsd == HB_NO_SOCKET && ! lsd->stop && timeout < 0 &&
hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT &&
hb_vmRequestQuery() == 0 );
if( connsd != HB_NO_SOCKET )
{
PHB_SOCKEX sock;
hb_socketSetKeepAlive( connsd, HB_TRUE );
hb_socketSetNoDelay( connsd, HB_TRUE );
if( iLevel == HB_ZLIB_COMPRESSION_DISABLE )
sock = hb_sockexNew( connsd, NULL, NULL );
else
sock = hb_sockexNewZNet( connsd, hb_parc( 3 ), keylen,
iLevel, iStrategy );
if( sock != NULL )
conn = s_consrvNew( sock, lsd->rootPath, lsd->rpc );
else
hb_socketClose( connsd );
}
}
s_consrvRet( conn );
}
/* netio_Compress( <pConnectionSocket>,
* [<cPass>], [<nCompressionLevel>], [<nStrategy>] ) --> NIL
*/
HB_FUNC( NETIO_COMPRESS )
{
PHB_CONSRV conn = s_consrvParam( 1 );
if( conn && conn->sock && ! conn->stop )
{
int iLevel, iStrategy, keylen = ( int ) hb_parclen( 2 );
PHB_SOCKEX sock;
if( keylen > NETIO_PASSWD_MAX )
keylen = NETIO_PASSWD_MAX;
iLevel = hb_parnidef( 3, keylen ? HB_ZLIB_COMPRESSION_DEFAULT :
HB_ZLIB_COMPRESSION_DISABLE );
iStrategy = hb_parnidef( 4, HB_ZLIB_STRATEGY_DEFAULT );
if( iLevel == HB_ZLIB_COMPRESSION_DISABLE )
sock = hb_sockexNew( hb_sockexGetHandle( conn->sock ), NULL, NULL );
else
sock = hb_sockexNewZNet( hb_sockexGetHandle( conn->sock ), hb_parc( 2 ), keylen,
iLevel, iStrategy );
if( sock )
{
hb_sockexClose( conn->sock, HB_FALSE );
conn->sock = sock;
}
}
}
static HB_BOOL s_netio_login_accept( PHB_CONSRV conn )
{
if( conn && conn->sock && ! conn->stop && ! conn->login )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
if( s_srvRecvAll( conn, msgbuf, NETIO_MSGLEN ) &&
HB_GET_LE_INT32( msgbuf ) == NETIO_LOGIN )
{
long len = HB_GET_LE_INT16( &msgbuf[ 4 ] );
if( len < ( long ) sizeof( msgbuf ) &&
len == ( long ) strlen( NETIO_LOGINSTRID ) &&
s_srvRecvAll( conn, msgbuf, len ) )
{
if( memcmp( NETIO_LOGINSTRID, msgbuf, len ) == 0 )
{
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_LOGIN );
HB_PUT_LE_UINT32( &msgbuf[ 4 ], NETIO_CONNECTED );
memset( msgbuf + 8, '\0', NETIO_MSGLEN - 8 );
if( s_srvSendAll( conn, msgbuf, NETIO_MSGLEN ) )
conn->login = HB_TRUE;
}
}
}
if( ! conn->login )
s_consrv_disconnect( conn );
}
return conn && conn->login;
}
/* netio_VerifyClient( <pConnectionSocket> ) --> <lAccepted>
*/
HB_FUNC( NETIO_VERIFYCLIENT )
{
PHB_CONSRV conn = s_consrvParam( 1 );
if( conn )
hb_retl( s_netio_login_accept( conn ) );
}
/* netio_Server( <pConnectionSocket> ) --> NIL
*/
HB_FUNC( NETIO_SERVER )
{
PHB_CONSRV conn = s_consrvParam( 1 );
if( s_netio_login_accept( conn ) )
{
/* clear return value if any */
hb_ret();
for( ;; )
{
HB_BYTE buffer[ 2048 ], * ptr = NULL, * msg;
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_BOOL fNoAnswer = HB_FALSE;
HB_ERRCODE errCode = 0, errFsCode;
long len = 0, size, size2;
long lJulian, lMillisec;
int iFileNo, iStreamID, iIndex, iResult;
HB_FATTR ulAttr;
HB_U32 uiMsg;
HB_FATTR nFlags;
HB_USHORT uiFlags;
char * szExt;
PHB_FILE pFile;
HB_FOFFSET llOffset, llSize;
HB_MAXINT nTimeout;
msg = buffer;
if( ! s_srvRecvAll( conn, msgbuf, NETIO_MSGLEN ) )
break;
uiMsg = HB_GET_LE_UINT32( msgbuf );
switch( uiMsg )
{
case NETIO_EXISTS:
case NETIO_DELETE:
case NETIO_DIREXISTS:
case NETIO_DIRMAKE:
case NETIO_DIRREMOVE:
size = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
if( size <= 0 )
errCode = NETIO_ERR_WRONG_PARAM;
else
{
if( size + conn->rootPathLen >= ( long ) sizeof( buffer ) )
ptr = msg = ( HB_BYTE * ) hb_xgrab( size + conn->rootPathLen + 1 );
msg[ size ] = '\0';
if( ! s_srvRecvAll( conn, msg, size ) )
errCode = NETIO_ERR_READ;
else
{
const char * pszName = s_consrvFilePath( ( char * ) msg, conn, HB_FALSE );
if( ! pszName )
errCode = NETIO_ERR_WRONG_FILE_PATH;
else if( ! ( uiMsg == NETIO_DELETE ? hb_fileDelete( pszName ) :
( uiMsg == NETIO_DIREXISTS ? hb_fileDirExists( pszName ) :
( uiMsg == NETIO_DIRMAKE ? hb_fileDirMake( pszName ) :
( uiMsg == NETIO_DIRREMOVE ? hb_fileDirRemove( pszName ) :
hb_fileExists( pszName, NULL ) ) ) ) ) )
errCode = s_srvFsError();
else
{
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
memset( msg + 4, '\0', NETIO_MSGLEN - 4 );
}
}
}
break;
case NETIO_DIRSPACE:
size = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
uiFlags = HB_GET_LE_UINT16( &msgbuf[ 6 ] );
if( size <= 0 )
errCode = NETIO_ERR_WRONG_PARAM;
else
{
if( size + conn->rootPathLen >= ( long ) sizeof( buffer ) )
ptr = msg = ( HB_BYTE * ) hb_xgrab( size + conn->rootPathLen + 1 );
msg[ size ] = '\0';
if( ! s_srvRecvAll( conn, msg, size ) )
errCode = NETIO_ERR_READ;
else
{
const char * pszName = s_consrvFilePath( ( char * ) msg, conn, HB_FALSE );
if( ! pszName )
errCode = NETIO_ERR_WRONG_FILE_PATH;
else
{
HB_MAXINT nSize = ( HB_MAXINT ) hb_fileDirSpace( pszName, uiFlags );
errFsCode = hb_fsError();
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
HB_PUT_LE_UINT64( &msg[ 4 ], nSize );
HB_PUT_LE_UINT32( &msg[ 12 ], errFsCode );
memset( msg + 16, '\0', NETIO_MSGLEN - 16 );
}
}
}
break;
case NETIO_DIRECTORY:
size = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
size2 = HB_GET_LE_UINT16( &msgbuf[ 6 ] );
if( size < 0 || size2 < 0 )
errCode = NETIO_ERR_WRONG_PARAM;
else
{
if( HB_MAX( size, size2 ) + conn->rootPathLen >= ( long ) sizeof( buffer ) )
ptr = msg = ( HB_BYTE * ) hb_xgrab( HB_MAX( size, size2 ) + conn->rootPathLen + 1 );
msg[ size ] = '\0';
if( ! s_srvRecvAll( conn, msg, size ) )
errCode = NETIO_ERR_READ;
else
{
const char * pszName = s_consrvFilePath( ( char * ) msg, conn, HB_FALSE );
char * pszDirSpec;
pszDirSpec = pszName ? hb_strdup( pszName ) : NULL;
msg[ size2 ] = '\0';
if( size2 && ! s_srvRecvAll( conn, msg, size2 ) )
errCode = NETIO_ERR_READ;
else if( ! pszName )
errCode = NETIO_ERR_WRONG_FILE_PATH;
else
{
HB_SIZE itmSize = 0;
char * itmData = NULL;
const char * pszAttr = size2 ? ( const char * ) msg : NULL;
PHB_ITEM pResult = hb_fileDirectory( pszDirSpec, pszAttr );
errFsCode = hb_fsError();
if( pResult )
{
itmData = hb_itemSerialize( pResult, HB_SERIALIZE_NUMSIZE, &itmSize );
hb_itemRelease( pResult );
}
if( itmSize <= sizeof( buffer ) - NETIO_MSGLEN )
msg = buffer;
else if( ! ptr || itmSize > ( HB_SIZE ) HB_MAX( size, size2 ) + conn->rootPathLen + 1 - NETIO_MSGLEN )
{
if( ptr )
hb_xfree( ptr );
ptr = msg = ( HB_BYTE * ) hb_xgrab( itmSize + NETIO_MSGLEN );
}
if( itmData )
{
memcpy( msg + NETIO_MSGLEN, itmData, itmSize );
hb_xfree( itmData );
}
len = ( long ) itmSize;
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
HB_PUT_LE_UINT32( &msg[ 4 ], len );
HB_PUT_LE_UINT32( &msg[ 8 ], errFsCode );
memset( msg + 12, '\0', NETIO_MSGLEN - 12 );
}
if( pszDirSpec )
hb_xfree( pszDirSpec );
}
}
break;
case NETIO_LINKREAD:
size = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
if( size < 0 )
errCode = NETIO_ERR_WRONG_PARAM;
else
{
if( size + conn->rootPathLen >= ( long ) sizeof( buffer ) )
ptr = msg = ( HB_BYTE * ) hb_xgrab( size + conn->rootPathLen + 1 );
msg[ size ] = '\0';
if( ! s_srvRecvAll( conn, msg, size ) )
errCode = NETIO_ERR_READ;
else
{
const char * pszName = s_consrvFilePath( ( char * ) msg, conn, HB_FALSE );
if( ! pszName )
errCode = NETIO_ERR_WRONG_FILE_PATH;
else
{
char * pszTarget = hb_fileLinkRead( pszName );
errFsCode = hb_fsError();
if( pszTarget )
{
len = ( long ) strlen( pszTarget );
if( len <= ( long ) ( sizeof( buffer ) - NETIO_MSGLEN ) )
msg = buffer;
else if( ! ptr || len > ( long ) ( size + conn->rootPathLen + 1 - NETIO_MSGLEN ) )
{
if( ptr )
hb_xfree( ptr );
ptr = msg = ( HB_BYTE * ) hb_xgrab( len + NETIO_MSGLEN );
}
memcpy( msg + NETIO_MSGLEN, pszTarget, len );
hb_xfree( pszTarget );
}
else
len = 0;
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
HB_PUT_LE_UINT32( &msg[ 4 ], len );
HB_PUT_LE_UINT32( &msg[ 8 ], errFsCode );
memset( msg + 12, '\0', NETIO_MSGLEN - 12 );
}
}
}
break;
case NETIO_RENAME:
case NETIO_COPY:
case NETIO_LINK:
case NETIO_LINKSYM:
size = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
size2 = HB_GET_LE_UINT16( &msgbuf[ 6 ] );
if( size <= 0 || size2 <= 0 )
errCode = NETIO_ERR_WRONG_PARAM;
else
{
if( HB_MAX( size, size2 ) + conn->rootPathLen >= ( long ) sizeof( buffer ) )
ptr = msg = ( HB_BYTE * ) hb_xgrab( HB_MAX( size, size2 ) + conn->rootPathLen + 1 );
msg[ size ] = '\0';
if( ! s_srvRecvAll( conn, msg, size ) )
errCode = NETIO_ERR_READ;
else
{
const char * szFile = s_consrvFilePath( ( char * ) msg, conn, uiMsg == NETIO_LINKSYM );
char * szOldName = szFile ? hb_strdup( szFile ) : NULL;
msg[ size2 ] = '\0';
if( ! s_srvRecvAll( conn, msg, size2 ) )
errCode = NETIO_ERR_READ;
else if( ! szOldName )
errCode = NETIO_ERR_WRONG_FILE_PATH;
else
{
szFile = s_consrvFilePath( ( char * ) msg, conn, HB_FALSE );
if( ! szFile )
errCode = NETIO_ERR_WRONG_FILE_PATH;
else if( ! ( uiMsg == NETIO_RENAME ? hb_fileRename( szOldName, szFile ) :
( uiMsg == NETIO_COPY ? hb_fileCopy( szOldName, szFile ) :
( uiMsg == NETIO_LINK ? hb_fileLink( szOldName, szFile ) :
hb_fileLinkSym( szOldName, szFile ) ) ) ) )
errCode = s_srvFsError();
else
{
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
memset( msg + 4, '\0', NETIO_MSGLEN - 4 );
}
}
if( szOldName )
hb_xfree( szOldName );
}
}
break;
case NETIO_ATTRSET:
case NETIO_ATTRGET:
size = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
ulAttr = HB_GET_LE_UINT32( &msgbuf[ 6 ] );
if( size <= 0 )
errCode = NETIO_ERR_WRONG_PARAM;
else
{
if( size + conn->rootPathLen >= ( long ) sizeof( buffer ) )
ptr = msg = ( HB_BYTE * ) hb_xgrab( size + conn->rootPathLen + 1 );
msg[ size ] = '\0';
if( ! s_srvRecvAll( conn, msg, size ) )
errCode = NETIO_ERR_READ;
else
{
const char * pszName = s_consrvFilePath( ( char * ) msg, conn, HB_FALSE );
if( ! pszName )
errCode = NETIO_ERR_WRONG_FILE_PATH;
else if( ! ( uiMsg == NETIO_ATTRSET ?
hb_fileAttrSet( pszName, ulAttr ) :
hb_fileAttrGet( pszName, &ulAttr ) ) )
errCode = s_srvFsError();
else
{
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
HB_PUT_LE_UINT32( &msg[ 4 ], ulAttr );
memset( msg + 8, '\0', NETIO_MSGLEN - 8 );
}
}
}
break;
case NETIO_FTIMESET:
case NETIO_FTIMEGET:
size = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
lJulian = HB_GET_LE_UINT32( &msgbuf[ 6 ] );
lMillisec = HB_GET_LE_UINT32( &msgbuf[ 10 ] );
if( size <= 0 )
errCode = NETIO_ERR_WRONG_PARAM;
else
{
if( size + conn->rootPathLen >= ( long ) sizeof( buffer ) )
ptr = msg = ( HB_BYTE * ) hb_xgrab( size + conn->rootPathLen + 1 );
msg[ size ] = '\0';
if( ! s_srvRecvAll( conn, msg, size ) )
errCode = NETIO_ERR_READ;
else
{
const char * pszName = s_consrvFilePath( ( char * ) msg, conn, HB_FALSE );
if( ! pszName )
errCode = NETIO_ERR_WRONG_FILE_PATH;
else if( ! ( uiMsg == NETIO_FTIMESET ?
hb_fileTimeSet( pszName, lJulian, lMillisec ) :
hb_fileTimeGet( pszName, &lJulian, &lMillisec ) ) )
errCode = s_srvFsError();
else
{
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
HB_PUT_LE_UINT32( &msg[ 4 ], lJulian );
HB_PUT_LE_UINT32( &msg[ 8 ], lMillisec );
memset( msg + 12, '\0', NETIO_MSGLEN - 12 );
}
}
}
break;
case NETIO_OPEN:
case NETIO_OPEN2:
size = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
if( uiMsg == NETIO_OPEN2 )
{
nFlags = HB_GET_LE_UINT32( &msgbuf[ 6 ] );
szExt = msgbuf[ 10 ] ? hb_strndup( ( const char * ) &msgbuf[ 10 ],
NETIO_MSGLEN - 10 ) : NULL;
}
else
{
nFlags = HB_GET_LE_UINT16( &msgbuf[ 6 ] );
szExt = msgbuf[ 8 ] ? hb_strndup( ( const char * ) &msgbuf[ 8 ],
NETIO_MSGLEN - 8 ) : NULL;
}
if( size <= 0 )
errCode = NETIO_ERR_WRONG_PARAM;
else
{
if( size + conn->rootPathLen >= ( long ) sizeof( buffer ) )
ptr = msg = ( HB_BYTE * ) hb_xgrab( size + conn->rootPathLen + 1 );
msg[ size ] = '\0';
if( ! s_srvRecvAll( conn, msg, size ) )
errCode = NETIO_ERR_READ;
else if( conn->filesCount >= NETIO_FILES_MAX )
errCode = NETIO_ERR_FILES_MAX;
else
{
const char * szFile = s_consrvFilePath( ( char * ) msg, conn, HB_FALSE );
if( ! szFile )
errCode = NETIO_ERR_WRONG_FILE_PATH;
else
{
nFlags &= ~ ( HB_FATTR ) FXO_COPYNAME;
pFile = hb_fileExtOpen( szFile, szExt, nFlags, NULL, NULL );
if( ! pFile )
errCode = s_srvFsError();
else
{
iFileNo = s_srvFileNew( conn, pFile );
if( iFileNo < 0 )
{
errCode = NETIO_ERR_FILES_MAX;
hb_fileClose( pFile );
}
else
{
HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_OPEN );
HB_PUT_LE_UINT16( &msg[ 4 ], iFileNo );
memset( msg + 6, '\0', NETIO_MSGLEN - 6 );
}
}
}
}
}
if( szExt )
hb_xfree( szExt );
break;
case NETIO_CONFIGURE:
iFileNo = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
size = HB_GET_LE_UINT32( &msgbuf[ 6 ] );
iIndex = HB_GET_LE_INT32( &msgbuf[ 10 ] );
if( size < 0 )
errCode = NETIO_ERR_WRONG_PARAM;
else
{
if( size > ( long ) ( sizeof( buffer ) - NETIO_MSGLEN ) )
ptr = msg = ( HB_BYTE * ) hb_xgrab( size + NETIO_MSGLEN );
if( ! s_srvRecvAll( conn, msg, size ) )
errCode = NETIO_ERR_READ;
else
{
pFile = s_srvFileGet( conn, iFileNo );
if( pFile == NULL )
errCode = NETIO_ERR_WRONG_FILE_HANDLE;
else
{
PHB_ITEM pValue = NULL;
if( size > 0 )
{
const char * data = ( const char * ) msg;
HB_SIZE nSize = size;
pValue = hb_itemDeserialize( &data, &nSize );
if( ! pValue || nSize != 0 )
errCode = NETIO_ERR_WRONG_PARAM;
}
if( errCode == 0 )
{
char * itmData = NULL;
HB_SIZE itmSize = 0;
iResult = hb_fileConfigure( pFile, iIndex, pValue ) ? 1 : 0;
if( pValue )
itmData = hb_itemSerialize( pValue, HB_SERIALIZE_NUMSIZE, &itmSize );
if( itmSize <= sizeof( buffer ) - NETIO_MSGLEN )
msg = buffer;
else if( ! ptr || itmSize > ( HB_SIZE ) size - NETIO_MSGLEN )
{
if( ptr )
hb_xfree( ptr );
ptr = msg = ( HB_BYTE * ) hb_xgrab( itmSize + NETIO_MSGLEN );
}
else
msg = ptr;
if( itmData )
{
memcpy( msg + NETIO_MSGLEN, itmData, itmSize );
hb_xfree( itmData );
}
len = ( long ) itmSize;
errFsCode = hb_fsError();
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
HB_PUT_LE_UINT32( &msg[ 4 ], len );
HB_PUT_LE_UINT32( &msg[ 8 ], iResult );
HB_PUT_LE_UINT32( &msg[ 12 ], errFsCode );
memset( msg + 12, '\0', NETIO_MSGLEN - 12 );
}
if( pValue )
hb_itemRelease( pValue );
}
}
}
break;
case NETIO_READ:
case NETIO_READAT:
iFileNo = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
size = HB_GET_LE_UINT32( &msgbuf[ 6 ] );
if( uiMsg == NETIO_READ )
{
nTimeout = HB_GET_LE_INT64( &msgbuf[ 10 ] );
llOffset = 0;
}
else
{
nTimeout = 0;
llOffset = HB_GET_LE_INT64( &msgbuf[ 10 ] );
}
if( size < 0 )
errCode = NETIO_ERR_WRONG_PARAM;
else
{
if( size > ( long ) ( sizeof( buffer ) - NETIO_MSGLEN ) )
ptr = msg = ( HB_BYTE * ) hb_xgrab( size + NETIO_MSGLEN );
pFile = s_srvFileGet( conn, iFileNo );
if( pFile == NULL )
errCode = NETIO_ERR_WRONG_FILE_HANDLE;
else
{
if( uiMsg == NETIO_READ )
len = ( long ) hb_fileRead( pFile, msg + NETIO_MSGLEN, size, nTimeout );
else
len = ( long ) hb_fileReadAt( pFile, msg + NETIO_MSGLEN, size, llOffset );
errFsCode = hb_fsError();
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
HB_PUT_LE_UINT32( &msg[ 4 ], len );
HB_PUT_LE_UINT32( &msg[ 8 ], errFsCode );
memset( msg + 12, '\0', NETIO_MSGLEN - 12 );
if( len == FS_ERROR )
len = 0;
}
}
break;
case NETIO_WRITE:
case NETIO_WRITEAT:
iFileNo = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
size = HB_GET_LE_UINT32( &msgbuf[ 6 ] );
if( uiMsg == NETIO_WRITE )
{
nTimeout = HB_GET_LE_INT64( &msgbuf[ 10 ] );
llOffset = 0;
}
else
{
nTimeout = 0;
llOffset = HB_GET_LE_INT64( &msgbuf[ 10 ] );
}
if( size < 0 )
errCode = NETIO_ERR_WRONG_PARAM;
else
{
if( size > ( long ) sizeof( buffer ) )
ptr = msg = ( HB_BYTE * ) hb_xgrab( size );
if( ! s_srvRecvAll( conn, msg, size ) )
errCode = NETIO_ERR_READ;
else
{
pFile = s_srvFileGet( conn, iFileNo );
if( pFile == NULL )
errCode = NETIO_ERR_WRONG_FILE_HANDLE;
else
{
if( uiMsg == NETIO_WRITE )
size = ( long ) hb_fileWrite( pFile, msg, size, nTimeout );
else
size = ( long ) hb_fileWriteAt( pFile, msg, size, llOffset );
errFsCode = hb_fsError();
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
HB_PUT_LE_UINT32( &msg[ 4 ], size );
HB_PUT_LE_UINT32( &msg[ 8 ], errFsCode );
memset( msg + 12, '\0', NETIO_MSGLEN - 12 );
}
}
}
break;
case NETIO_UNLOCK:
fNoAnswer = HB_TRUE;
/* fallthrough */
case NETIO_LOCK:
case NETIO_TESTLOCK:
iFileNo = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
llOffset = HB_GET_LE_INT64( &msgbuf[ 6 ] );
llSize = HB_GET_LE_INT64( &msgbuf[ 14 ] );
uiFlags = HB_GET_LE_UINT16( &msgbuf[ 22 ] );
pFile = s_srvFileGet( conn, iFileNo );
if( pFile == NULL )
errCode = NETIO_ERR_WRONG_FILE_HANDLE;
else if( uiMsg == NETIO_TESTLOCK )
{
iResult = hb_fileLockTest( pFile, llOffset, llSize, uiFlags );
errFsCode = hb_fsError();
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
HB_PUT_LE_UINT32( &msg[ 4 ], iResult );
HB_PUT_LE_UINT32( &msg[ 8 ], errFsCode );
memset( msg + 12, '\0', NETIO_MSGLEN - 4 );
}
else if( ! hb_fileLock( pFile, llOffset, llSize, uiFlags ) )
errCode = s_srvFsError();
else if( ! fNoAnswer )
{
HB_PUT_LE_UINT32( &msg[ 0 ], uiMsg );
memset( msg + 4, '\0', NETIO_MSGLEN - 4 );
}
break;
case NETIO_TRUNC:
iFileNo = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
llOffset = HB_GET_LE_INT64( &msgbuf[ 6 ] );
pFile = s_srvFileGet( conn, iFileNo );
if( pFile == NULL )
errCode = NETIO_ERR_WRONG_FILE_HANDLE;
else if( ! hb_fileTruncAt( pFile, llOffset ) )
errCode = s_srvFsError();
else
{
HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_TRUNC );
memset( msg + 4, '\0', NETIO_MSGLEN - 4 );
}
break;
case NETIO_SEEK:
iFileNo = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
llOffset = HB_GET_LE_INT64( &msgbuf[ 6 ] );
uiFlags = HB_GET_LE_UINT16( &msgbuf[ 14 ] );
pFile = s_srvFileGet( conn, iFileNo );
if( pFile == NULL )
errCode = NETIO_ERR_WRONG_FILE_HANDLE;
else
{
llOffset = hb_fileSeek( pFile, llOffset, uiFlags );
errFsCode = hb_fsError();
HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_SEEK );
HB_PUT_LE_UINT64( &msg[ 4 ], llOffset );
HB_PUT_LE_UINT32( &msg[ 12 ], errFsCode );
memset( msg + 16, '\0', NETIO_MSGLEN - 16 );
}
break;
case NETIO_SIZE:
iFileNo = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
pFile = s_srvFileGet( conn, iFileNo );
if( pFile == NULL )
errCode = NETIO_ERR_WRONG_FILE_HANDLE;
else
{
llOffset = hb_fileSize( pFile );
errFsCode = hb_fsError();
HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_SIZE );
HB_PUT_LE_UINT64( &msg[ 4 ], llOffset );
HB_PUT_LE_UINT32( &msg[ 12 ], errFsCode );
memset( msg + 16, '\0', NETIO_MSGLEN - 16 );
}
break;
case NETIO_EOF:
iFileNo = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
pFile = s_srvFileGet( conn, iFileNo );
if( pFile == NULL )
errCode = NETIO_ERR_WRONG_FILE_HANDLE;
else
{
iResult = hb_fileEof( pFile ) ? 1 : 0;
errFsCode = hb_fsError();
HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_EOF );
HB_PUT_LE_UINT32( &msg[ 4 ], iResult );
HB_PUT_LE_UINT32( &msg[ 8 ], errFsCode );
memset( msg + 12, '\0', NETIO_MSGLEN - 12 );
}
break;
case NETIO_COMMIT:
iFileNo = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
pFile = s_srvFileGet( conn, iFileNo );
if( pFile )
hb_fileCommit( pFile );
fNoAnswer = HB_TRUE;
break;
case NETIO_CLOSE:
iFileNo = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
pFile = s_srvFileFree( conn, iFileNo );
if( pFile == NULL )
errCode = NETIO_ERR_WRONG_FILE_HANDLE;
else
{
hb_fileClose( pFile );
HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_CLOSE );
memset( msg + 4, '\0', NETIO_MSGLEN - 4 );
}
break;
case NETIO_SRVCLOSE:
iStreamID = HB_GET_LE_INT32( &msgbuf[ 4 ] );
if( iStreamID && conn->mutex && hb_threadMutexLock( conn->mutex ) )
{
PHB_CONSTREAM * pStreamPtr = &conn->streams;
while( *pStreamPtr )
{
if( ( *pStreamPtr )->id == iStreamID )
break;
pStreamPtr = &( *pStreamPtr )->next;
}
if( *pStreamPtr != NULL )
{
PHB_CONSTREAM stream = *pStreamPtr;
*pStreamPtr = stream->next;
hb_xfree( stream );
}
else
iStreamID = 0;
hb_threadMutexUnlock( conn->mutex );
}
else
iStreamID = 0;
if( iStreamID == 0 )
errCode = NETIO_ERR_WRONG_STREAMID;
else
{
HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_SRVCLOSE );
memset( msg + 4, '\0', NETIO_MSGLEN - 4 );
}
break;
case NETIO_PROC:
fNoAnswer = HB_TRUE;
/* fallthrough */
case NETIO_PROCIS:
case NETIO_PROCW:
case NETIO_FUNC:
case NETIO_FUNCCTRL:
size = HB_GET_LE_UINT32( &msgbuf[ 4 ] );
if( size < 2 )
errCode = NETIO_ERR_WRONG_PARAM;
else
{
if( size > ( long ) sizeof( buffer ) )
ptr = msg = ( HB_BYTE * ) hb_xgrab( size );
if( ! s_srvRecvAll( conn, msg, size ) )
errCode = NETIO_ERR_READ;
else if( ! conn->rpc )
errCode = NETIO_ERR_UNSUPPORTED;
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 = NULL;
PHB_ITEM pItem = NULL;
if( conn->rpcFilter )
{
pItem = hb_hashGetCItemPtr( conn->rpcFilter, data );
if( ! pItem )
errCode = NETIO_ERR_NOT_EXISTS;
}
else
{
pDynSym = hb_dynsymFindName( data );
if( ! pDynSym || ! hb_dynsymIsFunction( pDynSym ) )
errCode = NETIO_ERR_NOT_EXISTS;
}
if( uiMsg != NETIO_PROCIS && errCode == 0 )
{
if( hb_vmRequestReenter() )
{
HB_SIZE nSize = size - size2;
HB_USHORT uiPCount = 0;
HB_BOOL fSend = HB_FALSE;
iStreamID = 0;
data += size2;
if( pItem )
{
fSend = HB_TRUE;
hb_vmPushEvalSym();
hb_vmPush( pItem );
}
else if( conn->rpcFunc )
{
hb_vmPushSymbol( conn->rpcFunc );
hb_vmPushNil();
hb_vmPushDynSym( pDynSym );
++uiPCount;
}
else
{
hb_vmPushDynSym( pDynSym );
hb_vmPushNil();
}
if( uiMsg == NETIO_FUNCCTRL )
{
int iStreamType;
iStreamID = HB_GET_LE_INT32( &msgbuf[ 8 ] );
iStreamType = HB_GET_LE_INT32( &msgbuf[ 12 ] );
hb_vmPush( hb_param( 1, HB_IT_ANY ) );
hb_vmPushInteger( iStreamID );
uiPCount += 2;
if( iStreamType != NETIO_SRVDATA &&
iStreamType != NETIO_SRVITEM )
iStreamID = 0;
if( iStreamID )
{
if( conn->mutex == NULL )
conn->mutex = hb_threadMutexCreate();
if( hb_threadMutexLock( conn->mutex ) )
{
PHB_CONSTREAM stream = ( PHB_CONSTREAM )
hb_xgrab( sizeof( HB_CONSTREAM ) );
stream->id = iStreamID;
stream->type = iStreamType;
stream->next = conn->streams;
conn->streams = stream;
}
else
{
errCode = NETIO_ERR_REFUSED;
iStreamID = 0;
}
}
else
errCode = NETIO_ERR_WRONG_PARAM;
}
while( nSize > 0 && errCode == 0 )
{
pItem = hb_itemDeserialize( &data, &nSize );
if( ! pItem )
{
errCode = NETIO_ERR_WRONG_PARAM;
break;
}
++uiPCount;
hb_vmPush( pItem );
hb_itemRelease( pItem );
}
if( errCode != 0 )
{
uiPCount += 2;
do
{
hb_stackPop();
}
while( --uiPCount );
}
else
{
if( fSend )
hb_vmSend( uiPCount );
else
hb_vmProc( uiPCount );
if( uiMsg == NETIO_FUNC || uiMsg == NETIO_FUNCCTRL )
{
HB_SIZE itmSize;
PHB_ITEM pResult = hb_stackReturnItem();
char * itmData = hb_itemSerialize( pResult, HB_SERIALIZE_NUMSIZE, &itmSize );
if( itmSize <= sizeof( buffer ) - NETIO_MSGLEN )
msg = buffer;
else if( ! ptr || itmSize > ( HB_SIZE ) size - NETIO_MSGLEN )
{
if( ptr )
hb_xfree( ptr );
ptr = msg = ( HB_BYTE * ) hb_xgrab( itmSize + NETIO_MSGLEN );
}
memcpy( msg + NETIO_MSGLEN, itmData, itmSize );
hb_xfree( itmData );
len = ( long ) itmSize;
if( iStreamID && hb_itemGetNI( pResult ) == iStreamID )
{
hb_threadMutexUnlock( conn->mutex );
iStreamID = 0;
}
}
}
hb_vmRequestRestore();
if( iStreamID )
{
PHB_CONSTREAM stream = conn->streams;
if( stream->id == iStreamID )
{
conn->streams = stream->next;
hb_xfree( stream );
}
hb_threadMutexUnlock( conn->mutex );
}
}
else
errCode = NETIO_ERR_REFUSED;
}
}
if( errCode == 0 && ! fNoAnswer )
{
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;
default: /* unrecognized message */
errCode = NETIO_ERR_UNKNOWN_COMMAND;
break;
}
if( fNoAnswer )
{
#if 0
continue; /* do not send dummy record */
#endif
HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_SYNC );
memset( msg + 4, '\0', NETIO_MSGLEN - 4 );
len = NETIO_MSGLEN;
}
else if( errCode != 0 )
{
HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_ERROR );
HB_PUT_LE_UINT32( &msg[ 4 ], errCode );
memset( msg + 8, '\0', NETIO_MSGLEN - 8 );
len = NETIO_MSGLEN;
}
else
len += NETIO_MSGLEN;
errCode = ! s_srvSendAll( conn, msg, len );
if( ptr )
hb_xfree( ptr );
if( errCode )
break;
}
}
}
/* netio_ServedConnection() --> <pConnectionSocket>
*/
HB_FUNC( NETIO_SERVEDCONNECTION )
{
static PHB_DYNS s_pDyns_netio_server = NULL;
if( s_pDyns_netio_server == NULL )
s_pDyns_netio_server = hb_dynsymGetCase( "NETIO_SERVER" );
if( s_pDyns_netio_server != NULL )
{
HB_ISIZ nOffset = hb_stackBaseSymbolOffset( hb_dynsymSymbol( s_pDyns_netio_server ) );
if( nOffset > 0 )
{
PHB_ITEM pItem = hb_stackItem( nOffset + 2 );
if( hb_itemGetPtrGC( pItem, &s_gcConSrvFuncs ) != NULL )
hb_itemReturn( pItem );
}
}
}
/* netio_SrvSendItem( <pConnectionSocket>, <nStreamID>, <xData> ) --> <lSent>
*/
HB_FUNC( NETIO_SRVSENDITEM )
{
PHB_CONSRV conn = s_consrvParam( 1 );
int iStreamID = hb_parni( 2 );
PHB_ITEM pItem = hb_param( 3, HB_IT_ANY );
HB_BOOL fResult = HB_FALSE;
if( conn && conn->sock && ! conn->stop && conn->mutex &&
iStreamID && pItem )
{
char * itmData, * msg;
HB_SIZE nLen;
long lLen;
itmData = hb_itemSerialize( pItem, HB_SERIALIZE_NUMSIZE, &nLen );
lLen = ( long ) nLen;
msg = ( char * ) hb_xgrab( lLen + NETIO_MSGLEN );
HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_SRVITEM );
HB_PUT_LE_UINT32( &msg[ 4 ], iStreamID );
HB_PUT_LE_UINT32( &msg[ 8 ], lLen );
memset( msg + 12, '\0', NETIO_MSGLEN - 12 );
memcpy( msg + NETIO_MSGLEN, itmData, lLen );
hb_xfree( itmData );
lLen += NETIO_MSGLEN;
if( hb_threadMutexLock( conn->mutex ) )
{
PHB_CONSTREAM stream = conn->streams;
while( stream )
{
if( stream->id == iStreamID )
break;
stream = stream->next;
}
if( stream && stream->type == NETIO_SRVITEM )
fResult = s_srvSendAll( conn, msg, lLen );
hb_threadMutexUnlock( conn->mutex );
}
hb_xfree( msg );
}
hb_retl( fResult );
}
/* netio_SrvSendData( <pConnectionSocket>, <nStreamID>, <cData> ) --> <lSent>
*/
HB_FUNC( NETIO_SRVSENDDATA )
{
PHB_CONSRV conn = s_consrvParam( 1 );
int iStreamID = hb_parni( 2 );
long lLen = ( long ) hb_parclen( 3 );
HB_BOOL fResult = HB_FALSE;
if( conn && conn->sock && ! conn->stop && conn->mutex &&
iStreamID && lLen > 0 )
{
char * msg;
msg = ( char * ) hb_xgrab( lLen + NETIO_MSGLEN );
HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_SRVDATA );
HB_PUT_LE_UINT32( &msg[ 4 ], iStreamID );
HB_PUT_LE_UINT32( &msg[ 8 ], lLen );
memset( msg + 12, '\0', NETIO_MSGLEN - 12 );
memcpy( msg + NETIO_MSGLEN, hb_parc( 3 ), lLen );
lLen += NETIO_MSGLEN;
if( hb_threadMutexLock( conn->mutex ) )
{
PHB_CONSTREAM stream = conn->streams;
while( stream )
{
if( stream->id == iStreamID )
break;
stream = stream->next;
}
if( stream && stream->type == NETIO_SRVDATA )
fResult = s_srvSendAll( conn, msg, lLen );
hb_threadMutexUnlock( conn->mutex );
}
hb_xfree( msg );
}
hb_retl( fResult );
}
/* netio_SrvStatus( <pConnectionSocket>
* [, <nStreamID> | <nSrvInfo>, @<xData>] ) --> <nStatus>
*/
HB_FUNC( NETIO_SRVSTATUS )
{
PHB_CONSRV conn = s_consrvParam( 1 );
int iStreamID = hb_parni( 2 ), iSrvInfo = 0;
int iStatus = NETIO_SRVSTAT_RUNNING;
if( iStreamID < 0 )
{
iSrvInfo = iStreamID;
iStreamID = 0;
}
if( ! conn )
iStatus = NETIO_SRVSTAT_WRONGHANDLE;
else if( conn->sock == NULL )
iStatus = NETIO_SRVSTAT_CLOSED;
else if( conn->stop )
iStatus = NETIO_SRVSTAT_STOPPED;
else if( iStreamID != 0 && conn->mutex )
{
if( hb_threadMutexLock( conn->mutex ) )
{
PHB_CONSTREAM stream = conn->streams;
while( stream )
{
if( stream->id == iStreamID )
{
iStatus = stream->type == NETIO_SRVDATA ?
NETIO_SRVSTAT_DATASTREAM : NETIO_SRVSTAT_ITEMSTREAM;
break;
}
stream = stream->next;
}
hb_threadMutexUnlock( conn->mutex );
}
}
else
{
switch( iSrvInfo )
{
case NETIO_SRVINFO_FILESCOUNT:
hb_storni( conn->filesCount, 3 );
break;
case NETIO_SRVINFO_BYTESSENT:
hb_stornint( conn->wr_count, 3 );
break;
case NETIO_SRVINFO_BYTESRECEIVED:
hb_stornint( conn->rd_count, 3 );
break;
case NETIO_SRVINFO_PEERADDRESS:
{
void * addr;
unsigned int len;
PHB_ITEM pItem = NULL;
if( hb_socketGetPeerName( hb_sockexGetHandle( conn->sock ), &addr, &len ) == 0 )
{
pItem = hb_socketAddrToItem( addr, len );
if( addr )
hb_xfree( addr );
}
if( ! hb_itemParamStoreRelease( 3, pItem ) && pItem )
hb_itemRelease( pItem );
break;
}
}
}
hb_retni( iStatus );
}