From bbd1e6b0a40c99581341351d600272bb0a55a209 Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Fri, 31 Jul 2009 09:32:11 +0000 Subject: [PATCH] 2009-07-31 11:31 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/source/rtl/hbinet.c ! modified hb_inetRecv[All]() to always return number of bytes read if at least one byte was successfully read just like in documentation so it's not longer necessary to use hb_inetCount() to check real number of read bytes. On error they return -1 and 0 when foreign host closed connection. ! modified hb_inetSend[All]() to always return number of written bytes if at least one byte was successfully written so it's not longer necessary to use hb_inetCount() to check real number of written bytes. On error they return -1. ! modified hb_inetRecvLine() to return "" on errors and always set numeric value with error code or number of bytes read in 2-nd parameter passed by reference ! modified hb_inetDataReady() to return -1 instead of .F. to indicate errors when socket is not open socket ! modified hb_inetRecvLine() and hb_inetRecvEndBlock() to work like in documentation and set in 2-nd parameter passed by reference the size of read line with line terminator, -1 or error and 0 when foreign host closed connection. ! modified hb_inetRecvEndBlock() to always use default EOL when there is no not empty string in passed string parameter or passed array with line terminators ! fixed some small differences between hb_inetRecvLine() and hb_inetRecvEndBlock() ! fixed returned values in hb_InetDGramSend() and hb_InetDGramRecv() to be synced with documentation * minor: modified hb_inetRecvEndBlock() to use as default EOL s_inetCRLF instead of hardcoded "\r\n" * eliminated some redundant code + added automatic socket initialization in windows builds % added support for read ahead buffer in hb_inetRecvLine() and hb_inetRecvEndBlock() and updated other functions which may interact with it. It greatly improved the speed of code which extensively uses above functions. Warning!!! Above modifications may force updating other code which used some undocumented hb_inet*() functions behavior i.e. some side effects in previous implementation. Please update your code if necessary. * harbour/doc/inet.txt ! modified hb_inetAccept() documentation wrongly describing value returned on error when it's NIL * harbour/config/os2/watcom.cf ! fixes for real OS2 command processor - please test --- harbour/ChangeLog | 48 ++ harbour/config/os2/watcom.cf | 48 +- harbour/doc/inet.txt | 3 +- harbour/source/rtl/hbinet.c | 1176 ++++++++++++++-------------------- 4 files changed, 555 insertions(+), 720 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 758f60f4a4..03456f9bea 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,54 @@ past entries belonging to author(s): Viktor Szakats. */ +2009-07-31 11:31 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/source/rtl/hbinet.c + ! modified hb_inetRecv[All]() to always return number + of bytes read if at least one byte was successfully read + just like in documentation so it's not longer necessary to + use hb_inetCount() to check real number of read bytes. + On error they return -1 and 0 when foreign host closed connection. + ! modified hb_inetSend[All]() to always return number of written + bytes if at least one byte was successfully written so it's not + longer necessary to use hb_inetCount() to check real number of + written bytes. On error they return -1. + ! modified hb_inetRecvLine() to return "" on errors and always + set numeric value with error code or number of bytes read + in 2-nd parameter passed by reference + ! modified hb_inetDataReady() to return -1 instead of .F. to + indicate errors when socket is not open socket + ! modified hb_inetRecvLine() and hb_inetRecvEndBlock() to work + like in documentation and set in 2-nd parameter passed by + reference the size of read line with line terminator, -1 + or error and 0 when foreign host closed connection. + ! modified hb_inetRecvEndBlock() to always use default EOL when + there is no not empty string in passed string parameter or + passed array with line terminators + ! fixed some small differences between hb_inetRecvLine() and + hb_inetRecvEndBlock() + ! fixed returned values in hb_InetDGramSend() and hb_InetDGramRecv() + to be synced with documentation + * minor: modified hb_inetRecvEndBlock() to use as default EOL + s_inetCRLF instead of hardcoded "\r\n" + * eliminated some redundant code + + added automatic socket initialization in windows builds + % added support for read ahead buffer in hb_inetRecvLine() and + hb_inetRecvEndBlock() and updated other functions which may + interact with it. It greatly improved the speed of code + which extensively uses above functions. + + Warning!!! Above modifications may force updating other code which used + some undocumented hb_inet*() functions behavior i.e. some side + effects in previous implementation. Please update your code + if necessary. + + * harbour/doc/inet.txt + ! modified hb_inetAccept() documentation wrongly describing value + returned on error when it's NIL + + * harbour/config/os2/watcom.cf + ! fixes for real OS2 command processor - please test + 2009-07-31 11:09 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) * include/hbdefs.h * include/hbsetup.h diff --git a/harbour/config/os2/watcom.cf b/harbour/config/os2/watcom.cf index 03e976f416..cd4d10ac5b 100644 --- a/harbour/config/os2/watcom.cf +++ b/harbour/config/os2/watcom.cf @@ -62,27 +62,9 @@ CC_RULE = $(CC) $(CPPFLAGS) $(subst /,\,$(CFLAGS)) $(HB_CDBG) $(subst /,\,$(HB_U endif endif -# Note: The empty line directly before 'endef' HAVE TO exist! -# It causes that the 'echo' command is separated by LF -define link_file -@echo FILE $(file) >> __link__.tmp - -endef - -#Note: The empty line directly before 'endef' HAVE TO exist! -define link_lib -@echo LIB $(lib) >> __link__.tmp - -endef - -define link_exe_file -@echo $(LDFLAGS) NAME $(EXE_DIR)/$@ > __link__.tmp -$(foreach file, $(^F), $(link_file)) -$(foreach lib, $(LINKLIBS), $(link_lib)) -$(foreach lib, $(RDDLIBS), $(link_lib)) -$(foreach lib, $(GTLIBS), $(link_lib)) --$(LD) @__link__.tmp -endef +empty:= +space:= $(empty) $(empty) +comma:= , LD = wlink LDFLAGS = sys OS2V2 @@ -101,20 +83,26 @@ ifeq ($(findstring hbrtl,$(LIBS)),hbrtl) GTLIBS = $(foreach gt, $(HB_GT_LIBS), $(LIB_DIR)/$(gt)) endif -LD_RULE = $(link_exe_file) $(HB_USER_LDFLAGS) - -#Note: The empty line below HAVE TO exist! -define lib_object -@echo -+$(file) >> __lib__.tmp - -endef +LDFILES = $(subst $(space),$(comma) ,$(^F)) +LDLIBS = $(subst $(space),$(comma) ,$(strip $(LINKLIBS) $(RDDLIBS) $(GTLIBS))) +LD_RULE = $(LD) $(LDFLAGS) $(HB_USER_LDFLAGS) NAME $(EXE_DIR)/$@ FILE $(LDFILES) $(if $(LDLIBS), LIB $(LDLIBS),) +# maximum size of command line in OS2 is limited to 1024 characters +# the trick below with 'wordlist' is workaround for it define create_library -@echo $(LIB_DIR)/$@ > __lib__.tmp -$(foreach file, $(^F), $(lib_object)) +echo $(LIB_DIR)/$@ > __lib__.tmp +$(if $(wordlist 1, 50,$(^F)), echo $(wordlist 1, 50,$(addprefix -+,$(^F))) >> __lib__.tmp,) +$(if $(wordlist 51,100,$(^F)), echo $(wordlist 51,100,$(addprefix -+,$(^F))) >> __lib__.tmp,) +$(if $(wordlist 101,150,$(^F)), echo $(wordlist 101,150,$(addprefix -+,$(^F))) >> __lib__.tmp,) +$(if $(wordlist 151,200,$(^F)), echo $(wordlist 151,200,$(addprefix -+,$(^F))) >> __lib__.tmp,) +$(if $(wordlist 201,250,$(^F)), echo $(wordlist 201,250,$(addprefix -+,$(^F))) >> __lib__.tmp,) +$(if $(wordlist 250,300,$(^F)), echo $(wordlist 250,300,$(addprefix -+,$(^F))) >> __lib__.tmp,) +$(if $(wordlist 300,999,$(^F)), echo $(wordlist 300,999,$(addprefix -+,$(^F))) >> __lib__.tmp,) $(AR) $(ARFLAGS) @__lib__.tmp endef +ARFILES = $(addprefix -+,$(^F)) + AR = wlib ARFLAGS = -p=64 -c -n $(HB_USER_AFLAGS) AR_RULE = $(create_library) diff --git a/harbour/doc/inet.txt b/harbour/doc/inet.txt index a02d6e7215..313564b55c 100644 --- a/harbour/doc/inet.txt +++ b/harbour/doc/inet.txt @@ -147,7 +147,8 @@ * hb_InetAccept( SOCKET ) --> SOCKET * Waits until a connection is available on a socket created with hb_InetServer; * Returns a socket that can be used to communicate with the incoming client. - * On error, sets error in the newly returned socket. + * On error, NIL is returned and error code sets in the passed SOCKET. + * This error can be accessed using hb_InetErrorCode() function. * * Client side socket functions * ---------------------------- diff --git a/harbour/source/rtl/hbinet.c b/harbour/source/rtl/hbinet.c index f247b7b0da..43110162e4 100644 --- a/harbour/source/rtl/hbinet.c +++ b/harbour/source/rtl/hbinet.c @@ -65,12 +65,17 @@ #include "hbsocket.h" #include "hbapierr.h" #include "hbvm.h" +#include "hbthread.h" typedef struct { HB_SOCKET sd; void * remote; unsigned remotelen; + char * buffer; + long inbuffer; + long posbuffer; + long readahead; char szErrorText[ 128 ]; const char * pszErrorText; int iErrorCode; @@ -80,6 +85,10 @@ typedef struct PHB_ITEM pPeriodicBlock; } HB_SOCKET_STRUCT, * PHB_SOCKET_STRUCT; +#define HB_INET_BUFFER_LEN 256 + +#define HB_INET_INITIALIZE() if( s_initialize ) hb_inetAutoInit() + #define HB_PARSOCKET( n ) ( ( PHB_SOCKET_STRUCT ) hb_parptrGC( hb_inetSocketFinalize, n ) ) #define HB_SOCKET_ZERO_ERROR( s ) \ @@ -108,15 +117,21 @@ typedef struct #define HB_SOCKET_INIT( s, p ) \ do { \ + HB_INET_INITIALIZE(); \ s = ( PHB_SOCKET_STRUCT ) hb_gcAlloc( sizeof( HB_SOCKET_STRUCT ), hb_inetSocketFinalize ); \ memset( s, '\0', sizeof( HB_SOCKET_STRUCT ) ); \ s->sd = HB_NO_SOCKET; \ + s->readahead = HB_INET_BUFFER_LEN; \ s->iTimeout = -1; \ s->iTimeLimit = -1; \ s->pszErrorText = ""; \ p = hb_itemPutPtrGC( p, s ); \ } while( 0 ) +static const char * s_inetCRLF = "\r\n"; + +static HB_COUNTER s_initialize = 1; + #if defined( HB_OS_LINUX ) /* #define HB_INET_LINUX_INTERRUPT SIGUSR1 + 90 */ # ifdef HB_INET_LINUX_INTERRUPT @@ -130,7 +145,10 @@ static void hb_inetLinuxSigusrHandle( int sig ) # endif #endif -static const char * s_inetCRLF = "\r\n"; +static void hb_inetErrRT( void ) +{ + hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); +} static BOOL hb_inetIsOpen( PHB_SOCKET_STRUCT socket ) { @@ -142,18 +160,12 @@ static BOOL hb_inetIsOpen( PHB_SOCKET_STRUCT socket ) return TRUE; } -static int hb_inetConnect( PHB_SOCKET_STRUCT socket ) +static int hb_inetCloseSocket( PHB_SOCKET_STRUCT socket ) { - int iErr; - - hb_socketSetKeepAlive( socket->sd, TRUE ); - - iErr = hb_socketConnect( socket->sd, socket->remote, socket->remotelen, - socket->iTimeout ); - if( iErr != 0 ) - HB_SOCKET_SET_ERROR( socket ); - - return iErr == 0; + int ret = hb_socketClose( socket->sd ); + socket->sd = HB_NO_SOCKET; + socket->inbuffer = 0; + return ret; } static HB_GARBAGE_FUNC( hb_inetSocketFinalize ) @@ -163,8 +175,7 @@ static HB_GARBAGE_FUNC( hb_inetSocketFinalize ) if( socket->sd != HB_NO_SOCKET ) { hb_socketShutdown( socket->sd, HB_SOCKET_SHUT_RDWR ); - hb_socketClose( socket->sd ); - socket->sd = HB_NO_SOCKET; + hb_inetCloseSocket( socket ); } if( socket->pPeriodicBlock ) @@ -177,14 +188,34 @@ static HB_GARBAGE_FUNC( hb_inetSocketFinalize ) hb_xfree( socket->remote ); socket->remote = NULL; } + if( socket->buffer ) + { + hb_xfree( socket->buffer ); + socket->buffer = NULL; + } } /***************************************************** * Socket Initialization ***/ +static void hb_inetAutoInit( void ) +{ + if( s_initialize ) + { + if( hb_atomic_dec( &s_initialize ) ) + { + hb_socketInit(); +#if defined( HB_INET_LINUX_INTERRUPT ) + signal( HB_INET_LINUX_INTERRUPT, hb_inetLinuxSigusrHandle ); +#endif + } + } +} + HB_FUNC( HB_INETINIT ) { + hb_atomic_set( &s_initialize, 0 ); hb_socketInit(); #if defined( HB_INET_LINUX_INTERRUPT ) signal( HB_INET_LINUX_INTERRUPT, hb_inetLinuxSigusrHandle ); @@ -221,9 +252,7 @@ HB_FUNC( HB_INETCLOSE ) if( socket->sd != HB_NO_SOCKET ) { hb_socketShutdown( socket->sd, HB_SOCKET_SHUT_RDWR ); - hb_retni( hb_socketClose( socket->sd ) ); - socket->sd = HB_NO_SOCKET; - + hb_retni( hb_inetCloseSocket( socket ) ); #ifdef HB_INET_LINUX_INTERRUPT kill( 0, HB_INET_LINUX_INTERRUPT ); #endif @@ -232,7 +261,7 @@ HB_FUNC( HB_INETCLOSE ) hb_retni( -1 ); } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETFD ) @@ -247,7 +276,7 @@ HB_FUNC( HB_INETFD ) socket->sd = HB_NO_SOCKET; } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } /************************************************ @@ -261,7 +290,7 @@ HB_FUNC( HB_INETSTATUS ) if( socket ) hb_retni( socket->sd == HB_NO_SOCKET ? -1 : 1 ); /* TODO: hb_retni( socket->status ); */ else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } /* Prepared, but still not used; being in wait for comments @@ -281,7 +310,7 @@ HB_FUNC( HB_INETSTATUSDESC ) } } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } */ @@ -292,7 +321,7 @@ HB_FUNC( HB_INETERRORCODE ) if( socket ) hb_retni( socket->iErrorCode ); else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETERRORDESC ) @@ -302,7 +331,7 @@ HB_FUNC( HB_INETERRORDESC ) if( socket ) hb_retc( socket->pszErrorText ); else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETCLEARERROR ) @@ -312,7 +341,7 @@ HB_FUNC( HB_INETCLEARERROR ) if( socket ) HB_SOCKET_ZERO_ERROR( socket ); else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETCOUNT ) @@ -322,7 +351,7 @@ HB_FUNC( HB_INETCOUNT ) if( socket ) hb_retni( socket->iCount ); else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETADDRESS ) @@ -339,7 +368,7 @@ HB_FUNC( HB_INETADDRESS ) hb_retc_null(); } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETPORT ) @@ -350,7 +379,7 @@ HB_FUNC( HB_INETPORT ) hb_retni( socket->remote ? hb_socketAddrGetPort( socket->remote, socket->remotelen ) : 0 ); else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETTIMEOUT ) @@ -365,7 +394,7 @@ HB_FUNC( HB_INETTIMEOUT ) socket->iTimeout = hb_parni( 2 ); } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETCLEARTIMEOUT ) @@ -375,7 +404,7 @@ HB_FUNC( HB_INETCLEARTIMEOUT ) if( socket ) socket->iTimeout = -1; else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETTIMELIMIT ) @@ -390,7 +419,7 @@ HB_FUNC( HB_INETTIMELIMIT ) socket->iTimeLimit = hb_parnl( 2 ); } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETCLEARTIMELIMIT ) @@ -400,7 +429,7 @@ HB_FUNC( HB_INETCLEARTIMELIMIT ) if( socket ) socket->iTimeLimit = -1; else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETPERIODCALLBACK ) @@ -422,7 +451,7 @@ HB_FUNC( HB_INETPERIODCALLBACK ) } } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETCLEARPERIODCALLBACK ) @@ -438,7 +467,7 @@ HB_FUNC( HB_INETCLEARPERIODCALLBACK ) } } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETGETSNDBUFSIZE ) @@ -456,7 +485,7 @@ HB_FUNC( HB_INETGETSNDBUFSIZE ) hb_retni( iSize ); } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETGETRCVBUFSIZE ) @@ -474,7 +503,7 @@ HB_FUNC( HB_INETGETRCVBUFSIZE ) hb_retni( iSize ); } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETSETSNDBUFSIZE ) @@ -492,7 +521,7 @@ HB_FUNC( HB_INETSETSNDBUFSIZE ) hb_retni( iSize ); } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETSETRCVBUFSIZE ) @@ -510,7 +539,7 @@ HB_FUNC( HB_INETSETRCVBUFSIZE ) hb_retni( iSize ); } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } @@ -519,6 +548,41 @@ HB_FUNC( HB_INETSETRCVBUFSIZE ) * TCP receive and send functions ***/ +static long s_inetRecv( PHB_SOCKET_STRUCT socket, char * buffer, long size, BOOL readahead ) +{ + long rec = 0; + + if( readahead && socket->inbuffer == 0 && socket->readahead > size ) + { + if( socket->buffer == NULL ) + socket->buffer = ( char * ) hb_xgrab( socket->readahead ); + socket->posbuffer = 0; + rec = hb_socketRecv( socket->sd, socket->buffer, socket->readahead, + 0, socket->iTimeout ); + socket->inbuffer = HB_MAX( 0, rec ); + } + else + readahead = FALSE; + + if( socket->inbuffer > 0 ) + { + rec = HB_MIN( size, socket->inbuffer ); + memcpy( buffer, socket->buffer + socket->posbuffer, rec ); + socket->posbuffer += rec; + socket->inbuffer -= rec; + if( size > rec && !readahead ) + { + size = hb_socketRecv( socket->sd, buffer + rec, size - rec, 0, 0 ); + if( size > 0 ) + size += rec; + } + } + else if( !readahead ) + rec = hb_socketRecv( socket->sd, buffer, size, 0, socket->iTimeout ); + + return rec; +} + static void s_inetRecvInternal( int iMode ) { PHB_SOCKET_STRUCT socket = HB_PARSOCKET( 1 ); @@ -529,95 +593,72 @@ static void s_inetRecvInternal( int iMode ) int iTimeElapsed; if( socket == NULL || pBuffer == NULL || ! HB_ISBYREF( 2 ) ) - { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); - return; - } + hb_inetErrRT(); else if( ! hb_inetIsOpen( socket ) ) - { - hb_retni( 0 ); - return; - } - - if( hb_itemGetWriteCL( pBuffer, &buffer, &ulLen ) ) - iLen = ( int ) ulLen; + hb_retni( -1 ); else { - iLen = 0; - buffer = NULL; - } + if( hb_itemGetWriteCL( pBuffer, &buffer, &ulLen ) ) + iLen = ( int ) ulLen; + else + { + iLen = 0; + buffer = NULL; + } - if( HB_ISNUM( 3 ) ) - { - iMaxLen = hb_parni( 3 ); - if( iLen < iMaxLen ) + if( HB_ISNUM( 3 ) ) + { + iMaxLen = hb_parni( 3 ); + if( iMaxLen < 0 ) + iMaxLen = 0; + else if( iLen < iMaxLen ) + iMaxLen = iLen; + } + else iMaxLen = iLen; - } - else - iMaxLen = iLen; - iReceived = 0; - iTimeElapsed = 0; - HB_SOCKET_ZERO_ERROR( socket ); - - do - { - iLen = hb_socketRecv( socket->sd, buffer + iReceived, iMaxLen - iReceived, - 0, socket->iTimeout ); - if( iLen >= 0 ) + iReceived = 0; + iTimeElapsed = 0; + HB_SOCKET_ZERO_ERROR( socket ); + do { - iReceived += iLen; - - /* Called from InetRecv()? */ - if( iMode == 0 ) - break; - } - else if( iLen == -1 && hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) - { - /* timed out; let's see if we have to run a cb routine */ - iTimeElapsed += socket->iTimeout; - - /* if we have a pPeriodicBlock, timeLimit is our REAL timeout */ - if( socket->pPeriodicBlock ) + iLen = s_inetRecv( socket, buffer + iReceived, iMaxLen - iReceived, FALSE ); + if( iLen >= 0 ) { - hb_execFromArray( socket->pPeriodicBlock ); - - /* do we continue? */ - if( ! hb_parl( -1 ) || hb_vmRequestQuery() != 0 || - ( socket->iTimeLimit != -1 && iTimeElapsed >= socket->iTimeLimit ) ) + iReceived += iLen; + if( iMode == 0 ) /* Called from InetRecv()? */ + break; + } + else if( iLen == -1 && hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) + { + /* timed out; let's see if we have to run a cb routine */ + iTimeElapsed += socket->iTimeout; + /* if we have a pPeriodicBlock, timeLimit is our REAL timeout */ + if( socket->pPeriodicBlock ) { - HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); - hb_retni( iReceived ); - return; + hb_execFromArray( socket->pPeriodicBlock ); + /* do we continue? */ + if( hb_parl( -1 ) && hb_vmRequestQuery() == 0 && + ( socket->iTimeLimit == -1 || iTimeElapsed < socket->iTimeLimit ) ) + iLen = 1; /* Declare success to continue loop */ } - - /* Declare success to continue loop */ - iLen = 1; - } - else /* the timeout has gone, and we have no recovery routine */ - { - HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); - hb_retni( iReceived ); - return; } } - } - while( iReceived < iMaxLen && iLen > 0 ); + while( iReceived < iMaxLen && iLen > 0 ); - socket->iCount = iReceived; + socket->iCount = iReceived; - if( iLen == 0 ) - { - HB_SOCKET_SET_ERROR2( socket, -2, "Connection closed" ); - hb_retni( iLen ); + if( iLen == 0 ) + HB_SOCKET_SET_ERROR2( socket, -2, "Connection closed" ); + else if( iLen < 0 ) + { + if( hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) + HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); + else + HB_SOCKET_SET_ERROR( socket ); + } + hb_retni( iReceived > 0 ? iReceived : iLen ); } - else if( iLen < 0 ) - { - HB_SOCKET_SET_ERROR( socket ); - hb_retni( iLen ); - } - else - hb_retni( iReceived ); } HB_FUNC( HB_INETRECV ) @@ -632,156 +673,26 @@ HB_FUNC( HB_INETRECVALL ) } -static void s_inetRecvPattern( const char * szPattern ) +static void s_inetRecvPattern( const char ** patterns, int * patternsizes, + int iPatternsCount, int iParam ) { PHB_SOCKET_STRUCT socket = HB_PARSOCKET( 1 ); - PHB_ITEM pResult = hb_param( 2, HB_IT_BYREF ); - PHB_ITEM pMaxSize = hb_param( 3, HB_IT_NUMERIC ); - PHB_ITEM pBufferSize = hb_param( 4, HB_IT_NUMERIC ); + PHB_ITEM pResult = hb_param( iParam, HB_IT_BYREF ); + PHB_ITEM pMaxSize = hb_param( iParam + 1, HB_IT_NUMERIC ); + PHB_ITEM pBufferSize = hb_param( iParam + 2, HB_IT_NUMERIC ); char cChar = '\0'; - char * Buffer; - int iAllocated, iBufferSize, iMax; - int iLen, iPatLen; - int iPos = 0, iTimeElapsed; - - if( socket == NULL ) - { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); - return; - } - else if( ! hb_inetIsOpen( socket ) ) - { - hb_retni( 0 ); - return; - } - - iBufferSize = pBufferSize ? hb_itemGetNI( pBufferSize ) : 80; - iMax = pMaxSize ? hb_itemGetNI( pMaxSize ) : 0; - - HB_SOCKET_ZERO_ERROR( socket ); - - Buffer = ( char * ) hb_xgrab( iBufferSize ); - iAllocated = iBufferSize; - iTimeElapsed = 0; - iPatLen = ( int ) strlen( szPattern ); - - do - { - if( iPos == iAllocated - 1 ) - { - iAllocated += iBufferSize; - Buffer = ( char * ) hb_xrealloc( Buffer, iAllocated ); - } - - iLen = hb_socketRecv( socket->sd, &cChar, 1, 0, socket->iTimeout ); - if( iLen == -1 && hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) - { - iTimeElapsed += socket->iTimeout; - - if( socket->pPeriodicBlock ) - { - BOOL fResult; - - hb_execFromArray( socket->pPeriodicBlock ); - fResult = hb_parl( -1 ) && hb_vmRequestQuery() == 0; - - /* do we continue? */ - if( fResult && - ( socket->iTimeLimit == -1 || iTimeElapsed < socket->iTimeLimit ) ) - { - continue; - } - } - - /* this signals timeout */ - iLen = -2; - } - - if( iLen > 0 ) - { - Buffer[ iPos++ ] = cChar; - /* verify endsequence recognition automata status */ - if( iPos >= iPatLen && - memcmp( Buffer + iPos - iPatLen, szPattern, iPatLen ) == 0 ) - { - break; - } - } - else - break; - } - while( iMax == 0 || iPos < iMax ); - - if( iLen <= 0 ) - { - if( pResult ) - hb_itemPutNI( pResult, iLen ); - - if( iLen == 0 ) - HB_SOCKET_SET_ERROR2( socket, -2, "Connection closed" ); - else if( iLen == -2 ) - HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); - else - HB_SOCKET_SET_ERROR( socket ); - - hb_xfree( Buffer ); - } - else - { - if( iMax == 0 || iPos < iMax ) - { - iPos -= iPatLen; - socket->iCount = iPos; - - if( pResult ) - hb_itemPutNI( pResult, iPos ); - - hb_retclen_buffer( Buffer, iPos ); - } - else - { - HB_SOCKET_SET_ERROR2( socket, -3, "Buffer overrun" ); - - if( pResult ) - hb_itemPutNI( pResult, -2 ); - - hb_xfree( Buffer ); - hb_retc_null(); - } - } -} - -HB_FUNC( HB_INETRECVLINE ) -{ - s_inetRecvPattern( s_inetCRLF ); -} - -HB_FUNC( HB_INETRECVENDBLOCK ) -{ - PHB_SOCKET_STRUCT socket = HB_PARSOCKET( 1 ); - PHB_ITEM pProto = hb_param( 2, HB_IT_ARRAY | HB_IT_STRING ); - PHB_ITEM pResult = hb_param( 3, HB_IT_BYREF ); - PHB_ITEM pMaxSize = hb_param( 4, HB_IT_NUMERIC ); - PHB_ITEM pBufferSize = hb_param( 5, HB_IT_NUMERIC ); - - char cChar = '\0'; - char * Buffer; - const char ** Proto; - int iAllocated, iBufferSize, iMax; - int iLen; - int iPos = 0; - int iPosProto; + char * buffer; + int iPaternFound = 0; int iTimeElapsed = 0; - int iprotos; + int iPos = 0; + int iLen; + int iAllocated, iBufferSize, iMax; int i; - int * iprotosize; - int ifindproto = 0; - BOOL bProtoFound; if( socket == NULL ) { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); return; } else if( ! hb_inetIsOpen( socket ) ) @@ -792,50 +703,13 @@ HB_FUNC( HB_INETRECVENDBLOCK ) return; } - if( pProto ) - { - if( HB_IS_ARRAY( pProto ) ) - { - iprotos = ( int ) hb_arrayLen( pProto ); - if( iprotos <= 0 ) - { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); - return; - } - - Proto = ( const char ** ) hb_xgrab( sizeof( char * ) * iprotos ); - iprotosize = ( int * ) hb_xgrab( sizeof( int ) * iprotos ); - - for( i = 0; i < iprotos; i++ ) - { - Proto[ i ] = hb_arrayGetCPtr( pProto, i + 1 ); - iprotosize[ i ] = hb_arrayGetCLen( pProto, i + 1 ); - } - } - else - { - Proto = ( const char ** ) hb_xgrab( sizeof( char * ) ); - iprotosize = ( int * ) hb_xgrab( sizeof( int ) ); - Proto[ 0 ] = hb_itemGetCPtr( pProto ); - iprotosize[ 0 ] = hb_itemGetCLen( pProto ); - iprotos = 1; - } - } - else - { - Proto = ( const char ** ) hb_xgrab( sizeof( char * ) ); - iprotosize = ( int * ) hb_xgrab( sizeof( int ) ); - Proto[ 0 ] = ( char * ) "\r\n"; - iprotos = 1; - iprotosize[ 0 ] = 2; - } iBufferSize = pBufferSize ? hb_itemGetNI( pBufferSize ) : 80; iMax = pMaxSize ? hb_itemGetNI( pMaxSize ) : 0; HB_SOCKET_ZERO_ERROR( socket ); - Buffer = ( char * ) hb_xgrab( iBufferSize ); + buffer = ( char * ) hb_xgrab( iBufferSize ); iAllocated = iBufferSize; do @@ -843,12 +717,13 @@ HB_FUNC( HB_INETRECVENDBLOCK ) if( iPos == iAllocated - 1 ) { iAllocated += iBufferSize; - Buffer = ( char * ) hb_xrealloc( Buffer, iAllocated ); + buffer = ( char * ) hb_xrealloc( buffer, iAllocated ); } - iLen = hb_socketRecv( socket->sd, &cChar, 1, 0, socket->iTimeout ); + iLen = s_inetRecv( socket, &cChar, 1, TRUE ); if( iLen == -1 && hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) { + iLen = -2; /* this signals timeout */ iTimeElapsed += socket->iTimeout; if( socket->pPeriodicBlock ) { @@ -859,114 +734,157 @@ HB_FUNC( HB_INETRECVENDBLOCK ) if( fResult && ( socket->iTimeLimit == -1 || iTimeElapsed < socket->iTimeLimit ) ) - { - continue; - } + iLen = 1; } - - iLen = -2; } - - if( iLen > 0 ) + else if( iLen > 0 ) { - int protos; - bProtoFound = 0; - - for( protos = 0; protos < iprotos; protos++ ) + buffer[ iPos++ ] = cChar; + for( i = 0; i < iPatternsCount; ++i ) { - if( cChar == Proto[ protos ][ iprotosize[ protos ] - 1 ] && iprotosize[ protos ] <= iPos ) + if( patternsizes[ i ] <= iPos && + cChar == patterns[ i ][ patternsizes[ i ] - 1 ] ) { - bProtoFound = 1; - for( iPosProto = 0; iPosProto < ( iprotosize[ protos ] - 1 ); iPosProto++ ) + if( memcmp( buffer + iPos - patternsizes[ i ], + patterns[ i ], patternsizes[ i ] ) == 0 ) { - if( Proto[ protos ][ iPosProto ] != Buffer[ ( iPos - iprotosize[ protos ] ) + iPosProto + 1 ] ) - { - bProtoFound = 0; - break; - } - } - - if( bProtoFound ) - { - ifindproto = protos; + iPaternFound = i + 1; break; } } } - - if( bProtoFound ) - break; - - Buffer[ iPos++ ] = cChar; } - else - break; } - while( iMax == 0 || iPos < iMax ); + while( iLen > 0 && iPaternFound == 0 && ( iMax == 0 || iPos < iMax ) ); - if( iLen <= 0 ) + if( iPaternFound ) { + socket->iCount = iPos; if( pResult ) - hb_itemPutNI( pResult, iLen ); - - if( iLen == 0 ) - HB_SOCKET_SET_ERROR2( socket, -2, "Connection closed" ); - else if( iLen == -2 ) - HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); - else - HB_SOCKET_SET_ERROR( socket ); - - hb_xfree( Buffer ); - hb_retc_null(); + hb_itemPutNI( pResult, iPos ); + hb_retclen_buffer( buffer, iPos - patternsizes[ iPaternFound - 1 ] ); } else { - if( iMax == 0 || iPos < iMax ) + if( iLen == 0 ) + HB_SOCKET_SET_ERROR2( socket, -2, "Connection closed" ); + else if( iLen < 0 ) { - socket->iCount = iPos; - - if( pResult ) - hb_itemPutNI( pResult, iPos - ( iprotosize[ ifindproto ] - 1 ) ); - - hb_retclen_buffer( Buffer, iPos - ( iprotosize[ ifindproto ] - 1 ) ); + if( hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) + HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); + else + HB_SOCKET_SET_ERROR( socket ); } else { - HB_SOCKET_SET_ERROR2( socket, -1, "Buffer overrun" ); + HB_SOCKET_SET_ERROR2( socket, -3, "Buffer overrun" ); + iLen = -1; + } + if( pResult ) + hb_itemPutNI( pResult, iLen ); + hb_xfree( buffer ); + hb_retc_null(); + } +} - if( pResult ) - hb_itemPutNI( pResult, -2 ); +HB_FUNC( HB_INETRECVLINE ) +{ + int iEolLen = ( int ) strlen( s_inetCRLF ); - hb_xfree( Buffer ); - hb_retc_null(); + s_inetRecvPattern( &s_inetCRLF, &iEolLen, 1, 2 ); +} + +#define HB_PATERN_BUF_SIZE 16 + +HB_FUNC( HB_INETRECVENDBLOCK ) +{ + PHB_ITEM pProto = hb_param( 2, HB_IT_ARRAY | HB_IT_STRING ); + const char * patterns_buf[ HB_PATERN_BUF_SIZE ]; + const char ** patterns = patterns_buf; + int patternsizes_buf[ HB_PATERN_BUF_SIZE ]; + int * patternsizes = patternsizes_buf; + int iPatternsCount = 0; + int iLen; + + if( pProto && HB_IS_ARRAY( pProto ) ) + { + int iPatternsMax = ( int ) hb_arrayLen( pProto ), i; + + for( i = 1; i <= iPatternsMax; i++ ) + { + iLen = ( int ) hb_arrayGetCLen( pProto, i ); + if( iLen > 0 ) + ++iPatternsCount; + } + if( iPatternsCount > 0 ) + { + if( iPatternsCount > HB_PATERN_BUF_SIZE ) + { + patterns = ( const char ** ) hb_xgrab( sizeof( char * ) * iPatternsCount ); + patternsizes = ( int * ) hb_xgrab( sizeof( int ) * iPatternsCount ); + } + iPatternsCount = 0; + for( i = 1; i <= iPatternsMax; i++ ) + { + iLen = ( int ) hb_arrayGetCLen( pProto, i ); + if( iLen > 0 ) + { + patterns[ iPatternsCount ] = hb_arrayGetCPtr( pProto, i ); + patternsizes[ iPatternsCount ] = iLen; + ++iPatternsCount; + } + } } } - hb_xfree( Proto ); - hb_xfree( iprotosize ); + if( iPatternsCount == 0 ) + { + iLen = ( int ) hb_itemGetCLen( pProto ); + if( iLen > 0 ) + { + patterns[ 0 ] = hb_itemGetCPtr( pProto ); + patternsizes[ 0 ] = iLen; + } + else + { + patterns[ 0 ] = s_inetCRLF; + patternsizes[ 0 ] = strlen( s_inetCRLF ); + } + iPatternsCount = 1; + } + + s_inetRecvPattern( patterns, patternsizes, iPatternsCount, 3 ); + + if( iPatternsCount > HB_PATERN_BUF_SIZE ) + { + hb_xfree( patterns ); + hb_xfree( patternsizes ); + } } + HB_FUNC( HB_INETDATAREADY ) { PHB_SOCKET_STRUCT socket = HB_PARSOCKET( 1 ); int iVal; if( socket == NULL || ( hb_pcount() >= 2 && ! HB_ISNUM( 2 ) ) ) - { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); - return; - } + hb_inetErrRT(); else if( ! hb_inetIsOpen( socket ) ) + hb_retni( -1 ); + else { - hb_retl( FALSE ); - return; + HB_SOCKET_ZERO_ERROR( socket ); + if( socket->inbuffer > 0 ) + iVal = 1; + else + { + iVal = hb_socketSelectRead( socket->sd, HB_ISNUM( 2 ) ? hb_parnint( 2 ) : 0 ); + if( iVal < 0 ) + HB_SOCKET_SET_ERROR( socket ); + } + hb_retni( iVal ); } - - HB_SOCKET_ZERO_ERROR( socket ); - iVal = hb_socketSelectRead( socket->sd, HB_ISNUM( 2 ) ? hb_parnint( 2 ) : 0 ); - if( iVal < 0 ) - HB_SOCKET_SET_ERROR( socket ); - hb_retni( iVal ); } @@ -974,60 +892,49 @@ static void s_inetSendInternal( int iMode ) { PHB_SOCKET_STRUCT socket = HB_PARSOCKET( 1 ); PHB_ITEM pBuffer = hb_param( 2, HB_IT_STRING ); - const char * Buffer; + const char * buffer; int iLen, iSent, iSend; if( socket == NULL || pBuffer == NULL ) - { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); - return; - } + hb_inetErrRT(); else if( ! hb_inetIsOpen( socket ) ) + hb_retni( -1 ); + else { - hb_retni( 0 ); - return; - } - - Buffer = hb_itemGetCPtr( pBuffer ); - iSend = ( int ) hb_itemGetCLen( pBuffer ); - - if( HB_ISNUM( 3 ) ) - { - iLen = hb_parni( 3 ); - if( iLen < iSend ) - iSend = iLen; - } - - HB_SOCKET_ZERO_ERROR( socket ); - - iSent = 0; - iLen = 0; - while( iSent < iSend ) - { - iLen = hb_socketSend( socket->sd, Buffer + iSent, iSend - iSent, 0, - socket->iTimeout ); - if( iLen > 0 ) + buffer = hb_itemGetCPtr( pBuffer ); + iSend = ( int ) hb_itemGetCLen( pBuffer ); + if( HB_ISNUM( 3 ) ) { - iSent += iLen; - } - else if( iLen == -1 && hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) - { - HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); - break; - } - else - { - HB_SOCKET_SET_ERROR( socket ); - break; + iLen = hb_parni( 3 ); + if( iLen < iSend ) + iSend = iLen; } - if( iMode == 0 ) - break; + HB_SOCKET_ZERO_ERROR( socket ); + + iSent = iLen = 0; + while( iSent < iSend ) + { + iLen = hb_socketSend( socket->sd, buffer + iSent, iSend - iSent, 0, + socket->iTimeout ); + if( iLen > 0 ) + { + iSent += iLen; + if( iMode == 0 ) + break; + } + else + { + if( iLen == -1 && hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) + HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); + else + HB_SOCKET_SET_ERROR( socket ); + break; + } + } + socket->iCount = iSent; + hb_retni( iSent > 0 ? iSent : iLen ); } - - socket->iCount = iSent; - - hb_retni( iLen > 0 ? iSent : -1 ); } HB_FUNC( HB_INETSEND ) @@ -1051,15 +958,17 @@ HB_FUNC( HB_INETGETHOSTS ) if( szHost ) { - PHB_ITEM pHosts = hb_socketGetHosts( szHost, HB_SOCKET_PF_INET ); + PHB_ITEM pHosts; + HB_INET_INITIALIZE(); + pHosts = hb_socketGetHosts( szHost, HB_SOCKET_PF_INET ); if( pHosts ) hb_itemReturnRelease( pHosts ); else hb_reta( 0 ); } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } HB_FUNC( HB_INETGETALIAS ) @@ -1068,15 +977,17 @@ HB_FUNC( HB_INETGETALIAS ) if( szHost ) { - PHB_ITEM pHosts = hb_socketGetAliases( szHost, HB_SOCKET_PF_INET ); + PHB_ITEM pHosts; + HB_INET_INITIALIZE(); + pHosts = hb_socketGetAliases( szHost, HB_SOCKET_PF_INET ); if( pHosts ) hb_itemReturnRelease( pHosts ); else hb_reta( 0 ); } else - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); } @@ -1088,71 +999,38 @@ HB_FUNC( HB_INETSERVER ) { PHB_SOCKET_STRUCT socket = HB_PARSOCKET( 2 ); PHB_ITEM pSocket = NULL; - const char * szAddress; - int iPort, iListen; - /* Parameter error checking */ if( ! HB_ISNUM( 1 ) || ( socket == NULL && ! HB_ISNIL( 2 ) ) ) { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); return; } - if( socket ) - HB_SOCKET_ZERO_ERROR( socket ); - else + if( !socket ) HB_SOCKET_INIT( socket, pSocket ); - - /* Creates comm socket */ - if( socket->sd != HB_NO_SOCKET ) - { - hb_socketClose( socket->sd ); - socket->sd = HB_NO_SOCKET; - } + else if( socket->sd != HB_NO_SOCKET ) + hb_inetCloseSocket( socket ); socket->sd = hb_socketOpen( HB_SOCKET_PF_INET, HB_SOCKET_PT_STREAM, 0 ); if( socket->sd == HB_NO_SOCKET ) - { HB_SOCKET_SET_ERROR( socket ); - if( pSocket ) - hb_itemReturnRelease( pSocket ); - else - hb_itemReturn( hb_param( 2, HB_IT_ANY ) ); - return; - } - - /* we'll be using only nonblocking sockets */ - /* hb_socketSetBlockingIO( socket->sd, FALSE ); */ - - hb_socketSetReuseAddr( socket->sd, TRUE ); - - iPort = hb_parni( 1 ); - szAddress = hb_parc( 2 ); - iListen = HB_ISNUM( 3 ) ? hb_parni( 3 ) : 10; - if( socket->remote ) - hb_xfree( socket->remote ); - if( hb_socketInetAddr( &socket->remote, &socket->remotelen, - szAddress, iPort ) ) - { - if( hb_socketBind( socket->sd, socket->remote, socket->remotelen ) == -1 ) - { - HB_SOCKET_SET_ERROR( socket ); - hb_socketClose( socket->sd ); - socket->sd = HB_NO_SOCKET; - } - else if( hb_socketListen( socket->sd, iListen ) == -1 ) - { - HB_SOCKET_SET_ERROR( socket ); - hb_socketClose( socket->sd ); - socket->sd = HB_NO_SOCKET; - } - } else { - HB_SOCKET_SET_ERROR( socket ); - hb_socketClose( socket->sd ); - socket->sd = HB_NO_SOCKET; - } + int iPort = hb_parni( 1 ); + const char * szAddress = hb_parc( 2 ); + int iListen = hb_parnidef( 3, 10 ); + if( socket->remote ) + hb_xfree( socket->remote ); + if( !hb_socketInetAddr( &socket->remote, &socket->remotelen, szAddress, iPort ) || + hb_socketBind( socket->sd, socket->remote, socket->remotelen ) != 0 || + hb_socketListen( socket->sd, iListen ) != 0 ) + { + HB_SOCKET_SET_ERROR( socket ); + hb_inetCloseSocket( socket ); + } + else + HB_SOCKET_ZERO_ERROR( socket ); + } if( pSocket ) hb_itemReturnRelease( pSocket ); else @@ -1162,47 +1040,33 @@ HB_FUNC( HB_INETSERVER ) HB_FUNC( HB_INETACCEPT ) { PHB_SOCKET_STRUCT socket = HB_PARSOCKET( 1 ); - HB_SOCKET incoming; - void * sa; - unsigned len; if( socket == NULL ) + hb_inetErrRT(); + else if( hb_inetIsOpen( socket ) ) { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); - return; - } - else if( ! hb_inetIsOpen( socket ) ) - return; + void * sa; + unsigned len; + HB_SOCKET incoming = hb_socketAccept( socket->sd, &sa, &len, socket->iTimeout ); - /* - * Accept can (and should) be asynchronously stopped by closing the - * accepting socket. this will make the wait to terminate, and the - * calling program will be notivfied through the status of the - * returned socket. - */ - - HB_SOCKET_ZERO_ERROR( socket ); - - incoming = hb_socketAccept( socket->sd, &sa, &len, socket->iTimeout ); - - if( incoming == HB_NO_SOCKET ) - { - if( hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) - HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); + if( incoming == HB_NO_SOCKET ) + { + if( hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) + HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); + else + HB_SOCKET_SET_ERROR( socket ); + } else - HB_SOCKET_SET_ERROR( socket ); - } - else - { - PHB_SOCKET_STRUCT new_socket; - PHB_ITEM pSocket = NULL; - HB_SOCKET_INIT( new_socket, pSocket ); - new_socket->remote = sa; - new_socket->remotelen = len; - new_socket->sd = incoming; - /* we'll be using only nonblocking sockets */ - /* hb_socketSetBlockingIO( socket->sd, FALSE ); */ - hb_itemReturnRelease( pSocket ); + { + PHB_SOCKET_STRUCT new_socket; + PHB_ITEM pSocket = NULL; + HB_SOCKET_INIT( new_socket, pSocket ); + new_socket->remote = sa; + new_socket->remotelen = len; + new_socket->sd = incoming; + hb_itemReturnRelease( pSocket ); + HB_SOCKET_ZERO_ERROR( socket ); + } } } @@ -1210,104 +1074,69 @@ HB_FUNC( HB_INETACCEPT ) * Client specific (connection functions) ****/ -HB_FUNC( HB_INETCONNECT ) +static void hb_inetConnectInternal( BOOL fResolve ) { const char * szHost = hb_parc( 1 ); - char * szAddr; + char * szAddr = NULL; PHB_SOCKET_STRUCT socket = HB_PARSOCKET( 3 ); PHB_ITEM pSocket = NULL; int iPort = hb_parni( 2 ); if( szHost == NULL || iPort == 0 || ( socket == NULL && ! HB_ISNIL( 3 ) ) ) - { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); - return; - } - - if( socket ) - { - if( socket->sd != HB_NO_SOCKET ) - { - hb_socketClose( socket->sd ); - socket->sd = HB_NO_SOCKET; - } - HB_SOCKET_ZERO_ERROR( socket ); - } - else - HB_SOCKET_INIT( socket, pSocket ); - - szAddr = hb_socketResolveAddr( szHost, HB_SOCKET_AF_INET ); - if( !szAddr ) - HB_SOCKET_SET_ERROR( socket ); + hb_inetErrRT(); else { - /* Creates comm socket */ - socket->sd = hb_socketOpen( HB_SOCKET_PF_INET, HB_SOCKET_PT_STREAM, 0 ); - if( socket->sd == HB_NO_SOCKET ) + if( !socket ) + HB_SOCKET_INIT( socket, pSocket ); + else if( socket->sd != HB_NO_SOCKET ) + hb_inetCloseSocket( socket ); + + if( fResolve ) + szHost = szAddr = hb_socketResolveAddr( szHost, HB_SOCKET_AF_INET ); + + if( fResolve && !szAddr ) HB_SOCKET_SET_ERROR( socket ); else { - if( socket->remote ) - hb_xfree( socket->remote ); - if( hb_socketInetAddr( &socket->remote, &socket->remotelen, - szAddr, iPort ) ) - hb_inetConnect( socket ); - else + /* Creates comm socket */ + socket->sd = hb_socketOpen( HB_SOCKET_PF_INET, HB_SOCKET_PT_STREAM, 0 ); + if( socket->sd == HB_NO_SOCKET ) HB_SOCKET_SET_ERROR( socket ); + else + { + if( socket->remote ) + hb_xfree( socket->remote ); + if( hb_socketInetAddr( &socket->remote, &socket->remotelen, + szHost, iPort ) ) + { + hb_socketSetKeepAlive( socket->sd, TRUE ); + if( hb_socketConnect( socket->sd, socket->remote, socket->remotelen, + socket->iTimeout ) != 0 ) + HB_SOCKET_SET_ERROR( socket ); + else + HB_SOCKET_ZERO_ERROR( socket ); + } + else + HB_SOCKET_SET_ERROR( socket ); + } + if( szAddr ) + hb_xfree( szAddr ); } - hb_xfree( szAddr ); + if( pSocket ) + hb_itemReturnRelease( pSocket ); + else + hb_itemReturn( hb_param( 3, HB_IT_ANY ) ); } +} - if( pSocket ) - hb_itemReturnRelease( pSocket ); - else - hb_itemReturn( hb_param( 3, HB_IT_ANY ) ); +HB_FUNC( HB_INETCONNECT ) +{ + hb_inetConnectInternal( TRUE ); } HB_FUNC( HB_INETCONNECTIP ) { - const char * szHost = hb_parc( 1 ); - PHB_SOCKET_STRUCT socket = HB_PARSOCKET( 3 ); - PHB_ITEM pSocket = NULL; - int iPort = hb_parni( 2 ); - - if( szHost == NULL || iPort == 0 || ( socket == NULL && ! HB_ISNIL( 3 ) ) ) - { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); - return; - } - - if( socket ) - { - if( socket->sd != HB_NO_SOCKET ) - { - hb_socketClose( socket->sd ); - socket->sd = HB_NO_SOCKET; - } - HB_SOCKET_ZERO_ERROR( socket ); - } - else - HB_SOCKET_INIT( socket, pSocket ); - - /* Creates comm socket */ - socket->sd = hb_socketOpen( HB_SOCKET_PF_INET, HB_SOCKET_PT_STREAM, 0 ); - if( socket->sd == HB_NO_SOCKET ) - HB_SOCKET_SET_ERROR( socket ); - else - { - if( socket->remote ) - hb_xfree( socket->remote ); - if( hb_socketInetAddr( &socket->remote, &socket->remotelen, - szHost, iPort ) ) - hb_inetConnect( socket ); - else - HB_SOCKET_SET_ERROR( socket ); - } - - if( pSocket ) - hb_itemReturnRelease( pSocket ); - else - hb_itemReturn( hb_param( 3, HB_IT_ANY ) ); + hb_inetConnectInternal( FALSE ); } /*********************************************************** @@ -1324,7 +1153,7 @@ HB_FUNC( HB_INETDGRAMBIND ) /* Parameter error checking */ if( iPort == 0 || ( hb_pcount() >= 4 && ! HB_ISCHAR( 4 ) ) ) { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + hb_inetErrRT(); return; } @@ -1339,8 +1168,6 @@ HB_FUNC( HB_INETDGRAMBIND ) return; } - hb_socketSetReuseAddr( socket->sd, TRUE ); - /* Setting broadcast if needed. */ if( hb_parl( 3 ) ) hb_socketSetBroadcast( socket->sd, TRUE ); @@ -1349,17 +1176,11 @@ HB_FUNC( HB_INETDGRAMBIND ) if( socket->remote ) hb_xfree( socket->remote ); if( !hb_socketInetAddr( &socket->remote, &socket->remotelen, - szAddress, iPort ) ) + szAddress, iPort ) || + hb_socketBind( socket->sd, socket->remote, socket->remotelen ) != 0 ) { HB_SOCKET_SET_ERROR( socket ); - hb_socketClose( socket->sd ); - socket->sd = HB_NO_SOCKET; - } - else if( hb_socketBind( socket->sd, socket->remote, socket->remotelen ) == -1 ) - { - HB_SOCKET_SET_ERROR( socket ); - hb_socketClose( socket->sd ); - socket->sd = HB_NO_SOCKET; + hb_inetCloseSocket( socket ); } else if( hb_pcount() >= 4 ) { @@ -1390,9 +1211,6 @@ HB_FUNC( HB_INETDGRAM ) if( hb_parl( 1 ) ) hb_socketSetBroadcast( socket->sd, TRUE ); - /* we'll be using non blocking sockets in all functions */ - /* hb_socketSetBlockingIO( socket->sd, FALSE ); */ - hb_itemReturnRelease( pSocket ); } @@ -1406,50 +1224,49 @@ HB_FUNC( HB_INETDGRAMSEND ) const char * szBuffer; if( socket == NULL || szAddress == NULL || iPort == 0 || pBuffer == NULL ) - { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); - return; - } + hb_inetErrRT(); else if( ! hb_inetIsOpen( socket ) ) { socket->iCount = 0; - hb_retni( 0 ); - return; + hb_retni( -1 ); } - - if( socket->remote ) - hb_xfree( socket->remote ); - if( !hb_socketInetAddr( &socket->remote, &socket->remotelen, szAddress, iPort ) ) - { - HB_SOCKET_SET_ERROR( socket ); - socket->iCount = 0; - hb_retni( 0 ); - return; - } - - szBuffer = hb_itemGetCPtr( pBuffer ); - iLen = ( int ) hb_itemGetCLen( pBuffer ); - if( HB_ISNUM( 5 ) ) - { - int iMaxLen = hb_parni( 5 ); - if( iMaxLen < iLen ) - iLen = iMaxLen; - } - - HB_SOCKET_ZERO_ERROR( socket ); - - socket->iCount = hb_socketSendTo( socket->sd, szBuffer, iLen, 0, - socket->remote, socket->remotelen, - socket->iTimeout ); - hb_retni( socket->iCount ); - - if( socket->iCount == -1 ) + else { socket->iCount = 0; - if( hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) - HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); - else + if( socket->remote ) + hb_xfree( socket->remote ); + if( !hb_socketInetAddr( &socket->remote, &socket->remotelen, szAddress, iPort ) ) + { HB_SOCKET_SET_ERROR( socket ); + iLen = -1; + } + else + { + szBuffer = hb_itemGetCPtr( pBuffer ); + iLen = ( int ) hb_itemGetCLen( pBuffer ); + if( HB_ISNUM( 5 ) ) + { + int iMaxLen = hb_parni( 5 ); + if( iMaxLen < iLen ) + iLen = HB_MAX( iMaxLen, 0 ); + } + iLen = hb_socketSendTo( socket->sd, szBuffer, iLen, 0, + socket->remote, socket->remotelen, + socket->iTimeout ); + if( iLen == -1 ) + { + if( hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) + HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); + else + HB_SOCKET_SET_ERROR( socket ); + } + else + { + HB_SOCKET_ZERO_ERROR( socket ); + socket->iCount = iLen; + } + } + hb_retni( iLen ); } } @@ -1458,81 +1275,62 @@ HB_FUNC( HB_INETDGRAMRECV ) PHB_SOCKET_STRUCT socket = HB_PARSOCKET( 1 ); PHB_ITEM pBuffer = hb_param( 2, HB_IT_STRING ); int iTimeElapsed = 0; - int iLen, iMaxLen; - char * Buffer; + int iLen = 0, iMax; + char * buffer = NULL; ULONG ulLen; BOOL fRepeat; if( socket == NULL || pBuffer == NULL || ! HB_ISBYREF( 2 ) ) - { - hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); - return; - } + hb_inetErrRT(); else if( ! hb_inetIsOpen( socket ) ) { socket->iCount = 0; hb_retni( -1 ); - return; - } - - if( hb_itemGetWriteCL( pBuffer, &Buffer, &ulLen ) ) - iLen = ( int ) ulLen; - else - { - iLen = 0; - Buffer = NULL; - } - - if( HB_ISNUM( 3 ) ) - { - iMaxLen = hb_parni( 3 ); - if( iLen < iMaxLen ) - iMaxLen = iLen; } else - iMaxLen = iLen; - - HB_SOCKET_ZERO_ERROR( socket ); - - do { - fRepeat = FALSE; - if( socket->remote ) - hb_xfree( socket->remote ); - iLen = hb_socketRecvFrom( socket->sd, Buffer, iMaxLen, 0, - &socket->remote, &socket->remotelen, - socket->iTimeout ); - iTimeElapsed += socket->iTimeout; - if( socket->pPeriodicBlock ) + socket->iCount = 0; + if( hb_itemGetWriteCL( pBuffer, &buffer, &ulLen ) ) + iLen = ( int ) ulLen; + if( HB_ISNUM( 3 ) ) { - hb_execFromArray( socket->pPeriodicBlock ); - /* do we continue? */ - fRepeat = hb_parl( -1 ) && hb_vmRequestQuery() == 0 && - ( socket->iTimeLimit == -1 || iTimeElapsed < socket->iTimeLimit ); + iMax = hb_parni( 3 ); + if( iMax < iLen ) + iLen = HB_MAX( iMax, 0 ); } - } - while( fRepeat ); - if( iLen == -1 && hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) - { - HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); - socket->iCount = 0; - iLen = -1; - } - else if( iLen == 0 ) - { - HB_SOCKET_SET_ERROR2( socket, -2, "Connection closed" ); - socket->iCount = 0; - } - else if( iLen < 0 ) - { - HB_SOCKET_SET_ERROR( socket ); - socket->iCount = 0; - } - else - socket->iCount = iLen; + do + { + fRepeat = FALSE; + if( socket->remote ) + hb_xfree( socket->remote ); + iMax = hb_socketRecvFrom( socket->sd, buffer, iLen, 0, + &socket->remote, &socket->remotelen, + socket->iTimeout ); + iTimeElapsed += socket->iTimeout; + if( socket->pPeriodicBlock ) + { + hb_execFromArray( socket->pPeriodicBlock ); + /* do we continue? */ + fRepeat = hb_parl( -1 ) && hb_vmRequestQuery() == 0 && + ( socket->iTimeLimit == -1 || iTimeElapsed < socket->iTimeLimit ); + } + } + while( fRepeat ); - hb_retni( iLen ); + if( iMax == 0 ) + HB_SOCKET_SET_ERROR2( socket, -2, "Connection closed" ); + else if( iMax < 0 ) + { + if( hb_socketGetError() == HB_SOCKET_ERR_TIMEOUT ) + HB_SOCKET_SET_ERROR2( socket, -1, "Timeout" ); + else + HB_SOCKET_SET_ERROR( socket ); + } + else + HB_SOCKET_ZERO_ERROR( socket ); + hb_retni( iMax ); + } }