2709 lines
78 KiB
C
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 */
|