Files
harbour-core/contrib/hbnetio/netiocli.c
Aleksander Czajczynski 4047c53980 2018-02-12 10:00 UTC+0100 Aleksander Czajczynski (hb fki.pl)
* contrib/hbnetio/netiocli.c
    ! fix indentation
2018-02-12 10:00:00 +01:00

2709 lines
78 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 client code with
* netio_Connect( [<cServer>], [<nPort>], [<nTimeOut>],
* [<cPasswd>], [<nCompressionLevel>], [<nStrategy>] )
* --> <lOK>
* function which register alternative RDD IO API, sets server
* address and port and connection timeout parameter.
* Then it tries to connect to the server and returns .T. on success.
* This code also provides the following .prg functions:
* netio_Disconnect( [<cServer>], [<nPort>] ) --> <lOK>
* netio_Decode( [@]<cFullName>, [@<cServer>], [@<nPort>], [@<nTimeOut>],
* [@<cPasswd>], [@<nCompressionLevel>], [@<nStrategy>] )
* --> <lDecoded>
* netio_ProcExists( <cProcName> ) --> <lExists>
* netio_ProcExec( <cProcName> [, <params,...>] ) --> <lSent>
* netio_ProcExecW( <cProcName> [, <params,...>] ) --> <lExecuted>
* netio_FuncExec( <cFuncName> [, <params,...>] ) --> <xFuncRetVal>
*
* netio_OpenDataStream( <cStreamFuncName> [, <params,...>] )
* --> <nStreamID>
* netio_OpenItemStream( <cStreamFuncName> [, <params,...>] )
* --> <nStreamID>
* netio_CloseStream( <nStreamID>, [<cServer>], [<nPort>] )
* --> <lOK>
* netio_GetData( <nStreamID>, [<cServer>], [<nPort>] )
* --> <aData> | <cData> | NIL
*
* 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.
*
*/
/* this has to be declared before hbapifs.h is included */
#define _HB_FILE_IMPLEMENTATION_
#include "hbapi.h"
#include "hbapifs.h"
#include "hbapiitm.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"
/*
* client code
*/
typedef struct _HB_SRVDATA
{
int id;
int type;
PHB_ITEM array;
char * data;
HB_SIZE size;
HB_SIZE bufsize;
HB_SIZE maxsize;
struct _HB_SRVDATA * next;
}
HB_SRVDATA, * PHB_SRVDATA;
typedef struct _HB_CONCLI
{
HB_COUNTER used;
HB_COUNTER usrcount;
PHB_ITEM mutex;
HB_ERRCODE errcode;
int timeout;
int port;
PHB_SOCKEX sock;
PHB_SRVDATA srvdata;
struct _HB_CONCLI * next;
char * path;
int level;
int strategy;
int passlen;
char passwd[ NETIO_PASSWD_MAX ];
char server[ 1 ];
}
HB_CONCLI, * PHB_CONCLI;
typedef struct _HB_FILE
{
const HB_FILE_FUNCS * pFuncs;
PHB_CONCLI conn;
HB_USHORT fd;
}
HB_FILE;
typedef struct
{
int timeout;
int port;
int level;
int strategy;
int passlen;
char server[ NETIO_SERVERNAME_MAX ];
char passwd[ NETIO_PASSWD_MAX ];
} HB_CONDATA, * PHB_CONDATA;
/* MT macros */
#define HB_NETIO_LOCK() hb_threadEnterCriticalSection( &s_netioMtx )
#define HB_NETIO_UNLOCK() hb_threadLeaveCriticalSection( &s_netioMtx )
static HB_CRITICAL_NEW( s_netioMtx );
static HB_TSD_NEW( s_conData, sizeof( HB_CONDATA ), NULL, NULL );
static PHB_CONCLI s_connections = NULL;
static HB_COUNTER s_pathCount = 0;
static HB_BOOL s_defaultInit = HB_TRUE;
static HB_CONDATA s_defaultConn = {
NETIO_DEFAULT_TIMEOUT,
NETIO_DEFAULT_PORT,
HB_ZLIB_COMPRESSION_DISABLE,
HB_ZLIB_STRATEGY_DEFAULT,
0,
NETIO_DEFAULT_SERVER,
""
};
static HB_BOOL s_fInit = HB_TRUE;
static const HB_FILE_FUNCS * s_fileMethods( void );
static void hb_errRT_NETIO( HB_ERRCODE errGenCode, HB_ERRCODE errSubCode,
HB_ERRCODE errOsCode, const char * szDescription,
const char * szOperation )
{
PHB_ITEM pError;
pError = hb_errRT_New( ES_ERROR, "NETIO", errGenCode, errSubCode,
szDescription, szOperation, errOsCode, EF_NONE );
hb_errLaunch( pError );
hb_itemRelease( pError );
}
static long s_fileRecvAll( PHB_CONCLI 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 )
{
l = hb_sockexRead( conn->sock, ptr + lRead, len - lRead, 1000 );
if( l > 0 )
lRead += l;
else if( l == 0 ||
hb_socketGetError() != HB_SOCKET_ERR_TIMEOUT ||
( timeout = hb_timerTest( timeout, &timer ) ) == 0 ||
hb_vmRequestQuery() != 0 )
break;
}
return lRead;
}
static long s_fileRecvTest( PHB_CONCLI conn, void * buffer, long len )
{
HB_BYTE * ptr = ( HB_BYTE * ) buffer;
long lRead = 0, l;
HB_MAXINT timeout = 0;
while( lRead < len )
{
l = hb_sockexRead( conn->sock, ptr + lRead, len - lRead, timeout );
if( l <= 0 )
break;
lRead += l;
timeout = conn->timeout;
}
return lRead;
}
static int s_fileGenSrvDataID( PHB_CONCLI conn )
{
PHB_SRVDATA pSrvData = conn->srvdata;
static int s_iStreamID = 0;
if( ++s_iStreamID <= 0 )
s_iStreamID = 1;
while( pSrvData )
{
if( pSrvData->id == s_iStreamID )
{
if( ++s_iStreamID <= 0 )
s_iStreamID = 1;
pSrvData = conn->srvdata;
}
else
pSrvData = pSrvData->next;
}
return s_iStreamID;
}
static PHB_SRVDATA s_fileFindSrvData( PHB_CONCLI conn, int iStreamID, int iType )
{
PHB_SRVDATA pSrvData = conn->srvdata;
while( pSrvData )
{
if( pSrvData->id == iStreamID )
return ( iType == 0 || pSrvData->type == iType ) ? pSrvData : NULL;
pSrvData = pSrvData->next;
}
return NULL;
}
static int s_fileNewSrvData( PHB_CONCLI conn, int iType )
{
PHB_SRVDATA pSrvData = ( PHB_SRVDATA ) hb_xgrabz( sizeof( HB_SRVDATA ) );
pSrvData->id = s_fileGenSrvDataID( conn );
pSrvData->type = iType;
if( iType == NETIO_SRVITEM )
pSrvData->maxsize = 4096;
else if( iType == NETIO_SRVDATA )
pSrvData->maxsize = 0x10000;
pSrvData->next = conn->srvdata;
if( ! conn->srvdata )
hb_atomic_inc( &conn->used );
conn->srvdata = pSrvData;
return pSrvData->id;
}
static HB_BOOL s_fileCloseSrvData( PHB_CONCLI conn, int iStreamID )
{
PHB_SRVDATA * pSrvDataPtr = &conn->srvdata;
while( *pSrvDataPtr )
{
if( ( *pSrvDataPtr )->id == iStreamID )
{
PHB_SRVDATA pSrvData = *pSrvDataPtr;
*pSrvDataPtr = pSrvData->next;
if( pSrvData->array )
hb_itemRelease( pSrvData->array );
if( pSrvData->data )
hb_xfree( pSrvData->data );
hb_xfree( pSrvData );
if( ! conn->srvdata )
hb_atomic_dec( &conn->used );
return HB_TRUE;
}
pSrvDataPtr = &( *pSrvDataPtr )->next;
}
return HB_FALSE;
}
static HB_BOOL s_fileRecvSrvData( PHB_CONCLI conn, long len, int iStreamID, int iType )
{
char * buffer = ( char * ) hb_xgrab( len );
HB_BOOL fResult = HB_FALSE;
if( s_fileRecvAll( conn, buffer, len ) == len )
{
PHB_SRVDATA pSrvData = s_fileFindSrvData( conn, iStreamID, iType );
if( pSrvData )
{
if( pSrvData->size < pSrvData->maxsize )
{
if( iType == NETIO_SRVITEM )
{
HB_SIZE nSize = len;
const char * data = buffer;
PHB_ITEM pItem = hb_itemDeserialize( &data, &nSize );
if( pItem )
{
if( nSize == 0 )
{
if( pSrvData->array == NULL )
pSrvData->array = hb_itemArrayNew( 0 );
if( hb_arrayLen( pSrvData->array ) < pSrvData->maxsize )
hb_arrayAddForward( pSrvData->array, pItem );
}
hb_itemRelease( pItem );
}
}
else if( iType == NETIO_SRVDATA )
{
long lmax = ( long ) ( pSrvData->maxsize - pSrvData->size );
if( len > lmax )
len = lmax;
if( pSrvData->size + len > pSrvData->bufsize )
{
pSrvData->bufsize = ( pSrvData->size + len ) << 1;
if( pSrvData->bufsize > pSrvData->maxsize )
pSrvData->bufsize = pSrvData->maxsize;
pSrvData->data = ( char * ) hb_xrealloc( pSrvData->data,
pSrvData->bufsize );
}
memcpy( pSrvData->data + pSrvData->size, buffer, len );
pSrvData->size += len;
}
}
}
fResult = HB_TRUE;
}
else
{
conn->errcode = hb_socketGetError();
hb_errRT_NETIO( EG_READ, 1001, conn->errcode, NULL, HB_ERR_FUNCNAME );
}
hb_xfree( buffer );
return fResult;
}
static HB_BOOL s_fileSendMsg( PHB_CONCLI conn, HB_BYTE * msgbuf,
const void * data, long len,
HB_BOOL fWait, HB_BOOL fNoError )
{
HB_BYTE buffer[ 2048 ];
HB_BYTE * msg, * ptr = NULL;
HB_LONG lSent = 0, l;
HB_BOOL fResult = HB_FALSE;
if( len == 0 )
{
msg = msgbuf;
len = NETIO_MSGLEN;
}
else
{
len += NETIO_MSGLEN;
if( len > ( long ) sizeof( buffer ) )
msg = ptr = ( HB_BYTE * ) hb_xgrab( len );
else
msg = buffer;
memcpy( msg, msgbuf, NETIO_MSGLEN );
memcpy( msg + NETIO_MSGLEN, data, len - NETIO_MSGLEN );
}
while( lSent < len )
{
l = hb_sockexWrite( conn->sock, msg + lSent, len - lSent, conn->timeout );
if( l <= 0 )
break;
lSent += l;
}
if( ptr )
hb_xfree( ptr );
if( lSent == len )
{
if( hb_sockexFlush( conn->sock, conn->timeout, HB_FALSE ) != 0 )
{
conn->errcode = hb_socketGetError();
if( ! fNoError )
hb_errRT_NETIO( EG_WRITE, 1002, conn->errcode, NULL, HB_ERR_FUNCNAME );
}
else if( fWait )
{
int iMsg = HB_GET_LE_INT32( msgbuf );
for( ;; )
{
int iResult;
if( s_fileRecvAll( conn, msgbuf, NETIO_MSGLEN ) != NETIO_MSGLEN )
{
conn->errcode = hb_socketGetError();
if( ! fNoError )
hb_errRT_NETIO( EG_READ, 1003, conn->errcode, NULL, HB_ERR_FUNCNAME );
break;
}
iResult = HB_GET_LE_INT32( msgbuf );
if( iResult == NETIO_SRVITEM || iResult == NETIO_SRVDATA )
{
int iStreamID = HB_GET_LE_UINT32( &msgbuf[ 4 ] );
len = HB_GET_LE_INT32( &msgbuf[ 8 ] );
if( len > 0 )
{
if( ! s_fileRecvSrvData( conn, len, iStreamID, iResult ) )
break;
}
}
else if( iResult != NETIO_SYNC )
{
if( iResult == NETIO_ERROR )
{
conn->errcode = ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 4 ] );
hb_fsSetError( conn->errcode );
}
else if( iResult != iMsg )
{
conn->errcode = NETIO_ERR_UNKNOWN_COMMAND;
if( ! fNoError )
hb_errRT_NETIO( EG_UNSUPPORTED, 1004, 0, NULL, HB_ERR_FUNCNAME );
}
else
fResult = HB_TRUE;
break;
}
}
}
else
fResult = HB_TRUE;
}
else
{
conn->errcode = hb_socketGetError();
if( ! fNoError )
hb_errRT_NETIO( EG_WRITE, 1005, conn->errcode, NULL, HB_ERR_FUNCNAME );
}
return fResult;
}
static HB_BOOL s_fileProcessData( PHB_CONCLI conn )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_BOOL fResult = HB_TRUE;
int iMsg, iStreamID;
for( ;; )
{
long len = s_fileRecvTest( conn, msgbuf, NETIO_MSGLEN );
if( len == NETIO_MSGLEN )
{
iMsg = HB_GET_LE_INT32( msgbuf );
if( iMsg == NETIO_SRVITEM || iMsg == NETIO_SRVDATA )
{
iStreamID = HB_GET_LE_INT32( &msgbuf[ 4 ] );
len = HB_GET_LE_INT32( &msgbuf[ 8 ] );
if( len > 0 )
{
if( ! s_fileRecvSrvData( conn, len, iStreamID, iMsg ) )
{
fResult = HB_FALSE;
break;
}
}
}
else if( iMsg == NETIO_ERROR )
{
conn->errcode = ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 4 ] );
hb_fsSetError( conn->errcode );
}
else if( iMsg != NETIO_SYNC )
{
fResult = HB_FALSE;
conn->errcode = NETIO_ERR_UNKNOWN_COMMAND;
hb_errRT_NETIO( EG_UNSUPPORTED, 1006, 0, NULL, HB_ERR_FUNCNAME );
break;
}
}
else
{
if( len != 0 )
{
fResult = HB_FALSE;
conn->errcode = hb_socketGetError();
hb_errRT_NETIO( EG_READ, 1007, conn->errcode, NULL, HB_ERR_FUNCNAME );
}
break;
}
}
return fResult;
}
static void s_fileConFree( PHB_CONCLI conn )
{
if( conn->sock )
hb_sockexClose( conn->sock, HB_TRUE );
while( conn->srvdata )
{
PHB_SRVDATA pSrvData = conn->srvdata;
conn->srvdata = pSrvData->next;
if( pSrvData->array )
hb_itemRelease( pSrvData->array );
if( pSrvData->data )
hb_xfree( pSrvData->data );
hb_xfree( pSrvData );
}
if( conn->mutex )
hb_itemRelease( conn->mutex );
if( conn->path )
{
hb_atomic_dec( &s_pathCount );
hb_xfree( conn->path );
}
hb_xfree( conn );
}
static PHB_CONCLI s_fileConNew( HB_SOCKET sd, const char * pszServer,
int iPort, int iTimeOut,
const char * pszPasswd, int iPassLen,
int iLevel, int iStrategy )
{
PHB_CONCLI conn;
int iLen;
iLen = ( int ) strlen( pszServer );
conn = ( PHB_CONCLI ) hb_xgrab( sizeof( HB_CONCLI ) + iLen );
hb_atomic_set( &conn->used, 1 );
hb_atomic_set( &conn->usrcount, 0 );
conn->mutex = hb_threadMutexCreate();
conn->errcode = 0;
conn->srvdata = NULL;
conn->next = NULL;
conn->path = NULL;
conn->timeout = iTimeOut;
conn->port = iPort;
memcpy( conn->server, pszServer, iLen + 1 );
conn->level = iLevel;
conn->strategy = iStrategy;
conn->passlen = iPassLen;
if( iPassLen )
memcpy( conn->passwd, pszPasswd, iPassLen );
if( iLevel == HB_ZLIB_COMPRESSION_DISABLE )
conn->sock = hb_sockexNew( sd, NULL, NULL );
else
conn->sock = hb_sockexNewZNet( sd, pszPasswd, iPassLen,
iLevel, iStrategy );
if( conn->sock == NULL )
{
s_fileConFree( conn );
conn = NULL;
}
else
hb_sockexSetShutDown( conn->sock, HB_TRUE );
return conn;
}
static void s_fileConRegister( PHB_CONCLI conn )
{
PHB_CONCLI * connPtr;
HB_NETIO_LOCK();
connPtr = &s_connections;
while( *connPtr )
connPtr = &( *connPtr )->next;
*connPtr = conn;
HB_NETIO_UNLOCK();
}
static void s_fileConClose( PHB_CONCLI conn )
{
if( hb_atomic_dec( &conn->used ) )
{
HB_NETIO_LOCK();
if( hb_atomic_get( &conn->used ) == 0 )
{
PHB_CONCLI * connPtr = &s_connections;
while( *connPtr )
{
if( *connPtr == conn )
{
*connPtr = conn->next;
break;
}
connPtr = &( *connPtr )->next;
}
}
else
conn = NULL; /* reused by other thread */
HB_NETIO_UNLOCK();
if( conn )
s_fileConFree( conn );
}
}
static PHB_CONCLI s_fileConFind( const char * pszServer, int iPort )
{
PHB_CONCLI conn;
HB_NETIO_LOCK();
conn = s_connections;
while( conn )
{
if( conn->port == iPort && hb_stricmp( conn->server, pszServer ) == 0 )
{
hb_atomic_inc( &conn->used );
break;
}
conn = conn->next;
}
HB_NETIO_UNLOCK();
return conn;
}
static HB_BOOL s_fileUsrDisconnect( const char * pszServer, int iPort )
{
PHB_CONCLI conn, connClose = NULL;
HB_NETIO_LOCK();
conn = s_connections;
while( conn )
{
if( conn->port == iPort && hb_stricmp( conn->server, pszServer ) == 0 )
{
if( hb_atomic_get( &conn->usrcount ) )
{
if( hb_atomic_dec( &conn->usrcount ) )
connClose = conn;
}
break;
}
conn = conn->next;
}
HB_NETIO_UNLOCK();
if( connClose )
s_fileConClose( connClose );
return conn != NULL;
}
static void s_fileUsrConnect( PHB_CONCLI conn )
{
hb_atomic_inc( &conn->usrcount );
}
static HB_BOOL s_fileConLock( PHB_CONCLI conn )
{
return ! conn->mutex || hb_threadMutexLock( conn->mutex );
}
static void s_fileConUnlock( PHB_CONCLI conn )
{
if( conn->mutex )
hb_threadMutexUnlock( conn->mutex );
}
static PHB_CONCLI s_fileNameConFind( const char ** pFileName, HB_BOOL fLock )
{
PHB_CONCLI conn = NULL;
if( s_pathCount > 0 )
{
HB_NETIO_LOCK();
conn = s_connections;
while( conn )
{
if( conn->path )
{
int iLen = ( int ) strlen( conn->path );
#ifdef HB_OS_UNIX
if( strncmp( *pFileName, conn->path, iLen ) == 0 )
#else
if( hb_strnicmp( *pFileName, conn->path, iLen ) == 0 )
#endif
{
if( fLock )
hb_atomic_inc( &conn->used );
*pFileName += iLen;
break;
}
}
conn = conn->next;
}
HB_NETIO_UNLOCK();
}
return conn;
}
static void s_fileGetConnParam( const char ** pszServer, int * piPort, int * piTimeOut,
const char ** pszPasswd, int * piPassLen )
{
PHB_CONDATA pConData = ( PHB_CONDATA ) hb_stackTestTSD( &s_conData );
if( pConData == NULL )
pConData = &s_defaultConn;
if( *pszServer == NULL )
*pszServer = pConData->server;
if( *piPort == 0 )
*piPort = pConData->port;
if( piTimeOut && ( *piTimeOut == 0 || *piTimeOut < -1 ) )
*piTimeOut = pConData->timeout;
if( piPassLen && *piPassLen == 0 && pConData->passlen != 0 )
{
*piPassLen = pConData->passlen;
*pszPasswd = pConData->passwd;
}
}
static const char * s_fileDecode( const char * pszFileName,
char * buffer, const char ** pServer,
int * piPort, int * piTimeOut,
const char ** pPasswd, int * piPassLen,
int * piLevel, int * piStrategy )
{
HB_SYMBOL_UNUSED( piTimeOut );
HB_SYMBOL_UNUSED( piLevel );
HB_SYMBOL_UNUSED( piStrategy );
if( pszFileName )
{
/* decode server address and port if given as part of file name
* in format like:
* "example.org:2941:path/to/file"
* or:
* "example.org:2941:passwd:path/to/file"
* or:
* "//example.org:2941/path/to/file"
*/
const char * psz, * pth = NULL;
if( ( pszFileName[ 0 ] == '/' || pszFileName[ 0 ] == '\\' ) &&
pszFileName[ 0 ] == pszFileName[ 1 ] )
{
pszFileName += 2;
pth = strchr( pszFileName, '/' );
psz = strchr( pszFileName, '\\' );
if( ! pth || ( psz && psz < pth ) )
{
pth = psz;
if( ! pth )
pth = pszFileName + strlen( pszFileName );
}
}
psz = strchr( pszFileName, ':' );
if( pth && ( ! psz || pth < psz ) )
psz = pth;
if( psz )
{
int iLen = ( int ) ( psz - pszFileName );
if( pth || iLen == 0 || iLen > 1 )
{
if( iLen >= NETIO_SERVERNAME_MAX )
iLen = NETIO_SERVERNAME_MAX - 1;
if( iLen > 0 )
{
hb_strncpy( buffer, pszFileName, iLen );
*pServer = buffer;
}
pszFileName = psz + 1;
if( ! pth || psz < pth )
{
char port_buf[ 10 ], c;
iLen = 0;
while( HB_ISDIGIT( pszFileName[ iLen ] ) &&
iLen < ( int ) sizeof( port_buf ) - 1 )
{
port_buf[ iLen ] = pszFileName[ iLen ];
++iLen;
}
c = pszFileName[ iLen ];
if( c == ':' || c == '/' || c == '\\' )
{
if( iLen > 0 )
{
int iOverflow;
HB_MAXINT llPort;
port_buf[ iLen ] = '\0';
llPort = hb_strValInt( port_buf, &iOverflow );
if( ! iOverflow && llPort > 0 && llPort < 0x10000 )
{
pszFileName += iLen;
*piPort = ( int ) llPort;
}
}
if( c == ':' )
{
++pszFileName;
iLen = 0;
while( pszFileName[ iLen ] &&
pszFileName[ iLen ] != ':' )
++iLen;
if( pszFileName[ iLen ] == ':' )
{
if( pPasswd )
*pPasswd = pszFileName;
pszFileName += iLen + 1;
if( iLen > NETIO_PASSWD_MAX )
iLen = NETIO_PASSWD_MAX;
if( piPassLen )
*piPassLen = iLen;
}
}
}
}
}
}
}
return pszFileName;
}
static PHB_CONCLI s_fileConnCheck( PHB_CONCLI conn, const char ** pFileName,
HB_BOOL fDefault, HB_BOOL * pfResult )
{
const char * pszFileName = *pFileName;
*pfResult = HB_TRUE;
if( hb_strnicmp( pszFileName, NETIO_FILE_PREFIX, NETIO_FILE_PREFIX_LEN ) == 0 )
{
char server[ NETIO_SERVERNAME_MAX ];
const char * pszServer = NULL;
int iPort = 0;
if( ! fDefault )
{
pszServer = conn->server;
iPort = conn->port;
}
else
s_fileGetConnParam( &pszServer, &iPort, NULL, NULL, NULL );
pszFileName = s_fileDecode( pszFileName + NETIO_FILE_PREFIX_LEN, server,
&pszServer, &iPort, NULL,
NULL, NULL, NULL, NULL );
if( iPort != conn->port )
*pfResult = HB_FALSE;
else
{
if( pszServer != conn->server && hb_stricmp( pszServer, conn->server ) != 0 )
{
char * pszIpAddres = hb_socketResolveAddr( pszServer, HB_SOCKET_AF_INET );
if( pszIpAddres == NULL || hb_stricmp( pszIpAddres, conn->server ) != 0 )
{
*pfResult = HB_FALSE;
conn = NULL;
}
if( pszIpAddres )
hb_xfree( pszIpAddres );
}
if( conn )
*pFileName = pszFileName;
return conn;
}
}
else if( s_pathCount > 0 && conn->path )
{
HB_NETIO_LOCK();
if( conn->path )
{
int iLen = ( int ) strlen( conn->path );
#ifdef HB_OS_UNIX
if( strncmp( *pFileName, conn->path, iLen ) == 0 )
#else
if( hb_strnicmp( *pFileName, conn->path, iLen ) == 0 )
#endif
*pFileName += iLen;
}
HB_NETIO_LOCK();
if( pszFileName != *pFileName )
return conn;
}
return NULL;
}
static PHB_CONCLI s_fileConnect( const char ** pFileName,
const char * pszServer,
int iPort, int iTimeOut, HB_BOOL fNoError,
const char * pszPasswd, int iPassLen,
int iLevel, int iStrategy )
{
PHB_CONCLI conn = NULL;
if( pFileName )
{
if( hb_strnicmp( *pFileName, NETIO_FILE_PREFIX, NETIO_FILE_PREFIX_LEN ) == 0 )
*pFileName += NETIO_FILE_PREFIX_LEN;
else
conn = s_fileNameConFind( pFileName, HB_TRUE );
}
if( conn == NULL )
{
char server[ NETIO_SERVERNAME_MAX ];
char * pszIpAddres;
s_fileGetConnParam( &pszServer, &iPort, &iTimeOut, &pszPasswd, &iPassLen );
if( pFileName )
*pFileName = s_fileDecode( *pFileName, server,
&pszServer, &iPort, &iTimeOut,
&pszPasswd, &iPassLen, &iLevel, &iStrategy );
if( iLevel == HB_ZLIB_COMPRESSION_DISABLE && iPassLen )
iLevel = HB_ZLIB_COMPRESSION_DEFAULT;
pszIpAddres = hb_socketResolveAddr( pszServer, HB_SOCKET_AF_INET );
if( pszIpAddres == NULL )
return NULL;
conn = s_fileConFind( pszIpAddres, iPort );
if( conn == NULL )
{
HB_SOCKET sd = hb_socketOpen( HB_SOCKET_PF_INET, HB_SOCKET_PT_STREAM, 0 );
if( sd != HB_NO_SOCKET )
{
void * pSockAddr;
unsigned uiLen;
if( hb_socketInetAddr( &pSockAddr, &uiLen, pszIpAddres, iPort ) )
{
hb_socketSetKeepAlive( sd, HB_TRUE );
if( hb_socketConnect( sd, pSockAddr, uiLen, iTimeOut ) == 0 )
{
hb_socketSetNoDelay( sd, HB_TRUE );
conn = s_fileConNew( sd, pszIpAddres, iPort, iTimeOut,
pszPasswd, iPassLen, iLevel, iStrategy );
if( conn )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( NETIO_LOGINSTRID );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_LOGIN );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
if( ! s_fileSendMsg( conn, msgbuf, NETIO_LOGINSTRID, len,
HB_TRUE, fNoError ) ||
HB_GET_LE_UINT32( &msgbuf[ 4 ] ) != NETIO_CONNECTED )
{
s_fileConFree( conn );
conn = NULL;
}
else
s_fileConRegister( conn );
sd = HB_NO_SOCKET;
}
}
hb_xfree( pSockAddr );
}
if( sd != HB_NO_SOCKET )
hb_socketClose( sd );
}
}
hb_xfree( pszIpAddres );
}
if( conn != NULL && s_defaultInit )
{
HB_NETIO_LOCK();
if( s_defaultInit )
{
hb_strncpy( s_defaultConn.server, conn->server,
sizeof( s_defaultConn.server ) - 1 );
s_defaultConn.port = iPort;
s_defaultConn.timeout = iTimeOut;
s_defaultConn.level = iLevel;
s_defaultConn.strategy = iStrategy;
s_defaultConn.passlen = iPassLen;
if( iPassLen )
memcpy( s_defaultConn.passwd, pszPasswd, iPassLen );
s_defaultInit = HB_FALSE;
}
HB_NETIO_UNLOCK();
}
return conn;
}
static void s_netio_exit( void * cargo )
{
HB_SYMBOL_UNUSED( cargo );
while( s_connections )
{
PHB_CONCLI conn = s_connections;
s_connections = conn->next;
s_fileConFree( conn );
}
if( ! s_fInit )
{
hb_socketCleanup();
s_fInit = HB_TRUE;
}
}
static void s_netio_init( void * cargo )
{
HB_SYMBOL_UNUSED( cargo );
if( s_fInit )
{
hb_socketInit();
hb_fileRegisterFull( s_fileMethods() );
hb_vmAtQuit( s_netio_exit, NULL );
s_fInit = HB_FALSE;
}
}
/* netio_Decode( [@]<cFullName>, [@<cServer>], [@<nPort>], [@<nTimeOut>], ;
* [@<cPasswd>], [@<nCompressionLevel>], [@<nStrategy>] ) --> <lOK>
*/
HB_FUNC( NETIO_DECODE )
{
char server[ NETIO_SERVERNAME_MAX ];
const char * pszFullName = hb_parc( 1 );
const char * pszServer, * pszPasswd, * pszFile;
int iPort, iTimeOut, iPassLen, iLevel, iStrategy;
pszServer = hb_parc( 2 );
iPort = hb_parni( 3 );
iTimeOut = hb_parni( 4 );
pszPasswd = hb_parc( 5 );
iPassLen = ( int ) hb_parclen( 5 );
iLevel = hb_parnidef( 6, HB_ZLIB_COMPRESSION_DISABLE );
iStrategy = hb_parnidef( 7, HB_ZLIB_STRATEGY_DEFAULT );
s_fileGetConnParam( &pszServer, &iPort, &iTimeOut, &pszPasswd, &iPassLen );
if( pszFullName )
{
if( hb_strnicmp( pszFullName, NETIO_FILE_PREFIX, NETIO_FILE_PREFIX_LEN ) == 0 )
pszFullName += NETIO_FILE_PREFIX_LEN;
pszFile = s_fileDecode( pszFullName, server,
&pszServer, &iPort, &iTimeOut,
&pszPasswd, &iPassLen, &iLevel, &iStrategy );
}
else
pszFile = NULL;
if( iLevel == HB_ZLIB_COMPRESSION_DISABLE && iPassLen )
iLevel = HB_ZLIB_COMPRESSION_DEFAULT;
hb_storc( pszServer, 2 );
hb_storni( iPort, 3 );
hb_storni( iTimeOut, 4 );
hb_storclen( pszPasswd, iPassLen, 5 );
hb_storni( iLevel, 6 );
hb_storni( iStrategy, 7 );
if( pszFile != pszFullName )
/* the order is important and 1st parameter
* should be assigned at the end
*/
hb_storc( pszFile, 1 );
hb_retl( pszFile != pszFullName );
}
/* netio_Connect( [<cServer>], [<nPort>], [<nTimeOut>], ;
* [<cPasswd>], [<nCompressionLevel>], [<nStrategy>] ) --> <lOK>
*/
HB_FUNC( NETIO_CONNECT )
{
const char * pszServer = hb_parc( 1 ),
* pszPasswd = hb_parc( 4 );
int iPort = hb_parni( 2 ),
iTimeOut = hb_parni( 3 ),
iPassLen = ( int ) hb_parclen( 4 ),
iLevel = hb_parnidef( 5, HB_ZLIB_COMPRESSION_DISABLE ),
iStrategy = hb_parnidef( 6, HB_ZLIB_STRATEGY_DEFAULT );
PHB_CONCLI conn;
if( iPassLen > NETIO_PASSWD_MAX )
iPassLen = NETIO_PASSWD_MAX;
s_netio_init( NULL );
conn = s_fileConnect( NULL, pszServer, iPort, iTimeOut, HB_TRUE,
pszPasswd, iPassLen, iLevel, iStrategy );
if( conn )
{
PHB_CONDATA pConData = ( PHB_CONDATA ) hb_stackGetTSD( &s_conData );
pConData->timeout = conn->timeout;
pConData->port = conn->port;
hb_strncpy( pConData->server, conn->server, sizeof( pConData->server ) - 1 );
pConData->level = conn->level;
pConData->strategy = conn->strategy;
pConData->passlen = conn->passlen;
if( conn->passlen )
memcpy( pConData->passwd, conn->passwd, conn->passlen );
s_fileUsrConnect( conn );
}
hb_retl( conn != NULL );
}
static HB_GARBAGE_FUNC( s_concli_destructor )
{
PHB_CONCLI * conn_ptr = ( PHB_CONCLI * ) Cargo;
if( *conn_ptr )
{
s_fileConClose( *conn_ptr );
*conn_ptr = NULL;
}
}
static const HB_GC_FUNCS s_gcConCliFuncs =
{
s_concli_destructor,
hb_gcDummyMark
};
static PHB_CONCLI s_connParam( int iParam )
{
PHB_CONCLI * conn_ptr = ( PHB_CONCLI * )
hb_parptrGC( &s_gcConCliFuncs, iParam );
if( conn_ptr )
{
PHB_CONCLI conn = *conn_ptr;
if( conn )
{
hb_atomic_inc( &conn->used );
return conn;
}
}
return NULL;
}
/* netio_GetConnection( [<cServer>], [<nPort>], [<nTimeOut>], ;
* [<cPasswd>], [<nCompressionLevel>], [<nStrategy>] )
* --> <pConnection> | NIL
*/
HB_FUNC( NETIO_GETCONNECTION )
{
const char * pszServer = hb_parc( 1 ),
* pszPasswd = hb_parc( 4 );
int iPort = hb_parni( 2 ),
iTimeOut = hb_parni( 3 ),
iPassLen = ( int ) hb_parclen( 4 ),
iLevel = hb_parnidef( 5, HB_ZLIB_COMPRESSION_DISABLE ),
iStrategy = hb_parnidef( 6, HB_ZLIB_STRATEGY_DEFAULT );
PHB_CONCLI conn;
if( iPassLen > NETIO_PASSWD_MAX )
iPassLen = NETIO_PASSWD_MAX;
s_netio_init( NULL );
conn = s_fileConnect( NULL, pszServer, iPort, iTimeOut, HB_TRUE,
pszPasswd, iPassLen, iLevel, iStrategy );
if( conn )
{
PHB_CONCLI * conn_ptr = ( PHB_CONCLI * ) hb_gcAllocate( sizeof( PHB_CONCLI ),
&s_gcConCliFuncs );
*conn_ptr = conn;
hb_retptrGC( conn_ptr );
}
}
/* netio_Disconnect( [<cServer>], [<nPort>] ) --> <lOK>
*/
HB_FUNC( NETIO_DISCONNECT )
{
const char * pszServer = hb_parc( 1 );
char * pszIpAddres;
int iPort = hb_parni( 2 );
HB_BOOL fDisconnected = HB_FALSE;
s_fileGetConnParam( &pszServer, &iPort, NULL, NULL, NULL );
pszIpAddres = hb_socketResolveAddr( pszServer, HB_SOCKET_AF_INET );
if( pszIpAddres != NULL )
{
fDisconnected = s_fileUsrDisconnect( pszIpAddres, iPort );
hb_xfree( pszIpAddres );
}
hb_retl( fDisconnected );
}
/* netio_TimeOut( <pConnection> [, <nTimeOut>] ) --> [<nTimeOut>]
*/
HB_FUNC( NETIO_TIMEOUT )
{
PHB_CONCLI conn = s_connParam( 1 );
if( conn )
{
if( s_fileConLock( conn ) )
{
hb_retni( conn->timeout );
if( HB_ISNUM( 2 ) )
conn->timeout = hb_parni( 2 );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
else
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}
HB_FUNC( NETIO_SETPATH )
{
PHB_CONCLI conn = s_connParam( 1 );
if( conn )
{
if( s_fileConLock( conn ) )
{
const char * pszNewPath = hb_parc( 2 );
char * pszSetPath = NULL, * pszOldPath = NULL;
if( pszNewPath && *pszNewPath )
pszSetPath = hb_strdup( pszNewPath );
HB_NETIO_LOCK();
if( pszNewPath )
{
if( conn->path )
{
hb_atomic_dec( &s_pathCount );
pszOldPath = conn->path;
conn->path = NULL;
}
if( pszSetPath )
{
conn->path = pszSetPath;
hb_atomic_inc( &s_pathCount );
}
}
else if( conn->path )
pszOldPath = hb_strdup( conn->path );
HB_NETIO_UNLOCK();
s_fileConUnlock( conn );
hb_retc_buffer( pszOldPath );
}
s_fileConClose( conn );
}
else
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}
static const char * s_netio_params( int iParam, int iMsg, const char * pszName, HB_U32 * pSize, char ** pFree )
{
int iPCount = iMsg == NETIO_PROCIS ? 0 : hb_pcount();
char * data = NULL;
HB_SIZE size, itmSize;
size = strlen( pszName ) + 1;
while( ++iParam <= iPCount )
{
char * itmData = hb_itemSerialize( hb_param( iParam, HB_IT_ANY ), HB_SERIALIZE_NUMSIZE, &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 = ( HB_U32 ) size;
return data ? data : pszName;
}
static HB_BOOL s_netio_procexec( int iMsg, int iType )
{
HB_BOOL fResult = HB_FALSE;
const char * pszProcName;
PHB_CONCLI conn;
int iParam = 1;
conn = s_connParam( 1 );
if( conn )
++iParam;
pszProcName = hb_parc( iParam );
if( pszProcName )
{
if( ! conn )
conn = s_fileConnect( &pszProcName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
const char * data;
char * buffer;
HB_U32 size;
int iStreamID = 0;
data = s_netio_params( iParam, iMsg, pszProcName, &size, &buffer );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], iMsg );
HB_PUT_LE_UINT32( &msgbuf[ 4 ], size );
if( iMsg == NETIO_FUNCCTRL )
{
iStreamID = s_fileNewSrvData( conn, iType );
HB_PUT_LE_UINT32( &msgbuf[ 8 ], iStreamID );
HB_PUT_LE_UINT32( &msgbuf[ 12 ], iType );
memset( msgbuf + 16, '\0', sizeof( msgbuf ) - 16 );
}
else
memset( msgbuf + 8, '\0', sizeof( msgbuf ) - 8 );
fResult = s_fileSendMsg( conn, msgbuf, data, size,
iMsg != NETIO_PROC, HB_FALSE );
if( fResult && ( iMsg == NETIO_FUNC || iMsg == NETIO_FUNCCTRL ) )
{
HB_SIZE nResult = HB_GET_LE_UINT32( &msgbuf[ 4 ] );
if( nResult > 0 )
{
PHB_ITEM pItem = NULL;
HB_SIZE nRecv;
if( nResult > size && buffer )
{
hb_xfree( buffer );
buffer = NULL;
}
if( buffer == NULL )
buffer = ( char * ) hb_xgrab( nResult );
nRecv = s_fileRecvAll( conn, buffer, ( long ) nResult );
if( nResult == nRecv )
{
data = buffer;
pItem = hb_itemDeserialize( &data, &nResult );
}
if( pItem )
{
if( iMsg == NETIO_FUNCCTRL )
{
if( iStreamID == hb_itemGetNI( pItem ) )
iStreamID = 0;
else
hb_itemPutNI( pItem, -1 );
}
hb_itemReturnRelease( pItem );
}
else
{
HB_ERRCODE errOsCode = 0;
if( nResult != nRecv )
conn->errcode = errOsCode = hb_socketGetError();
else
conn->errcode = NETIO_ERR_WRONG_PARAM;
hb_errRT_NETIO( EG_CORRUPTION, 1008, errOsCode, NULL, HB_ERR_FUNCNAME );
}
}
}
if( iStreamID != 0 )
s_fileCloseSrvData( conn, iStreamID );
if( buffer )
hb_xfree( buffer );
s_fileConUnlock( conn );
}
}
}
if( conn )
s_fileConClose( conn );
return fResult;
}
/* check if function/procedure exists on the server side:
*
* netio_ProcExists( <cProcName> ) --> <lExists>
*/
HB_FUNC( NETIO_PROCEXISTS )
{
hb_retl( s_netio_procexec( NETIO_PROCIS, 0 ) );
}
/* execute function/procedure on server the side,
* do not wait for confirmation:
*
* netio_ProcExec( <cProcName> [, <params,...>] ) --> <lSent>
*/
HB_FUNC( NETIO_PROCEXEC )
{
hb_retl( s_netio_procexec( NETIO_PROC, 0 ) );
}
/* execute function/procedure on the server side and wait for
* confirmation:
*
* netio_ProcExecW( <cProcName> [, <params,...>] ) --> <lExecuted>
*/
HB_FUNC( NETIO_PROCEXECW )
{
hb_retl( s_netio_procexec( NETIO_PROCW, 0 ) );
}
/* execute function on the server side and wait for its return value:
*
* netio_FuncExec( <cFuncName> [, <params,...>] ) --> <xFuncRetVal>
*/
HB_FUNC( NETIO_FUNCEXEC )
{
s_netio_procexec( NETIO_FUNC, 0 );
}
/* open communication stream/channel which allow to send data
* asynchronously from server to client:
*
* netio_OpenDataStream( <cStreamFuncName> [, <params,...>] ) --> <nStreamID>
*
* it executes on the server side:
* <cStreamFuncName>( <pConnSock>, <nStreamID> [, <params,...>] )
* and then check value returned by above function. If it's equal to
* <nStreamID> then the communication stream is opened and <nStreamID>
* is returned to the client.
* The function returns new stream ID or -1 if the communication stream
* cannot be set.
*/
HB_FUNC( NETIO_OPENDATASTREAM )
{
s_netio_procexec( NETIO_FUNCCTRL, NETIO_SRVDATA );
}
/* open communication stream/channel which allow to send data
* asynchronously from server to client:
*
* netio_OpenItemStream( <cStreamFuncName> [, <params,...>] ) --> <nStreamID>
*
* it executes on the server side:
* <cStreamFuncName>( <pConnSock>, <nStreamID> [, <params,...>] )
* and then check value returned by above function. If it's equal to
* <nStreamID> then the communication stream is opened and <nStreamID>
* is returned to the client.
* The function returns new stream ID or -1 if the communication stream
* cannot be set.
*/
HB_FUNC( NETIO_OPENITEMSTREAM )
{
s_netio_procexec( NETIO_FUNCCTRL, NETIO_SRVITEM );
}
static PHB_CONCLI s_netio_getConn( void )
{
PHB_CONCLI conn = s_connParam( 2 );
if( ! conn )
{
const char * pszServer = hb_parc( 2 );
char * pszIpAddres;
int iPort = hb_parni( 3 );
s_fileGetConnParam( &pszServer, &iPort, NULL, NULL, NULL );
pszIpAddres = hb_socketResolveAddr( pszServer, HB_SOCKET_AF_INET );
if( pszIpAddres != NULL )
{
conn = s_fileConFind( pszIpAddres, iPort );
hb_xfree( pszIpAddres );
}
}
return conn;
}
/* close communication stream/channel:
*
* netio_CloseStream( <nStreamID>, [<pConnection>] | [[<cServer>], [<nPort>]] )
* --> <lOK>
*/
HB_FUNC( NETIO_CLOSESTREAM )
{
int iStreamID = hb_parni( 1 );
HB_BOOL fResult = HB_FALSE;
if( iStreamID )
{
PHB_CONCLI conn = s_netio_getConn();
if( conn )
{
if( s_fileConLock( conn ) )
{
fResult = s_fileCloseSrvData( conn, iStreamID );
if( fResult )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_SRVCLOSE );
HB_PUT_LE_UINT32( &msgbuf[ 4 ], iStreamID );
memset( msgbuf + 8, '\0', sizeof( msgbuf ) - 8 );
s_fileSendMsg( conn, msgbuf, NULL, 0, HB_TRUE, HB_FALSE );
}
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
}
hb_retl( fResult );
}
/* retrieve data sent from the server by cominication stream
*
* netio_GetData( <nStreamID>, [<pConnection>] | [[<cServer>], [<nPort>]] )
* --> <aData> | <cData> | NIL
*/
HB_FUNC( NETIO_GETDATA )
{
int iStreamID = hb_parni( 1 );
if( iStreamID )
{
PHB_CONCLI conn = s_netio_getConn();
if( conn )
{
if( s_fileConLock( conn ) )
{
if( s_fileProcessData( conn ) )
{
PHB_SRVDATA pSrvData = s_fileFindSrvData( conn, iStreamID, 0 );
if( pSrvData )
{
if( pSrvData->type == NETIO_SRVITEM )
{
if( pSrvData->array )
{
hb_itemReturnForward( pSrvData->array );
hb_arrayNew( pSrvData->array, 0 );
}
else
hb_reta( 0 );
}
else if( pSrvData->type == NETIO_SRVDATA )
{
hb_retclen( pSrvData->data, pSrvData->size );
pSrvData->size = 0;
}
}
}
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
}
}
/* Client methods
*/
static HB_BOOL s_fileAccept( PHB_FILE_FUNCS pFuncs, const char * pszFileName )
{
HB_SYMBOL_UNUSED( pFuncs );
return hb_strnicmp( pszFileName, NETIO_FILE_PREFIX, NETIO_FILE_PREFIX_LEN ) == 0 ||
s_fileNameConFind( &pszFileName, HB_FALSE ) != NULL;
}
static HB_BOOL s_fileDirExists( PHB_FILE_FUNCS pFuncs, const char * pszDirName )
{
HB_BOOL fResult = HB_FALSE;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszDirName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( pszDirName );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_DIREXISTS );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
fResult = s_fileSendMsg( conn, msgbuf, pszDirName, len, HB_TRUE, HB_FALSE );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static HB_BOOL s_fileDirMake( PHB_FILE_FUNCS pFuncs, const char * pszDirName )
{
HB_BOOL fResult = HB_FALSE;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszDirName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( pszDirName );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_DIRMAKE );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
fResult = s_fileSendMsg( conn, msgbuf, pszDirName, len, HB_TRUE, HB_FALSE );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static HB_BOOL s_fileDirRemove( PHB_FILE_FUNCS pFuncs, const char * pszDirName )
{
HB_BOOL fResult = HB_FALSE;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszDirName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( pszDirName );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_DIRREMOVE );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
fResult = s_fileSendMsg( conn, msgbuf, pszDirName, len, HB_TRUE, HB_FALSE );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static double s_fileDirSpace( PHB_FILE_FUNCS pFuncs, const char * pszDirName, HB_USHORT uiType )
{
double dResult = 0.0;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszDirName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( pszDirName );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_DIRSPACE );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
HB_PUT_LE_UINT16( &msgbuf[ 6 ], uiType );
memset( msgbuf + 8, '\0', sizeof( msgbuf ) - 8 );
if( s_fileSendMsg( conn, msgbuf, pszDirName, len, HB_TRUE, HB_FALSE ) )
{
dResult = ( double ) HB_GET_LE_UINT64( &msgbuf[ 4 ] );
hb_fsSetError( ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 12 ] ) );
}
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return dResult;
}
static PHB_ITEM s_fileDirectory( PHB_FILE_FUNCS pFuncs, const char * pszDirSpec, const char * pszAttr )
{
PHB_ITEM pDirArray = NULL;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszDirSpec, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len1 = ( HB_U16 ) ( pszDirSpec ? strlen( pszDirSpec ) : 0 );
HB_U16 len2 = ( HB_U16 ) ( pszAttr ? strlen( pszAttr ) : 0 );
HB_BYTE * pBuffer = NULL;
if( len1 + len2 > 0 )
{
pBuffer = ( HB_BYTE * ) hb_xgrab( len1 + len2 );
if( len1 )
memcpy( pBuffer, pszDirSpec, len1 );
if( len2 )
memcpy( pBuffer + len1, pszAttr, len2 );
}
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_DIRECTORY );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len1 );
HB_PUT_LE_UINT16( &msgbuf[ 6 ], len2 );
memset( msgbuf + 8, '\0', sizeof( msgbuf ) - 8 );
if( s_fileSendMsg( conn, msgbuf, pBuffer, len1 + len2, HB_TRUE, HB_FALSE ) )
{
HB_ERRCODE errCode = ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 8 ] );
HB_SIZE nResult = HB_GET_LE_UINT32( &msgbuf[ 4 ] ), nRecv = 0;
if( nResult > 0 )
{
char * buffer = ( char * ) hb_xgrab( nResult );
const char * data = buffer;
nRecv = s_fileRecvAll( conn, buffer, ( long ) nResult );
if( nRecv == nResult )
pDirArray = hb_itemDeserialize( &data, &nResult );
hb_xfree( buffer );
}
hb_fsSetError( errCode );
if( pDirArray == NULL )
{
HB_ERRCODE errOsCode = 0;
if( nResult != nRecv )
conn->errcode = errOsCode = hb_socketGetError();
else
conn->errcode = NETIO_ERR_WRONG_PARAM;
hb_errRT_NETIO( EG_CORRUPTION, 1013, errOsCode, NULL, HB_ERR_FUNCNAME );
}
}
if( pBuffer )
hb_xfree( pBuffer );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
if( pDirArray == NULL )
pDirArray = hb_itemArrayNew( 0 );
return pDirArray;
}
static HB_BOOL s_fileExists( PHB_FILE_FUNCS pFuncs, const char * pszFileName, char * pRetPath )
{
HB_BOOL fResult = HB_FALSE;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
if( pRetPath )
hb_strncpy( pRetPath, pszFileName, HB_PATH_MAX - 1 );
conn = s_fileConnect( &pszFileName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( pszFileName );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_EXISTS );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
fResult = s_fileSendMsg( conn, msgbuf, pszFileName, len, HB_TRUE, HB_FALSE );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static HB_BOOL s_fileDelete( PHB_FILE_FUNCS pFuncs, const char * pszFileName )
{
HB_BOOL fResult = HB_FALSE;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszFileName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( pszFileName );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_DELETE );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
fResult = s_fileSendMsg( conn, msgbuf, pszFileName, len, HB_TRUE, HB_FALSE );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static HB_BOOL s_fileRename( PHB_FILE_FUNCS pFuncs, const char * pszFileName, const char * pszNewName )
{
HB_BOOL fResult = HB_FALSE;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszFileName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
s_fileConnCheck( conn, &pszNewName, HB_FALSE, &fResult );
if( ! fResult )
{
conn->errcode = 2;
hb_fsSetError( conn->errcode );
}
else if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len1 = ( HB_U16 ) strlen( pszFileName );
HB_U16 len2 = ( HB_U16 ) strlen( pszNewName );
HB_BYTE * pBuffer = ( HB_BYTE * ) hb_xgrab( len1 + len2 );
memcpy( pBuffer, pszFileName, len1 );
memcpy( pBuffer + len1, pszNewName, len2 );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_RENAME );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len1 );
HB_PUT_LE_UINT16( &msgbuf[ 6 ], len2 );
memset( msgbuf + 8, '\0', sizeof( msgbuf ) - 8 );
fResult = s_fileSendMsg( conn, msgbuf, pBuffer, len1 + len2,
HB_TRUE, HB_FALSE );
hb_xfree( pBuffer );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static HB_BOOL s_fileCopy( PHB_FILE_FUNCS pFuncs, const char * pszSrcFile, const char * pszDstFile )
{
HB_BOOL fResult = HB_FALSE;
const char * pszSource = pszSrcFile;
PHB_CONCLI conn;
if( ! s_fileAccept( pFuncs, pszDstFile ) )
return hb_fsCopy( pszSrcFile, pszDstFile );
conn = s_fileConnect( &pszSource, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConnCheck( conn, &pszDstFile, HB_FALSE, &fResult ) == NULL )
fResult = hb_fsCopy( pszSrcFile, pszDstFile );
else if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len1 = ( HB_U16 ) strlen( pszSource );
HB_U16 len2 = ( HB_U16 ) strlen( pszDstFile );
HB_BYTE * pBuffer = ( HB_BYTE * ) hb_xgrab( len1 + len2 );
memcpy( pBuffer, pszSource, len1 );
memcpy( pBuffer + len1, pszDstFile, len2 );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_COPY );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len1 );
HB_PUT_LE_UINT16( &msgbuf[ 6 ], len2 );
memset( msgbuf + 8, '\0', sizeof( msgbuf ) - 8 );
fResult = s_fileSendMsg( conn, msgbuf, pBuffer, len1 + len2,
HB_TRUE, HB_FALSE );
hb_xfree( pBuffer );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static HB_BOOL s_fileAttrGet( PHB_FILE_FUNCS pFuncs, const char * pszFileName, HB_FATTR * pulAttr )
{
HB_BOOL fResult = HB_FALSE;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszFileName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( pszFileName );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_ATTRGET );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
if( s_fileSendMsg( conn, msgbuf, pszFileName, len, HB_TRUE, HB_FALSE ) )
{
* pulAttr = HB_GET_LE_UINT32( &msgbuf[ 4 ] );
fResult = HB_TRUE;
}
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static HB_BOOL s_fileAttrSet( PHB_FILE_FUNCS pFuncs, const char * pszFileName, HB_FATTR ulAttr )
{
HB_BOOL fResult = HB_FALSE;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszFileName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( pszFileName );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_ATTRSET );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
HB_PUT_LE_UINT32( &msgbuf[ 6 ], ulAttr );
memset( msgbuf + 10, '\0', sizeof( msgbuf ) - 10 );
fResult = s_fileSendMsg( conn, msgbuf, pszFileName, len, HB_TRUE, HB_FALSE );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static HB_BOOL s_fileTimeGet( PHB_FILE_FUNCS pFuncs, const char * pszFileName, long * plJulian, long * plMillisec )
{
HB_BOOL fResult = HB_FALSE;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszFileName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( pszFileName );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_FTIMEGET );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
if( s_fileSendMsg( conn, msgbuf, pszFileName, len, HB_TRUE, HB_FALSE ) )
{
* plJulian = HB_GET_LE_UINT32( &msgbuf[ 4 ] );
* plMillisec = HB_GET_LE_UINT32( &msgbuf[ 8 ] );
fResult = HB_TRUE;
}
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static HB_BOOL s_fileTimeSet( PHB_FILE_FUNCS pFuncs, const char * pszFileName, long lJulian, long lMillisec )
{
HB_BOOL fResult = HB_FALSE;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszFileName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( pszFileName );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_FTIMESET );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
HB_PUT_LE_UINT32( &msgbuf[ 6 ], lJulian );
HB_PUT_LE_UINT32( &msgbuf[ 10 ], lMillisec );
memset( msgbuf + 14, '\0', sizeof( msgbuf ) - 14 );
fResult = s_fileSendMsg( conn, msgbuf, pszFileName, len, HB_TRUE, HB_FALSE );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static HB_BOOL s_fileLink( PHB_FILE_FUNCS pFuncs, const char * pszExisting, const char * pszNewName )
{
HB_BOOL fResult = HB_FALSE;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszExisting, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
s_fileConnCheck( conn, &pszNewName, HB_FALSE, &fResult );
if( ! fResult )
{
conn->errcode = 2;
hb_fsSetError( conn->errcode );
}
else if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len1 = ( HB_U16 ) strlen( pszExisting );
HB_U16 len2 = ( HB_U16 ) strlen( pszNewName );
HB_BYTE * pBuffer = ( HB_BYTE * ) hb_xgrab( len1 + len2 );
memcpy( pBuffer, pszExisting, len1 );
memcpy( pBuffer + len1, pszNewName, len2 );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_LINK );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len1 );
HB_PUT_LE_UINT16( &msgbuf[ 6 ], len2 );
memset( msgbuf + 8, '\0', sizeof( msgbuf ) - 8 );
fResult = s_fileSendMsg( conn, msgbuf, pBuffer, len1 + len2,
HB_TRUE, HB_FALSE );
hb_xfree( pBuffer );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static HB_BOOL s_fileLinkSym( PHB_FILE_FUNCS pFuncs, const char * pszTarget, const char * pszNewName )
{
HB_BOOL fResult = HB_FALSE;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszTarget, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
s_fileConnCheck( conn, &pszNewName, HB_FALSE, &fResult );
if( ! fResult )
{
conn->errcode = 2;
hb_fsSetError( conn->errcode );
}
else if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len1 = ( HB_U16 ) strlen( pszTarget );
HB_U16 len2 = ( HB_U16 ) strlen( pszNewName );
HB_BYTE * pBuffer = ( HB_BYTE * ) hb_xgrab( len1 + len2 );
memcpy( pBuffer, pszTarget, len1 );
memcpy( pBuffer + len1, pszNewName, len2 );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_LINKSYM );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len1 );
HB_PUT_LE_UINT16( &msgbuf[ 6 ], len2 );
memset( msgbuf + 8, '\0', sizeof( msgbuf ) - 8 );
fResult = s_fileSendMsg( conn, msgbuf, pBuffer, len1 + len2,
HB_TRUE, HB_FALSE );
hb_xfree( pBuffer );
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return fResult;
}
static char * s_fileLinkRead( PHB_FILE_FUNCS pFuncs, const char * pszFileName )
{
char * pszResult = NULL;
PHB_CONCLI conn;
HB_SYMBOL_UNUSED( pFuncs );
conn = s_fileConnect( &pszFileName, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( pszFileName );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_LINKREAD );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
if( s_fileSendMsg( conn, msgbuf, pszFileName, len, HB_TRUE, HB_FALSE ) )
{
HB_SIZE nResult = HB_GET_LE_UINT32( &msgbuf[ 4 ] ), nRecv = 0;
HB_ERRCODE errCode = ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 8 ] );
if( nResult > 0 )
{
pszResult = ( char * ) hb_xgrab( nResult + 1 );
nRecv = s_fileRecvAll( conn, pszResult, ( long ) nResult );
if( nRecv != nResult )
{
hb_xfree( pszResult );
pszResult = NULL;
}
else
pszResult[ nResult ] = '\0';
}
if( nRecv != nResult )
{
conn->errcode = hb_socketGetError();
hb_errRT_NETIO( EG_CORRUPTION, 1014, conn->errcode, NULL, HB_ERR_FUNCNAME );
}
hb_fsSetError( errCode );
}
s_fileConUnlock( conn );
}
s_fileConClose( conn );
}
return pszResult;
}
static PHB_FILE s_fileOpen( PHB_FILE_FUNCS pFuncs, const char * pszFileName,
const char * pDefExt, HB_FATTR nExFlags,
const char * pPaths, PHB_ITEM pError )
{
PHB_FILE pFile = NULL;
PHB_CONCLI conn;
const char * pszFile = pszFileName;
HB_SYMBOL_UNUSED( pFuncs );
HB_SYMBOL_UNUSED( pPaths );
conn = s_fileConnect( &pszFile, NULL, 0, 0, HB_FALSE,
NULL, 0, HB_ZLIB_COMPRESSION_DISABLE, 0 );
if( conn )
{
if( s_fileConLock( conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_U16 len = ( HB_U16 ) strlen( pszFile );
if( nExFlags & 0xFFFF0000 )
{
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_OPEN2 );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
HB_PUT_LE_UINT32( &msgbuf[ 6 ], nExFlags );
memset( msgbuf + 10, '\0', sizeof( msgbuf ) - 10 );
if( pDefExt )
hb_strncpy( ( char * ) &msgbuf[ 10 ],
( const char * ) pDefExt, sizeof( msgbuf ) - 11 );
}
else
{
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_OPEN );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], len );
HB_PUT_LE_UINT16( &msgbuf[ 6 ], ( HB_U16 ) nExFlags );
memset( msgbuf + 8, '\0', sizeof( msgbuf ) - 8 );
if( pDefExt )
hb_strncpy( ( char * ) &msgbuf[ 8 ],
( const char * ) pDefExt, sizeof( msgbuf ) - 9 );
}
if( s_fileSendMsg( conn, msgbuf, pszFile, len, HB_TRUE, HB_FALSE ) )
{
pFile = ( PHB_FILE ) hb_xgrab( sizeof( HB_FILE ) );
pFile->pFuncs = s_fileMethods();
pFile->conn = conn;
pFile->fd = HB_GET_LE_UINT16( &msgbuf[ 4 ] );
}
s_fileConUnlock( conn );
}
if( ! pFile )
s_fileConClose( conn );
}
if( pError )
{
hb_errPutFileName( pError, pszFileName );
if( pFile == NULL )
{
hb_errPutOsCode( pError, hb_fsError() );
hb_errPutGenCode( pError, ( HB_ERRCODE ) ( ( nExFlags & FXO_TRUNCATE ) ? EG_CREATE : EG_OPEN ) );
}
}
return pFile;
}
static void s_fileClose( PHB_FILE pFile )
{
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_CLOSE );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
s_fileSendMsg( pFile->conn, msgbuf, NULL, 0, HB_TRUE, HB_FALSE );
s_fileConUnlock( pFile->conn );
}
s_fileConClose( pFile->conn );
hb_xfree( pFile );
}
static HB_BOOL s_fileLock( PHB_FILE pFile, HB_FOFFSET ulStart, HB_FOFFSET ulLen,
int iType )
{
HB_BOOL fResult = HB_FALSE;
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_BOOL fUnLock = ( iType & FL_MASK ) == FL_UNLOCK;
HB_PUT_LE_UINT32( &msgbuf[ 0 ], fUnLock ? NETIO_UNLOCK : NETIO_LOCK );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
HB_PUT_LE_UINT64( &msgbuf[ 6 ], ulStart );
HB_PUT_LE_UINT64( &msgbuf[ 14 ], ulLen );
HB_PUT_LE_UINT16( &msgbuf[ 22 ], ( HB_USHORT ) iType );
#if NETIO_MSGLEN > 24
memset( msgbuf + 24, '\0', sizeof( msgbuf ) - 24 );
#endif
fResult = s_fileSendMsg( pFile->conn, msgbuf, NULL, 0, ! fUnLock, HB_FALSE );
s_fileConUnlock( pFile->conn );
}
return fResult;
}
static int s_fileLockTest( PHB_FILE pFile, HB_FOFFSET ulStart, HB_FOFFSET ulLen,
int iType )
{
int iResult = -1;
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_TESTLOCK );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
HB_PUT_LE_UINT64( &msgbuf[ 6 ], ulStart );
HB_PUT_LE_UINT64( &msgbuf[ 14 ], ulLen );
HB_PUT_LE_UINT16( &msgbuf[ 22 ], ( HB_USHORT ) iType );
#if NETIO_MSGLEN > 24
memset( msgbuf + 24, '\0', sizeof( msgbuf ) - 24 );
#endif
if( s_fileSendMsg( pFile->conn, msgbuf, NULL, 0, HB_TRUE, HB_FALSE ) )
iResult = HB_GET_LE_INT32( &msgbuf[ 4 ] );
s_fileConUnlock( pFile->conn );
}
return iResult;
}
static HB_SIZE s_fileRead( PHB_FILE pFile, void * data, HB_SIZE nSize,
HB_MAXINT timeout )
{
HB_SIZE nResult = 0;
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_READ );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
HB_PUT_LE_UINT32( &msgbuf[ 6 ], nSize );
HB_PUT_LE_UINT64( &msgbuf[ 10 ], timeout );
memset( msgbuf + 18, '\0', sizeof( msgbuf ) - 18 );
if( s_fileSendMsg( pFile->conn, msgbuf, NULL, 0, HB_TRUE, HB_FALSE ) )
{
HB_ERRCODE errCode = ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 8 ] );
nResult = HB_GET_LE_UINT32( &msgbuf[ 4 ] );
if( nResult > 0 && nResult != ( HB_SIZE ) FS_ERROR )
{
if( nResult > nSize ) /* error, it should not happen, enemy attack? */
{
pFile->conn->errcode = errCode = NETIO_ERR_WRONG_FILE_SIZE;
hb_errRT_NETIO( EG_DATAWIDTH, 1011, 0, NULL, HB_ERR_FUNCNAME );
nResult = 0;
}
else if( s_fileRecvAll( pFile->conn, data, ( long ) nResult ) != ( long ) nResult )
{
pFile->conn->errcode = hb_socketGetError();
errCode = NETIO_ERR_READ;
hb_errRT_NETIO( EG_READ, 1012, pFile->conn->errcode, NULL, HB_ERR_FUNCNAME );
}
}
hb_fsSetError( errCode );
}
s_fileConUnlock( pFile->conn );
}
return nResult;
}
static HB_SIZE s_fileWrite( PHB_FILE pFile, const void * data, HB_SIZE nSize,
HB_MAXINT timeout )
{
HB_SIZE nResult = 0;
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_WRITE );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
HB_PUT_LE_UINT32( &msgbuf[ 6 ], ( long ) nSize );
HB_PUT_LE_UINT64( &msgbuf[ 10 ], timeout );
memset( msgbuf + 18, '\0', sizeof( msgbuf ) - 18 );
if( s_fileSendMsg( pFile->conn, msgbuf, data, ( long ) nSize, HB_TRUE, HB_FALSE ) )
{
nResult = HB_GET_LE_UINT32( &msgbuf[ 4 ] );
hb_fsSetError( ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 8 ] ) );
}
s_fileConUnlock( pFile->conn );
}
return nResult;
}
static HB_SIZE s_fileReadAt( PHB_FILE pFile, void * data, HB_SIZE nSize,
HB_FOFFSET llOffset )
{
HB_SIZE nResult = 0;
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_READAT );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
HB_PUT_LE_UINT32( &msgbuf[ 6 ], nSize );
HB_PUT_LE_UINT64( &msgbuf[ 10 ], llOffset );
memset( msgbuf + 18, '\0', sizeof( msgbuf ) - 18 );
if( s_fileSendMsg( pFile->conn, msgbuf, NULL, 0, HB_TRUE, HB_FALSE ) )
{
HB_ERRCODE errCode = ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 8 ] );
nResult = HB_GET_LE_UINT32( &msgbuf[ 4 ] );
if( nResult > 0 && nResult != ( HB_SIZE ) FS_ERROR )
{
if( nResult > nSize ) /* error, it should not happen, enemy attack? */
{
pFile->conn->errcode = errCode = NETIO_ERR_WRONG_FILE_SIZE;
hb_errRT_NETIO( EG_DATAWIDTH, 1009, 0, NULL, HB_ERR_FUNCNAME );
nResult = 0;
}
else if( s_fileRecvAll( pFile->conn, data, ( long ) nResult ) != ( long ) nResult )
{
pFile->conn->errcode = hb_socketGetError();
errCode = NETIO_ERR_READ;
hb_errRT_NETIO( EG_READ, 1010, pFile->conn->errcode, NULL, HB_ERR_FUNCNAME );
}
}
hb_fsSetError( errCode );
}
s_fileConUnlock( pFile->conn );
}
return nResult;
}
static HB_SIZE s_fileWriteAt( PHB_FILE pFile, const void * data, HB_SIZE nSize,
HB_FOFFSET llOffset )
{
HB_SIZE nResult = 0;
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_WRITEAT );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
HB_PUT_LE_UINT32( &msgbuf[ 6 ], ( long ) nSize );
HB_PUT_LE_UINT64( &msgbuf[ 10 ], llOffset );
memset( msgbuf + 18, '\0', sizeof( msgbuf ) - 18 );
if( s_fileSendMsg( pFile->conn, msgbuf, data, ( long ) nSize, HB_TRUE, HB_FALSE ) )
{
nResult = HB_GET_LE_UINT32( &msgbuf[ 4 ] );
hb_fsSetError( ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 8 ] ) );
}
s_fileConUnlock( pFile->conn );
}
return nResult;
}
static HB_BOOL s_fileTruncAt( PHB_FILE pFile, HB_FOFFSET llOffset )
{
HB_BOOL fResult = HB_FALSE;
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_TRUNC );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
HB_PUT_LE_UINT64( &msgbuf[ 6 ], llOffset );
memset( msgbuf + 14, '\0', sizeof( msgbuf ) - 14 );
fResult = s_fileSendMsg( pFile->conn, msgbuf, NULL, 0, HB_TRUE, HB_FALSE );
s_fileConUnlock( pFile->conn );
}
return fResult;
}
static HB_FOFFSET s_fileSeek( PHB_FILE pFile, HB_FOFFSET llOffset, HB_USHORT uiFlags )
{
HB_FOFFSET llResult = 0;
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_SEEK );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
HB_PUT_LE_UINT64( &msgbuf[ 6 ], llOffset );
HB_PUT_LE_UINT16( &msgbuf[ 14 ], uiFlags );
memset( msgbuf + 16, '\0', sizeof( msgbuf ) - 16 );
if( s_fileSendMsg( pFile->conn, msgbuf, NULL, 0, HB_TRUE, HB_FALSE ) )
{
llResult = HB_GET_LE_UINT64( &msgbuf[ 4 ] );
hb_fsSetError( ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 12 ] ) );
}
s_fileConUnlock( pFile->conn );
}
return llResult;
}
static HB_FOFFSET s_fileSize( PHB_FILE pFile )
{
HB_FOFFSET llOffset = 0;
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_PUT_LE_UINT32( msgbuf, NETIO_SIZE );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
if( s_fileSendMsg( pFile->conn, msgbuf, NULL, 0, HB_TRUE, HB_FALSE ) )
{
llOffset = HB_GET_LE_UINT64( &msgbuf[ 4 ] );
hb_fsSetError( ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 12 ] ) );
}
s_fileConUnlock( pFile->conn );
}
return llOffset;
}
static HB_BOOL s_fileEof( PHB_FILE pFile )
{
HB_BOOL fEof = HB_TRUE;
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_PUT_LE_UINT32( msgbuf, NETIO_EOF );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
if( s_fileSendMsg( pFile->conn, msgbuf, NULL, 0, HB_TRUE, HB_FALSE ) )
{
fEof = HB_GET_LE_UINT16( &msgbuf[ 4 ] ) != 0;
hb_fsSetError( ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 8 ] ) );
}
s_fileConUnlock( pFile->conn );
}
return fEof;
}
static void s_fileFlush( PHB_FILE pFile, HB_BOOL fDirty )
{
HB_SYMBOL_UNUSED( pFile );
HB_SYMBOL_UNUSED( fDirty );
}
static void s_fileCommit( PHB_FILE pFile )
{
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_PUT_LE_UINT32( msgbuf, NETIO_COMMIT );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 );
s_fileSendMsg( pFile->conn, msgbuf, NULL, 0, HB_FALSE, HB_FALSE );
s_fileConUnlock( pFile->conn );
}
}
static HB_BOOL s_fileConfigure( PHB_FILE pFile, int iIndex, PHB_ITEM pValue )
{
HB_BOOL fResult = HB_FALSE;
if( s_fileConLock( pFile->conn ) )
{
HB_BYTE msgbuf[ NETIO_MSGLEN ];
HB_SIZE itmSize = 0;
char * itmData = NULL;
if( pValue )
itmData = hb_itemSerialize( pValue, HB_SERIALIZE_NUMSIZE, &itmSize );
HB_PUT_LE_UINT32( &msgbuf[ 0 ], NETIO_CONFIGURE );
HB_PUT_LE_UINT16( &msgbuf[ 4 ], pFile->fd );
HB_PUT_LE_UINT32( &msgbuf[ 6 ], itmSize );
HB_PUT_LE_UINT32( &msgbuf[ 10 ], iIndex );
memset( msgbuf + 14, '\0', sizeof( msgbuf ) - 14 );
hb_itemClear( pValue );
if( s_fileSendMsg( pFile->conn, msgbuf, itmData, ( long ) itmSize, HB_TRUE, HB_FALSE ) )
{
HB_ERRCODE errCode = ( HB_ERRCODE ) HB_GET_LE_UINT32( &msgbuf[ 12 ] );
HB_SIZE nResult = HB_GET_LE_UINT32( &msgbuf[ 4 ] ), nRecv = 0;
fResult = HB_GET_LE_UINT32( &msgbuf[ 8 ] ) != 0;
if( nResult > 0 )
{
char * buffer = ( char * ) hb_xgrab( nResult );
const char * data = buffer;
nRecv = s_fileRecvAll( pFile->conn, buffer, ( long ) nResult );
if( nRecv == nResult && pValue )
{
PHB_ITEM pResult = hb_itemDeserialize( &data, &nResult );
if( pResult )
{
hb_itemMove( pValue, pResult );
hb_itemRelease( pResult );
if( iIndex == HB_VF_IONAME )
hb_itemPutCPtr( pValue, hb_xstrcpy( NULL, NETIO_FILE_PREFIX, hb_itemGetCPtr( pValue ), NULL ) );
}
}
hb_xfree( buffer );
}
hb_fsSetError( errCode );
if( nRecv != nResult )
{
pFile->conn->errcode = hb_socketGetError();
hb_errRT_NETIO( EG_CORRUPTION, 1015, pFile->conn->errcode, NULL, HB_ERR_FUNCNAME );
fResult = HB_FALSE;
}
}
if( itmData )
hb_xfree( itmData );
s_fileConUnlock( pFile->conn );
}
return fResult;
}
static HB_FHANDLE s_fileHandle( PHB_FILE pFile )
{
return pFile ? hb_sockexGetHandle( pFile->conn->sock ) : HB_NO_SOCKET;
}
static const HB_FILE_FUNCS * s_fileMethods( void )
{
static const HB_FILE_FUNCS s_fileFuncs =
{
s_fileAccept,
s_fileExists,
s_fileDelete,
s_fileRename,
s_fileCopy,
s_fileDirExists,
s_fileDirMake,
s_fileDirRemove,
s_fileDirSpace,
s_fileDirectory,
s_fileTimeGet,
s_fileTimeSet,
s_fileAttrGet,
s_fileAttrSet,
s_fileLink,
s_fileLinkSym,
s_fileLinkRead,
s_fileOpen,
s_fileClose,
s_fileLock,
s_fileLockTest,
s_fileRead,
s_fileWrite,
s_fileReadAt,
s_fileWriteAt,
s_fileTruncAt,
s_fileSeek,
s_fileSize,
s_fileEof,
s_fileFlush,
s_fileCommit,
s_fileConfigure,
s_fileHandle
};
return &s_fileFuncs;
}
/* set HB_NETIO_STARTUP_INIT macro if you want to register NETIO client
* automatically at application startup
*/
#if defined( HB_NETIO_STARTUP_INIT )
HB_CALL_ON_STARTUP_BEGIN( _hb_file_netio_init_ )
hb_vmAtInit( s_netio_init, NULL );
HB_CALL_ON_STARTUP_END( _hb_file_netio_init_ )
#if defined( HB_PRAGMA_STARTUP )
#pragma startup _hb_file_netio_init_
#elif defined( HB_DATASEG_STARTUP )
#define HB_DATASEG_BODY HB_DATASEG_FUNC( _hb_file_netio_init_ )
#include "hbiniseg.h"
#endif
#endif /* HB_NETIO_STARTUP_INIT */