diff --git a/dtool/Config.FreeBSD.pp b/dtool/Config.FreeBSD.pp index a0870f19a2..001c01d9c7 100644 --- a/dtool/Config.FreeBSD.pp +++ b/dtool/Config.FreeBSD.pp @@ -162,9 +162,6 @@ #define PYTHON_IPATH /usr/local/include/python2.4 #define PYTHON_LPATH /usr/local/lib/python2.4 -#define NSPR_IPATH /usr/local/include/nspr -#define NSPR_LPATH /usr/local/lib/nspr - #define SSL_IPATH /usr/local/openssl //#define SSL_097 1 @@ -190,4 +187,3 @@ //#defer alt_ipath $[alt_ipath] /usr/local/include //#defer alt_lpath $[alt_lpath] /usr/local/lib -#defer NSPR_LIBS $[NSPR_LIBS] thr diff --git a/dtool/Config.Win32.pp b/dtool/Config.Win32.pp index 26f7d6e1c9..80164a41e1 100644 --- a/dtool/Config.Win32.pp +++ b/dtool/Config.Win32.pp @@ -20,7 +20,6 @@ // ******************************************************************* // What additional flags should we pass to interrogate? -// NSPR versions prior to 4.4 used _declspec instead of __declspec. #define SYSTEM_IGATE_FLAGS -longlong __int64 -D_X86_ -DWIN32_VC -D"_declspec(param)=" -D"__declspec(param)=" -D_near -D_far -D__near -D__far -D_WIN32 -D__stdcall -Dvolatile= // Additional flags to pass to the Tau instrumentor. diff --git a/dtool/Config.pp b/dtool/Config.pp index 12a4688b6d..bdb0a5b866 100644 --- a/dtool/Config.pp +++ b/dtool/Config.pp @@ -398,22 +398,17 @@ //#defer ALTERNATIVE_MALLOC $[or $[WINDOWS_PLATFORM],$[DO_MEMORY_USAGE],$[not $[HAVE_THREADS]]] #define ALTERNATIVE_MALLOC -// Is NSPR installed, and where? This is the Netscape Portable -// Runtime library, downloadable as part of the Mozilla package from -// mozilla.org. It provides portable threading and networking -// services to Panda. Panda should compile without it, although -// without any threading or networking capabilities; eventually, -// native support for these capabilities may be added for certain -// platforms. See also HAVE_IPC and HAVE_NET. -#define NSPR_IPATH /usr/include/nspr -#define NSPR_LPATH -#define NSPR_LIBS nspr4 -#defer HAVE_NSPR $[isfile $[NSPR_IPATH]/prtypes.h] - -// Define this true to build a native network implementation, -// which does not require NSPR. +// Define this true to build the low-level native network +// implementation. Normally this should be set true. #define WANT_NATIVE_NET 1 -#define NATIVE_NET_LIBS $[if $[WINDOWS_PLATFORM],Ws2_32.lib] +#define NATIVE_NET_IPATH +#define NATIVE_NET_LPATH +#define NATIVE_NET_LIBS $[if $[WINDOWS_PLATFORM],wsock32.lib] + +// Do you want to build the high-level network interface? This layers +// on top of the low-level native_net interface, specified above. +// Normally, if you build NATIVE_NET, you will also build NET. +#defer HAVE_NET $[WANT_NATIVE_NET] // Is a third-party STL library installed, and where? This is only // necessary if the default include and link lines that come with the @@ -683,9 +678,8 @@ // You should only turn this on if you have some threading library // available (most people will have one). Windows has one built-in. // Linux uses Posix threads, which most Linuxes provide. -// Alternatively, the NSPR library also provides a threading interface -// that Panda can use. #define HAVE_THREADS +#define THREADS_LIBS $[if $[not $[WINDOWS_PLATFORM]],pthread] // Whether threading is defined or not, you might want to validate the // thread and synchronization operations. With threading enabled, @@ -703,17 +697,6 @@ // than CPU's. Even then, OS-based locking is probably better. #define MUTEX_SPINLOCK -// Do you want to build the network interface? What additional libraries -// are required? Currently, this requires NSPR. -#define NET_IPATH -#define NET_LPATH -#if $[WINDOWS_PLATFORM] - #define NET_LIBS wsock32.lib -#else - #define NET_LIBS -#endif -#defer HAVE_NET $[HAVE_NSPR] - // Do you want to build the PStats interface, for graphical run-time // performance statistics? This requires NET to be available. By // default, we don't build PStats when OPTIMIZE = 4, although this is diff --git a/dtool/LocalSetup.pp b/dtool/LocalSetup.pp index 7da87a7d45..e7fbf83429 100644 --- a/dtool/LocalSetup.pp +++ b/dtool/LocalSetup.pp @@ -11,11 +11,6 @@ #print #print Configuring support for the following optional third-party packages: -#if $[HAVE_NSPR] -#print + NSPR -#else -#print - Did not find NSPR -#endif #if $[HAVE_OPENSSL] #print + OpenSSL #else @@ -181,9 +176,6 @@ $[cdefine MAYA_PRE_5_0] /* Define if we have SoftImage available. */ $[cdefine HAVE_SOFTIMAGE] -/* Define if we have NSPR installed. */ -$[cdefine HAVE_NSPR] - /* Define if we have OpenSSL installed. */ $[cdefine HAVE_OPENSSL] $[cdefine OPENSSL_097] diff --git a/dtool/Package.pp b/dtool/Package.pp index 71bf30627d..b4e42a32d9 100644 --- a/dtool/Package.pp +++ b/dtool/Package.pp @@ -108,10 +108,12 @@ #set PYTHON_FRAMEWORK $[unixfilename $[PYTHON_FRAMEWORK]] #set HAVE_PYTHON $[HAVE_PYTHON] -#set NSPR_IPATH $[unixfilename $[NSPR_IPATH]] -#set NSPR_LPATH $[unixfilename $[NSPR_LPATH]] -#set NSPR_LIBS $[NSPR_LIBS] -#set HAVE_NSPR $[HAVE_NSPR] +#set NATIVE_NET_IPATH $[unixfilename $[NATIVE_NET_IPATH]] +#set NATIVE_NET_LPATH $[unixfilename $[NATIVE_NET_LPATH]] +#set NATIVE_NET_LIBS $[NATIVE_NET_LIBS] +#set WANT_NATIVE_NET $[WANT_NATIVE_NET] + +#set HAVE_NET $[HAVE_NET] #set OPENSSL_IPATH $[unixfilename $[OPENSSL_IPATH]] #set OPENSSL_LPATH $[unixfilename $[OPENSSL_LPATH]] @@ -238,11 +240,6 @@ #set DEBUG_THREADS $[DEBUG_THREADS] #set MUTEX_SPINLOCK $[MUTEX_SPINLOCK] -#set NET_IPATH $[unixfilename $[NET_IPATH]] -#set NET_LPATH $[unixfilename $[NET_LPATH]] -#set NET_LIBS $[NET_LIBS] -#set HAVE_NET $[HAVE_NET] - #set DO_PSTATS $[DO_PSTATS] #set RAD_MSS_IPATH $[unixfilename $[RAD_MSS_IPATH]] diff --git a/dtool/pptempl/Global.pp b/dtool/pptempl/Global.pp index 866db5a965..d4ba7db098 100644 --- a/dtool/pptempl/Global.pp +++ b/dtool/pptempl/Global.pp @@ -97,12 +97,12 @@ #define python_framework $[PYTHON_FRAMEWORK] #endif -#if $[HAVE_NSPR] - #define nspr_ipath $[wildcard $[NSPR_IPATH]] - #define nspr_lpath $[wildcard $[NSPR_LPATH]] - #define nspr_cflags $[NSPR_CFLAGS] - #define nspr_libs $[NSPR_LIBS] - #define nspr_framework $[NSPR_FRAMEWORK] +#if $[HAVE_THREADS] + #define threads_ipath $[wildcard $[THREADS_IPATH]] + #define threads_lpath $[wildcard $[THREADS_LPATH]] + #define threads_cflags $[THREADS_CFLAGS] + #define threads_libs $[THREADS_LIBS] + #define threads_framework $[THREADS_FRAMEWORK] #endif #if $[HAVE_OPENSSL] @@ -458,8 +458,8 @@ // on the various external packages this particular target claims to // require. #defun get_cflags - // hack to add stl,nspr,python. should be removed - #define alt_cflags $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_cflags] $[nspr_cflags] $[python_cflags]] + // hack to add stl,python. should be removed + #define alt_cflags $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_cflags] $[python_cflags]] #foreach package $[use_packages] #set alt_cflags $[alt_cflags] $[$[package]_cflags] @@ -472,8 +472,8 @@ // on the various external packages this particular target claims to // require. #defun get_lflags - // hack to add stl,nspr,python. should be removed - #define alt_lflags $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_lflags] $[nspr_lflags] $[python_lflags]] + // hack to add stl,python. should be removed + #define alt_lflags $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_lflags] $[python_lflags]] #foreach package $[use_packages] #set alt_lflags $[alt_lflags] $[$[package]_lflags] @@ -487,8 +487,8 @@ // claims to require. This returns a space-separated set of directory // names only; the -I switch is not included here. #defun get_ipath - // hack to add stl,nspr,python. should be removed - #define alt_ipath $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_ipath] $[nspr_ipath] $[python_ipath]] + // hack to add stl,python. should be removed + #define alt_ipath $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_ipath] $[python_ipath]] #foreach package $[use_packages] #set alt_ipath $[alt_ipath] $[$[package]_ipath] @@ -502,7 +502,7 @@ // target claims to require. This returns a space-separated set of // directory names only; the -L switch is not included here. #defun get_lpath - #define alt_lpath $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_lpath] $[nspr_lpath] $[python_lpath]] + #define alt_lpath $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_lpath] $[python_lpath]] #if $[WINDOWS_PLATFORM] #set alt_lpath $[WIN32_PLATFORMSDK_LIBPATH] $[alt_lpath] @@ -520,7 +520,7 @@ // target claims to require. This returns a space-separated set of // directory names only; the -F switch is not included here. #defun get_fpath - #define alt_fpath $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_fpath] $[nspr_fpath] $[python_fpath]] + #define alt_fpath $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_fpath] $[python_fpath]] #foreach package $[use_packages] #set alt_fpath $[alt_fpath] $[$[package]_fpath] @@ -534,7 +534,7 @@ // target claims to require. This returns a space-separated set of // framework names only; the -framework switch is not included here. #defun get_frameworks - #define alt_frameworks $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_framework] $[nspr_framework] $[python_framework]] + #define alt_frameworks $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_framework] $[python_framework]] #if $[OSX_PLATFORM] #set alt_frameworks $[alt_frameworks] $[OSX_SYS_FRAMEWORKS] @@ -553,7 +553,7 @@ // space-separated set of library names only; the -l switch is not // included here. #defun get_libs - #define alt_libs $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_libs] $[nspr_libs] $[python_libs]] + #define alt_libs $[if $[IGNORE_LIB_DEFAULTS_HACK],,$[stl_libs] $[python_libs]] #define alt_libs $[alt_libs] $[EXTRA_LIBS] diff --git a/dtool/src/dtoolbase/Sources.pp b/dtool/src/dtoolbase/Sources.pp index fb06ab4023..c468d73c8d 100644 --- a/dtool/src/dtoolbase/Sources.pp +++ b/dtool/src/dtoolbase/Sources.pp @@ -1,4 +1,5 @@ #define SELECT_TAU select.tau +#define USE_PACKAGES threads #begin lib_target #define TARGET dtoolbase @@ -10,7 +11,6 @@ atomicAdjust.h \ atomicAdjustDummyImpl.h atomicAdjustDummyImpl.I \ atomicAdjustI386Impl.h atomicAdjustI386Impl.I \ - atomicAdjustNsprImpl.h atomicAdjustNsprImpl.I \ atomicAdjustPosixImpl.h atomicAdjustPosixImpl.I \ atomicAdjustWin32Impl.h atomicAdjustWin32Impl.I \ cmath.I cmath.h \ @@ -22,7 +22,6 @@ memoryBase.h \ mutexImpl.h \ mutexDummyImpl.h mutexDummyImpl.I \ - mutexNsprImpl.h mutexNsprImpl.I \ mutexLinuxImpl.h mutexLinuxImpl.I \ mutexPosixImpl.h mutexPosixImpl.I \ mutexWin32Impl.h mutexWin32Impl.I \ @@ -44,13 +43,11 @@ addHash.cxx \ atomicAdjustDummyImpl.cxx \ atomicAdjustI386Impl.cxx \ - atomicAdjustNsprImpl.cxx \ atomicAdjustPosixImpl.cxx \ atomicAdjustWin32Impl.cxx \ dtoolbase.cxx \ memoryBase.cxx \ mutexDummyImpl.cxx \ - mutexNsprImpl.cxx \ mutexLinuxImpl.cxx \ mutexPosixImpl.cxx \ mutexWin32Impl.cxx \ @@ -65,7 +62,6 @@ atomicAdjust.h \ atomicAdjustDummyImpl.h atomicAdjustDummyImpl.I \ atomicAdjustI386Impl.h atomicAdjustI386Impl.I \ - atomicAdjustNsprImpl.h atomicAdjustNsprImpl.I \ atomicAdjustPosixImpl.h atomicAdjustPosixImpl.I \ atomicAdjustWin32Impl.h atomicAdjustWin32Impl.I \ cmath.I cmath.h \ @@ -76,7 +72,6 @@ memoryBase.h \ mutexImpl.h \ mutexDummyImpl.h mutexDummyImpl.I \ - mutexNsprImpl.h mutexNsprImpl.I \ mutexLinuxImpl.h mutexLinuxImpl.I \ mutexPosixImpl.h mutexPosixImpl.I \ mutexWin32Impl.h mutexWin32Impl.I \ diff --git a/dtool/src/dtoolbase/atomicAdjust.h b/dtool/src/dtoolbase/atomicAdjust.h index b1ff44a937..06eed575bd 100644 --- a/dtool/src/dtoolbase/atomicAdjust.h +++ b/dtool/src/dtoolbase/atomicAdjust.h @@ -60,11 +60,6 @@ typedef AtomicAdjustWin32Impl AtomicAdjust; #include "atomicAdjustPosixImpl.h" typedef AtomicAdjustPosixImpl AtomicAdjust; -#elif defined(THREAD_NSPR_IMPL) - -#include "atomicAdjustNsprImpl.h" -typedef AtomicAdjustNsprImpl AtomicAdjust; - #endif #endif diff --git a/dtool/src/dtoolbase/atomicAdjustNsprImpl.I b/dtool/src/dtoolbase/atomicAdjustNsprImpl.I deleted file mode 100644 index 725f5dafe7..0000000000 --- a/dtool/src/dtoolbase/atomicAdjustNsprImpl.I +++ /dev/null @@ -1,140 +0,0 @@ -// Filename: atomicAdjustNsprImpl.I -// Created by: drose (09Aug02) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: AtomicAdjustNsprImpl::inc -// Access: Public, Static -// Description: Atomically increments the indicated variable. -//////////////////////////////////////////////////////////////////// -INLINE void AtomicAdjustNsprImpl:: -inc(TVOLATILE PN_int32 &var) { - PR_AtomicIncrement((PRInt32 *)&var); -} - -//////////////////////////////////////////////////////////////////// -// Function: AtomicAdjustNsprImpl::dec -// Access: Public, Static -// Description: Atomically decrements the indicated variable and -// returns true if the new value is nonzero, false if it -// is zero. -//////////////////////////////////////////////////////////////////// -INLINE bool AtomicAdjustNsprImpl:: -dec(TVOLATILE PN_int32 &var) { - return (PR_AtomicDecrement((PRInt32 *)&var) != 0); -} - -//////////////////////////////////////////////////////////////////// -// Function: AtomicAdjustNsprImpl::set -// Access: Public, Static -// Description: Atomically changes the indicated variable and -// returns the original value. -//////////////////////////////////////////////////////////////////// -INLINE PN_int32 AtomicAdjustNsprImpl:: -set(TVOLATILE PN_int32 &var, PN_int32 new_value) { - return PR_AtomicSet((PRInt32 *)&var, new_value); -} - -//////////////////////////////////////////////////////////////////// -// Function: AtomicAdjustNsprImpl::get -// Access: Public, Static -// Description: Atomically retrieves the snapshot value of the -// indicated variable. This is the only guaranteed safe -// way to retrieve the value that other threads might be -// asynchronously setting, incrementing, or decrementing -// (via other AtomicAjust methods). -//////////////////////////////////////////////////////////////////// -INLINE PN_int32 AtomicAdjustNsprImpl:: -get(const TVOLATILE PN_int32 &var) { - return var; -} - -//////////////////////////////////////////////////////////////////// -// Function: AtomicAdjustNsprImpl::set_ptr -// Access: Public, Static -// Description: Atomically changes the indicated variable and -// returns the original value. -//////////////////////////////////////////////////////////////////// -INLINE void *AtomicAdjustNsprImpl:: -set_ptr(void * TVOLATILE &var, void *new_value) { - return (void *)PR_AtomicSet((PRInt32 *)&var, (PRInt32)new_value); -} - -//////////////////////////////////////////////////////////////////// -// Function: AtomicAdjustNsprImpl::get_ptr -// Access: Public, Static -// Description: Atomically retrieves the snapshot value of the -// indicated variable. This is the only guaranteed safe -// way to retrieve the value that other threads might be -// asynchronously setting, incrementing, or decrementing -// (via other AtomicAjust methods). -//////////////////////////////////////////////////////////////////// -INLINE void *AtomicAdjustNsprImpl:: -get_ptr(void * const TVOLATILE &var) { - return var; -} - -//////////////////////////////////////////////////////////////////// -// Function: AtomicAdjustNsprImpl::compare_and_exchange -// Access: Public, Static -// Description: Atomic compare and exchange. -// -// If mem is equal to old_value, store new_value in mem. -// In either case, return the original value of mem. -// The caller can test for success by comparing -// return_value == old_value. -// -// The atomic function expressed in pseudo-code: -// -// orig_value = mem; -// if (mem == old_value) { -// mem = new_value; -// } -// return orig_value; -// -//////////////////////////////////////////////////////////////////// -INLINE PN_int32 AtomicAdjustNsprImpl:: -compare_and_exchange(TVOLATILE PN_int32 &mem, PN_int32 old_value, - PN_int32 new_value) { - PR_Lock(_mutex); - PN_int32 orig_value = mem; - if (mem == old_value) { - mem = new_value; - } - PR_Unlock(_mutex); - return orig_value; -} - -//////////////////////////////////////////////////////////////////// -// Function: AtomicAdjustNsprImpl::compare_and_exchange_ptr -// Access: Public, Static -// Description: Atomic compare and exchange. -// -// As above, but works on pointers instead of integers. -//////////////////////////////////////////////////////////////////// -INLINE void *AtomicAdjustNsprImpl:: -compare_and_exchange_ptr(void * TVOLATILE &mem, void *old_value, - void *new_value) { - PR_Lock(_mutex); - void *orig_value = mem; - if (mem == old_value) { - mem = new_value; - } - PR_Unlock(_mutex); - return orig_value; -} diff --git a/dtool/src/dtoolbase/atomicAdjustNsprImpl.h b/dtool/src/dtoolbase/atomicAdjustNsprImpl.h deleted file mode 100644 index 56dacdc90f..0000000000 --- a/dtool/src/dtoolbase/atomicAdjustNsprImpl.h +++ /dev/null @@ -1,62 +0,0 @@ -// Filename: atomicAdjustNsprImpl.h -// Created by: drose (09Aug02) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef ATOMICADJUSTNSPRIMPL_H -#define ATOMICADJUSTNSPRIMPL_H - -#include "dtoolbase.h" -#include "selectThreadImpl.h" - -#ifdef HAVE_NSPR - -#include "numeric_types.h" - -#include -#include - -//////////////////////////////////////////////////////////////////// -// Class : AtomicAdjustNsprImpl -// Description : Uses NSPR to implement atomic adjustments. -//////////////////////////////////////////////////////////////////// -class EXPCL_DTOOL AtomicAdjustNsprImpl { -public: - INLINE static void inc(TVOLATILE PN_int32 &var); - INLINE static bool dec(TVOLATILE PN_int32 &var); - INLINE static PN_int32 set(TVOLATILE PN_int32 &var, PN_int32 new_value); - INLINE static PN_int32 get(const TVOLATILE PN_int32 &var); - - INLINE static void *set_ptr(void * TVOLATILE &var, void *new_value); - INLINE static void *get_ptr(void * const TVOLATILE &var); - - INLINE static PN_int32 compare_and_exchange(TVOLATILE PN_int32 &mem, - PN_int32 old_value, - PN_int32 new_value); - - INLINE static void *compare_and_exchange_ptr(void * TVOLATILE &mem, - void *old_value, - void *new_value); - -private: - static PRLock *_mutex; -}; - -#include "atomicAdjustNsprImpl.I" - -#endif // HAVE_NSPR - -#endif diff --git a/dtool/src/dtoolbase/dtoolbase_composite1.cxx b/dtool/src/dtoolbase/dtoolbase_composite1.cxx index 225d6f5163..b7650059ab 100644 --- a/dtool/src/dtoolbase/dtoolbase_composite1.cxx +++ b/dtool/src/dtoolbase/dtoolbase_composite1.cxx @@ -1,7 +1,6 @@ #include "addHash.cxx" #include "atomicAdjustDummyImpl.cxx" #include "atomicAdjustI386Impl.cxx" -#include "atomicAdjustNsprImpl.cxx" #include "atomicAdjustPosixImpl.cxx" #include "atomicAdjustWin32Impl.cxx" #include "dtoolbase.cxx" diff --git a/dtool/src/dtoolbase/dtoolbase_composite2.cxx b/dtool/src/dtoolbase/dtoolbase_composite2.cxx index b22b54018c..23b746c82f 100644 --- a/dtool/src/dtoolbase/dtoolbase_composite2.cxx +++ b/dtool/src/dtoolbase/dtoolbase_composite2.cxx @@ -1,5 +1,4 @@ #include "mutexDummyImpl.cxx" -#include "mutexNsprImpl.cxx" #include "mutexLinuxImpl.cxx" #include "mutexPosixImpl.cxx" #include "mutexWin32Impl.cxx" diff --git a/dtool/src/dtoolbase/mutexImpl.h b/dtool/src/dtoolbase/mutexImpl.h index 6b2f1624c5..4e4df9fb2c 100644 --- a/dtool/src/dtoolbase/mutexImpl.h +++ b/dtool/src/dtoolbase/mutexImpl.h @@ -55,13 +55,6 @@ typedef MutexPosixImpl MutexImpl; typedef ReMutexPosixImpl ReMutexImpl; #define HAVE_REMUTEXIMPL 1 -#elif defined(THREAD_NSPR_IMPL) - -#include "mutexNsprImpl.h" -typedef MutexNsprImpl MutexImpl; -typedef ReMutexNsprImpl ReMutexImpl; -#define HAVE_REMUTEXIMPL 1 - #endif #endif diff --git a/dtool/src/dtoolbase/mutexNsprImpl.I b/dtool/src/dtoolbase/mutexNsprImpl.I deleted file mode 100644 index de3589af84..0000000000 --- a/dtool/src/dtoolbase/mutexNsprImpl.I +++ /dev/null @@ -1,126 +0,0 @@ -// Filename: mutexNsprImpl.I -// Created by: drose (08Aug02) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: MutexNsprImpl::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE MutexNsprImpl:: -MutexNsprImpl() { - _lock = PR_NewLock(); - assert(_lock != (PRLock *)NULL); -} - -//////////////////////////////////////////////////////////////////// -// Function: MutexNsprImpl::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE MutexNsprImpl:: -~MutexNsprImpl() { - PR_DestroyLock(_lock); -} - -//////////////////////////////////////////////////////////////////// -// Function: MutexNsprImpl::lock -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void MutexNsprImpl:: -lock() { - PR_Lock(_lock); -} - -//////////////////////////////////////////////////////////////////// -// Function: MutexNsprImpl::try_lock -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE bool MutexNsprImpl:: -try_lock() { - // NSPR doesn't define a try_lock function. Too bad. We just - // report that it would always block (since we don't know). - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: MutexNsprImpl::release -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void MutexNsprImpl:: -release() { - int status = PR_Unlock(_lock); - assert(status == PR_SUCCESS); -} - -//////////////////////////////////////////////////////////////////// -// Function: ReMutexNsprImpl::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE ReMutexNsprImpl:: -ReMutexNsprImpl() { - _monitor = PR_NewMonitor(); - assert(_monitor != (PRMonitor *)NULL); -} - -//////////////////////////////////////////////////////////////////// -// Function: ReMutexNsprImpl::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE ReMutexNsprImpl:: -~ReMutexNsprImpl() { - PR_DestroyMonitor(_monitor); -} - -//////////////////////////////////////////////////////////////////// -// Function: ReMutexNsprImpl::lock -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void ReMutexNsprImpl:: -lock() { - PR_EnterMonitor(_monitor); -} - -//////////////////////////////////////////////////////////////////// -// Function: ReMutexNsprImpl::try_lock -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE bool ReMutexNsprImpl:: -try_lock() { - // NSPR doesn't define a try_lock function. Too bad. We just - // report that it would always block (since we don't know). - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: ReMutexNsprImpl::release -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void ReMutexNsprImpl:: -release() { - int status = PR_ExitMonitor(_monitor); - assert(status == PR_SUCCESS); -} diff --git a/dtool/src/dtoolbase/mutexNsprImpl.h b/dtool/src/dtoolbase/mutexNsprImpl.h deleted file mode 100644 index e692c4e7a8..0000000000 --- a/dtool/src/dtoolbase/mutexNsprImpl.h +++ /dev/null @@ -1,70 +0,0 @@ -// Filename: mutexNsprImpl.h -// Created by: drose (08Aug02) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef MUTEXNSPRIMPL_H -#define MUTEXNSPRIMPL_H - -#include "dtoolbase.h" -#include "selectThreadImpl.h" - -#ifdef HAVE_NSPR - -#include -#include -#include - -//////////////////////////////////////////////////////////////////// -// Class : MutexNsprImpl -// Description : Uses NSPR to implement a mutex. -//////////////////////////////////////////////////////////////////// -class EXPCL_DTOOL MutexNsprImpl { -public: - INLINE MutexNsprImpl(); - INLINE ~MutexNsprImpl(); - - INLINE void lock(); - INLINE bool try_lock(); - INLINE void release(); - -private: - PRLock *_lock; - friend class ConditionVarNsprImpl; -}; - -//////////////////////////////////////////////////////////////////// -// Class : ReMutexNsprImpl -// Description : Uses NSPR to implement a reMutex. -//////////////////////////////////////////////////////////////////// -class EXPCL_DTOOL ReMutexNsprImpl { -public: - INLINE ReMutexNsprImpl(); - INLINE ~ReMutexNsprImpl(); - - INLINE void lock(); - INLINE bool try_lock(); - INLINE void release(); - -private: - PRMonitor *_monitor; -}; - -#include "mutexNsprImpl.I" - -#endif // HAVE_NSPR - -#endif diff --git a/dtool/src/dtoolbase/numeric_types.h b/dtool/src/dtoolbase/numeric_types.h index cb489ea51f..48c60eed65 100644 --- a/dtool/src/dtoolbase/numeric_types.h +++ b/dtool/src/dtoolbase/numeric_types.h @@ -25,34 +25,7 @@ // the various numeric types for unsigned and signed numbers of // various widths. -// At the present, we use the logic in NSPR to determine this for us. -// Later (especially for non-NSPR platforms) we'll have to do the work -// ourselves. - - -#ifdef HAVE_NSPR - -#include - -typedef PRInt8 PN_int8; -typedef PRInt16 PN_int16; -typedef PRInt32 PN_int32; -typedef PRInt64 PN_int64; - -typedef PRUint8 PN_uint8; -typedef PRUint16 PN_uint16; -typedef PRUint32 PN_uint32; -typedef PRUint64 PN_uint64; - -typedef PRFloat64 PN_float64; - -// NSPR doesn't define a float32. -typedef float PN_float32; - -#else // HAVE_NSPR - -// Without NSPR, and without any other information, we need some -// fallback. For now, we'll just assume a typical environment. +// For now, we'll just assume a typical 32-bit environment. typedef signed char PN_int8; typedef short PN_int16; @@ -73,8 +46,6 @@ typedef unsigned long long PN_uint64; typedef double PN_float64; typedef float PN_float32; -#endif // HAVE_NSPR - #endif diff --git a/dtool/src/dtoolbase/selectThreadImpl.h b/dtool/src/dtoolbase/selectThreadImpl.h index 629b768895..8b02dd8da5 100644 --- a/dtool/src/dtoolbase/selectThreadImpl.h +++ b/dtool/src/dtoolbase/selectThreadImpl.h @@ -64,11 +64,6 @@ // Posix threads are nice. #define THREAD_POSIX_IMPL 1 -#elif defined(HAVE_NSPR) - -// If NSPR is available, use that. -#define THREAD_NSPR_IMPL 1 - #else // This is a configuration error. For some reason, HAVE_THREADS is diff --git a/dtool/src/parser-inc/Sources.pp b/dtool/src/parser-inc/Sources.pp index cc03ca290e..851bda3780 100644 --- a/dtool/src/parser-inc/Sources.pp +++ b/dtool/src/parser-inc/Sources.pp @@ -3,7 +3,9 @@ pair pthread.h queue set stack stdcompare.h stdtypedefs.h \ string vector windows.h winsock2.h zlib.h files.h hex.h \ md5.h evp.h bits/pthreadtypes.h \ - openssl/md5.h openssl/evp.h openssl/rand.h openssl/ssl.h openssl/x509.h openssl/err.h \ + openssl/md5.h openssl/evp.h openssl/rand.h openssl/ssl.h \ + openssl/x509.h openssl/err.h openssl/rsa.h openssl/crypto.h \ + openssl/pem.h \ nurbs.hh stddef.h krb5.h MainHelix.h dllpath.h hxcom.h \ hxcomm.h hxcore.h hxengin.h hxerror.h hxfiles.h hxtbuf.h \ hxtbuff.h hxwin.h Python.h Cg/cg.h Cg/cgGL.h \ diff --git a/dtool/src/parser-inc/crypto.h b/dtool/src/parser-inc/crypto.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dtool/src/parser-inc/pem.h b/dtool/src/parser-inc/pem.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dtool/src/parser-inc/rsa.h b/dtool/src/parser-inc/rsa.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dtool/src/parser-inc/ssl.h b/dtool/src/parser-inc/ssl.h index 9e4fef7e1e..a816856362 100644 --- a/dtool/src/parser-inc/ssl.h +++ b/dtool/src/parser-inc/ssl.h @@ -9,5 +9,6 @@ struct EVP_PKEY; struct X509; struct X509_STORE; struct X509_NAME; +struct SSL; #endif diff --git a/panda/src/express/Sources.pp b/panda/src/express/Sources.pp index e4ad3107ba..57a07ac75f 100644 --- a/panda/src/express/Sources.pp +++ b/panda/src/express/Sources.pp @@ -4,7 +4,7 @@ #begin lib_target #define TARGET express - #define USE_PACKAGES nspr net zlib openssl + #define USE_PACKAGES zlib openssl #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx diff --git a/panda/src/nativenet/Sources.pp b/panda/src/nativenet/Sources.pp index 5f24bf7faf..9d3076210f 100644 --- a/panda/src/nativenet/Sources.pp +++ b/panda/src/nativenet/Sources.pp @@ -5,7 +5,7 @@ dtoolutil:c dtoolbase:c prc:c dtool:m #define BUILD_DIRECTORY $[WANT_NATIVE_NET] -#define USE_PACKAGES native_net +#define USE_PACKAGES native_net openssl #begin lib_target #define TARGET nativenet @@ -19,12 +19,22 @@ socket_tcp_listen.h time_accumulator.h time_out.h \ socket_address.h \ socket_portable.h time_base.h time_span.h buffered_datagramwriter.h \ - socket_base.h socket_selector.h socket_udp_incoming.h time_clock.h \ + socket_base.h socket_selector.h \ + socket_udp.h \ + socket_udp_incoming.h time_clock.h \ membuffer.h membuffer.i socket_fdset.h socket_tcp.h \ socket_udp_outgoing.h time_general.h - #define INCLUDED_SOURCES \ + buffered_datagramconnection.cxx \ + config_nativenet.cxx \ + socket_ip.cxx \ + socket_tcp.cxx \ + socket_tcp_listen.cxx \ + socket_tcp_ssl.cxx \ + socket_udp.cxx \ + socket_udp_incoming.cxx \ + socket_udp_outgoing.cxx #define INSTALL_HEADERS \ buffered_datagramconnection.h \ @@ -33,7 +43,9 @@ buffered_datagramreader.h buffered_datagramreader.i \ socket_address.h \ socket_portable.h time_base.h time_span.h buffered_datagramwriter.h \ - socket_base.h socket_selector.h socket_udp_incoming.h time_clock.h \ + socket_base.h socket_selector.h \ + socket_udp.h \ + socket_udp_incoming.h time_clock.h \ membuffer.h membuffer.i socket_fdset.h socket_tcp.h \ socket_udp_outgoing.h time_general.h diff --git a/panda/src/nativenet/buffered_datagramconnection.cxx b/panda/src/nativenet/buffered_datagramconnection.cxx new file mode 100644 index 0000000000..2caec75ded --- /dev/null +++ b/panda/src/nativenet/buffered_datagramconnection.cxx @@ -0,0 +1,21 @@ +// Filename: buffered_datagramconnection.cxx +// Created by: drose (05Mar07) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "buffered_datagramconnection.h" + +TypeHandle Buffered_DatagramConnection::_type_handle; diff --git a/panda/src/nativenet/buffered_datagramconnection.h b/panda/src/nativenet/buffered_datagramconnection.h index 5b555d0a70..645178a4d0 100755 --- a/panda/src/nativenet/buffered_datagramconnection.h +++ b/panda/src/nativenet/buffered_datagramconnection.h @@ -26,7 +26,7 @@ // 3. Socket is open and writable.. ( Fully powered up )... // /////////////////////////////////////////////////////////////// -class EXPCL_PANDA Buffered_DatagramConnection : protected Socket_TCP +class EXPCL_PANDA Buffered_DatagramConnection : public Socket_TCP { private: struct AddressQueue : private pvector // this is used to do a round robin for addres to connect to .. @@ -89,7 +89,24 @@ private: friend class Buffered_DatagramReader; friend class Buffered_DatagramWriter; +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + Socket_IP::init_type(); + register_type(_type_handle, "Buffered_DatagramConnection", + Socket_IP::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; }; + //////////////////////////////////////////////////////////////////// // Function name : Buffered_DatagramConnection::ClearAll // Description : used to do a full reset of buffers diff --git a/panda/src/nativenet/config_nativenet.cxx b/panda/src/nativenet/config_nativenet.cxx new file mode 100644 index 0000000000..e594af8a6b --- /dev/null +++ b/panda/src/nativenet/config_nativenet.cxx @@ -0,0 +1,72 @@ +// Filename: config_nativenet.cxx +// Created by: drose (01Mar07) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "config_nativenet.h" + +#include "socket_ip.h" +#include "socket_tcp.h" +#include "socket_tcp_listen.h" +#include "socket_tcp_ssl.h" +#include "socket_udp_incoming.h" +#include "socket_udp_outgoing.h" +#include "socket_udp.h" +#include "socket_portable.h" +#include "buffered_datagramconnection.h" +#include "pandaSystem.h" + +#include "dconfig.h" + +Configure(config_nativenet); +NotifyCategoryDef(nativenet, ""); + +ConfigureFn(config_nativenet) { + init_libnativenet(); +} + + +//////////////////////////////////////////////////////////////////// +// Function: init_libnativenet +// Description: Initializes the library. This must be called at +// least once before any of the functions or classes in +// this library can be used. Normally it will be +// called by the static initializers and need not be +// called explicitly, but special cases exist. +//////////////////////////////////////////////////////////////////// +void +init_libnativenet() { + static bool initialized = false; + if (initialized) { + return; + } + initialized = true; + + Socket_IP::init_type(); + Socket_TCP::init_type(); + Socket_TCP_Listen::init_type(); + Socket_TCP_SSL::init_type(); + Socket_UDP_Incoming::init_type(); + Socket_UDP_Outgoing::init_type(); + Socket_UDP::init_type(); + Buffered_DatagramConnection::init_type(); + + PandaSystem *ps = PandaSystem::get_global_ptr(); + ps->add_system("nativenet"); + + init_network(); +} + diff --git a/panda/src/nativenet/config_nativenet.h b/panda/src/nativenet/config_nativenet.h new file mode 100644 index 0000000000..d12b2c1edc --- /dev/null +++ b/panda/src/nativenet/config_nativenet.h @@ -0,0 +1,32 @@ +// Filename: config_nativenet.h +// Created by: drose (01Mar07) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef CONFIG_NATIVENET_H +#define CONFIG_NATIVENET_H + +#include "pandabase.h" +#include "notifyCategoryProxy.h" + +// Configure variables for nativenet package. + +NotifyCategoryDecl(nativenet, EXPCL_PANDA, EXPTP_PANDA); + +extern EXPCL_PANDA void init_libnativenet(); + +#endif + diff --git a/panda/src/nativenet/nativenet_composite1.cxx b/panda/src/nativenet/nativenet_composite1.cxx index 7fd12c492b..2c20529336 100755 --- a/panda/src/nativenet/nativenet_composite1.cxx +++ b/panda/src/nativenet/nativenet_composite1.cxx @@ -1,3 +1,9 @@ -#include "socket_base.h" - - +#include "buffered_datagramconnection.cxx" +#include "config_nativenet.cxx" +#include "socket_ip.cxx" +#include "socket_tcp.cxx" +#include "socket_tcp_listen.cxx" +#include "socket_tcp_ssl.cxx" +#include "socket_udp.cxx" +#include "socket_udp_incoming.cxx" +#include "socket_udp_outgoing.cxx" diff --git a/panda/src/nativenet/socket_address.h b/panda/src/nativenet/socket_address.h index f2546be516..02ee91e65a 100755 --- a/panda/src/nativenet/socket_address.h +++ b/panda/src/nativenet/socket_address.h @@ -3,6 +3,7 @@ #include "pandabase.h" #include "numeric_types.h" +#include "socket_portable.h" /////////////////////////////////// // Class : Socket_Address diff --git a/panda/src/nativenet/socket_fdset.h b/panda/src/nativenet/socket_fdset.h index eaaf28998c..7a1f7469be 100755 --- a/panda/src/nativenet/socket_fdset.h +++ b/panda/src/nativenet/socket_fdset.h @@ -14,6 +14,7 @@ #include "pandabase.h" #include "numeric_types.h" #include "time_base.h" +#include "socket_ip.h" class Socket_fdset { diff --git a/dtool/src/dtoolbase/mutexNsprImpl.cxx b/panda/src/nativenet/socket_ip.cxx similarity index 79% rename from dtool/src/dtoolbase/mutexNsprImpl.cxx rename to panda/src/nativenet/socket_ip.cxx index cbed5b2bcd..b98dd90678 100644 --- a/dtool/src/dtoolbase/mutexNsprImpl.cxx +++ b/panda/src/nativenet/socket_ip.cxx @@ -1,5 +1,5 @@ -// Filename: mutexNsprImpl.cxx -// Created by: drose (09Aug02) +// Filename: socket_ip.cxx +// Created by: drose (01Mar07) // //////////////////////////////////////////////////////////////////// // @@ -16,10 +16,6 @@ // //////////////////////////////////////////////////////////////////// -#include "selectThreadImpl.h" +#include "socket_ip.h" -#ifdef HAVE_NSPR - -#include "mutexNsprImpl.h" - -#endif // HAVE_NSPR +TypeHandle Socket_IP::_type_handle; diff --git a/panda/src/nativenet/socket_ip.h b/panda/src/nativenet/socket_ip.h index 241319d254..2593bffa3a 100755 --- a/panda/src/nativenet/socket_ip.h +++ b/panda/src/nativenet/socket_ip.h @@ -1,6 +1,11 @@ #ifndef __SOCKET_IP_H__ #define __SOCKET_IP_H__ +#include "pandabase.h" +#include "socket_portable.h" +#include "socket_address.h" +#include "typedObject.h" + // forward declarations for friends... class Socket_TCP; class Socket_UDP; @@ -26,8 +31,7 @@ class Socket_UDP_Outgoing; // socket_fdset // ///////////////////////////////////////////////////////////////////// -class EXPCL_PANDA Socket_IP -{ +class EXPCL_PANDA Socket_IP : public TypedObject { public: PUBLISHED: @@ -39,7 +43,7 @@ PUBLISHED: inline static int GetLastError(); inline int SetNonBlocking(); inline int SetBlocking(); - inline bool SetReuseAddress(); + inline bool SetReuseAddress(bool flag = true); inline bool Active(); inline int SetRecvBufferSize(int size); inline void SetSocket(SOCKET ins); @@ -62,6 +66,23 @@ private: friend class Socket_UDP_Incoming; friend class Socket_UDP_Outgoing; friend class Socket_TCP_SSL; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedObject::init_type(); + register_type(_type_handle, "Socket_IP", + TypedObject::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; }; //////////////////////////////////////////////////////////////////// @@ -204,9 +225,9 @@ inline int Socket_IP::SetBlocking() // Function name : SetReuseAddress // Description : Informs a socket to reuse IP address as needed //////////////////////////////////////////////////////////////////// -inline bool Socket_IP::SetReuseAddress() +inline bool Socket_IP::SetReuseAddress(bool flag) { - int bOption = 1; + int bOption = flag; if (setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&bOption, sizeof(bOption)) != 0) return false; return true; diff --git a/panda/src/net/pprerror.h b/panda/src/nativenet/socket_tcp.cxx similarity index 78% rename from panda/src/net/pprerror.h rename to panda/src/nativenet/socket_tcp.cxx index 3ea29c9c33..bb0e7564f0 100644 --- a/panda/src/net/pprerror.h +++ b/panda/src/nativenet/socket_tcp.cxx @@ -1,5 +1,5 @@ -// Filename: pprerror.h -// Created by: drose (08Feb00) +// Filename: socket_tcp.cxx +// Created by: drose (01Mar07) // //////////////////////////////////////////////////////////////////// // @@ -16,12 +16,6 @@ // //////////////////////////////////////////////////////////////////// -#ifndef PPRERROR_H -#define PPRERROR_H - -#include "pandabase.h" - -void pprerror(const char *format, ...); - -#endif +#include "socket_tcp.h" +TypeHandle Socket_TCP::_type_handle; diff --git a/panda/src/nativenet/socket_tcp.h b/panda/src/nativenet/socket_tcp.h index f982902093..20a9be6e7f 100755 --- a/panda/src/nativenet/socket_tcp.h +++ b/panda/src/nativenet/socket_tcp.h @@ -1,6 +1,9 @@ #ifndef __SOCKET_TCP_H__ #define __SOCKET_TCP_H__ +#include "pandabase.h" +#include "socket_ip.h" + ///////////////////////////////////////////////////////////////////// // Class : Socket_TCP // @@ -15,7 +18,7 @@ public: PUBLISHED: inline Socket_TCP(SOCKET); inline Socket_TCP() { }; - inline int SetNoDelay(); + inline int SetNoDelay(bool flag = true); inline int SetLinger(int interval_seconds = 0); inline int DontLinger(); inline int SetSendBufferSize(int insize); @@ -30,6 +33,23 @@ PUBLISHED: public: inline int SendData(const char * data, int size); inline int RecvData(char * data, int size); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + Socket_IP::init_type(); + register_type(_type_handle, "Socket_TCP", + Socket_IP::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; }; ////////////////////////////////////////////////////////////// @@ -44,9 +64,9 @@ inline Socket_TCP::Socket_TCP(SOCKET sck) : ::Socket_IP(sck) // Function name : SetNoDelay // Description : Disable Nagle algorithm. Don't delay send to coalesce packets //////////////////////////////////////////////////////////////////// -inline int Socket_TCP::SetNoDelay() +inline int Socket_TCP::SetNoDelay(bool flag) { - int nodel = 1; + int nodel = flag; int ret1; ret1 = setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char *) & nodel, sizeof(nodel)); diff --git a/panda/src/nativenet/socket_tcp_listen.cxx b/panda/src/nativenet/socket_tcp_listen.cxx new file mode 100644 index 0000000000..361ddcd523 --- /dev/null +++ b/panda/src/nativenet/socket_tcp_listen.cxx @@ -0,0 +1,21 @@ +// Filename: socket_tcp_listen.cxx +// Created by: drose (01Mar07) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "socket_tcp_listen.h" + +TypeHandle Socket_TCP_Listen::_type_handle; diff --git a/panda/src/nativenet/socket_tcp_listen.h b/panda/src/nativenet/socket_tcp_listen.h index a18f207720..293be0cbba 100755 --- a/panda/src/nativenet/socket_tcp_listen.h +++ b/panda/src/nativenet/socket_tcp_listen.h @@ -1,6 +1,9 @@ #ifndef __SOCKET_TCP_LISTEN_H__ #define __SOCKET_TCP_LISTEN_H__ +#include "pandabase.h" +#include "socket_ip.h" + ///////////////////////////////////////////////////////////////////// // Class : Socket_TCP_Listen // Description : Base functionality for a TCP rendezvous socket @@ -11,29 +14,48 @@ public: PUBLISHED: Socket_TCP_Listen() {}; ~Socket_TCP_Listen() {}; - inline bool OpenForListen(Socket_Address & Inaddess, int backlog_size = 1024); + inline bool OpenForListen(const Socket_Address & Inaddess, int backlog_size = 1024); inline bool GetIncomingConnection(Socket_TCP & newsession, Socket_Address &address); public: inline bool GetIncomingConnection(SOCKET & newsession, Socket_Address &address); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + Socket_IP::init_type(); + register_type(_type_handle, "Socket_TCP_Listen", + Socket_IP::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; }; //////////////////////////////////////////////////////////////////// // Function name : OpenForListen // Description : This function will initialize a listening Socket //////////////////////////////////////////////////////////////////// -inline bool Socket_TCP_Listen::OpenForListen(Socket_Address & Inaddess, int backlog_size ) +inline bool Socket_TCP_Listen::OpenForListen(const Socket_Address & Inaddess, int backlog_size ) { ErrorClose(); _socket = DO_NEWTCP(); SetReuseAddress(); - if (DO_BIND(_socket, &Inaddess.GetAddressInfo()) != 0) - return ErrorClose(); - - if (DO_LISTEN(_socket, backlog_size) != 0) - return ErrorClose(); + if (DO_BIND(_socket, &Inaddess.GetAddressInfo()) != 0) { + return ErrorClose(); + } + if (DO_LISTEN(_socket, backlog_size) != 0) { + return ErrorClose(); + } + return true; } //////////////////////////////////////////////////////////////////// diff --git a/dtool/src/dtoolbase/atomicAdjustNsprImpl.cxx b/panda/src/nativenet/socket_tcp_ssl.cxx similarity index 73% rename from dtool/src/dtoolbase/atomicAdjustNsprImpl.cxx rename to panda/src/nativenet/socket_tcp_ssl.cxx index 2791690031..315b99bccf 100644 --- a/dtool/src/dtoolbase/atomicAdjustNsprImpl.cxx +++ b/panda/src/nativenet/socket_tcp_ssl.cxx @@ -1,5 +1,5 @@ -// Filename: atomicAdjustNsprImpl.cxx -// Created by: drose (09Aug02) +// Filename: socket_tcp_ssl.cxx +// Created by: drose (01Mar07) // //////////////////////////////////////////////////////////////////// // @@ -16,12 +16,11 @@ // //////////////////////////////////////////////////////////////////// -#include "selectThreadImpl.h" +#include "socket_tcp_ssl.h" -#ifdef HAVE_NSPR +#ifdef HAVE_OPENSSL -#include "atomicAdjustNsprImpl.h" +SSL_CTX *global_ssl_ctx; +TypeHandle Socket_TCP_SSL::_type_handle; -PRLock *AtomicAdjustNsprImpl::_mutex = PR_NewLock(); - -#endif // HAVE_NSPR +#endif // HAVE_OPENSSL diff --git a/panda/src/nativenet/socket_tcp_ssl.h b/panda/src/nativenet/socket_tcp_ssl.h index 5b9460289a..323c5dda5e 100755 --- a/panda/src/nativenet/socket_tcp_ssl.h +++ b/panda/src/nativenet/socket_tcp_ssl.h @@ -1,17 +1,12 @@ #ifndef __SOCKET_TCP_SSL_H__ #define __SOCKET_TCP_SSL_H__ -///////////////////////////////////////////////////////////////////// -// Class : Socket_TCP -// -// Description : Base functionality for a TCP connected socket -// This class is pretty useless by itself but it does hide some of the -// platform differences from machine to machine -// -///////////////////////////////////////////////////////////////////// #include "pandabase.h" +#include "socket_ip.h" #include "numeric_types.h" +#ifdef HAVE_OPENSSL + #include /* SSLeay stuff */ #include #include @@ -19,9 +14,14 @@ #include #include +///////////////////////////////////////////////////////////////////// +// Class : Socket_TCP_SSL +// +// Description : +// +///////////////////////////////////////////////////////////////////// - -extern SSL_CTX *global_ssl_ctx; +extern EXPCL_PANDA SSL_CTX *global_ssl_ctx; struct SSlStartup @@ -47,7 +47,7 @@ struct SSlStartup }; -class Socket_TCP_SSL : public Socket_IP +class EXPCL_PANDA Socket_TCP_SSL : public Socket_IP { public: @@ -84,6 +84,23 @@ private: _ssl = NULL; } } + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + Socket_IP::init_type(); + register_type(_type_handle, "Socket_TCP_SSL", + Socket_IP::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; }; ////////////////////////////////////////////////////////////// @@ -101,7 +118,7 @@ inline Socket_TCP_SSL::Socket_TCP_SSL(SOCKET sck) : ::Socket_IP(sck) return; SSL_set_fd (_ssl,(int)GetSocket() ); - int err = SSL_accept(_ssl); + SSL_accept(_ssl); ERR_clear_error(); // printf(" Ssl Accept = %d \n",err); @@ -244,7 +261,9 @@ inline bool Socket_TCP_SSL::ErrorIs_WouldBlocking(int err) { if(_ssl == NULL || err >= 0) { - LOGWARNING("Socket_TCP_SSL::ErrorIs_WouldBlocking->Called With Error numebr %d or _ssl is NULL",err); + nativenet_cat.warning() + << "Socket_TCP_SSL::ErrorIs_WouldBlocking->Called With Error number " + << err << " or _ssl is NULL\n"; return false; } @@ -296,9 +315,13 @@ inline void Socket_TCP_SSL::DetailErrorFormat(void) { ERR_error_string_n(l, buf, sizeof( buf) ); BIO_snprintf(buf2, sizeof(buf2), "***%lu:%s:%s:%d:%s\n", es, buf,file, line, (flags & ERR_TXT_STRING) ? data : "NoText"); - LOGWARNING("Socket_TCP_SSL::DetailErrorFormat->[%s]",buf2); + nativenet_cat.warning() + << "Socket_TCP_SSL::DetailErrorFormat->[" << buf2 << "]\n"; } } + +#endif // HAVE_OPENSSL + #endif //__SOCKET_TCP_SSL_H__ diff --git a/panda/src/nativenet/socket_udp.cxx b/panda/src/nativenet/socket_udp.cxx new file mode 100644 index 0000000000..bb68b3b9bb --- /dev/null +++ b/panda/src/nativenet/socket_udp.cxx @@ -0,0 +1,21 @@ +// Filename: socket_udp.cxx +// Created by: drose (01Mar07) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "socket_udp.h" + +TypeHandle Socket_UDP::_type_handle; diff --git a/panda/src/nativenet/socket_udp.h b/panda/src/nativenet/socket_udp.h new file mode 100644 index 0000000000..7ad2edb5ba --- /dev/null +++ b/panda/src/nativenet/socket_udp.h @@ -0,0 +1,169 @@ +// Filename: socket_udp.h +// Created by: drose (01Mar07) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef __SOCKET_UDP_H__ +#define __SOCKET_UDP_H__ + +#include "socket_udp_incoming.h" + +///////////////////////////////////////////////////////////////////// +// Class : Socket_UDP +// +// Description : Base functionality for a combination UDP Reader and +// Writer. This duplicates code from +// Socket_UDP_Outgoing, to avoid the problems of +// multiple inheritance. +///////////////////////////////////////////////////////////////////// +class EXPCL_PANDA Socket_UDP : public Socket_UDP_Incoming +{ +public: +PUBLISHED: + inline Socket_UDP() { } + + // use this interface for a tagreted UDP connection + inline bool InitToAddress(const Socket_Address & address); +public: + inline bool Send(const char * data, int len); +PUBLISHED: + inline bool Send(const string &data); + // use this interface for a none tagreted UDP connection + inline bool InitNoAddress(); +public: + inline bool SendTo(const char * data, int len, const Socket_Address & address); +PUBLISHED: + inline bool SendTo(const string &data, const Socket_Address & address); + inline bool SetToBroadCast(); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + Socket_UDP_Incoming::init_type(); + register_type(_type_handle, "Socket_UDP", + Socket_UDP_Incoming::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; +////////////////////////////////////////////////////////////// +// Function name : Socket_UDP:SetToBroadCast +// Description : Ask the OS to let us receive BROADCASt packets on this port.. +// Return type : bool +// Argument : void +////////////////////////////////////////////////////////////// +inline bool Socket_UDP::SetToBroadCast() +{ + int optval = 1; + + if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) + return false; + return true; +} +//////////////////////////////////////////////////////////////////// +// Function name : Socket_UDP::InitToAddress +// Description : Connects the Socket to a Specified address +// +// Return type : inline bool +// Argument : NetAddress & address +//////////////////////////////////////////////////////////////////// +inline bool Socket_UDP::InitToAddress(const Socket_Address & address) +{ + if (InitNoAddress() != true) + return false; + + if (DO_CONNECT(_socket, &address.GetAddressInfo()) != 0) + return ErrorClose(); + + return true; +} +//////////////////////////////////////////////////////////////////// +// Function name : Socket_UDP::InitNoAddress +// Description : This will set a udp up for targeted sends.. +// +// Return type : inline bool +// Argument : void +//////////////////////////////////////////////////////////////////// +inline bool Socket_UDP::InitNoAddress() +{ + Close(); + _socket = DO_NEWUDP(); + if (_socket == BAD_SOCKET) + return false; + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function name : Socket_UDP::Send +// Description : Send data to connected address +// +// Return type : inline bool +// Argument : char * data +// Argument : int len +//////////////////////////////////////////////////////////////////// +inline bool Socket_UDP::Send(const char * data, int len) +{ + return (DO_SOCKET_WRITE(_socket, data, len) == len); +} + +//////////////////////////////////////////////////////////////////// +// Function name : Socket_UDP::Send +// Description : Send data to connected address +// +// Return type : inline bool +// Argument : const string &data +//////////////////////////////////////////////////////////////////// +inline bool Socket_UDP::Send(const string &data) +{ + return Send(data.data(), data.size()); +} + +//////////////////////////////////////////////////////////////////// +// Function name : Socket_UDP::SendTo +// Description : Send data to specified address +// +// Return type : inline bool +// Argument : char * data +// Argument : int len +// Argument : NetAddress & address +//////////////////////////////////////////////////////////////////// +inline bool Socket_UDP::SendTo(const char * data, int len, const Socket_Address & address) +{ + return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len); +} + +//////////////////////////////////////////////////////////////////// +// Function name : Socket_UDP::SendTo +// Description : Send data to specified address +// +// Return type : inline bool +// Argument : const string &data +// Argument : NetAddress & address +//////////////////////////////////////////////////////////////////// +inline bool Socket_UDP::SendTo(const string &data, const Socket_Address & address) +{ + return SendTo(data.data(), data.size(), address); +} + +#endif //__SOCKET_UDP_H__ diff --git a/panda/src/nativenet/socket_udp_incoming.cxx b/panda/src/nativenet/socket_udp_incoming.cxx new file mode 100644 index 0000000000..826e67360c --- /dev/null +++ b/panda/src/nativenet/socket_udp_incoming.cxx @@ -0,0 +1,21 @@ +// Filename: socket_udp_incoming.cxx +// Created by: drose (01Mar07) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "socket_udp_incoming.h" + +TypeHandle Socket_UDP_Incoming::_type_handle; diff --git a/panda/src/nativenet/socket_udp_incoming.h b/panda/src/nativenet/socket_udp_incoming.h index f50a857019..61919c5662 100755 --- a/panda/src/nativenet/socket_udp_incoming.h +++ b/panda/src/nativenet/socket_udp_incoming.h @@ -1,5 +1,9 @@ #ifndef __SOCKET_UDP_INCOMING_H__ #define __SOCKET_UDP_INCOMING_H__ + +#include "pandabase.h" +#include "socket_ip.h" + ///////////////////////////////////////////////////////////////////// // Class : Socket_UDP_Incoming // @@ -7,17 +11,36 @@ // // ///////////////////////////////////////////////////////////////////// -class Socket_UDP_Incoming : public Socket_IP +class EXPCL_PANDA Socket_UDP_Incoming : public Socket_IP { -public: PUBLISHED: - inline bool OpenForInput(Socket_Address & address); - inline bool OpenForInputMCast(Socket_Address & address ); + inline Socket_UDP_Incoming() { } + + inline bool OpenForInput(const Socket_Address & address); + inline bool OpenForInputMCast(const Socket_Address & address ); inline bool GetPacket(char * data, int *max_len, Socket_Address & address); inline bool SendTo(const char * data, int len, const Socket_Address & address); inline bool InitNoAddress(); inline bool SetToBroadCast(); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + Socket_IP::init_type(); + register_type(_type_handle, "Socket_UDP_Incoming", + Socket_IP::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; }; + ////////////////////////////////////////////////////////////// // Function name : Socket_UDP_Incoming::tToBroadCast // Description : Flips the OS bits that allow for brodcast @@ -57,7 +80,7 @@ inline bool Socket_UDP_Incoming::InitNoAddress() // Return type : bool // Argument : NetAddress & address //////////////////////////////////////////////////////////////////// -inline bool Socket_UDP_Incoming::OpenForInput(Socket_Address & address) +inline bool Socket_UDP_Incoming::OpenForInput(const Socket_Address & address) { Close(); _socket = DO_NEWUDP(); @@ -77,7 +100,7 @@ inline bool Socket_UDP_Incoming::OpenForInput(Socket_Address & address) // Return type : bool // Argument : NetAddress & address //////////////////////////////////////////////////////////////////// -inline bool Socket_UDP_Incoming::OpenForInputMCast(Socket_Address & address) +inline bool Socket_UDP_Incoming::OpenForInputMCast(const Socket_Address & address) { Close(); _socket = DO_NEWUDP(); diff --git a/panda/src/nativenet/socket_udp_outgoing.cxx b/panda/src/nativenet/socket_udp_outgoing.cxx new file mode 100644 index 0000000000..d7e4244bf9 --- /dev/null +++ b/panda/src/nativenet/socket_udp_outgoing.cxx @@ -0,0 +1,21 @@ +// Filename: socket_udp_outgoing.cxx +// Created by: drose (01Mar07) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "socket_udp_outgoing.h" + +TypeHandle Socket_UDP_Outgoing::_type_handle; diff --git a/panda/src/nativenet/socket_udp_outgoing.h b/panda/src/nativenet/socket_udp_outgoing.h index 9ec86c8e23..6c267b8b9f 100755 --- a/panda/src/nativenet/socket_udp_outgoing.h +++ b/panda/src/nativenet/socket_udp_outgoing.h @@ -15,7 +15,7 @@ PUBLISHED: inline Socket_UDP_Outgoing() { } // use this interface for a tagreted UDP connection - inline bool InitToAddress(Socket_Address & address); + inline bool InitToAddress(const Socket_Address & address); public: inline bool Send(const char * data, int len); PUBLISHED: @@ -27,6 +27,23 @@ public: PUBLISHED: inline bool SendTo(const string &data, const Socket_Address & address); inline bool SetToBroadCast(); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + Socket_IP::init_type(); + register_type(_type_handle, "Socket_UDP_Outgoing", + Socket_IP::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; }; ////////////////////////////////////////////////////////////// // Function name : Socket_UDP_Outgoing:SetToBroadCast @@ -49,7 +66,7 @@ inline bool Socket_UDP_Outgoing::SetToBroadCast() // Return type : inline bool // Argument : NetAddress & address //////////////////////////////////////////////////////////////////// -inline bool Socket_UDP_Outgoing::InitToAddress(Socket_Address & address) +inline bool Socket_UDP_Outgoing::InitToAddress(const Socket_Address & address) { if (InitNoAddress() != true) return false; diff --git a/panda/src/net/Sources.pp b/panda/src/net/Sources.pp index a59170da4d..e11f9a8405 100644 --- a/panda/src/net/Sources.pp +++ b/panda/src/net/Sources.pp @@ -1,13 +1,13 @@ #define OTHER_LIBS \ interrogatedb:c dconfig:c dtoolconfig:m \ dtoolutil:c dtoolbase:c prc:c dtool:m -#define BUILD_DIRECTORY $[and $[HAVE_NET],$[HAVE_NSPR]] -#define USE_PACKAGES net nspr +#define BUILD_DIRECTORY $[and $[HAVE_NET],$[WANT_NATIVE_NET]] +#define USE_PACKAGES net #begin lib_target #define TARGET net #define LOCAL_LIBS \ - express pandabase + express pandabase nativenet pipeline #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx @@ -18,7 +18,7 @@ datagramTCPHeader.I datagramTCPHeader.h \ datagramUDPHeader.I datagramUDPHeader.h \ netAddress.h netDatagram.I netDatagram.h \ - pprerror.h queuedConnectionListener.I \ + queuedConnectionListener.I \ queuedConnectionListener.h queuedConnectionManager.h \ queuedConnectionReader.h recentConnectionReader.h \ queuedReturn.h queuedReturn.I @@ -28,7 +28,7 @@ connectionManager.cxx connectionReader.cxx \ connectionWriter.cxx datagramQueue.cxx datagramTCPHeader.cxx \ datagramUDPHeader.cxx netAddress.cxx netDatagram.cxx \ - pprerror.cxx queuedConnectionListener.cxx \ + queuedConnectionListener.cxx \ queuedConnectionManager.cxx queuedConnectionReader.cxx \ recentConnectionReader.cxx @@ -38,7 +38,7 @@ datagramTCPHeader.I datagramTCPHeader.h \ datagramUDPHeader.I datagramUDPHeader.h \ netAddress.h netDatagram.I \ - netDatagram.h pprerror.h queuedConnectionListener.I \ + netDatagram.h queuedConnectionListener.I \ queuedConnectionListener.h queuedConnectionManager.h \ queuedConnectionReader.h queuedReturn.I queuedReturn.h \ recentConnectionReader.h @@ -59,7 +59,7 @@ #begin test_bin_target #define TARGET test_spam_client - #define LOCAL_LIBS net + #define LOCAL_LIBS net putil #define OTHER_LIBS $[OTHER_LIBS] pystub #define SOURCES \ @@ -69,7 +69,7 @@ #begin test_bin_target #define TARGET test_spam_server - #define LOCAL_LIBS net + #define LOCAL_LIBS net putil #define OTHER_LIBS $[OTHER_LIBS] pystub #define SOURCES \ diff --git a/panda/src/net/connection.cxx b/panda/src/net/connection.cxx index cc4b3c80b3..180bd08ad0 100644 --- a/panda/src/net/connection.cxx +++ b/panda/src/net/connection.cxx @@ -21,11 +21,15 @@ #include "netDatagram.h" #include "datagramTCPHeader.h" #include "datagramUDPHeader.h" -#include "pprerror.h" #include "config_net.h" #include "config_express.h" // for collect_tcp #include "trueClock.h" #include "pnotify.h" +#include "mutexHolder.h" +#include "socket_ip.h" +#include "socket_tcp.h" +#include "socket_udp.h" +#include "dcast.h" //////////////////////////////////////////////////////////////////// @@ -37,11 +41,10 @@ // connection. //////////////////////////////////////////////////////////////////// Connection:: -Connection(ConnectionManager *manager, PRFileDesc *socket) : +Connection(ConnectionManager *manager, Socket_IP *socket) : _manager(manager), _socket(socket) { - _write_mutex = PR_NewLock(); _collect_tcp = collect_tcp; _collect_tcp_interval = collect_tcp_interval; _queued_data_start = 0.0; @@ -58,16 +61,12 @@ Connection:: net_cat.info() << "Deleting connection " << (void *)this << "\n"; - if (_socket != (PRFileDesc *)NULL) { + if (_socket != (Socket_IP *)NULL) { flush(); - PRStatus result = PR_Close(_socket); - if (result != PR_SUCCESS) { - pprerror("PR_Close"); - } + _socket->Close(); + delete _socket; } - - PR_DestroyLock(_write_mutex); } //////////////////////////////////////////////////////////////////// @@ -78,11 +77,7 @@ Connection:: //////////////////////////////////////////////////////////////////// NetAddress Connection:: get_address() const { - PRNetAddr addr; - if (PR_GetSockName(_socket, &addr) != PR_SUCCESS) { - pprerror("PR_GetSockName"); - } - + Socket_Address addr = _socket->GetPeerName(); return NetAddress(addr); } @@ -100,10 +95,10 @@ get_manager() const { //////////////////////////////////////////////////////////////////// // Function: Connection::get_socket // Access: Published -// Description: Returns the internal NSPR pointer that defines the +// Description: Returns the internal Socket_IP that defines the // connection. //////////////////////////////////////////////////////////////////// -PRFileDesc *Connection:: +Socket_IP *Connection:: get_socket() const { return _socket; } @@ -182,7 +177,7 @@ get_collect_tcp_interval() const { //////////////////////////////////////////////////////////////////// bool Connection:: consider_flush() { - PR_Lock(_write_mutex); + MutexHolder holder(_write_mutex); if (!_collect_tcp) { return do_flush(); @@ -197,7 +192,6 @@ consider_flush() { } } - PR_Unlock(_write_mutex); return true; } @@ -210,7 +204,7 @@ consider_flush() { //////////////////////////////////////////////////////////////////// bool Connection:: flush() { - PR_Lock(_write_mutex); + MutexHolder holder(_write_mutex); return do_flush(); } @@ -221,10 +215,11 @@ flush() { //////////////////////////////////////////////////////////////////// void Connection:: set_nonblock(bool flag) { - PRSocketOptionData data; - data.option = PR_SockOpt_Nonblocking; - data.value.non_blocking = flag; - PR_SetSocketOption(_socket, &data); + if (flag) { + _socket->SetNonBlocking(); + } else { + _socket->SetBlocking(); + } } //////////////////////////////////////////////////////////////////// @@ -241,11 +236,14 @@ set_nonblock(bool flag) { //////////////////////////////////////////////////////////////////// void Connection:: set_linger(bool flag, double time) { - PRSocketOptionData data; - data.option = PR_SockOpt_Linger; - data.value.linger.polarity = flag; - data.value.linger.linger = PRIntervalTime(time * PR_INTERVAL_MIN); - PR_SetSocketOption(_socket, &data); + Socket_TCP *tcp; + DCAST_INTO_V(tcp, _socket); + + if (flag) { + tcp->SetLinger((int)time); + } else { + tcp->DontLinger(); + } } //////////////////////////////////////////////////////////////////// @@ -255,10 +253,7 @@ set_linger(bool flag, double time) { //////////////////////////////////////////////////////////////////// void Connection:: set_reuse_addr(bool flag) { - PRSocketOptionData data; - data.option = PR_SockOpt_Reuseaddr; - data.value.reuse_addr = flag; - PR_SetSocketOption(_socket, &data); + _socket->SetReuseAddress(flag); } //////////////////////////////////////////////////////////////////// @@ -269,10 +264,7 @@ set_reuse_addr(bool flag) { //////////////////////////////////////////////////////////////////// void Connection:: set_keep_alive(bool flag) { - PRSocketOptionData data; - data.option = PR_SockOpt_Keepalive; - data.value.keep_alive = flag; - PR_SetSocketOption(_socket, &data); + // TODO. } //////////////////////////////////////////////////////////////////// @@ -282,10 +274,7 @@ set_keep_alive(bool flag) { //////////////////////////////////////////////////////////////////// void Connection:: set_recv_buffer_size(int size) { - PRSocketOptionData data; - data.option = PR_SockOpt_RecvBufferSize; - data.value.recv_buffer_size = size; - PR_SetSocketOption(_socket, &data); + _socket->SetRecvBufferSize(size); } //////////////////////////////////////////////////////////////////// @@ -295,10 +284,10 @@ set_recv_buffer_size(int size) { //////////////////////////////////////////////////////////////////// void Connection:: set_send_buffer_size(int size) { - PRSocketOptionData data; - data.option = PR_SockOpt_SendBufferSize; - data.value.send_buffer_size = size; - PR_SetSocketOption(_socket, &data); + Socket_TCP *tcp; + DCAST_INTO_V(tcp, _socket); + + tcp->SetSendBufferSize(size); } //////////////////////////////////////////////////////////////////// @@ -308,10 +297,7 @@ set_send_buffer_size(int size) { //////////////////////////////////////////////////////////////////// void Connection:: set_ip_time_to_live(int ttl) { - PRSocketOptionData data; - data.option = PR_SockOpt_IpTimeToLive; - data.value.ip_ttl = ttl; - PR_SetSocketOption(_socket, &data); + // TODO. } //////////////////////////////////////////////////////////////////// @@ -321,10 +307,7 @@ set_ip_time_to_live(int ttl) { //////////////////////////////////////////////////////////////////// void Connection:: set_ip_type_of_service(int tos) { - PRSocketOptionData data; - data.option = PR_SockOpt_IpTypeOfService; - data.value.tos = tos; - PR_SetSocketOption(_socket, &data); + // TODO. } //////////////////////////////////////////////////////////////////// @@ -335,10 +318,10 @@ set_ip_type_of_service(int tos) { //////////////////////////////////////////////////////////////////// void Connection:: set_no_delay(bool flag) { - PRSocketOptionData data; - data.option = PR_SockOpt_NoDelay; - data.value.no_delay = flag; - PR_SetSocketOption(_socket, &data); + Socket_TCP *tcp; + DCAST_INTO_V(tcp, _socket); + + tcp->SetNoDelay(flag); } //////////////////////////////////////////////////////////////////// @@ -348,10 +331,7 @@ set_no_delay(bool flag) { //////////////////////////////////////////////////////////////////// void Connection:: set_max_segment(int size) { - PRSocketOptionData data; - data.option = PR_SockOpt_MaxSegment; - data.value.max_segment = size; - PR_SetSocketOption(_socket, &data); + // TODO. } //////////////////////////////////////////////////////////////////// @@ -365,37 +345,34 @@ set_max_segment(int size) { //////////////////////////////////////////////////////////////////// bool Connection:: send_datagram(const NetDatagram &datagram, int tcp_header_size) { - nassertr(_socket != (PRFileDesc *)NULL, false); + nassertr(_socket != (Socket_IP *)NULL, false); - if (PR_GetDescType(_socket) == PR_DESC_SOCKET_UDP) { + if (_socket->is_exact_type(Socket_UDP::get_class_type())) { // We have to send UDP right away. - PR_Lock(_write_mutex); + Socket_UDP *udp; + DCAST_INTO_R(udp, _socket, false); + + MutexHolder holder(_write_mutex); DatagramUDPHeader header(datagram); string data; data += header.get_header(); data += datagram.get_message(); - - PRInt32 bytes_to_send = data.length(); - PRInt32 result; - result = PR_SendTo(_socket, - data.data(), bytes_to_send, - 0, - datagram.get_address().get_addr(), - PR_INTERVAL_NO_TIMEOUT); - PRErrorCode errcode = PR_GetError(); - + + int bytes_to_send = data.length(); + bool okflag = udp->SendTo(data, datagram.get_address().get_addr()); + if (net_cat.is_debug()) { header.verify_datagram(datagram); } - + if (net_cat.is_spam()) { net_cat.spam() << "Sending UDP datagram with " - << bytes_to_send << " bytes to " << (void *)this << "\n"; + << bytes_to_send << " bytes to " << (void *)this + << ", ok = " << okflag << "\n"; } - - PR_Unlock(_write_mutex); - return check_send_error(result, errcode, bytes_to_send); + + return check_send_error(okflag); } // We might queue up TCP packets for later sending. @@ -409,7 +386,7 @@ send_datagram(const NetDatagram &datagram, int tcp_header_size) { DatagramTCPHeader header(datagram, tcp_header_size); - PR_Lock(_write_mutex); + MutexHolder holder(_write_mutex); _queued_data += header.get_header(); _queued_data += datagram.get_message(); _queued_count++; @@ -423,7 +400,6 @@ send_datagram(const NetDatagram &datagram, int tcp_header_size) { return do_flush(); } - PR_Unlock(_write_mutex); return true; } @@ -436,36 +412,30 @@ send_datagram(const NetDatagram &datagram, int tcp_header_size) { //////////////////////////////////////////////////////////////////// bool Connection:: send_raw_datagram(const NetDatagram &datagram) { - nassertr(_socket != (PRFileDesc *)NULL, false); + nassertr(_socket != (Socket_IP *)NULL, false); - if (PR_GetDescType(_socket) == PR_DESC_SOCKET_UDP) { + if (_socket->is_exact_type(Socket_UDP::get_class_type())) { // We have to send UDP right away. + Socket_UDP *udp; + DCAST_INTO_R(udp, _socket, false); string data = datagram.get_message(); - PRInt32 bytes_to_send = data.length(); + MutexHolder holder(_write_mutex); + bool okflag = udp->SendTo(data, datagram.get_address().get_addr()); + if (net_cat.is_spam()) { net_cat.spam() << "Sending UDP datagram with " - << bytes_to_send << " bytes to " << (void *)this << "\n"; + << data.size() << " bytes to " << (void *)this + << ", ok = " << okflag << "\n"; } - PR_Lock(_write_mutex); - PRInt32 result; - result = PR_SendTo(_socket, - data.data(), bytes_to_send, - 0, - datagram.get_address().get_addr(), - PR_INTERVAL_NO_TIMEOUT); - PRErrorCode errcode = PR_GetError(); - - PR_Unlock(_write_mutex); - return check_send_error(result, errcode, bytes_to_send); + return check_send_error(okflag); } // We might queue up TCP packets for later sending. - - PR_Lock(_write_mutex); + MutexHolder holder(_write_mutex); _queued_data += datagram.get_message(); _queued_count++; @@ -474,7 +444,6 @@ send_raw_datagram(const NetDatagram &datagram) { return do_flush(); } - PR_Unlock(_write_mutex); return true; } @@ -482,70 +451,48 @@ send_raw_datagram(const NetDatagram &datagram) { // Function: Connection::do_flush // Access: Private // Description: The private implementation of flush(), this assumes -// the _write_mutex has already been locked on entry. -// It will be unlocked on return. +// the _write_mutex is already held. //////////////////////////////////////////////////////////////////// bool Connection:: do_flush() { - PRInt32 bytes_to_send = _queued_data.length(); - if (bytes_to_send == 0) { + if (_queued_data.empty()) { _queued_count = 0; _queued_data_start = TrueClock::get_global_ptr()->get_short_time(); - PR_Unlock(_write_mutex); return true; } if (net_cat.is_spam()) { net_cat.spam() << "Sending " << _queued_count << " TCP datagram(s) with " - << bytes_to_send << " total bytes to " << (void *)this << "\n"; + << _queued_data.length() << " total bytes to " << (void *)this << "\n"; } - PRInt32 result; - result = PR_Send(_socket, - _queued_data.data(), bytes_to_send, - 0, - PR_INTERVAL_NO_TIMEOUT); - PRErrorCode errcode = PR_GetError(); + Socket_TCP *tcp; + DCAST_INTO_R(tcp, _socket, false); + + bool okflag = (tcp->SendData(_queued_data) == _queued_data.size()); _queued_data = string(); _queued_count = 0; _queued_data_start = TrueClock::get_global_ptr()->get_short_time(); - PR_Unlock(_write_mutex); - - return check_send_error(result, errcode, bytes_to_send); + return check_send_error(okflag); } //////////////////////////////////////////////////////////////////// // Function: Connection::check_send_error // Access: Private -// Description: Checks the return value of a PR_Send() or PR_SendTo() +// Description: Checks the return value of a Send() or SendTo() // call. //////////////////////////////////////////////////////////////////// bool Connection:: -check_send_error(PRInt32 result, PRErrorCode errcode, PRInt32 bytes_to_send) { - if (result < 0) { - if (errcode == PR_CONNECT_RESET_ERROR -#ifdef PR_SOCKET_SHUTDOWN_ERROR - || errcode == PR_SOCKET_SHUTDOWN_ERROR - || errcode == PR_CONNECT_ABORTED_ERROR -#endif - ) { - // The connection has been reset; tell our manager about it - // and ignore it. - if (_manager != (ConnectionManager *)NULL) { - _manager->connection_reset(this, errcode); - } - - } else if (errcode != PR_PENDING_INTERRUPT_ERROR) { - pprerror("PR_SendTo"); +check_send_error(bool okflag) { + if (!okflag) { + // Assume any error means the connection has been reset; tell + // our manager about it and ignore it. + if (_manager != (ConnectionManager *)NULL) { + _manager->connection_reset(this, okflag); } - - return false; - - } else if (result != bytes_to_send) { - net_cat.error() << "Not enough bytes sent to socket.\n"; return false; } diff --git a/panda/src/net/connection.h b/panda/src/net/connection.h index c55503700d..7970e1eb49 100644 --- a/panda/src/net/connection.h +++ b/panda/src/net/connection.h @@ -22,11 +22,9 @@ #include "pandabase.h" #include "referenceCount.h" #include "netAddress.h" +#include "pmutex.h" -#include -#include -#include - +class Socket_IP; class ConnectionManager; class NetDatagram; @@ -37,13 +35,13 @@ class NetDatagram; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA Connection : public ReferenceCount { PUBLISHED: - Connection(ConnectionManager *manager, PRFileDesc *socket); + Connection(ConnectionManager *manager, Socket_IP *socket); ~Connection(); NetAddress get_address() const; ConnectionManager *get_manager() const; - PRFileDesc *get_socket() const; + Socket_IP *get_socket() const; void set_collect_tcp(bool collect_tcp); bool get_collect_tcp() const; @@ -69,11 +67,11 @@ private: bool send_datagram(const NetDatagram &datagram, int tcp_header_size); bool send_raw_datagram(const NetDatagram &datagram); bool do_flush(); - bool check_send_error(PRInt32 result, PRErrorCode errcode, PRInt32 bytes_to_send); + bool check_send_error(bool okflag); ConnectionManager *_manager; - PRFileDesc *_socket; - PRLock *_write_mutex; + Socket_IP *_socket; + Mutex _write_mutex; bool _collect_tcp; double _collect_tcp_interval; diff --git a/panda/src/net/connectionListener.cxx b/panda/src/net/connectionListener.cxx index 1b5c483a96..6abc93b2f2 100644 --- a/panda/src/net/connectionListener.cxx +++ b/panda/src/net/connectionListener.cxx @@ -20,8 +20,8 @@ #include "connection.h" #include "connectionManager.h" #include "netAddress.h" -#include "pprerror.h" #include "config_net.h" +#include "socket_tcp_listen.h" //////////////////////////////////////////////////////////////////// // Function: ConnectionListener::Constructor @@ -56,13 +56,15 @@ receive_datagram(const NetDatagram &) { //////////////////////////////////////////////////////////////////// void ConnectionListener:: process_incoming_data(SocketInfo *sinfo) { - PRNetAddr addr; + Socket_TCP_Listen *socket; + DCAST_INTO_V(socket, sinfo->get_socket()); - PRFileDesc *socket = - PR_Accept(sinfo->get_socket(), &addr, PR_INTERVAL_NO_TIMEOUT); - - if (socket == (PRFileDesc *)NULL) { - pprerror("PR_Accept"); + Socket_Address addr; + Socket_TCP *session = new Socket_TCP; + if (!socket->GetIncomingConnection(*session, addr)) { + net_cat.error() + << "Error when accepting new connection.\n"; + delete session; } else { NetAddress net_addr(addr); @@ -71,7 +73,7 @@ process_incoming_data(SocketInfo *sinfo) { << " on port " << sinfo->_connection->get_address().get_port() << "\n"; - PT(Connection) new_connection = new Connection(_manager, socket); + PT(Connection) new_connection = new Connection(_manager, session); if (_manager != (ConnectionManager *)NULL) { _manager->new_connection(new_connection); } diff --git a/panda/src/net/connectionManager.cxx b/panda/src/net/connectionManager.cxx index f885991647..c60e26f147 100644 --- a/panda/src/net/connectionManager.cxx +++ b/panda/src/net/connectionManager.cxx @@ -21,10 +21,8 @@ #include "connectionReader.h" #include "connectionWriter.h" #include "netAddress.h" -#include "pprerror.h" #include "config_net.h" - -#include +#include "mutexHolder.h" #ifdef WIN32_VC #include // For gethostname() @@ -37,7 +35,6 @@ //////////////////////////////////////////////////////////////////// ConnectionManager:: ConnectionManager() { - _set_mutex = PR_NewLock(); } //////////////////////////////////////////////////////////////////// @@ -56,8 +53,6 @@ ConnectionManager:: for (wi = _writers.begin(); wi != _writers.end(); ++wi) { (*wi)->clear_manager(); } - - PR_DestroyLock(_set_mutex); } @@ -65,41 +60,42 @@ ConnectionManager:: // Function: ConnectionManager::open_UDP_connection // Access: Public // Description: Opens a socket for sending and/or receiving UDP -// packets. If the port number is negative, it will not -// be bound to a socket; this is generally a pointless -// thing to do. If the port number is zero, a random -// socket will be chosen. Otherwise, the specified -// port number is used. Normally, you don't care what -// port a UDP connection is opened on, so you should use -// the default value of zero. +// packets. If the port number is greater than zero, +// the UDP connection will be opened for listening on +// the indicated port; otherwise, it will be useful only +// for sending. // // Use a ConnectionReader and ConnectionWriter to handle // the actual communication. //////////////////////////////////////////////////////////////////// PT(Connection) ConnectionManager:: open_UDP_connection(int port) { - NetAddress address; - address.set_any(port); + Socket_UDP *socket = new Socket_UDP; - PRFileDesc *socket = PR_NewUDPSocket(); - if (socket == (PRFileDesc *)NULL) { - pprerror("PR_NewUDPSocket"); - return PT(Connection)(); - } - - if (port >= 0) { - PRStatus result = PR_Bind(socket, address.get_addr()); - if (result != PR_SUCCESS) { - pprerror("PR_Bind"); - PR_Close(socket); + if (port > 0) { + NetAddress address; + address.set_any(port); + + if (!socket->OpenForInput(address.get_addr())) { + net_cat.error() + << "Unable to bind to port " << port << " for UDP.\n"; + delete socket; return PT(Connection)(); } net_cat.info() << "Creating UDP connection for port " << port << "\n"; + } else { + if (!socket->InitNoAddress()) { + net_cat.error() + << "Unable to initialize outgoing UDP.\n"; + delete socket; + return PT(Connection)(); + } + net_cat.info() - << "Creating UDP connection\n"; + << "Creating outgoing UDP connection\n"; } PT(Connection) connection = new Connection(this, socket); @@ -125,27 +121,12 @@ open_TCP_server_rendezvous(int port, int backlog) { NetAddress address; address.set_any(port); - PRFileDesc *socket = PR_NewTCPSocket(); - if (socket == (PRFileDesc *)NULL) { - pprerror("PR_NewTCPSocket"); - return PT(Connection)(); - } - - PRStatus result = PR_Bind(socket, address.get_addr()); - if (result != PR_SUCCESS) { - pprerror("PR_Bind"); - net_cat.info() - << "Unable to bind to port " << port << " for TCP.\n"; - PR_Close(socket); - return PT(Connection)(); - } - - result = PR_Listen(socket, backlog); - if (result != PR_SUCCESS) { - pprerror("PR_Listen"); + Socket_TCP_Listen *socket = new Socket_TCP_Listen; + bool okflag = socket->OpenForListen(address.get_addr(), backlog); + if (!okflag) { net_cat.info() << "Unable to listen to port " << port << " for TCP.\n"; - PR_Close(socket); + delete socket; return PT(Connection)(); } @@ -167,22 +148,13 @@ open_TCP_server_rendezvous(int port, int backlog) { //////////////////////////////////////////////////////////////////// PT(Connection) ConnectionManager:: open_TCP_client_connection(const NetAddress &address, int timeout_ms) { - PRFileDesc *socket = PR_NewTCPSocket(); - if (socket == (PRFileDesc *)NULL) { - pprerror("PR_NewTCPSocket"); - return PT(Connection)(); - } - - PRStatus result = PR_Connect(socket, address.get_addr(), - PR_MillisecondsToInterval(timeout_ms)); - if (result != PR_SUCCESS) { - if (PR_GetError() != PR_CONNECT_RESET_ERROR) { - pprerror("PR_Connect"); - } - net_cat.info() + Socket_TCP *socket = new Socket_TCP; + bool okflag = socket->ActiveOpen(address.get_addr()); + if (!okflag) { + net_cat.error() << "Unable to open TCP connection to server " << address.get_ip_string() << " on port " << address.get_port() << "\n"; - PR_Close(socket); + delete socket; return PT(Connection)(); } @@ -199,7 +171,7 @@ open_TCP_client_connection(const NetAddress &address, int timeout_ms) { // Function: ConnectionManager::open_TCP_client_connection // Access: Public // Description: This is a shorthand version of the function to -// directly establish communcations to a named host and +// directly establish communications to a named host and // port. //////////////////////////////////////////////////////////////////// PT(Connection) ConnectionManager:: @@ -238,42 +210,33 @@ close_connection(const PT(Connection) &connection) { connection->flush(); } - PR_Lock(_set_mutex); - Connections::iterator ci = _connections.find(connection); - if (ci == _connections.end()) { - // Already closed, or not part of this ConnectionManager. - PR_Unlock(_set_mutex); - return false; - } - _connections.erase(ci); - - Readers::iterator ri; - for (ri = _readers.begin(); ri != _readers.end(); ++ri) { - (*ri)->remove_connection(connection); - } - PR_Unlock(_set_mutex); - - PRFileDesc *socket = connection->get_socket(); - - if (PR_GetDescType(socket) == PR_DESC_SOCKET_TCP) { - // We can't *actually* close the connection right now, because - // there might be outstanding pointers to it. But we can at least - // shut it down. It will be eventually closed when all the - // pointers let go. - - net_cat.info() - << "Shutting down connection " << (void *)connection - << " locally.\n"; - - PRStatus result = PR_Shutdown(socket, PR_SHUTDOWN_BOTH); - if (result != PR_SUCCESS) { - PRErrorCode errcode = PR_GetError(); - if (errcode != PR_NOT_CONNECTED_ERROR) { - pprerror("PR_Shutdown"); - } + { + MutexHolder holder(_set_mutex); + Connections::iterator ci = _connections.find(connection); + if (ci == _connections.end()) { + // Already closed, or not part of this ConnectionManager. + return false; + } + _connections.erase(ci); + + Readers::iterator ri; + for (ri = _readers.begin(); ri != _readers.end(); ++ri) { + (*ri)->remove_connection(connection); } } + Socket_IP *socket = connection->get_socket(); + + // We can't *actually* close the connection right now, because + // there might be outstanding pointers to it. But we can at least + // shut it down. It will be eventually closed when all the + // pointers let go. + + net_cat.info() + << "Shutting down connection " << (void *)connection + << " locally.\n"; + socket->Close(); + return true; } @@ -305,9 +268,8 @@ get_host_name() { //////////////////////////////////////////////////////////////////// void ConnectionManager:: new_connection(const PT(Connection) &connection) { - PR_Lock(_set_mutex); + MutexHolder holder(_set_mutex); _connections.insert(connection); - PR_Unlock(_set_mutex); } //////////////////////////////////////////////////////////////////// @@ -320,9 +282,9 @@ new_connection(const PT(Connection) &connection) { // been reset. //////////////////////////////////////////////////////////////////// void ConnectionManager:: -connection_reset(const PT(Connection) &connection, PRErrorCode errcode) { +connection_reset(const PT(Connection) &connection, bool okflag) { if (net_cat.is_info()) { - if (errcode == 0) { + if (okflag) { net_cat.info() << "Connection " << (void *)connection << " was closed normally by the other end"; @@ -330,33 +292,8 @@ connection_reset(const PT(Connection) &connection, PRErrorCode errcode) { } else { net_cat.info() << "Lost connection " << (void *)connection - << " unexpectedly: "; - - switch (errcode) { - case PR_CONNECT_RESET_ERROR: - net_cat.info(false) - << "connection reset"; - break; - -#ifdef PR_SOCKET_SHUTDOWN_ERROR - case PR_SOCKET_SHUTDOWN_ERROR: - net_cat.info(false) - << "socket shutdown"; - break; - - case PR_CONNECT_ABORTED_ERROR: - net_cat.info(false) - << "connection aborted"; - break; -#endif - - default: - net_cat.info(false) - << "NSPR error code " << errcode; - } + << " unexpectedly\n"; } - net_cat.info(false) - << " (os error = " << PR_GetOSError() << ").\n"; } // Turns out we do need to explicitly mark the connection as closed @@ -374,9 +311,8 @@ connection_reset(const PT(Connection) &connection, PRErrorCode errcode) { //////////////////////////////////////////////////////////////////// void ConnectionManager:: add_reader(ConnectionReader *reader) { - PR_Lock(_set_mutex); + MutexHolder holder(_set_mutex); _readers.insert(reader); - PR_Unlock(_set_mutex); } //////////////////////////////////////////////////////////////////// @@ -387,9 +323,8 @@ add_reader(ConnectionReader *reader) { //////////////////////////////////////////////////////////////////// void ConnectionManager:: remove_reader(ConnectionReader *reader) { - PR_Lock(_set_mutex); + MutexHolder holder(_set_mutex); _readers.erase(reader); - PR_Unlock(_set_mutex); } //////////////////////////////////////////////////////////////////// @@ -400,9 +335,8 @@ remove_reader(ConnectionReader *reader) { //////////////////////////////////////////////////////////////////// void ConnectionManager:: add_writer(ConnectionWriter *writer) { - PR_Lock(_set_mutex); + MutexHolder holder(_set_mutex); _writers.insert(writer); - PR_Unlock(_set_mutex); } //////////////////////////////////////////////////////////////////// @@ -413,7 +347,6 @@ add_writer(ConnectionWriter *writer) { //////////////////////////////////////////////////////////////////// void ConnectionManager:: remove_writer(ConnectionWriter *writer) { - PR_Lock(_set_mutex); + MutexHolder holder(_set_mutex); _writers.erase(writer); - PR_Unlock(_set_mutex); } diff --git a/panda/src/net/connectionManager.h b/panda/src/net/connectionManager.h index 348e45bd71..5c784130c7 100644 --- a/panda/src/net/connectionManager.h +++ b/panda/src/net/connectionManager.h @@ -25,9 +25,7 @@ #include "connection.h" #include "pointerTo.h" #include "pset.h" - -#include -#include +#include "pmutex.h" class NetAddress; class ConnectionReader; @@ -69,7 +67,7 @@ PUBLISHED: protected: void new_connection(const PT(Connection) &connection); virtual void connection_reset(const PT(Connection) &connection, - PRErrorCode errcode); + bool okflag); void add_reader(ConnectionReader *reader); void remove_reader(ConnectionReader *reader); @@ -82,7 +80,7 @@ protected: Connections _connections; Readers _readers; Writers _writers; - PRLock *_set_mutex; + Mutex _set_mutex; private: friend class ConnectionReader; diff --git a/panda/src/net/connectionReader.cxx b/panda/src/net/connectionReader.cxx index b35cab8d76..200c4420c9 100644 --- a/panda/src/net/connectionReader.cxx +++ b/panda/src/net/connectionReader.cxx @@ -21,20 +21,17 @@ #include "netDatagram.h" #include "datagramTCPHeader.h" #include "datagramUDPHeader.h" -#include "pprerror.h" #include "config_net.h" #include "trueClock.h" - +#include "socket_udp.h" +#include "socket_tcp.h" +#include "mutexHolder.h" #include "pnotify.h" -#include -#include -#include +#include "atomicAdjust.h" static const int read_buffer_size = maximum_udp_datagram + datagram_udp_header_size; -// We have to impose a maximum timeout on the PR_Poll() call because -// PR_Poll() doesn't seem to be interruptible! (!) -static const PRUint32 max_timeout_ms = 100; +static const int max_timeout_ms = 100; //////////////////////////////////////////////////////////////////// // Function: ConnectionReader::SocketInfo::Constructor @@ -56,7 +53,7 @@ SocketInfo(const PT(Connection) &connection) : //////////////////////////////////////////////////////////////////// bool ConnectionReader::SocketInfo:: is_udp() const { - return (PR_GetDescType(_connection->get_socket()) == PR_DESC_SOCKET_UDP); + return (_connection->get_socket()->is_exact_type(Socket_UDP::get_class_type())); } //////////////////////////////////////////////////////////////////// @@ -64,11 +61,34 @@ is_udp() const { // Access: Public // Description: //////////////////////////////////////////////////////////////////// -PRFileDesc *ConnectionReader::SocketInfo:: +Socket_IP *ConnectionReader::SocketInfo:: get_socket() const { return _connection->get_socket(); } +//////////////////////////////////////////////////////////////////// +// Function: ConnectionReader::ReaderThread::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +ConnectionReader::ReaderThread:: +ReaderThread(ConnectionReader *reader, int thread_index) : + Thread("ReaderThread", "ReaderThread"), + _reader(reader), + _thread_index(thread_index) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ConnectionReader::ReaderThread::thread_main +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void ConnectionReader::ReaderThread:: +thread_main() { + _reader->thread_run(_thread_index); +} + //////////////////////////////////////////////////////////////////// // Function: ConnectionReader::Constructor // Access: Public @@ -83,10 +103,6 @@ ConnectionReader(ConnectionManager *manager, int num_threads) : _manager(manager) { #ifndef HAVE_THREADS - // Although this code is written to use thread-locking primitives - // regardless of the definition of HAVE_THREADS, it is not safe to - // spawn multiple threads when HAVE_THREADS is not true, since we - // might be using a non-thread-safe malloc scheme. #ifndef NDEBUG if (num_threads != 0) { net_cat.error() @@ -101,36 +117,20 @@ ConnectionReader(ConnectionManager *manager, int num_threads) : _polling = (num_threads <= 0); _shutdown = false; - _startup_mutex = PR_NewLock(); _next_index = 0; _num_results = 0; - _select_mutex = PR_NewLock(); _currently_polling_thread = -1; - _reexamine_sockets = false; - _sockets_mutex = PR_NewLock(); - - // Before we create all the threads, grab _startup_mutex. That will - // prevent our new threads from trying to look themselves up in the - // _threads array before we have filled it up. - PR_Lock(_startup_mutex); - - for (int i = 0; i < num_threads; i++) { - PRThread *thread = - PR_CreateThread(PR_USER_THREAD, - thread_start, (void *)this, - PR_PRIORITY_NORMAL, - PR_GLOBAL_THREAD, // Since thread will mostly do I/O. - PR_JOINABLE_THREAD, - 0); // Select a suitable stack size. - - nassertv(thread != (PRThread *)NULL); + int i; + for (i = 0; i < num_threads; i++) { + PT(ReaderThread) thread = new ReaderThread(this, i); _threads.push_back(thread); } - - PR_Unlock(_startup_mutex); + for (i = 0; i < num_threads; i++) { + _threads[i]->start(TP_normal, true, true); + } _manager->add_reader(this); } @@ -166,10 +166,6 @@ ConnectionReader:: sinfo->_connection.clear(); } } - - PR_DestroyLock(_startup_mutex); - PR_DestroyLock(_select_mutex); - PR_DestroyLock(_sockets_mutex); } //////////////////////////////////////////////////////////////////// @@ -190,24 +186,21 @@ ConnectionReader:: // will by any thread. //////////////////////////////////////////////////////////////////// bool ConnectionReader:: -add_connection(const PT(Connection) &connection) { +add_connection(Connection *connection) { nassertr(connection != (Connection *)NULL, false); - PR_Lock(_sockets_mutex); + MutexHolder holder(_sockets_mutex); // Make sure it's not already on the _sockets list. Sockets::const_iterator si; for (si = _sockets.begin(); si != _sockets.end(); ++si) { if ((*si)->_connection == connection) { // Whoops, already there. - PR_Unlock(_sockets_mutex); return false; } } _sockets.push_back(new SocketInfo(connection)); - _reexamine_sockets = true; - PR_Unlock(_sockets_mutex); return true; } @@ -224,8 +217,8 @@ add_connection(const PT(Connection) &connection) { // at will by any thread. //////////////////////////////////////////////////////////////////// bool ConnectionReader:: -remove_connection(const PT(Connection) &connection) { - PR_Lock(_sockets_mutex); +remove_connection(Connection *connection) { + MutexHolder holder(_sockets_mutex); // Walk through the list of sockets to find the one we're removing. Sockets::iterator si; @@ -234,14 +227,11 @@ remove_connection(const PT(Connection) &connection) { ++si; } if (si == _sockets.end()) { - PR_Unlock(_sockets_mutex); return false; } _removed_sockets.push_back(*si); _sockets.erase(si); - _reexamine_sockets = true; - PR_Unlock(_sockets_mutex); return true; } @@ -258,8 +248,8 @@ remove_connection(const PT(Connection) &connection) { // the connection.) //////////////////////////////////////////////////////////////////// bool ConnectionReader:: -is_connection_ok(const PT(Connection) &connection) { - PR_Lock(_sockets_mutex); +is_connection_ok(Connection *connection) { + MutexHolder holder(_sockets_mutex); // Walk through the list of sockets to find the one we're asking // about. @@ -270,13 +260,11 @@ is_connection_ok(const PT(Connection) &connection) { } if (si == _sockets.end()) { // Don't know that connection. - PR_Unlock(_sockets_mutex); return false; } SocketInfo *sinfo = (*si); bool is_ok = !sinfo->_error; - PR_Unlock(_sockets_mutex); return is_ok; } @@ -299,14 +287,14 @@ poll() { return; } - SocketInfo *sinfo = get_next_available_socket(PR_INTERVAL_NO_WAIT, -2); + SocketInfo *sinfo = get_next_available_socket(false, -2); if (sinfo != (SocketInfo *)NULL) { double max_poll_cycle = get_max_poll_cycle(); if (max_poll_cycle < 0.0) { // Continue to read all data. while (sinfo != (SocketInfo *)NULL) { process_incoming_data(sinfo); - sinfo = get_next_available_socket(PR_INTERVAL_NO_WAIT, -2); + sinfo = get_next_available_socket(false, -2); } } else { @@ -319,7 +307,7 @@ poll() { if (global_clock->get_short_time() >= stop) { return; } - sinfo = get_next_available_socket(PR_INTERVAL_NO_WAIT, -2); + sinfo = get_next_available_socket(false, -2); } } } @@ -429,16 +417,7 @@ shutdown() { // Now wait for all of our threads to terminate. Threads::iterator ti; for (ti = _threads.begin(); ti != _threads.end(); ++ti) { - // Interrupt the thread so it can notice the shutdown. - PRStatus result = PR_Interrupt(*ti); - if (result != PR_SUCCESS) { - pprerror("PR_Interrupt"); - } - - result = PR_JoinThread(*ti); - if (result != PR_SUCCESS) { - pprerror("PR_JoinThread"); - } + (*ti)->join(); } } @@ -470,34 +449,14 @@ finish_socket(SocketInfo *sinfo) { // By marking the SocketInfo nonbusy, we make it available for // future polls. sinfo->_busy = false; - _reexamine_sockets = true; - - // However, someone might be already blocking on an - // earlier-established PR_Poll() that doesn't involve this socket. - // That complicates things. It means we'll have to wake that thread - // up so it can rebuild the poll with the new socket. - - // Actually, don't bother, since it turns out that PR_Poll() isn't - // interruptible anyway. Sigh. Maybe we'll revisit this later, but - // in the meantime it means we have to rig up the PR_Poll() to - // return every so often and check the _reexamine_sockets flag by - // itself. - - /* - int thread = _currently_polling_thread; - if (thread != -1) { - nassertv(thread >= 0 && thread < _threads.size()); - PR_Interrupt(_threads[thread]); - } - */ } //////////////////////////////////////////////////////////////////// // Function: ConnectionReader::process_incoming_data // Access: Protected, Virtual // Description: This is run within a thread when the call to -// PR_Poll() indicates there is data available -// on a socket. +// select() indicates there is data available on a +// socket. //////////////////////////////////////////////////////////////////// void ConnectionReader:: process_incoming_data(SocketInfo *sinfo) { @@ -523,21 +482,17 @@ process_incoming_data(SocketInfo *sinfo) { //////////////////////////////////////////////////////////////////// void ConnectionReader:: process_incoming_udp_data(SocketInfo *sinfo) { - PRFileDesc *socket = sinfo->get_socket(); - PRNetAddr addr; + Socket_UDP *socket; + DCAST_INTO_V(socket, sinfo->get_socket()); + Socket_Address addr; // Read as many bytes as we can. - PRInt8 buffer[read_buffer_size]; - PRInt32 bytes_read; + char buffer[read_buffer_size]; + int bytes_read = read_buffer_size; - bytes_read = PR_RecvFrom(socket, buffer, read_buffer_size, 0, - &addr, PR_INTERVAL_NO_TIMEOUT); + bool okflag = socket->GetPacket(buffer, &bytes_read, addr); - if (bytes_read < 0) { - PRErrorCode errcode = PR_GetError(); - if (errcode != PR_PENDING_INTERRUPT_ERROR) { - pprerror("PR_RecvFrom"); - } + if (!okflag) { finish_socket(sinfo); return; @@ -563,7 +518,7 @@ process_incoming_udp_data(SocketInfo *sinfo) { DatagramUDPHeader header(buffer); - PRInt8 *dp = buffer + datagram_udp_header_size; + char *dp = buffer + datagram_udp_header_size; bytes_read -= datagram_udp_header_size; NetDatagram datagram(dp, bytes_read); @@ -594,44 +549,20 @@ process_incoming_udp_data(SocketInfo *sinfo) { //////////////////////////////////////////////////////////////////// void ConnectionReader:: process_incoming_tcp_data(SocketInfo *sinfo) { - PRFileDesc *socket = sinfo->get_socket(); - PRNetAddr addr; + Socket_TCP *socket; + DCAST_INTO_V(socket, sinfo->get_socket()); // Read only the header bytes to start with. - PRInt8 buffer[read_buffer_size]; - PRInt32 header_bytes_read = 0; - - if (PR_GetSockName(socket, &addr) != PR_SUCCESS) { - pprerror("PR_GetSockName"); - } + char buffer[read_buffer_size]; + int header_bytes_read = 0; // First, we have to read the first _tcp_header_size bytes. while (header_bytes_read < _tcp_header_size) { - PRInt32 bytes_read = - PR_Recv(socket, buffer + header_bytes_read, - _tcp_header_size - header_bytes_read, 0, - PR_INTERVAL_NO_TIMEOUT); + int bytes_read = + socket->RecvData(buffer + header_bytes_read, + _tcp_header_size - header_bytes_read); - if (bytes_read < 0) { - PRErrorCode errcode = PR_GetError(); - if (errcode == PR_CONNECT_RESET_ERROR -#ifdef PR_SOCKET_SHUTDOWN_ERROR - || errcode == PR_SOCKET_SHUTDOWN_ERROR - || errcode == PR_CONNECT_ABORTED_ERROR -#endif - ) { - // The socket was closed. - if (_manager != (ConnectionManager *)NULL) { - _manager->connection_reset(sinfo->_connection, errcode); - } - - } else if (errcode != PR_PENDING_INTERRUPT_ERROR) { - pprerror("PR_Recv"); - } - finish_socket(sinfo); - return; - - } else if (bytes_read == 0) { + if (bytes_read <= 0) { // The socket was closed. Report that and return. if (_manager != (ConnectionManager *)NULL) { _manager->connection_reset(sinfo->_connection, 0); @@ -655,41 +586,20 @@ process_incoming_tcp_data(SocketInfo *sinfo) { } DatagramTCPHeader header(buffer, _tcp_header_size); - PRInt32 size = header.get_datagram_size(_tcp_header_size); + int size = header.get_datagram_size(_tcp_header_size); // We have to loop until the entire datagram is read. NetDatagram datagram; while (!_shutdown && (int)datagram.get_length() < size) { - PRInt32 bytes_read; + int bytes_read; bytes_read = - PR_Recv(socket, buffer, - min((PRInt32)read_buffer_size, - (PRInt32)(size - datagram.get_length())), - 0, PR_INTERVAL_NO_TIMEOUT); - PRInt8 *dp = buffer; + socket->RecvData(buffer, min(read_buffer_size, + (int)(size - datagram.get_length()))); + char *dp = buffer; - if (bytes_read < 0) { - PRErrorCode errcode = PR_GetError(); - if (errcode == PR_CONNECT_RESET_ERROR -#ifdef PR_SOCKET_SHUTDOWN_ERROR - || errcode == PR_SOCKET_SHUTDOWN_ERROR - || errcode == PR_CONNECT_ABORTED_ERROR -#endif - ) { - // The socket was closed. - if (_manager != (ConnectionManager *)NULL) { - _manager->connection_reset(sinfo->_connection, errcode); - } - - } else if (errcode != PR_PENDING_INTERRUPT_ERROR) { - pprerror("PR_Recv"); - } - finish_socket(sinfo); - return; - - } else if (bytes_read == 0) { + if (bytes_read <= 0) { // The socket was closed. Report that and return. if (_manager != (ConnectionManager *)NULL) { _manager->connection_reset(sinfo->_connection, 0); @@ -698,8 +608,8 @@ process_incoming_tcp_data(SocketInfo *sinfo) { return; } - PRInt32 datagram_bytes = - min(bytes_read, (PRInt32)(size - datagram.get_length())); + int datagram_bytes = + min(bytes_read, (int)(size - datagram.get_length())); datagram.append_data(dp, datagram_bytes); if (bytes_read > datagram_bytes) { @@ -725,7 +635,7 @@ process_incoming_tcp_data(SocketInfo *sinfo) { << "Ignoring invalid TCP datagram.\n"; } else { datagram.set_connection(sinfo->_connection); - datagram.set_address(NetAddress(addr)); + datagram.set_address(NetAddress(socket->GetPeerName())); receive_datagram(datagram); } } @@ -737,21 +647,17 @@ process_incoming_tcp_data(SocketInfo *sinfo) { //////////////////////////////////////////////////////////////////// void ConnectionReader:: process_raw_incoming_udp_data(SocketInfo *sinfo) { - PRFileDesc *socket = sinfo->get_socket(); - PRNetAddr addr; + Socket_UDP *socket; + DCAST_INTO_V(socket, sinfo->get_socket()); + Socket_Address addr; // Read as many bytes as we can. - PRInt8 buffer[read_buffer_size]; - PRInt32 bytes_read; + char buffer[read_buffer_size]; + int bytes_read = read_buffer_size; - bytes_read = PR_RecvFrom(socket, buffer, read_buffer_size, 0, - &addr, PR_INTERVAL_NO_TIMEOUT); + bool okflag = socket->GetPacket(buffer, &bytes_read, addr); - if (bytes_read < 0) { - PRErrorCode errcode = PR_GetError(); - if (errcode != PR_PENDING_INTERRUPT_ERROR) { - pprerror("PR_RecvFrom"); - } + if (!okflag) { finish_socket(sinfo); return; @@ -789,29 +695,14 @@ process_raw_incoming_udp_data(SocketInfo *sinfo) { //////////////////////////////////////////////////////////////////// void ConnectionReader:: process_raw_incoming_tcp_data(SocketInfo *sinfo) { - PRFileDesc *socket = sinfo->get_socket(); - PRNetAddr addr; + Socket_TCP *socket; + DCAST_INTO_V(socket, sinfo->get_socket()); // Read as many bytes as we can. - PRInt8 buffer[read_buffer_size]; - PRInt32 bytes_read; + char buffer[read_buffer_size]; + int bytes_read = socket->RecvData(buffer, read_buffer_size); - if (PR_GetSockName(socket, &addr) != PR_SUCCESS) { - pprerror("PR_GetSockName"); - } - - bytes_read = PR_Recv(socket, buffer, read_buffer_size, 0, - PR_INTERVAL_NO_TIMEOUT); - - if (bytes_read < 0) { - PRErrorCode errcode = PR_GetError(); - if (errcode != PR_PENDING_INTERRUPT_ERROR) { - pprerror("PR_RecvFrom"); - } - finish_socket(sinfo); - return; - - } else if (bytes_read == 0) { + if (bytes_read <= 0) { // The socket was closed. Report that and return. if (_manager != (ConnectionManager *)NULL) { _manager->connection_reset(sinfo->_connection, 0); @@ -833,24 +724,10 @@ process_raw_incoming_tcp_data(SocketInfo *sinfo) { } datagram.set_connection(sinfo->_connection); - datagram.set_address(NetAddress(addr)); + datagram.set_address(NetAddress(socket->GetPeerName())); receive_datagram(datagram); } - -//////////////////////////////////////////////////////////////////// -// Function: ConnectionReader::thread_start -// Access: Private, Static -// Description: The static wrapper around the thread's executing -// function. This must be a static member function -// because it is passed through the C interface to -// PR_CreateThread(). -//////////////////////////////////////////////////////////////////// -void ConnectionReader:: -thread_start(void *data) { - ((ConnectionReader *)data)->thread_run(); -} - //////////////////////////////////////////////////////////////////// // Function: ConnectionReader::thread_run // Access: Private @@ -858,24 +735,13 @@ thread_start(void *data) { // thread. //////////////////////////////////////////////////////////////////// void ConnectionReader:: -thread_run() { +thread_run(int thread_index) { nassertv(!_polling); - - // First determine our own thread index. - PR_Lock(_startup_mutex); - Threads::const_iterator ti = - find(_threads.begin(), _threads.end(), PR_GetCurrentThread()); - - nassertv(ti != _threads.end()); - PRInt32 current_thread_index = (ti - _threads.begin()); - - nassertv(_threads[current_thread_index] == PR_GetCurrentThread()); - PR_Unlock(_startup_mutex); + nassertv(_threads[thread_index] == Thread::get_current_thread()); while (!_shutdown) { SocketInfo *sinfo = - get_next_available_socket(PR_INTERVAL_NO_TIMEOUT, - current_thread_index); + get_next_available_socket(false, thread_index); if (sinfo != (SocketInfo *)NULL) { process_incoming_data(sinfo); } @@ -892,59 +758,29 @@ thread_run() { // // This function may block indefinitely if it is being // called by multiple threads; if there are no other -// threads, it may block only if timeout != -// PR_INTERVAL_NO_WAIT. +// threads, it may block only if allow_block is true. //////////////////////////////////////////////////////////////////// ConnectionReader::SocketInfo *ConnectionReader:: -get_next_available_socket(PRIntervalTime timeout, - PRInt32 current_thread_index) { +get_next_available_socket(bool allow_block, int current_thread_index) { // Go to sleep on the select() mutex. This guarantees that only one // thread is in this function at a time. - PR_Lock(_select_mutex); - - int num_sockets = _polled_sockets.size(); - nassertr(num_sockets == (int)_poll.size(), NULL); + MutexHolder holder(_select_mutex); do { - // First, check the result from the previous PR_Poll() call. If + // First, check the result from the previous select call. If // there are any sockets remaining there, process them first. while (!_shutdown && _num_results > 0) { - nassertr(_next_index < num_sockets, NULL); + nassertr(_next_index < (int)_selecting_sockets.size(), NULL); int i = _next_index; _next_index++; - if (_poll[i].out_flags != 0) { + if (_fdset.IsSetFor(*_selecting_sockets[i]->get_socket())) { _num_results--; - SocketInfo *sinfo = _polled_sockets[i]; + SocketInfo *sinfo = _selecting_sockets[i]; - if ((_poll[i].out_flags & PR_POLL_READ) != 0) { - // Some genuine noise on the port. - sinfo->_busy = true; - _reexamine_sockets = true; - PR_Unlock(_select_mutex); - PR_Sleep(PR_INTERVAL_NO_WAIT); - return sinfo; - - } else if ((_poll[i].out_flags & - (PR_POLL_ERR | PR_POLL_NVAL | PR_POLL_HUP)) != 0) { - // Something bad happened to this socket. Tell the - // ConnectionManager to drop it. - if (_manager != (ConnectionManager *)NULL) { - // Perform a recv to force an error code. - char buffer[1]; - PRInt32 got_bytes = - PR_Recv(sinfo->get_socket(), buffer, 1, 0, PR_INTERVAL_NO_WAIT); - if (got_bytes > 0) { - net_cat.error() - << "poll returned error flags " << hex << _poll[i].out_flags - << dec << " but read " << got_bytes << " from socket.\n"; - } - PRErrorCode errcode = PR_GetError(); - _manager->connection_reset(sinfo->_connection, errcode); - } - sinfo->_error = true; - _reexamine_sockets = true; - } + // Some noise on this socket. + sinfo->_busy = true; + return sinfo; } } @@ -952,93 +788,70 @@ get_next_available_socket(PRIntervalTime timeout, do { interrupted = false; - // Ok, no results from previous PR_Poll() calls. Prepare to set - // up for a new poll. + // Ok, no results from previous select calls. Prepare to set up + // for a new select. // First, report to anyone else who cares that we're the thread // about to do the poll. That way, if any new sockets come // available while we're polling, we can service them. - PR_AtomicSet(&_currently_polling_thread, current_thread_index); + AtomicAdjust::set(_currently_polling_thread, current_thread_index); + + rebuild_select_list(); - if (_reexamine_sockets) { - _reexamine_sockets = false; - rebuild_poll_list(); - num_sockets = _polled_sockets.size(); - nassertr(num_sockets == (int)_poll.size(), NULL); - } - - // Now we can execute PR_Poll(). This basically maps to a Unix - // select() call. + // Now we can execute the select. _num_results = 0; _next_index = 0; if (!_shutdown) { - PRIntervalTime poll_timeout = - PR_MillisecondsToInterval(max_timeout_ms); - if (timeout != PR_INTERVAL_NO_TIMEOUT) { - poll_timeout = min(timeout, poll_timeout); + PN_uint32 timeout = max_timeout_ms; + if (!allow_block) { + timeout = 0; } - _num_results = PR_Poll(&_poll[0], num_sockets, poll_timeout); + _num_results = _fdset.WaitForRead(false, timeout); } - if (_num_results == 0 && timeout == PR_INTERVAL_NO_TIMEOUT) { - // If we reached max_timeout_ms, but the caller didn't request - // a timeout, consider that an interrupt: go back and - // reconsider. (This is a kludge around the fact that - // PR_Poll() appears to be non-interruptible.) + if (_num_results == 0 && allow_block) { + // If we reached max_timeout_ms, go back and reconsider. (We + // never timeout indefinitely, so we can check the shutdown + // flag every once in a while.) interrupted = true; } else if (_num_results < 0) { - // If our poll was interrupted by another thread, rebuild the - // list and poll again. - PRErrorCode errcode = PR_GetError(); - if (errcode == PR_PENDING_INTERRUPT_ERROR) { - interrupted = true; - } else { - pprerror("PR_Poll"); - } + // If we had an error, just return. + return (SocketInfo *)NULL; } } while (!_shutdown && interrupted); - PR_AtomicSet(&_currently_polling_thread, -1); - // Just in case someone interrupted us while we were polling and - // we didn't catch it, clear it now--we don't care any more. - PR_ClearInterrupt(); + AtomicAdjust::set(_currently_polling_thread, current_thread_index); // Repeat the above until we (a) find a socket with actual noise // on it, or (b) return from PR_Poll() with no sockets available. } while (!_shutdown && _num_results > 0); - PR_Unlock(_select_mutex); return (SocketInfo *)NULL; } //////////////////////////////////////////////////////////////////// -// Function: ConnectionReader::rebuild_poll_list +// Function: ConnectionReader::rebuild_select_list // Access: Private -// Description: Rebuilds the _poll and _polled_sockets arrays based -// on the sockets that are currently available for -// polling. +// Description: Rebuilds the _fdset and _selecting_sockets arrays +// based on the sockets that are currently available for +// selecting. //////////////////////////////////////////////////////////////////// void ConnectionReader:: -rebuild_poll_list() { - _poll.clear(); - _polled_sockets.clear(); +rebuild_select_list() { + _fdset.clear(); + _selecting_sockets.clear(); - PR_Lock(_sockets_mutex); + MutexHolder holder(_sockets_mutex); Sockets::const_iterator si; for (si = _sockets.begin(); si != _sockets.end(); ++si) { SocketInfo *sinfo = (*si); if (!sinfo->_busy && !sinfo->_error) { - PRPollDesc pd; - pd.fd = sinfo->get_socket(); - pd.in_flags = PR_POLL_READ; - pd.out_flags = 0; - - _poll.push_back(pd); - _polled_sockets.push_back(sinfo); + _fdset.setForSocket(*sinfo->get_socket()); + _selecting_sockets.push_back(sinfo); } } @@ -1056,6 +869,4 @@ rebuild_poll_list() { } _removed_sockets.swap(still_busy_sockets); } - - PR_Unlock(_sockets_mutex); } diff --git a/panda/src/net/connectionReader.h b/panda/src/net/connectionReader.h index 9f173f8080..21c0d6e80c 100644 --- a/panda/src/net/connectionReader.h +++ b/panda/src/net/connectionReader.h @@ -24,15 +24,15 @@ #include "connection.h" #include "pointerTo.h" - -#include -#include -#include +#include "pmutex.h" #include "pvector.h" #include "pset.h" +#include "socket_fdset.h" class NetDatagram; class ConnectionManager; +class Socket_Address; +class Socket_IP; //////////////////////////////////////////////////////////////////// // Class : ConnectionReader @@ -72,9 +72,9 @@ PUBLISHED: ConnectionReader(ConnectionManager *manager, int num_threads); virtual ~ConnectionReader(); - bool add_connection(const PT(Connection) &connection); - bool remove_connection(const PT(Connection) &connection); - bool is_connection_ok(const PT(Connection) &connection); + bool add_connection(Connection *connection); + bool remove_connection(Connection *connection); + bool is_connection_ok(Connection *connection); void poll(); @@ -95,7 +95,7 @@ protected: public: SocketInfo(const PT(Connection) &connection); bool is_udp() const; - PRFileDesc *get_socket() const; + Socket_IP *get_socket() const; PT(Connection) _connection; bool _busy; @@ -113,13 +113,12 @@ protected: virtual void process_raw_incoming_tcp_data(SocketInfo *sinfo); private: - static void thread_start(void *data); - void thread_run(); + void thread_run(int thread_index); - SocketInfo *get_next_available_socket(PRIntervalTime timeout, - PRInt32 current_thread_index); + SocketInfo *get_next_available_socket(bool allow_block, + int current_thread_index); - void rebuild_poll_list(); + void rebuild_select_list(); protected: ConnectionManager *_manager; @@ -129,27 +128,34 @@ private: int _tcp_header_size; bool _shutdown; - typedef pvector Threads; + class ReaderThread : public Thread { + public: + ReaderThread(ConnectionReader *reader, int thread_index); + virtual void thread_main(); + + ConnectionReader *_reader; + int _thread_index; + }; + + typedef pvector< PT(ReaderThread) > Threads; Threads _threads; - PRLock *_startup_mutex; bool _polling; - // These structures are used to manage polling for noise on + // These structures are used to manage selecting for noise on // available sockets. - typedef pvector Poll; + Socket_fdset _fdset; typedef pvector Sockets; - Poll _poll; - Sockets _polled_sockets; + Sockets _selecting_sockets; int _next_index; int _num_results; // Threads go to sleep on this mutex waiting for their chance to // read a socket. - PRLock *_select_mutex; + Mutex _select_mutex; // This is atomically updated with the index (in _threads) of the // thread that is currently waiting on the PR_Poll() call. It // contains -1 if no thread is so waiting. - PRInt32 _currently_polling_thread; + PN_int32 _currently_polling_thread; // These structures track the total set of sockets (connections) we // know about. @@ -157,14 +163,12 @@ private: // This is the list of recently-removed sockets. We can't actually // delete them until they're no longer _busy. Sockets _removed_sockets; - // Threads may set this true to force the polling thread to rebuild - // its Poll() list. - bool _reexamine_sockets; // Any operations on _sockets are protected by this mutex. - PRLock *_sockets_mutex; + Mutex _sockets_mutex; -friend class ConnectionManager; + friend class ConnectionManager; + friend class ReaderThread; }; #endif diff --git a/panda/src/net/connectionWriter.cxx b/panda/src/net/connectionWriter.cxx index 1e447c4cbf..c98ab99f37 100644 --- a/panda/src/net/connectionWriter.cxx +++ b/panda/src/net/connectionWriter.cxx @@ -19,11 +19,33 @@ #include "connectionWriter.h" #include "connectionManager.h" #include "datagramTCPHeader.h" -#include "pprerror.h" #include "config_net.h" - +#include "socket_tcp.h" +#include "socket_udp.h" #include "pnotify.h" -#include + +//////////////////////////////////////////////////////////////////// +// Function: ConnectionWriter::WriterThread::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +ConnectionWriter::WriterThread:: +WriterThread(ConnectionWriter *writer, int thread_index) : + Thread("WriterThread", "WriterThread"), + _writer(writer), + _thread_index(thread_index) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ConnectionWriter::WriterThread::thread_main +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void ConnectionWriter::WriterThread:: +thread_main() { + _writer->thread_run(_thread_index); +} //////////////////////////////////////////////////////////////////// // Function: ConnectionWriter::Constructor @@ -57,18 +79,14 @@ ConnectionWriter(ConnectionManager *manager, int num_threads) : _tcp_header_size = datagram_tcp16_header_size; _immediate = (num_threads <= 0); - for (int i = 0; i < num_threads; i++) { - PRThread *thread = - PR_CreateThread(PR_USER_THREAD, - thread_start, (void *)this, - PR_PRIORITY_NORMAL, - PR_GLOBAL_THREAD, // Since thread will mostly do I/O. - PR_JOINABLE_THREAD, - 0); // Select a suitable stack size. - - nassertv(thread != (PRThread *)NULL); + int i; + for (i = 0; i < num_threads; i++) { + PT(WriterThread) thread = new WriterThread(this, i); _threads.push_back(thread); } + for (i = 0; i < num_threads; i++) { + _threads[i]->start(TP_normal, true, true); + } _manager->add_writer(this); } @@ -91,16 +109,7 @@ ConnectionWriter:: // Now wait for all threads to terminate. Threads::iterator ti; for (ti = _threads.begin(); ti != _threads.end(); ++ti) { - // Interrupt the thread just in case it was stuck waiting for I/O. - PRStatus result = PR_Interrupt(*ti); - if (result != PR_SUCCESS) { - pprerror("PR_Interrupt"); - } - - result = PR_JoinThread(*ti); - if (result != PR_SUCCESS) { - pprerror("PR_JoinThread"); - } + (*ti)->join(); } } @@ -123,7 +132,7 @@ ConnectionWriter:: bool ConnectionWriter:: send(const Datagram &datagram, const PT(Connection) &connection) { nassertr(connection != (Connection *)NULL, false); - nassertr(PR_GetDescType(connection->get_socket()) == PR_DESC_SOCKET_TCP, false); + nassertr(connection->get_socket()->is_exact_type(Socket_TCP::get_class_type()), false); NetDatagram copy(datagram); copy.set_connection(connection); @@ -159,10 +168,9 @@ bool ConnectionWriter:: send(const Datagram &datagram, const PT(Connection) &connection, const NetAddress &address) { nassertr(connection != (Connection *)NULL, false); - nassertr(PR_GetDescType(connection->get_socket()) == PR_DESC_SOCKET_UDP, false); + nassertr(connection->get_socket()->is_exact_type(Socket_UDP::get_class_type()), false); - if (PR_GetDescType(connection->get_socket()) == PR_DESC_SOCKET_UDP && - (int)datagram.get_length() > maximum_udp_datagram) { + if ((int)datagram.get_length() > maximum_udp_datagram) { net_cat.warning() << "Attempt to send UDP datagram of " << datagram.get_length() << " bytes, more than the\n" @@ -299,19 +307,6 @@ clear_manager() { _manager = (ConnectionManager *)NULL; } -//////////////////////////////////////////////////////////////////// -// Function: ConnectionWriter::thread_start -// Access: Private, Static -// Description: The static wrapper around the thread's executing -// function. This must be a static member function -// because it is passed through the C interface to -// PR_CreateThread(). -//////////////////////////////////////////////////////////////////// -void ConnectionWriter:: -thread_start(void *data) { - ((ConnectionWriter *)data)->thread_run(); -} - //////////////////////////////////////////////////////////////////// // Function: ConnectionWriter::thread_run // Access: Private @@ -319,7 +314,7 @@ thread_start(void *data) { // thread. //////////////////////////////////////////////////////////////////// void ConnectionWriter:: -thread_run() { +thread_run(int thread_index) { nassertv(!_immediate); NetDatagram datagram; diff --git a/panda/src/net/connectionWriter.h b/panda/src/net/connectionWriter.h index d8019b085d..e7f77b1c91 100644 --- a/panda/src/net/connectionWriter.h +++ b/panda/src/net/connectionWriter.h @@ -20,13 +20,10 @@ #define CONNECTIONWRITER_H #include "pandabase.h" - #include "datagramQueue.h" #include "connection.h" - #include "pointerTo.h" - -#include +#include "thread.h" #include "pvector.h" class ConnectionManager; @@ -38,7 +35,7 @@ class NetAddress; // various TCP or UDP sockets. // // A ConnectionWriter may define an arbitrary number of -// threads (at least one) to write its datagrams to +// threads (0 or more) to write its datagrams to // sockets. The number of threads is specified at // construction time and cannot be changed. //////////////////////////////////////////////////////////////////// @@ -70,8 +67,7 @@ protected: void clear_manager(); private: - static void thread_start(void *data); - void thread_run(); + void thread_run(int thread_index); bool send_datagram(const NetDatagram &datagram); protected: @@ -82,11 +78,22 @@ private: int _tcp_header_size; DatagramQueue _queue; - typedef pvector Threads; + class WriterThread : public Thread { + public: + WriterThread(ConnectionWriter *writer, int thread_index); + virtual void thread_main(); + + ConnectionWriter *_writer; + int _thread_index; + }; + + typedef pvector< PT(WriterThread) > Threads; Threads _threads; + bool _immediate; -friend class ConnectionManager; + friend class ConnectionManager; + friend class WriterThread; }; #endif diff --git a/panda/src/net/datagramQueue.cxx b/panda/src/net/datagramQueue.cxx index 78f7c1feb6..b24c05b74e 100644 --- a/panda/src/net/datagramQueue.cxx +++ b/panda/src/net/datagramQueue.cxx @@ -18,6 +18,7 @@ #include "datagramQueue.h" #include "config_net.h" +#include "mutexHolder.h" //////////////////////////////////////////////////////////////////// // Function: DatagramQueue::Constructor @@ -25,10 +26,8 @@ // Description: //////////////////////////////////////////////////////////////////// DatagramQueue:: -DatagramQueue() { +DatagramQueue() : _cv(_cvlock) { _shutdown = false; - _cvlock = PR_NewLock(); - _cv = PR_NewCondVar(_cvlock); _max_queue_size = get_net_max_write_queue(); } @@ -42,9 +41,6 @@ DatagramQueue:: // It's an error to delete a DatagramQueue without first shutting it // down (and waiting for any associated threads to terminate). nassertv(_shutdown); - - PR_DestroyCondVar(_cv); - PR_DestroyLock(_cvlock); } //////////////////////////////////////////////////////////////////// @@ -61,10 +57,10 @@ void DatagramQueue:: shutdown() { // Notify all of our threads that we're shutting down. This will // cause any thread blocking on extract() to return false. - PR_Lock(_cvlock); + MutexHolder holder(_cvlock); + _shutdown = true; - PR_NotifyAllCondVar(_cv); - PR_Unlock(_cvlock); + _cv.signal_all(); } @@ -79,17 +75,14 @@ shutdown() { //////////////////////////////////////////////////////////////////// bool DatagramQueue:: insert(const NetDatagram &data) { - PR_Lock(_cvlock); + MutexHolder holder(_cvlock); + bool enqueue_ok = ((int)_queue.size() < _max_queue_size); if (enqueue_ok) { -#ifdef __ICL - _queue.push_back(new NetDatagram(data)); -#else _queue.push_back(data); -#endif } - PR_NotifyCondVar(_cv); - PR_Unlock(_cvlock); + _cv.signal(); + return enqueue_ok; } @@ -118,27 +111,20 @@ extract(NetDatagram &result) { // connection pointer--we're about to go to sleep for a while. result.clear(); - PR_Lock(_cvlock); + MutexHolder holder(_cvlock); + while (_queue.empty() && !_shutdown) { - PR_WaitCondVar(_cv, PR_INTERVAL_NO_TIMEOUT); + _cv.wait(); } if (_shutdown) { - PR_Unlock(_cvlock); return false; } nassertr(!_queue.empty(), false); -#ifdef __ICL - NetDatagram *ptr = _queue.front(); - result = *ptr; - delete ptr; -#else result = _queue.front(); -#endif _queue.pop_front(); - PR_Unlock(_cvlock); return true; } @@ -156,9 +142,8 @@ extract(NetDatagram &result) { //////////////////////////////////////////////////////////////////// void DatagramQueue:: set_max_queue_size(int max_size) { - PR_Lock(_cvlock); + MutexHolder holder(_cvlock); _max_queue_size = max_size; - PR_Unlock(_cvlock); } //////////////////////////////////////////////////////////////////// @@ -179,8 +164,7 @@ get_max_queue_size() const { //////////////////////////////////////////////////////////////////// int DatagramQueue:: get_current_queue_size() const { - PR_Lock(_cvlock); + MutexHolder holder(_cvlock); int size = _queue.size(); - PR_Unlock(_cvlock); return size; } diff --git a/panda/src/net/datagramQueue.h b/panda/src/net/datagramQueue.h index 1c78413ff8..47f0271b62 100644 --- a/panda/src/net/datagramQueue.h +++ b/panda/src/net/datagramQueue.h @@ -22,9 +22,8 @@ #include "pandabase.h" #include "netDatagram.h" - -#include -#include +#include "pmutex.h" +#include "conditionVarFull.h" #include "pdeque.h" //////////////////////////////////////////////////////////////////// @@ -47,17 +46,10 @@ public: int get_current_queue_size() const; private: - PRLock *_cvlock; - PRCondVar *_cv; + Mutex _cvlock; + ConditionVarFull _cv; -#ifdef __ICL - // The Intel compiler for some reason dumps core on a queue of - // NetDatagrams. - typedef pdeque QueueType; -#else typedef pdeque QueueType; -#endif - QueueType _queue; bool _shutdown; int _max_queue_size; diff --git a/panda/src/net/datagramTCPHeader.cxx b/panda/src/net/datagramTCPHeader.cxx index dfb79c4a43..11a5b1d65f 100644 --- a/panda/src/net/datagramTCPHeader.cxx +++ b/panda/src/net/datagramTCPHeader.cxx @@ -38,7 +38,7 @@ DatagramTCPHeader(const NetDatagram &datagram, int header_size) { case datagram_tcp16_header_size: { - PRUint16 size = str.length(); + PN_uint16 size = str.length(); nassertv(size == str.length()); _header.add_uint16(size); } @@ -46,7 +46,7 @@ DatagramTCPHeader(const NetDatagram &datagram, int header_size) { case datagram_tcp32_header_size: { - PRUint32 size = str.length(); + PN_uint32 size = str.length(); nassertv(size == str.length()); _header.add_uint32(size); } diff --git a/panda/src/net/datagramTCPHeader.h b/panda/src/net/datagramTCPHeader.h index 73d7cd2afd..35fbb2c340 100644 --- a/panda/src/net/datagramTCPHeader.h +++ b/panda/src/net/datagramTCPHeader.h @@ -24,11 +24,10 @@ #include "netDatagram.h" #include "datagramIterator.h" +#include "numeric_types.h" -#include - -static const int datagram_tcp16_header_size = sizeof(PRUint16); -static const int datagram_tcp32_header_size = sizeof(PRUint32); +static const int datagram_tcp16_header_size = sizeof(PN_uint16); +static const int datagram_tcp32_header_size = sizeof(PN_uint32); class NetDatagram; diff --git a/panda/src/net/datagramUDPHeader.cxx b/panda/src/net/datagramUDPHeader.cxx index 1a9697de08..bcb7413640 100644 --- a/panda/src/net/datagramUDPHeader.cxx +++ b/panda/src/net/datagramUDPHeader.cxx @@ -32,9 +32,9 @@ DatagramUDPHeader:: DatagramUDPHeader(const NetDatagram &datagram) { const string &str = datagram.get_message(); - PRUint16 checksum = 0; + PN_uint16 checksum = 0; for (size_t p = 0; p < str.size(); p++) { - checksum += (PRUint16)(PRUint8)str[p]; + checksum += (PN_uint16)(PN_uint8)str[p]; } // Now pack the header. @@ -64,9 +64,9 @@ bool DatagramUDPHeader:: verify_datagram(const NetDatagram &datagram) const { const string &str = datagram.get_message(); - PRUint16 checksum = 0; + PN_uint16 checksum = 0; for (size_t p = 0; p < str.size(); p++) { - checksum += (PRUint16)(PRUint8)str[p]; + checksum += (PN_uint16)(PN_uint8)str[p]; } if (checksum == get_datagram_checksum()) { diff --git a/panda/src/net/datagramUDPHeader.h b/panda/src/net/datagramUDPHeader.h index dfc15fb8d2..eeccef0db4 100644 --- a/panda/src/net/datagramUDPHeader.h +++ b/panda/src/net/datagramUDPHeader.h @@ -24,10 +24,9 @@ #include "netDatagram.h" #include "datagramIterator.h" +#include "numeric_types.h" -#include - -static const int datagram_udp_header_size = sizeof(PRUint16); +static const int datagram_udp_header_size = sizeof(PN_uint16); class NetDatagram; diff --git a/panda/src/net/netAddress.cxx b/panda/src/net/netAddress.cxx index 9ad66bac52..d8d21ddb10 100644 --- a/panda/src/net/netAddress.cxx +++ b/panda/src/net/netAddress.cxx @@ -17,12 +17,8 @@ //////////////////////////////////////////////////////////////////// #include "netAddress.h" -#include "pprerror.h" #include "config_net.h" -#include -#include - //////////////////////////////////////////////////////////////////// // Function: NetAddress::Constructor @@ -31,19 +27,18 @@ //////////////////////////////////////////////////////////////////// NetAddress:: NetAddress() { - PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &_addr); } //////////////////////////////////////////////////////////////////// // Function: NetAddress::Constructor // Access: Public -// Description: Constructs an address from a given PRNetAddr. +// Description: Constructs an address from a given Socket_Address. // Normally, this constructor should not be used by user // code; instead, create a default NetAddress and use // one of the set_*() functions to set up an address. //////////////////////////////////////////////////////////////////// NetAddress:: -NetAddress(const PRNetAddr &addr) : _addr(addr) { +NetAddress(const Socket_Address &addr) : _addr(addr) { } @@ -57,9 +52,7 @@ NetAddress(const PRNetAddr &addr) : _addr(addr) { //////////////////////////////////////////////////////////////////// bool NetAddress:: set_any(int port) { - PR_InitializeNetAddr(PR_IpAddrAny, port, &_addr); - - return true; + return _addr.set_any_IP(port); } //////////////////////////////////////////////////////////////////// @@ -70,9 +63,7 @@ set_any(int port) { //////////////////////////////////////////////////////////////////// bool NetAddress:: set_localhost(int port) { - PR_InitializeNetAddr(PR_IpAddrLoopback, port, &_addr); - - return true; + return _addr.set_host("127.0.0.1", port); } //////////////////////////////////////////////////////////////////// @@ -84,90 +75,7 @@ set_localhost(int port) { //////////////////////////////////////////////////////////////////// bool NetAddress:: set_host(const string &hostname, int port) { - // If the hostname appears to be a dot-separated IPv4 address, then - // parse it directly and store it. Some OS system libraries - // (notably Win95) can't parse this themselves. - union { - PRUint32 l; - unsigned char n[4]; - } ipaddr; - int ni = 0; - bool is_ip = true; - size_t p = 0; - size_t q = 0; - unsigned int num = 0; - - while (p < hostname.length() && ni < 4 && is_ip) { - if (hostname[p] == '.' && p > q) { - // Now we have a number between q and p. - ipaddr.n[ni] = (unsigned char)num; - p++; - q = p; - num = 0; - ni++; - - if (num >= 256 || ni >= 4) { - is_ip = false; - } - - } else if (isdigit(hostname[p])) { - num = 10 * num + (unsigned int)(hostname[p] - '0'); - p++; - if (num >= 256) { - is_ip = false; - } - } else { - is_ip = false; - } - } - - if (p == hostname.length() && ni < 4 && is_ip && p > q) { - ipaddr.n[ni] = (unsigned char)num; - ni++; - - if (num >= 256) { - is_ip = false; - } - } - - if (p == hostname.length() && ni == 4 && is_ip) { - net_cat.debug() - << "Parsed IP " << (int)ipaddr.n[0] << "." << (int)ipaddr.n[1] - << "." << (int)ipaddr.n[2] << "." << (int)ipaddr.n[3] << "\n"; - - memset(&_addr, 0, sizeof(PRNetAddr)); - _addr.inet.family = PR_AF_INET; - _addr.inet.port = PR_htons(port); - _addr.inet.ip = ipaddr.l; - - } else { - // If it's not a numeric IPv4 address, pass the whole thing on to - // GetHostByName and let NSPR deal with it. - - char buf[PR_NETDB_BUF_SIZE]; - PRHostEnt host; - PRStatus result = - PR_GetHostByName(hostname.c_str(), buf, PR_NETDB_BUF_SIZE, &host); - if (result != PR_SUCCESS) { - pprerror("PR_GetHostByName"); - net_cat.error() - << "Unable to look up hostname " << hostname << ".\n"; - return false; - } - - PRIntn next = PR_EnumerateHostEnt(0, &host, port, &_addr); - - if (next == -1) { - pprerror("PR_EnumerateHostEnt"); - return false; - } else if (next == 0) { - net_cat.error() - << "No addresses available for " << hostname << ".\n"; - return false; - } - } - - return true; + return _addr.set_host(hostname, port); } //////////////////////////////////////////////////////////////////// @@ -177,7 +85,7 @@ set_host(const string &hostname, int port) { //////////////////////////////////////////////////////////////////// void NetAddress:: clear() { - PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &_addr); + _addr.clear(); } //////////////////////////////////////////////////////////////////// @@ -187,7 +95,7 @@ clear() { //////////////////////////////////////////////////////////////////// int NetAddress:: get_port() const { - return PR_ntohs(_addr.inet.port); + return _addr.get_port(); } //////////////////////////////////////////////////////////////////// @@ -198,7 +106,7 @@ get_port() const { //////////////////////////////////////////////////////////////////// void NetAddress:: set_port(int port) { - PR_InitializeNetAddr(PR_IpAddrNull, port, &_addr); + _addr.set_port(port); } //////////////////////////////////////////////////////////////////// @@ -209,17 +117,7 @@ set_port(int port) { //////////////////////////////////////////////////////////////////// string NetAddress:: get_ip_string() const { - static const int buf_len = 1024; - char buf[buf_len]; - - PRStatus result = - PR_NetAddrToString(&_addr, buf, buf_len); - if (result != PR_SUCCESS) { - pprerror("PR_NetAddrToString"); - return "error"; - } - - return string(buf); + return _addr.get_ip(); } //////////////////////////////////////////////////////////////////// @@ -230,7 +128,7 @@ get_ip_string() const { //////////////////////////////////////////////////////////////////// PN_uint32 NetAddress:: get_ip() const { - return PR_ntohl(_addr.inet.ip); + return _addr.GetIPAddressRaw(); } //////////////////////////////////////////////////////////////////// @@ -244,7 +142,8 @@ get_ip() const { PN_uint8 NetAddress:: get_ip_component(int n) const { nassertr(n >= 0 && n < 4, 0); - const PN_uint8 *ip = (const PN_uint8 *)&_addr.inet.ip; + PN_uint32 ip_long = _addr.GetIPAddressRaw(); + const PN_uint8 *ip = (const PN_uint8 *)&ip_long; return ip[n]; } @@ -252,11 +151,11 @@ get_ip_component(int n) const { //////////////////////////////////////////////////////////////////// // Function: NetAddress::get_addr // Access: Public -// Description: Returns the PRNetAddr for this address. +// Description: Returns the Socket_Address for this address. //////////////////////////////////////////////////////////////////// -PRNetAddr *NetAddress:: +const Socket_Address &NetAddress:: get_addr() const { - return (PRNetAddr *)&_addr; + return _addr; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/net/netAddress.h b/panda/src/net/netAddress.h index 297d4fd098..d97e0e2231 100644 --- a/panda/src/net/netAddress.h +++ b/panda/src/net/netAddress.h @@ -21,8 +21,7 @@ #include "pandabase.h" #include "numeric_types.h" - -#include +#include "socket_address.h" //////////////////////////////////////////////////////////////////// // Class : NetAddress @@ -32,7 +31,7 @@ class EXPCL_PANDA NetAddress { PUBLISHED: NetAddress(); - NetAddress(const PRNetAddr &addr); + NetAddress(const Socket_Address &addr); bool set_any(int port); bool set_localhost(int port); @@ -46,12 +45,12 @@ PUBLISHED: PN_uint32 get_ip() const; PN_uint8 get_ip_component(int n) const; - PRNetAddr *get_addr() const; + const Socket_Address &get_addr() const; void output(ostream &out) const; private: - PRNetAddr _addr; + Socket_Address _addr; }; INLINE ostream &operator << (ostream &out, const NetAddress &addr) { diff --git a/panda/src/net/net_composite1.cxx b/panda/src/net/net_composite1.cxx index a6d4c466b7..4470824594 100644 --- a/panda/src/net/net_composite1.cxx +++ b/panda/src/net/net_composite1.cxx @@ -1,6 +1,5 @@ #include "config_net.cxx" -#include "pprerror.cxx" #include "connection.cxx" #include "connectionListener.cxx" #include "connectionManager.cxx" diff --git a/panda/src/net/pprerror.cxx b/panda/src/net/pprerror.cxx deleted file mode 100644 index 66d92f0e1c..0000000000 --- a/panda/src/net/pprerror.cxx +++ /dev/null @@ -1,238 +0,0 @@ -// Filename: pprerror.cxx -// Created by: drose (08Feb00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "pandabase.h" -#include "pprerror.h" -#include "config_net.h" - -#include -#include -#include - -#include -#include - -static const char *get_error_message(PRErrorCode code); - -//////////////////////////////////////////////////////////////////// -// Function: pprerror -// Description: A handy function like perror(). It outputs the -// printf-style format string and its arguments, -// followed by a colon and the NSPR-given description of -// its current error state. -//////////////////////////////////////////////////////////////////// -void -pprerror(const char *format, ...) { - va_list ap; - va_start(ap, format); - - char *str = PR_vsprintf_append(NULL, format, ap); - if (str == (char *)NULL) { - net_cat.error() - << string("Invalid format string: ") + format + "\n"; - return; - } - - PRErrorCode code = PR_GetError(); - const char *error_message = get_error_message(code); - - if (error_message == (const char *)NULL) { - str = PR_sprintf_append(str, ": (%d)\n", code); - } else { - str = PR_sprintf_append(str, ": %s (%d)\n", error_message, code); - } - - net_cat.error() << str; - - PR_Free(str); - if (get_net_error_abort()) { - abort(); - } - va_end(ap); -} - -//////////////////////////////////////////////////////////////////// -// Function: get_error_message -// Description: A local function to this module, it returns a -// sensibly formatted string to describe the given NSPR -// error code. The strings in this function were -// extracted from the NSPR documentation web site. -//////////////////////////////////////////////////////////////////// -static const char * -get_error_message(PRErrorCode code) { - switch (code) { - case PR_OUT_OF_MEMORY_ERROR: - return "PR_OUT_OF_MEMORY_ERROR--Insufficient memory to perform request."; - case PR_BAD_DESCRIPTOR_ERROR: - return "PR_BAD_DESCRIPTOR_ERROR--The file descriptor used as an argument in the preceding function is invalid."; - case PR_WOULD_BLOCK_ERROR: - return "PR_WOULD_BLOCK_ERROR--The operation would have blocked, which conflicts with the semantics that have been established."; - case PR_ACCESS_FAULT_ERROR: - return "PR_ACCESS_FAULT_ERROR--One of the arguments of the preceding function specified an invalid memory address."; - case PR_INVALID_METHOD_ERROR: - return "PR_INVALID_METHOD_ERROR--The preceding function is invalid for the type of file descriptor used."; - case PR_ILLEGAL_ACCESS_ERROR: - return "PR_ILLEGAL_ACCESS_ERROR--One of the arguments of the preceding function specified an invalid memory address."; - case PR_UNKNOWN_ERROR: - return "PR_UNKNOWN_ERROR--Some unknown error has occurred."; - case PR_PENDING_INTERRUPT_ERROR: - return "PR_PENDING_INTERRUPT_ERROR--The operation terminated because another thread has interrupted it with PR_Interrupt."; - case PR_NOT_IMPLEMENTED_ERROR: - return "PR_NOT_IMPLEMENTED_ERROR--The preceding function has not been implemented."; - case PR_IO_ERROR: - return "PR_IO_ERROR--The preceding I/O function encountered some sort of an error, perhaps an invalid device."; - case PR_IO_TIMEOUT_ERROR: - return "PR_IO_TIMEOUT_ERROR--The I/O operation has not completed in the time specified for the preceding function."; - case PR_IO_PENDING_ERROR: - return "PR_IO_PENDING_ERROR--An I/O operation has been attempted on a file descriptor that is currently busy with another operation."; - case PR_DIRECTORY_OPEN_ERROR: - return "PR_DIRECTORY_OPEN_ERROR--The directory could not be opened."; - case PR_INVALID_ARGUMENT_ERROR: - return "PR_INVALID_ARGUMENT_ERROR--One or more of the arguments to the function is invalid."; - case PR_ADDRESS_NOT_AVAILABLE_ERROR: - return "PR_ADDRESS_NOT_AVAILABLE_ERROR--The network address (PRNetAddr) is not available (probably in use)."; - case PR_ADDRESS_NOT_SUPPORTED_ERROR: - return "PR_ADDRESS_NOT_SUPPORTED_ERROR--The type of network address specified is not supported."; - case PR_IS_CONNECTED_ERROR: - return "PR_IS_CONNECTED_ERROR--An attempt to connect on an already connected network file descriptor."; - case PR_BAD_ADDRESS_ERROR: - return "PR_BAD_ADDRESS_ERROR--The network address specified is invalid (as reported by the network)."; - case PR_ADDRESS_IN_USE_ERROR: - return "PR_ADDRESS_IN_USE_ERROR--Network address specified (PRNetAddr) is in use."; - case PR_CONNECT_REFUSED_ERROR: - return "PR_CONNECT_REFUSED_ERROR--The peer has refused to allow the connection to be established."; - case PR_NETWORK_UNREACHABLE_ERROR: - return "PR_NETWORK_UNREACHABLE_ERROR--The network address specifies a host that is unreachable (perhaps temporary)."; - case PR_CONNECT_TIMEOUT_ERROR: - return "PR_CONNECT_TIMEOUT_ERROR--The connection attempt did not complete in a reasonable period of time."; - case PR_NOT_CONNECTED_ERROR: - return "PR_NOT_CONNECTED_ERROR--The preceding function attempted to use connected semantics on a network file descriptor that was not connected."; - case PR_LOAD_LIBRARY_ERROR: - return "PR_LOAD_LIBRARY_ERROR--Failure to load a dynamic library."; - case PR_UNLOAD_LIBRARY_ERROR: - return "PR_UNLOAD_LIBRARY_ERROR--Failure to unload a dynamic library."; - case PR_FIND_SYMBOL_ERROR: - return "PR_FIND_SYMBOL_ERROR--Symbol could not be found in the specified library."; - case PR_INSUFFICIENT_RESOURCES_ERROR: - return "PR_INSUFFICIENT_RESOURCES_ERROR--There are insufficient system resources to process the request."; - case PR_DIRECTORY_LOOKUP_ERROR: - return "PR_DIRECTORY_LOOKUP_ERROR--A directory lookup on a network address has failed."; - case PR_TPD_RANGE_ERROR: - return "PR_TPD_RANGE_ERROR--Attempt to access a thread-private data index that is out of range of any index that has been allocated to the process."; - case PR_PROC_DESC_TABLE_FULL_ERROR: - return "PR_PROC_DESC_TABLE_FULL_ERROR--The process' table for holding open file descriptors is full."; - case PR_SYS_DESC_TABLE_FULL_ERROR: - return "PR_SYS_DESC_TABLE_FULL_ERROR--The system's table for holding open file descriptors has been exceeded."; - case PR_NOT_SOCKET_ERROR: - return "PR_NOT_SOCKET_ERROR--An attempt to use a non-network file descriptor on a network-only operation."; - case PR_NOT_TCP_SOCKET_ERROR: - return "PR_NOT_TCP_SOCKET_ERROR--Attempt to perform a TCP specific function on a non-TCP file descriptor."; - case PR_SOCKET_ADDRESS_IS_BOUND_ERROR: - return "PR_SOCKET_ADDRESS_IS_BOUND_ERROR--Attempt to bind an address to a TCP file descriptor that is already bound."; - case PR_NO_ACCESS_RIGHTS_ERROR: - return "PR_NO_ACCESS_RIGHTS_ERROR--Calling thread does not have privilege to perform the operation requested."; - case PR_OPERATION_NOT_SUPPORTED_ERROR: - return "PR_OPERATION_NOT_SUPPORTED_ERROR--The requested operation is not supported by the platform."; - case PR_PROTOCOL_NOT_SUPPORTED_ERROR: - return "PR_PROTOCOL_NOT_SUPPORTED_ERROR--The host operating system does not support the protocol requested."; - case PR_REMOTE_FILE_ERROR: - return "PR_REMOTE_FILE_ERROR--Access to the remote file has been severed."; - case PR_BUFFER_OVERFLOW_ERROR: - return "PR_BUFFER_OVERFLOW_ERROR--The value retrieved is too large to be stored in the buffer provided."; - case PR_CONNECT_RESET_ERROR: - return "PR_CONNECT_RESET_ERROR--The (TCP) connection has been reset by the peer."; - case PR_RANGE_ERROR: - return "PR_RANGE_ERROR--Unused."; - case PR_DEADLOCK_ERROR: - return "PR_DEADLOCK_ERROR--Performing the requested operation would have caused a deadlock. The deadlock was avoided."; - case PR_FILE_IS_LOCKED_ERROR: - return "PR_FILE_IS_LOCKED_ERROR--An attempt to acquire a lock on a file has failed because the file is already locked."; - case PR_FILE_TOO_BIG_ERROR: - return "PR_FILE_TOO_BIG_ERROR--Completing the write or seek operation would have resulted in a file larger than the system could handle."; - case PR_NO_DEVICE_SPACE_ERROR: - return "PR_NO_DEVICE_SPACE_ERROR--The device for storing the file is full."; - case PR_PIPE_ERROR: - return "PR_PIPE_ERROR--Unused."; - case PR_NO_SEEK_DEVICE_ERROR: - return "PR_NO_SEEK_DEVICE_ERROR--Unused."; - case PR_IS_DIRECTORY_ERROR: - return "PR_IS_DIRECTORY_ERROR--Attempt to perform a normal file operation on a directory."; - case PR_LOOP_ERROR: - return "PR_LOOP_ERROR--Symbolic link loop."; - case PR_NAME_TOO_LONG_ERROR: - return "PR_NAME_TOO_LONG_ERROR--Filename is longer than allowed by the host operating system."; - case PR_FILE_NOT_FOUND_ERROR: - return "PR_FILE_NOT_FOUND_ERROR--The requested file was not found."; - case PR_NOT_DIRECTORY_ERROR: - return "PR_NOT_DIRECTORY_ERROR--Attempt to perform directory specific operations on a normal file."; - case PR_READ_ONLY_FILESYSTEM_ERROR: - return "PR_READ_ONLY_FILESYSTEM_ERROR--Attempt to write to a read-only file system."; - case PR_DIRECTORY_NOT_EMPTY_ERROR: - return "PR_DIRECTORY_NOT_EMPTY_ERROR--Attempt to delete a directory that is not empty."; - case PR_FILESYSTEM_MOUNTED_ERROR: - return "PR_FILESYSTEM_MOUNTED_ERROR--Attempt to delete or rename a file object while the file system is busy."; - case PR_NOT_SAME_DEVICE_ERROR: - return "PR_NOT_SAME_DEVICE_ERROR--Request to rename a file to a file system on another device."; - case PR_DIRECTORY_CORRUPTED_ERROR: - return "PR_DIRECTORY_CORRUPTED_ERROR--The directory object in the file system is corrupted."; - case PR_FILE_EXISTS_ERROR: - return "PR_FILE_EXISTS_ERROR--Attempt to create or rename a file when the new name is already being used."; - case PR_MAX_DIRECTORY_ENTRIES_ERROR: - return "PR_MAX_DIRECTORY_ENTRIES_ERROR--Attempt to add new filename to directory would exceed the limit allowed."; - case PR_INVALID_DEVICE_STATE_ERROR: - return "PR_INVALID_DEVICE_STATE_ERROR--The device was in an invalid state to complete the desired operation."; - case PR_DEVICE_IS_LOCKED_ERROR: - return "PR_DEVICE_IS_LOCKED_ERROR--The device needed to perform the desired request is locked."; - case PR_NO_MORE_FILES_ERROR: - return "PR_NO_MORE_FILES_ERROR--There are no more entries in the directory."; - case PR_END_OF_FILE_ERROR: - return "PR_END_OF_FILE_ERROR--Unexpectedly encountered end of file (Mac OS only)."; - case PR_FILE_SEEK_ERROR: - return "PR_FILE_SEEK_ERROR--An unexpected seek error (Mac OS only)."; - case PR_FILE_IS_BUSY_ERROR: - return "PR_FILE_IS_BUSY_ERROR--The file is busy and the operation cannot be performed (Mac OS only)."; - case PR_IN_PROGRESS_ERROR: - return "PR_IN_PROGRESS_ERROR--The operation is still in progress (probably a nonblocking connect)."; - case PR_ALREADY_INITIATED_ERROR: - return "PR_ALREADY_INITIATED_ERROR--The (retried) operation has already been initiated (probably a nonblocking connect)."; - case PR_GROUP_EMPTY_ERROR: - return "PR_GROUP_EMPTY_ERROR--The wait group is empty."; - case PR_INVALID_STATE_ERROR: - return "PR_INVALID_STATE_ERROR--The attempted operation is on an object that was in an improper state to perform the request."; - - // These were added with NSPR 4.0. -#ifdef PR_NETWORK_DOWN_ERROR - case PR_NETWORK_DOWN_ERROR: - return "PR_NETWORK_DOWN_ERROR--The network is down."; - - case PR_SOCKET_SHUTDOWN_ERROR: - return "PR_SOCKET_SHUTDOWN_ERROR--The socket has been shut down."; - - case PR_CONNECT_ABORTED_ERROR: - return "PR_CONNECT_ABORTED_ERROR--The connection has been aborted."; - - case PR_HOST_UNREACHABLE_ERROR: - return "PR_HOST_UNREACHABLE_ERROR--The host is unreachable."; -#endif - - case PR_MAX_ERROR: - return "PR_MAX_ERROR--Placeholder for the end of the list."; - } - - return (const char *)NULL; -} diff --git a/panda/src/net/queuedConnectionListener.h b/panda/src/net/queuedConnectionListener.h index 0b5a4e7655..f65ff0b47d 100644 --- a/panda/src/net/queuedConnectionListener.h +++ b/panda/src/net/queuedConnectionListener.h @@ -25,8 +25,6 @@ #include "connection.h" #include "netAddress.h" #include "queuedReturn.h" - -#include #include "pdeque.h" diff --git a/panda/src/net/queuedConnectionManager.cxx b/panda/src/net/queuedConnectionManager.cxx index 86da10f4c7..352f810305 100644 --- a/panda/src/net/queuedConnectionManager.cxx +++ b/panda/src/net/queuedConnectionManager.cxx @@ -98,8 +98,8 @@ get_reset_connection(PT(Connection) &connection) { // been reset. //////////////////////////////////////////////////////////////////// void QueuedConnectionManager:: -connection_reset(const PT(Connection) &connection, PRErrorCode errcode) { - ConnectionManager::connection_reset(connection, errcode); +connection_reset(const PT(Connection) &connection, bool okflag) { + ConnectionManager::connection_reset(connection, okflag); // Largely, we don't care if this particular queue fills up. If it // does, it probably just means the user isn't bothering to track diff --git a/panda/src/net/queuedConnectionManager.h b/panda/src/net/queuedConnectionManager.h index 32f89585a7..1128d978dc 100644 --- a/panda/src/net/queuedConnectionManager.h +++ b/panda/src/net/queuedConnectionManager.h @@ -25,8 +25,6 @@ #include "queuedReturn.h" #include "pdeque.h" -#include - EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, QueuedReturn< PT(Connection) >); //////////////////////////////////////////////////////////////////// @@ -53,7 +51,7 @@ PUBLISHED: protected: virtual void connection_reset(const PT(Connection) &connection, - PRErrorCode errcode); + bool okflag); }; #endif diff --git a/panda/src/net/queuedConnectionReader.cxx b/panda/src/net/queuedConnectionReader.cxx index fd386586b6..e1687e334e 100644 --- a/panda/src/net/queuedConnectionReader.cxx +++ b/panda/src/net/queuedConnectionReader.cxx @@ -19,6 +19,7 @@ #include "queuedConnectionReader.h" #include "config_net.h" #include "trueClock.h" +#include "mutexHolder.h" //////////////////////////////////////////////////////////////////// // Function: QueuedConnectionReader::Constructor @@ -30,7 +31,6 @@ QueuedConnectionReader(ConnectionManager *manager, int num_threads) : ConnectionReader(manager, num_threads) { #ifdef SIMULATE_NETWORK_DELAY - _dd_mutex = PR_NewLock(); _delay_active = false; _min_delay = 0.0; _delay_variance = 0.0; @@ -47,10 +47,6 @@ QueuedConnectionReader:: // We call shutdown() here to guarantee that all threads are gone // before the QueuedReturn destructs. shutdown(); - -#ifdef SIMULATE_NETWORK_DELAY - PR_DestroyLock(_dd_mutex); -#endif // SIMULATE_NETWORK_DELAY } //////////////////////////////////////////////////////////////////// @@ -149,11 +145,10 @@ receive_datagram(const NetDatagram &datagram) { //////////////////////////////////////////////////////////////////// void QueuedConnectionReader:: start_delay(double min_delay, double max_delay) { - PR_Lock(_dd_mutex); + MutexHolder holder(_dd_mutex); _min_delay = min_delay; _delay_variance = max(max_delay - min_delay, 0.0); _delay_active = true; - PR_Unlock(_dd_mutex); } //////////////////////////////////////////////////////////////////// @@ -165,7 +160,7 @@ start_delay(double min_delay, double max_delay) { //////////////////////////////////////////////////////////////////// void QueuedConnectionReader:: stop_delay() { - PR_Lock(_dd_mutex); + MutexHolder holder(_dd_mutex); _delay_active = false; // Copy the entire contents of the delay queue to the normal queue. @@ -177,8 +172,6 @@ stop_delay() { } _delayed.pop_front(); } - - PR_Unlock(_dd_mutex); } //////////////////////////////////////////////////////////////////// @@ -191,7 +184,7 @@ stop_delay() { void QueuedConnectionReader:: get_delayed() { if (_delay_active) { - PR_Lock(_dd_mutex); + MutexHolder holder(_dd_mutex); double now = TrueClock::get_global_ptr()->get_short_time(); while (!_delayed.empty()) { const DelayedDatagram &dd = _delayed.front(); @@ -205,7 +198,6 @@ get_delayed() { } _delayed.pop_front(); } - PR_Unlock(_dd_mutex); } } @@ -223,7 +215,7 @@ delay_datagram(const NetDatagram &datagram) { << "QueuedConnectionReader queue full!\n"; } } else { - PR_Lock(_dd_mutex); + MutexHolder holder(_dd_mutex); // Check the delay_active flag again, now that we have grabbed the // mutex. if (!_delay_active) { @@ -244,7 +236,6 @@ delay_datagram(const NetDatagram &datagram) { dd._reveal_time = reveal_time; dd._datagram = datagram; } - PR_Unlock(_dd_mutex); } } diff --git a/panda/src/net/queuedConnectionReader.h b/panda/src/net/queuedConnectionReader.h index 889516437b..713001027b 100644 --- a/panda/src/net/queuedConnectionReader.h +++ b/panda/src/net/queuedConnectionReader.h @@ -24,8 +24,7 @@ #include "connectionReader.h" #include "netDatagram.h" #include "queuedReturn.h" - -#include +#include "pmutex.h" #include "pdeque.h" EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, QueuedReturn); @@ -67,7 +66,7 @@ private: NetDatagram _datagram; }; - PRLock *_dd_mutex; + Mutex _dd_mutex; typedef pdeque Delayed; Delayed _delayed; bool _delay_active; diff --git a/panda/src/net/queuedReturn.I b/panda/src/net/queuedReturn.I index 63e4611e52..b8a1bdd0d5 100644 --- a/panda/src/net/queuedReturn.I +++ b/panda/src/net/queuedReturn.I @@ -16,9 +16,6 @@ // //////////////////////////////////////////////////////////////////// -#include "config_net.h" - -#include //////////////////////////////////////////////////////////////////// // Function: QueuedReturn::set_max_queue_size @@ -35,9 +32,8 @@ template void QueuedReturn:: set_max_queue_size(int max_size) { - PR_Lock(_mutex); + MutexHolder holder(_mutex); _max_queue_size = max_size; - PR_Unlock(_mutex); } //////////////////////////////////////////////////////////////////// @@ -60,9 +56,8 @@ get_max_queue_size() const { template int QueuedReturn:: get_current_queue_size() const { - PR_Lock(_mutex); + MutexHolder holder(_mutex); int size = _things.size(); - PR_Unlock(_mutex); return size; } @@ -100,7 +95,6 @@ reset_overflow_flag() { template QueuedReturn:: QueuedReturn() { - _mutex = PR_NewLock(); _available = false; _max_queue_size = get_net_max_response_queue(); _overflow_flag = false; @@ -114,7 +108,6 @@ QueuedReturn() { template QueuedReturn:: ~QueuedReturn() { - PR_DestroyLock(_mutex); } //////////////////////////////////////////////////////////////////// @@ -145,18 +138,16 @@ thing_available() const { template bool QueuedReturn:: get_thing(Thing &result) { - PR_Lock(_mutex); + MutexHolder holder(_mutex); if (_things.empty()) { // Huh. Nothing after all. _available = false; - PR_Unlock(_mutex); return false; } result = _things.front(); _things.pop_front(); _available = !_things.empty(); - PR_Unlock(_mutex); return true; } @@ -170,7 +161,7 @@ get_thing(Thing &result) { template bool QueuedReturn:: enqueue_thing(const Thing &thing) { - PR_Lock(_mutex); + MutexHolder holder(_mutex); bool enqueue_ok = ((int)_things.size() < _max_queue_size); if (enqueue_ok) { _things.push_back(thing); @@ -178,7 +169,6 @@ enqueue_thing(const Thing &thing) { _overflow_flag = true; } _available = true; - PR_Unlock(_mutex); return enqueue_ok; } @@ -195,7 +185,7 @@ enqueue_thing(const Thing &thing) { template bool QueuedReturn:: enqueue_unique_thing(const Thing &thing) { - PR_Lock(_mutex); + MutexHolder holder(_mutex); bool enqueue_ok = ((int)_things.size() < _max_queue_size); if (enqueue_ok) { if (find(_things.begin(), _things.end(), thing) == _things.end()) { @@ -210,7 +200,6 @@ enqueue_unique_thing(const Thing &thing) { _overflow_flag = true; } _available = true; - PR_Unlock(_mutex); return enqueue_ok; } diff --git a/panda/src/net/queuedReturn.h b/panda/src/net/queuedReturn.h index eba8b3ebf2..7f7113f458 100644 --- a/panda/src/net/queuedReturn.h +++ b/panda/src/net/queuedReturn.h @@ -24,9 +24,12 @@ #include "connectionListener.h" #include "connection.h" #include "netAddress.h" - -#include +#include "pmutex.h" #include "pdeque.h" +#include "config_net.h" +#include "mutexHolder.h" + +#include //////////////////////////////////////////////////////////////////// // Class : QueuedReturn @@ -56,7 +59,7 @@ protected: bool enqueue_unique_thing(const Thing &thing); private: - PRLock *_mutex; + Mutex _mutex; pdeque _things; bool _available; int _max_queue_size; diff --git a/panda/src/net/recentConnectionReader.cxx b/panda/src/net/recentConnectionReader.cxx index 563af27c60..ef7a774fb9 100644 --- a/panda/src/net/recentConnectionReader.cxx +++ b/panda/src/net/recentConnectionReader.cxx @@ -18,6 +18,7 @@ #include "recentConnectionReader.h" #include "config_net.h" +#include "mutexHolder.h" //////////////////////////////////////////////////////////////////// // Function: RecentConnectionReader::Constructor @@ -33,7 +34,6 @@ RecentConnectionReader(ConnectionManager *manager) : // this should be impossible, because we can't receive datagrams // before we call add_connection(). _available = false; - _mutex = PR_NewLock(); } //////////////////////////////////////////////////////////////////// @@ -46,8 +46,6 @@ RecentConnectionReader:: // We call shutdown() here to guarantee that all threads are gone // before the RecentConnectionReader destructs. shutdown(); - - PR_DestroyLock(_mutex); } //////////////////////////////////////////////////////////////////// @@ -76,16 +74,14 @@ data_available() { //////////////////////////////////////////////////////////////////// bool RecentConnectionReader:: get_data(NetDatagram &result) { - PR_Lock(_mutex); + MutexHolder holder(_mutex); if (!_available) { // Huh. Nothing after all. - PR_Unlock(_mutex); return false; } result = _datagram; _available = false; - PR_Unlock(_mutex); return true; } @@ -125,8 +121,7 @@ receive_datagram(const NetDatagram &datagram) { << " bytes\n"; } - PR_Lock(_mutex); + MutexHolder holder(_mutex); _datagram = datagram; _available = true; - PR_Unlock(_mutex); } diff --git a/panda/src/net/recentConnectionReader.h b/panda/src/net/recentConnectionReader.h index 4990a8d56b..a620693e92 100644 --- a/panda/src/net/recentConnectionReader.h +++ b/panda/src/net/recentConnectionReader.h @@ -23,8 +23,7 @@ #include "connectionReader.h" #include "netDatagram.h" - -#include +#include "pmutex.h" //////////////////////////////////////////////////////////////////// // Class : RecentConnectionReader @@ -53,7 +52,7 @@ protected: private: bool _available; Datagram _datagram; - PRLock *_mutex; + Mutex _mutex; }; #endif diff --git a/panda/src/net/test_raw_server.cxx b/panda/src/net/test_raw_server.cxx index ce62e9cf1d..1ab3b379ba 100644 --- a/panda/src/net/test_raw_server.cxx +++ b/panda/src/net/test_raw_server.cxx @@ -25,7 +25,7 @@ #include "netAddress.h" #include "connection.h" #include "netDatagram.h" - +#include "thread.h" #include "pset.h" int @@ -99,7 +99,7 @@ main(int argc, char *argv[]) { } // Yield the timeslice before we poll again. - PR_Sleep(PR_MillisecondsToInterval(100)); + Thread::sleep(0.1); } return (0); diff --git a/panda/src/net/test_spam_client.cxx b/panda/src/net/test_spam_client.cxx index be30584ef4..50e878aa56 100644 --- a/panda/src/net/test_spam_client.cxx +++ b/panda/src/net/test_spam_client.cxx @@ -22,10 +22,9 @@ #include "netAddress.h" #include "connection.h" #include "netDatagram.h" - +#include "clockObject.h" #include "datagram_ui.h" - -#include +#include "thread.h" int main(int argc, char *argv[]) { @@ -69,12 +68,14 @@ main(int argc, char *argv[]) { int num_sent = 0; int num_received = 0; - PRIntervalTime last_reported_time = PR_IntervalNow(); - PRIntervalTime report_interval = PR_SecondsToInterval(5); + + ClockObject *global_clock = ClockObject::get_global_clock(); + double last_reported_time = global_clock->get_real_time(); + static const double report_interval = 5.0; while (!lost_connection) { // Send the datagram. - if (writer.send(datagram, c, host)) { + if (writer.send(datagram, c)) { num_sent++; } @@ -99,15 +100,15 @@ main(int argc, char *argv[]) { } } - PRIntervalTime now = PR_IntervalNow(); - if ((PRIntervalTime)(now - last_reported_time) > report_interval) { + double now = global_clock->get_real_time(); + if ((now - last_reported_time) > report_interval) { nout << "Sent " << num_sent << ", received " << num_received << " datagrams.\n"; last_reported_time = now; } // Yield the timeslice before we poll again. - // PR_Sleep(PR_MillisecondsToInterval(1)); + Thread::sleep(0.001); } return (0); diff --git a/panda/src/net/test_spam_server.cxx b/panda/src/net/test_spam_server.cxx index 2f0502d253..0001c004e9 100644 --- a/panda/src/net/test_spam_server.cxx +++ b/panda/src/net/test_spam_server.cxx @@ -27,8 +27,8 @@ #include "netDatagram.h" #include "datagram_ui.h" - -#include +#include "clockObject.h" +#include "thread.h" #include "pset.h" #include @@ -65,8 +65,10 @@ main(int argc, char *argv[]) { int num_sent = 0; int num_received = 0; - PRIntervalTime last_reported_time = PR_IntervalNow(); - PRIntervalTime report_interval = PR_SecondsToInterval(5); + + ClockObject *global_clock = ClockObject::get_global_clock(); + double last_reported_time = global_clock->get_real_time(); + static const double report_interval = 5.0; bool shutdown = false; while (!shutdown) { @@ -107,15 +109,15 @@ main(int argc, char *argv[]) { } } - PRIntervalTime now = PR_IntervalNow(); - if ((PRIntervalTime)(now - last_reported_time) > report_interval) { + double now = global_clock->get_real_time(); + if ((now - last_reported_time) > report_interval) { nout << "Sent " << num_sent << ", received " << num_received << " datagrams.\n"; last_reported_time = now; } // Yield the timeslice before we poll again. - // PR_Sleep(PR_MillisecondsToInterval(1)); + Thread::sleep(0.001); } return (0); diff --git a/panda/src/net/test_tcp_server.cxx b/panda/src/net/test_tcp_server.cxx index e24c7fde31..5535f33f41 100644 --- a/panda/src/net/test_tcp_server.cxx +++ b/panda/src/net/test_tcp_server.cxx @@ -25,7 +25,7 @@ #include "netAddress.h" #include "connection.h" #include "netDatagram.h" - +#include "thread.h" #include "datagram_ui.h" #include "pset.h" @@ -119,7 +119,7 @@ main(int argc, char *argv[]) { } // Yield the timeslice before we poll again. - PR_Sleep(PR_MillisecondsToInterval(100)); + Thread::sleep(0.1); } return (0); diff --git a/panda/src/pipeline/Sources.pp b/panda/src/pipeline/Sources.pp index 231c07c129..87aa0e02e0 100644 --- a/panda/src/pipeline/Sources.pp +++ b/panda/src/pipeline/Sources.pp @@ -6,6 +6,7 @@ #begin lib_target #define TARGET pipeline + #define USE_PACKAGES threads #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx diff --git a/panda/src/pstatclient/pStatClientImpl.cxx b/panda/src/pstatclient/pStatClientImpl.cxx index 56cc4ea32e..90538249cc 100644 --- a/panda/src/pstatclient/pStatClientImpl.cxx +++ b/panda/src/pstatclient/pStatClientImpl.cxx @@ -458,9 +458,14 @@ handle_server_control_message(const PStatServerControlMessage &message) { // has been lost. //////////////////////////////////////////////////////////////////// void PStatClientImpl:: -connection_reset(const PT(Connection) &connection, PRErrorCode) { +connection_reset(const PT(Connection) &connection, bool) { if (connection == _tcp_connection) { _client->client_disconnect(); + } else if (connection == _udp_connection) { + pstats_cat.warning() + << "Trouble sending UDP; switching to TCP only.\n"; + _tcp_count_factor = 0.0f; + _udp_count_factor = 1.0f; } else { pstats_cat.warning() << "Ignoring spurious connection_reset() message\n"; diff --git a/panda/src/pstatclient/pStatClientImpl.h b/panda/src/pstatclient/pStatClientImpl.h index 3af65cc001..38388ff8d1 100644 --- a/panda/src/pstatclient/pStatClientImpl.h +++ b/panda/src/pstatclient/pStatClientImpl.h @@ -94,7 +94,7 @@ private: void handle_server_control_message(const PStatServerControlMessage &message); virtual void connection_reset(const PT(Connection) &connection, - PRErrorCode errcode); + bool okflag); PStatClient *_client; diff --git a/pandatool/src/pstatserver/pStatServer.cxx b/pandatool/src/pstatserver/pStatServer.cxx index 8331d682f3..cec8baaf6f 100644 --- a/pandatool/src/pstatserver/pStatServer.cxx +++ b/pandatool/src/pstatserver/pStatServer.cxx @@ -18,7 +18,7 @@ #include "pStatServer.h" #include "pStatReader.h" - +#include "thread.h" #include "config_pstats.h" //////////////////////////////////////////////////////////////////// @@ -146,10 +146,7 @@ void PStatServer:: main_loop(bool *interrupt_flag) { while (interrupt_flag == (bool *)NULL || !*interrupt_flag) { poll(); - // Not great. This will totally blow in a threaded environment. - // We need a portable way to sleep or block. - PRIntervalTime sleep_timeout = PR_MillisecondsToInterval(100); - PR_Sleep(sleep_timeout); + Thread::sleep(0.1); } } @@ -336,7 +333,7 @@ is_thread_safe() { // parties and clean up gracefully. //////////////////////////////////////////////////////////////////// void PStatServer:: -connection_reset(const PT(Connection) &connection, PRErrorCode errcode) { +connection_reset(const PT(Connection) &connection, bool okflag) { // Was this a client connection? Tell the reader about it if it // was. close_connection(connection); diff --git a/pandatool/src/pstatserver/pStatServer.h b/pandatool/src/pstatserver/pStatServer.h index accda29600..7501e81729 100644 --- a/pandatool/src/pstatserver/pStatServer.h +++ b/pandatool/src/pstatserver/pStatServer.h @@ -70,7 +70,7 @@ public: protected: virtual void connection_reset(const PT(Connection) &connection, - PRErrorCode errcode); + bool okflag); private: void user_guide_bars_changed();