diff --git a/harbour/ChangeLog b/harbour/ChangeLog index c2b3bb9628..014b986f29 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,41 @@ The license applies to all entries newer than 2009-04-28. */ +2010-11-26 13:44 UTC+0100 Viktor Szakats (harbour.01 syenar.hu) + * include/hbapi.h + * src/common/hbver.c + + Added hb_iswin2k3(). + + * src/rtl/hbsocket.c + + Comment. + ; TOFIX: Use SO_EXCLUSIVEADDRUSE on Windows. + See: http://paste.lisp.org/display/59751 + + - examples/udpds + + contrib/hbmisc/tests/udpdstst.prg + + contrib/hbmisc/udpds.prg + * contrib/hbmisc/hbmisc.hbp + + Moved UDPDS functions to hbmisc lib. Added hb_ prefix to names, + plus formatted with hbformat. + + * contrib/hbhttpd/tests/webapp.prg + * Formatting. + + ; Patch from Tamas: + + * config/bsd/gcc.mk + * config/bsd/clang.mk + * switch bsd to -fPIC, otherwise not even core builds (on 8.1/amd64) + * while there, bring bsd/gcc.mk in line with linux/gcc.mk (now they + are identical) + * ditto for bsd/clang.mk + + * contrib/hbqt/hbqt_common.hbc + * for hbqt, switch static supc++ to dynamic stdc++, otherwise dyn hbqt + doesn't build. this is because on at least fbsd supc++ is apparently + not pic; but switching from static supc++ to dynamic stdc++ easily + fixes it. + 2010-11-26 12:55 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/src/rdd/dbf1.c * harbour/src/rdd/sdf1.c diff --git a/harbour/config/bsd/clang.mk b/harbour/config/bsd/clang.mk index 507581e7dd..40960d1f32 100644 --- a/harbour/config/bsd/clang.mk +++ b/harbour/config/bsd/clang.mk @@ -18,6 +18,8 @@ OBJ_EXT := .o LIB_PREF := lib LIB_EXT := .a +HB_DYN_COPT := -DHB_DYNLIB -fPIC + CC := $(HB_CCACHE) $(HB_CCPREFIX)$(HB_CMP)$(HB_CCPOSTFIX) ifneq ($(filter --analyze, $(HB_USER_CFLAGS)),) CC_IN := @@ -58,17 +60,6 @@ DFLAGS += -shared $(LIBPATHS) DY_OUT := -o$(subst x,x, ) DLIBS := $(foreach lib,$(HB_USER_LIBS) $(SYSLIBS),-l$(lib)) -# NOTE: The empty line directly before 'endef' HAVE TO exist! -define dynlib_object - @$(ECHO) $(ECHOQUOTE)INPUT($(subst \,/,$(file)))$(ECHOQUOTE) >> __dyn__.tmp - -endef -define create_dynlib - $(if $(wildcard __dyn__.tmp),@$(RM) __dyn__.tmp,) - $(foreach file,$^,$(dynlib_object)) - $(DY) $(DFLAGS) $(HB_USER_DFLAGS) $(DY_OUT)$(DYN_DIR)/$@ __dyn__.tmp $(DLIBS) $(DYSTRIP) -endef - -DY_RULE = $(create_dynlib) +DY_RULE = $(DY) $(DFLAGS) $(HB_USER_DFLAGS) $(DY_OUT)$(DYN_DIR)/$@ $^ $(DLIBS) $(DYSTRIP) && $(LN) $(@F) $(DYN_FILE2) include $(TOP)$(ROOT)config/rules.mk diff --git a/harbour/config/bsd/gcc.mk b/harbour/config/bsd/gcc.mk index bb35fa74a5..33c7df1253 100644 --- a/harbour/config/bsd/gcc.mk +++ b/harbour/config/bsd/gcc.mk @@ -2,16 +2,20 @@ # $Id$ # -ifeq ($(HB_BUILD_MODE),cpp) - HB_CMP := g++ -else - HB_CMP := gcc +ifeq ($(HB_CMP),) + ifeq ($(HB_BUILD_MODE),cpp) + HB_CMP := g++ + else + HB_CMP := gcc + endif endif OBJ_EXT := .o LIB_PREF := lib LIB_EXT := .a +HB_DYN_COPT := -DHB_DYNLIB -fPIC + CC := $(HB_CCACHE) $(HB_CCPREFIX)$(HB_CMP)$(HB_CCPOSTFIX) CC_IN := -c CC_OUT := -o @@ -48,17 +52,6 @@ DFLAGS += -shared $(LIBPATHS) DY_OUT := -o$(subst x,x, ) DLIBS := $(foreach lib,$(HB_USER_LIBS) $(SYSLIBS),-l$(lib)) -# NOTE: The empty line directly before 'endef' HAVE TO exist! -define dynlib_object - @$(ECHO) $(ECHOQUOTE)INPUT($(subst \,/,$(file)))$(ECHOQUOTE) >> __dyn__.tmp - -endef -define create_dynlib - $(if $(wildcard __dyn__.tmp),@$(RM) __dyn__.tmp,) - $(foreach file,$^,$(dynlib_object)) - $(DY) $(DFLAGS) $(HB_USER_DFLAGS) $(DY_OUT)$(DYN_DIR)/$@ __dyn__.tmp $(DLIBS) $(DYSTRIP) -endef - -DY_RULE = $(create_dynlib) +DY_RULE = $(DY) $(DFLAGS) $(HB_USER_DFLAGS) $(DY_OUT)$(DYN_DIR)/$@ $^ $(DLIBS) $(DYSTRIP) && $(LN) $(@F) $(DYN_FILE2) include $(TOP)$(ROOT)config/rules.mk diff --git a/harbour/contrib/hbhttpd/tests/webapp.prg b/harbour/contrib/hbhttpd/tests/webapp.prg index 358063e3b4..33cd2f4b24 100644 --- a/harbour/contrib/hbhttpd/tests/webapp.prg +++ b/harbour/contrib/hbhttpd/tests/webapp.prg @@ -94,17 +94,17 @@ FUNCTION Main() aMap := {; - "login" => @proc_login(), ; - "logout" => @proc_logout(), ; - "register" => @proc_register(), ; - "account" => @proc_account(), ; - "account/edit" => @proc_account_edit(), ; - "main" => @proc_main(), ; - "shopping" => @proc_shopping(), ; - "cart" => @proc_cart() } + "login" => @proc_login(), ; + "logout" => @proc_logout(), ; + "register" => @proc_register(), ; + "account" => @proc_account(), ; + "account/edit" => @proc_account_edit(), ; + "main" => @proc_main(), ; + "shopping" => @proc_shopping(), ; + "cart" => @proc_cart() } oServer:aMount := {; - "/hello" => { {|| UWrite( "Hello!")}, .F. }, ; + "/hello" => { {|| UWrite( "Hello!" ) }, .F. }, ; "/info" => { {|| UProcInfo() }, .F. }, ; "/files/*" => { {|x| UProcFiles( hb_dirBase() + "files/" + x, .F. ) }, .F. }, ; "/app/*" => { {|x| UProcWidgets( x, aMap ) }, .T. }, ; diff --git a/harbour/contrib/hbmisc/hbmisc.hbp b/harbour/contrib/hbmisc/hbmisc.hbp index d571d2121b..037678fd47 100644 --- a/harbour/contrib/hbmisc/hbmisc.hbp +++ b/harbour/contrib/hbmisc/hbmisc.hbp @@ -28,3 +28,4 @@ numtxthu.prg numtxten.prg stringp.prg twirler.prg +udpds.prg diff --git a/harbour/contrib/hbmisc/tests/udpdstst.prg b/harbour/contrib/hbmisc/tests/udpdstst.prg new file mode 100644 index 0000000000..2d46461ed9 --- /dev/null +++ b/harbour/contrib/hbmisc/tests/udpdstst.prg @@ -0,0 +1,42 @@ +/* + * $Id$ + */ + +/* + * This module demonstrates a simple UDP Discovery Server + */ + +PROCEDURE main( cParam ) + + LOCAL h + + IF ! hb_MTVM() + ? "This sample should be compiled using MultiThread" + RETURN + ENDIF + + IF cParam == NIL + ? "udpdstst {c|s|cs}" + ? "Parameter:" + ? " s - run as a server" + ? " c - run as a client" + RETURN + ENDIF + + IF "S" $ Upper( cParam ) + IF ! Empty( h := hb_UDPDS_Start( 39999, "UDPDSDemo", NetName() + " " + hb_TSToStr( hb_DateTime() ) ) ) + hb_idleSleep( 0.1 ) + ENDIF + ENDIF + + IF "C" $ Upper( cParam ) + ? HB_VALTOEXP( hb_UDPDS_Find( 39999, "UDPDSDemo" ) ) + ENDIF + + IF "S" $ Upper( cParam ) + ? "Press any key to stop server" + Inkey( 0 ) + hb_UDPDS_Stop( h ) + ENDIF + + RETURN diff --git a/harbour/contrib/hbmisc/udpds.prg b/harbour/contrib/hbmisc/udpds.prg new file mode 100644 index 0000000000..0d4fa7ce61 --- /dev/null +++ b/harbour/contrib/hbmisc/udpds.prg @@ -0,0 +1,97 @@ +/* + * $Id$ + */ + +/* + * This module demonstrates a simple UDP Discovery Server + * + * If you run some service on the network (ex., netio) you need to + * know server IP address and configure client to connect to this + * address. UDPDS helps client to find server address (or addresses + * of multiple servers) on local network. UDPDS should be run in + * parallel to real server (ex., netio). Server part of UDPDS uses + * threads, so, it should be compiled in MT mode. + * + * Server functions: + * hb_UDPDS_Start( nPort, cName [, cVersion ] ) --> hServer + * hb_UDPDS_Stop( hServer ) + * + * Client function: + * hb_UDPDS_Find( nPort, cName ) --> { { "ip_addr_1", "version_1" }, ... } + * + */ + +#include "hbsocket.ch" + +/* Client */ + +FUNCTION hb_UDPDS_Find( nPort, cName ) + + LOCAL hSocket, aRet, nEnd, nTime, cBuffer, nLen, aAddr + + IF ! Empty( hSocket := hb_socketOpen( , HB_SOCKET_PT_DGRAM ) ) + hb_socketSetBroadcast( hSocket, .T. ) + IF hb_socketSendTo( hSocket, Chr( 5 ) + cName + Chr( 0 ), , , { HB_SOCKET_AF_INET, "255.255.255.255", nPort } ) == Len( cName ) + 2 + nTime := hb_milliseconds() + nEnd := nTime + 100 /* 100ms delay is enough on LAN */ + aRet := {} + DO WHILE nEnd > nTime + cBuffer := Space( 2000 ) + nLen := hb_socketRecvFrom( hSocket, @cBuffer, , , @aAddr, nEnd - nTime ) + IF Left( cBuffer, Len( cName ) + 2 ) == Chr( 6 ) + cName + Chr( 0 ) + AAdd( aRet, { aAddr[ 2 ], SubStr( cBuffer, Len( cName ) + 3, nLen - Len( cName ) - 2 ) } ) + ENDIF + nTime := hb_milliseconds() + ENDDO + ENDIF + hb_socketClose( hSocket ) + ENDIF + + RETURN aRet + +/* Server */ + +FUNCTION hb_UDPDS_Start( nPort, cName, cVersion ) + + LOCAL hSocket + + IF ! Empty( hSocket := hb_socketOpen( , HB_SOCKET_PT_DGRAM ) ) + IF hb_socketBind( hSocket, { HB_SOCKET_AF_INET, "0.0.0.0", nPort } ) + hb_threadDetach( hb_threadStart( @UDPDS(), hSocket, cName, cVersion ) ) + RETURN hSocket + ENDIF + hb_socketClose( hSocket ) + ENDIF + + RETURN NIL + +PROCEDURE hb_UDPDS_Stop( hSocket ) + + hb_socketClose( hSocket ) + + RETURN + +STATIC PROCEDURE UDPDS( hSocket, cName, cVersion ) + + LOCAL cBuffer, nLen, aAddr + + DO WHILE .T. + cBuffer := Space( 2000 ) + nLen := hb_socketRecvFrom( hSocket, @cBuffer, , , @aAddr, 1000 ) + IF nLen == - 1 + IF hb_socketGetError() != HB_SOCKET_ERR_TIMEOUT + RETURN + ENDIF + ELSE + /* + * Communication protocol: + * Broadcast request: ENQ, ServerName, NUL + * Server response: ACK, ServerName, NUL, Version + */ + IF Left( cBuffer, nLen ) == Chr( 5 ) + cName + Chr( 0 ) + hb_socketSendTo( hSocket, Chr( 6 ) + cName + Chr( 0 ) + iif( cVersion == NIL, "", cVersion ), , , aAddr ) + ENDIF + ENDIF + ENDDO + + RETURN diff --git a/harbour/contrib/hbqt/hbqt_common.hbc b/harbour/contrib/hbqt/hbqt_common.hbc index 78ece62848..2d094b7048 100644 --- a/harbour/contrib/hbqt/hbqt_common.hbc +++ b/harbour/contrib/hbqt/hbqt_common.hbc @@ -18,6 +18,7 @@ plugins=hbqt_hbmk2_plugin.hbs {allwin|os2}libpaths=${HB_WITH_QT}\..\lib -{allgcc}libs=supc++ +{allgcc&!bsd}libs=supc++ +{allgcc&bsd}libs=stdc++ {win|os2}hbcppmm=yes diff --git a/harbour/examples/udpds/udpds.hbp b/harbour/examples/udpds/udpds.hbp deleted file mode 100644 index 45dc4bf973..0000000000 --- a/harbour/examples/udpds/udpds.hbp +++ /dev/null @@ -1,6 +0,0 @@ -# -# $Id$ -# - -*.prg --mt diff --git a/harbour/examples/udpds/udpds.prg b/harbour/examples/udpds/udpds.prg deleted file mode 100644 index 62f28fcf91..0000000000 --- a/harbour/examples/udpds/udpds.prg +++ /dev/null @@ -1,127 +0,0 @@ -/* - * $Id$ - */ - -/* - * This module demonstrates a simple UDP Discovery Server - * - * If you run some service on the network (ex., netio) you need to - * know server IP address and configure client to connect to this - * address. UDPDS helps client to find server address (or addresses - * of multiple servers) on local network. UDPDS should be run in - * parallel to real server (ex., netio). Server part of UDPDS uses - * threads, so, it should be compiled in MT mode. - * - * Server functions: - * UDPDS_Start( nPort, cName [, cVersion ] ) --> hServer - * UDPDS_Stop( hServer ) - * - * Client function: - * UDPDS_Find( nPort, cName ) --> { {"ip_addr_1", "version_1"}, ... } - * - */ - -#include "hbsocket.ch" - -/* Test application */ - -PROC main( cParam ) -LOCAL h - - IF ! HB_MTVM() - ? "This sample should be compiled using MultiThread" - RETURN - ENDIF - - IF cParam == NIL - ? "udpds {c|s|cs}" - ? "Parameter:" - ? " s - run as a server" - ? " c - run as a client" - RETURN - ENDIF - - IF "S" $ UPPER( cParam ) - IF ! EMPTY( h := UDPDS_Start( 39999, "UDPDSDemo", NETNAME() + " " + HB_TSTOSTR(HB_DATETIME() ) ) ) - hb_idleSleep( 0.1 ) - ENDIF - ENDIF - - IF "C" $ UPPER( cParam ) - ? HB_VALTOEXP( UDPDS_Find( 39999, "UDPDSDemo" ) ) - ENDIF - - IF "S" $ UPPER( cParam ) - ? "Press any key to stop server" - INKEY(0) - UDPDS_Stop( h ) - ENDIF -RETURN - - -/* Client */ - -FUNC UDPDS_Find( nPort, cName ) -LOCAL hSocket, aRet, nEnd, nTime, cBuffer, nLen, aAddr - - IF ! EMPTY( hSocket := hb_socketOpen( , HB_SOCKET_PT_DGRAM ) ) - hb_socketSetBroadcast( hSocket, .T. ) - IF hb_socketSendTo( hSocket, CHR( 5 ) + cName + CHR( 0 ),,, { HB_SOCKET_AF_INET, "255.255.255.255", nPort } ) == LEN( cName ) + 2 - nTime := hb_milliseconds() - nEnd := nTime + 100 /* 100ms delay is enough on LAN */ - aRet := {} - DO WHILE nEnd > nTime - cBuffer := SPACE( 2000 ) - nLen := hb_socketRecvFrom( hSocket, @cBuffer,,, @aAddr, nEnd - nTime ) - IF LEFT( cBuffer, LEN( cName ) + 2 ) == CHR( 6 ) + cName + CHR( 0 ) - AADD( aRet, { aAddr[ 2 ], SUBSTR( cBuffer, LEN( cName ) + 3, nLen - LEN( cName ) - 2 ) } ) - ENDIF - nTime := hb_milliseconds() - ENDDO - ENDIF - hb_socketClose( hSocket ) - ENDIF -RETURN aRet - - -/* Server */ - -FUNC UDPDS_Start( nPort, cName, cVersion ) -LOCAL hSocket - IF ! EMPTY( hSocket := hb_socketOpen( , HB_SOCKET_PT_DGRAM ) ) - IF hb_socketBind( hSocket, { HB_SOCKET_AF_INET, "0.0.0.0", nPort } ) - hb_threadDetach( hb_threadStart( @UDPDS(), hSocket, cName, cVersion ) ) - RETURN hSocket - ENDIF - hb_socketClose( hSocket ) - ENDIF -RETURN NIL - - -PROC UDPDS_Stop( hSocket ) - hb_socketClose( hSocket ) -RETURN - - -STATIC PROC UDPDS( hSocket, cName, cVersion ) -LOCAL cBuffer, nLen, aAddr - DO WHILE .T. - cBuffer := SPACE( 2000 ) - nLen := hb_socketRecvFrom( hSocket, @cBuffer,,, @aAddr, 1000 ) - IF nLen == -1 - IF hb_socketGetError() != HB_SOCKET_ERR_TIMEOUT - RETURN - ENDIF - ELSE - /* - * Communication protocol: - * Broadcast request: ENQ, ServerName, NUL - * Server response: ACK, ServerName, NUL, Version - */ - IF LEFT( cBuffer, nLen ) == CHR( 5 ) + cName + CHR( 0 ) - hb_socketSendTo( hSocket, CHR( 6 ) + cName + CHR( 0 ) + IIF( cVersion == NIL, "", cVersion ),,, aAddr ) - ENDIF - ENDIF - ENDDO -RETURN - diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index b58e8fe2ba..19a39a64a8 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -1157,6 +1157,7 @@ extern HB_EXPORT const char * hb_verHB_COMP( void ); /* retrieves a stat extern HB_EXPORT HB_BOOL hb_iswin9x( void ); /* return HB_TRUE if OS == Windows 9x, ME */ extern HB_EXPORT HB_BOOL hb_iswinnt( void ); /* return HB_TRUE if OS == Windows NT or newer */ extern HB_EXPORT HB_BOOL hb_iswin2k( void ); /* return HB_TRUE if OS == Windows 2000 or newer */ +extern HB_EXPORT HB_BOOL hb_iswin2k3( void ); /* return HB_TRUE if OS == Windows 2003 Server or newer */ extern HB_EXPORT HB_BOOL hb_iswinvista( void ); /* return HB_TRUE if OS == Windows Vista or newer */ extern HB_EXPORT HB_BOOL hb_iswince( void ); /* return HB_TRUE if OS is Windows CE or Windows Mobile */ diff --git a/harbour/src/common/hbver.c b/harbour/src/common/hbver.c index 40898e141b..d4b1af93a8 100644 --- a/harbour/src/common/hbver.c +++ b/harbour/src/common/hbver.c @@ -470,6 +470,7 @@ char * hb_verPlatform( void ) static HB_BOOL s_fWinVerInit = HB_FALSE; static HB_BOOL s_fWinVista = HB_FALSE; +static HB_BOOL s_fWin2K3 = HB_FALSE; static HB_BOOL s_fWin2K = HB_FALSE; static HB_BOOL s_fWinNT = HB_FALSE; static HB_BOOL s_fWin9x = HB_FALSE; @@ -482,9 +483,22 @@ static void s_hb_winVerInit( void ) if( GetVersionEx( &osvi ) ) { s_fWinVista = osvi.dwMajorVersion >= 6; + s_fWin2K3 = s_fWinVista; s_fWin2K = osvi.dwMajorVersion >= 5; s_fWinNT = osvi.dwPlatformId == VER_PLATFORM_WIN32_NT; /* && osvi.dwMajorVersion >= 4); */ s_fWin9x = osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS; + +#if !defined( HB_OS_WIN_CE ) && !defined( __DMC__ ) && \ + ( !defined( _MSC_VER ) || _MSC_VER >= 1400 ) + + if( ! s_fWin2K3 && osvi.dwMajorVersion == 5 && osvi.dwMinorVersion >= 2 ) + { + OSVERSIONINFOEX osVerEx; + osVerEx.dwOSVersionInfoSize = sizeof( osVerEx ); + if( GetVersionEx( ( OSVERSIONINFO * ) &osVerEx ) ) + s_fWin2K3 = ( osVerEx.wProductType != VER_NT_WORKSTATION ); + } +#endif } s_fWinVerInit = HB_TRUE; } @@ -494,6 +508,7 @@ static void s_hb_winVerInit( void ) static HB_BOOL s_fWinVerInit = HB_FALSE; static HB_BOOL s_fWinVista = HB_FALSE; +static HB_BOOL s_fWin2K3 = HB_FALSE; static HB_BOOL s_fWin2K = HB_FALSE; static HB_BOOL s_fWinNT = HB_FALSE; static HB_BOOL s_fWin9x = HB_FALSE; @@ -504,6 +519,7 @@ static void s_hb_winVerInit( void ) /* TODO */ s_fWinVista = HB_FALSE; + s_fWin2K3 = s_fWinVista; s_fWin2K = HB_FALSE; /* Host OS detection: Windows NT family */ @@ -545,6 +561,17 @@ HB_BOOL hb_iswinvista( void ) #endif } +HB_BOOL hb_iswin2k3( void ) +{ +#if defined( HB_OS_WIN ) || defined( HB_OS_DOS ) + if( ! s_fWinVerInit ) + s_hb_winVerInit(); + return s_fWin2K3; +#else + return HB_FALSE; +#endif +} + HB_BOOL hb_iswin2k( void ) { #if defined( HB_OS_WIN ) || defined( HB_OS_DOS ) diff --git a/harbour/src/rtl/hbsocket.c b/harbour/src/rtl/hbsocket.c index 25e0e6a19f..e392a5a0ae 100644 --- a/harbour/src/rtl/hbsocket.c +++ b/harbour/src/rtl/hbsocket.c @@ -2432,6 +2432,8 @@ int hb_socketSetNoDelay( HB_SOCKET sd, HB_BOOL fNoDelay ) return ret; } +/* NOTE: For notes on Windows, see: + http://paste.lisp.org/display/59751 */ int hb_socketSetReuseAddr( HB_SOCKET sd, HB_BOOL fReuse ) { /* it allows to reuse port immediately without timeout used to