Compare commits
150 Commits
shycurl
...
curlthread
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8c2087d74 | ||
|
|
7adc0e24ab | ||
|
|
ba65f29a72 | ||
|
|
76eef6fe59 | ||
|
|
fe38f59bbb | ||
|
|
2bcabce1d6 | ||
|
|
ed4c6b7c92 | ||
|
|
785729abdf | ||
|
|
fb38f6adea | ||
|
|
3a30f1dc71 | ||
|
|
8802d5033f | ||
|
|
3d39564605 | ||
|
|
a8a30ae3b9 | ||
|
|
15af410e6f | ||
|
|
9e5cbf330f | ||
|
|
2fa9334090 | ||
|
|
fcdf5d377e | ||
|
|
756a284048 | ||
|
|
32e2b584b9 | ||
|
|
add52b4d57 | ||
|
|
a4d2cb3d12 | ||
|
|
72fbb3f63e | ||
|
|
c62290accb | ||
|
|
8ad40c5d66 | ||
|
|
cd5a721c23 | ||
|
|
643844c01d | ||
|
|
c84f080fc8 | ||
|
|
5fcdbfdd9e | ||
|
|
96fa4af939 | ||
|
|
2334793554 | ||
|
|
20e445b4be | ||
|
|
051263117d | ||
|
|
085db93fc8 | ||
|
|
8fe6925414 | ||
|
|
57ad7e62d2 | ||
|
|
03608103b8 | ||
|
|
675d171104 | ||
|
|
405af67f45 | ||
|
|
f772cbee51 | ||
|
|
72d93b8723 | ||
|
|
7f78870295 | ||
|
|
706b9c55c2 | ||
|
|
48ae0d003d | ||
|
|
51c5933b76 | ||
|
|
0204d09a89 | ||
|
|
465c6b9ed6 | ||
|
|
39847c4688 | ||
|
|
7721c6e3da | ||
|
|
648ed00ce2 | ||
|
|
87c9358813 | ||
|
|
64b968b262 | ||
|
|
c0fbf4bf55 | ||
|
|
900e533b4b | ||
|
|
01818582cf | ||
|
|
9a0620f140 | ||
|
|
0216925e05 | ||
|
|
32b24a98ca | ||
|
|
93d7a4938a | ||
|
|
56265b78ec | ||
|
|
6ee76aa6f7 | ||
|
|
32d6aefe00 | ||
|
|
84795863e5 | ||
|
|
9deb3e433c | ||
|
|
92a5b14347 | ||
|
|
3cee90fe8b | ||
|
|
2bb58bac2e | ||
|
|
9dc1897b35 | ||
|
|
7a7da24df5 | ||
|
|
46f7250f08 | ||
|
|
58bfe23e5a | ||
|
|
ccb914ea83 | ||
|
|
10fe67f4a6 | ||
|
|
a34247ebf4 | ||
|
|
53e96b02c0 | ||
|
|
7c022d6061 | ||
|
|
14e5b46687 | ||
|
|
0243c61ea1 | ||
|
|
d73d4e9d48 | ||
|
|
3d60d9e3c5 | ||
|
|
59e0367dd4 | ||
|
|
a6bb2604f6 | ||
|
|
b2c71c099f | ||
|
|
102eca7d65 | ||
|
|
55a1d54b8e | ||
|
|
1e24b889dd | ||
|
|
988e2c3fdf | ||
|
|
92dc20850d | ||
|
|
3acaf773b8 | ||
|
|
5080746fa0 | ||
|
|
07e1f0e802 | ||
|
|
340f8f1f17 | ||
|
|
0316b7ff9a | ||
|
|
7416d2aaf1 | ||
|
|
533675416c | ||
|
|
8baceee06c | ||
|
|
f7bf5c33bc | ||
|
|
0419f8bee9 | ||
|
|
f012f664d2 | ||
|
|
744563a150 | ||
|
|
389074d1e9 | ||
|
|
93778eccbb | ||
|
|
f46d8e8a10 | ||
|
|
f5bfab139c | ||
|
|
df20f918ba | ||
|
|
b8fc1f634e | ||
|
|
ae9dadb5d8 | ||
|
|
d31c062693 | ||
|
|
544928a039 | ||
|
|
14276b3cf8 | ||
|
|
07e7eeedd1 | ||
|
|
125a10bb44 | ||
|
|
9b8e5c8719 | ||
|
|
a803507d67 | ||
|
|
cb5efad026 | ||
|
|
26922a1578 | ||
|
|
90493b6571 | ||
|
|
2dee921cd5 | ||
|
|
433c7c3f99 | ||
|
|
fef461fd13 | ||
|
|
1f56645b69 | ||
|
|
69ca6cd5b2 | ||
|
|
8805e3fb27 | ||
|
|
64d8397ea5 | ||
|
|
4d4496fc4d | ||
|
|
af67342969 | ||
|
|
d9cbd52ea8 | ||
|
|
8b25d44bcf | ||
|
|
3d6733bed8 | ||
|
|
c3f3db518b | ||
|
|
385ec62e53 | ||
|
|
881524831f | ||
|
|
376be8b990 | ||
|
|
96ddbf2a8b | ||
|
|
c2ee420917 | ||
|
|
74a1ba0d1e | ||
|
|
0dc05a39e6 | ||
|
|
72fe406f64 | ||
|
|
90ac174260 | ||
|
|
b555e02220 | ||
|
|
507c94c24c | ||
|
|
2699fa8cf9 | ||
|
|
513002416c | ||
|
|
22530cd77e | ||
|
|
81521b98fd | ||
|
|
73c2feee97 | ||
|
|
d4212d390d | ||
|
|
2b8a55f396 | ||
|
|
f253da09ec | ||
|
|
e232abdab2 | ||
|
|
fae40e0bdf |
@@ -269,14 +269,23 @@ if (DARWIN)
|
||||
add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE)
|
||||
set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlong-branch")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mlong-branch")
|
||||
# NOTE: it's critical that the optimization flag is put in front.
|
||||
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
if(${CMAKE_C_COMPILER} MATCHES "gcc*")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlong-branch")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mlong-branch")
|
||||
# NOTE: it's critical that the optimization flag is put in front.
|
||||
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
elseif(${CMAKE_C_COMPILER} MATCHES "clang*")
|
||||
# NOTE: it's critical that the optimization flag is put in front.
|
||||
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -msse3")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -msse3")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -msse3")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 -msse3")
|
||||
endif()
|
||||
endif (DARWIN)
|
||||
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ else (STANDALONE)
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.0.dylib
|
||||
)
|
||||
set(APRUTIL_LIBRARIES
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libaprutil-1.0.dylib
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.0.dylib
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libaprutil-1.dylib
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.dylib
|
||||
)
|
||||
set(APRICONV_LIBRARIES iconv)
|
||||
else (WINDOWS)
|
||||
|
||||
@@ -40,10 +40,10 @@ else (STANDALONE)
|
||||
debug libboost_regex-vc${MSVC_SUFFIX}-${BOOST_DEBUG_SUFFIX}-${BOOST_VERSION})
|
||||
|
||||
elseif (DARWIN)
|
||||
set(BOOST_FILESYSTEM_LIBRARY boost_filesystem-mt)
|
||||
set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-mt)
|
||||
set(BOOST_REGEX_LIBRARY boost_regex-mt)
|
||||
set(BOOST_SYSTEM_LIBRARY boost_system-mt)
|
||||
set(BOOST_FILESYSTEM_LIBRARY boost_filesystem)
|
||||
set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options)
|
||||
set(BOOST_REGEX_LIBRARY boost_regex)
|
||||
set(BOOST_SYSTEM_LIBRARY boost_system)
|
||||
elseif (LINUX)
|
||||
set(BOOST_FILESYSTEM_LIBRARY boost_filesystem-mt)
|
||||
set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-mt)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
|
||||
set(CURL_FIND_QUIETLY ON)
|
||||
set(CURL_FIND_QUIETLY OFF)
|
||||
set(CURL_FIND_REQUIRED ON)
|
||||
|
||||
if (STANDALONE)
|
||||
@@ -14,6 +14,9 @@ else (STANDALONE)
|
||||
optimized libcurl)
|
||||
else (WINDOWS)
|
||||
set(CURL_LIBRARIES curl)
|
||||
if(LINUX AND WORD_SIZE EQUAL 64)
|
||||
list(APPEND CURL_LIBRARIES idn)
|
||||
endif(LINUX AND WORD_SIZE EQUAL 64)
|
||||
endif (WINDOWS)
|
||||
set(CURL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -18,7 +18,7 @@ if (NOT FMODEX_LIBRARY)
|
||||
set(FMODEX_SDK_DIR CACHE PATH "Path to the FMOD Ex SDK.")
|
||||
if (FMODEX_SDK_DIR)
|
||||
find_library(FMODEX_LIBRARY
|
||||
fmodex fmodex_vc fmodexL_vc
|
||||
fmodex_vc fmodexL_vc fmodex fmodexL fmodex64 fmodexL64
|
||||
PATHS
|
||||
${FMODEX_SDK_DIR}/api/lib
|
||||
${FMODEX_SDK_DIR}/api
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
|
||||
if(WORD_SIZE EQUAL 64)
|
||||
set(DISABLE_TCMALLOC TRUE)
|
||||
endif(WORD_SIZE EQUAL 64)
|
||||
|
||||
if (STANDALONE)
|
||||
include(FindGooglePerfTools)
|
||||
else (STANDALONE)
|
||||
if (LINUX OR WINDOWS)
|
||||
if (LINUX OR WINDOWS AND NOT WORD_SIZE EQUAL 64)
|
||||
use_prebuilt_binary(gperftools)
|
||||
endif (LINUX OR WINDOWS)
|
||||
endif (LINUX OR WINDOWS AND NOT WORD_SIZE EQUAL 64)
|
||||
if (WINDOWS)
|
||||
set(TCMALLOC_LIBRARIES libtcmalloc_minimal.lib)
|
||||
set(TCMALLOC_LINKER_FLAGS "/INCLUDE:\"__tcmalloc\"")
|
||||
|
||||
@@ -6,7 +6,7 @@ if (STANDALONE)
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(hunspell)
|
||||
|
||||
set(HUNSPELL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/hunspell)
|
||||
set(HUNSPELL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/hunspell)
|
||||
|
||||
if (LINUX OR DARWIN)
|
||||
set(HUNSPELL_LIBRARY hunspell-1.3)
|
||||
|
||||
@@ -13,8 +13,8 @@ else (STANDALONE)
|
||||
set(JPEG_LIBRARIES jpeg)
|
||||
elseif (DARWIN)
|
||||
set(JPEG_LIBRARIES
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/liblljpeg.a
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/liblljpeg.a
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libjpeg.a
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libjpeg.a
|
||||
)
|
||||
elseif (WINDOWS)
|
||||
set(JPEG_LIBRARIES jpeglib)
|
||||
|
||||
@@ -14,7 +14,7 @@ else (STANDALONE)
|
||||
debug json_vc${MSVC_SUFFIX}d
|
||||
optimized json_vc${MSVC_SUFFIX})
|
||||
elseif (DARWIN)
|
||||
set(JSONCPP_LIBRARIES json_mac-universal-gcc_libmt)
|
||||
set(JSONCPP_LIBRARIES json_linux-gcc-4.0.1_libmt)
|
||||
elseif (LINUX)
|
||||
set(JSONCPP_LIBRARIES jsoncpp)
|
||||
endif (WINDOWS)
|
||||
|
||||
@@ -18,7 +18,11 @@ else (STANDALONE)
|
||||
use_prebuilt_binary(SDL)
|
||||
set (SDL_FOUND TRUE)
|
||||
set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR})
|
||||
set (SDL_LIBRARY SDL directfb fusion direct)
|
||||
if(WORD_SIZE EQUAL 64)
|
||||
set (SDL_LIBRARY SDL)
|
||||
else(WORD_SIZE EQUAL 64)
|
||||
set (SDL_LIBRARY SDL directfb fusion direct)
|
||||
endif(WORD_SIZE EQUAL 64)
|
||||
endif (LINUX)
|
||||
endif (STANDALONE)
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ if (NOT STANDALONE)
|
||||
set(ARCH_PREBUILT_DIRS_RELEASE ${ARCH_PREBUILT_DIRS})
|
||||
set(ARCH_PREBUILT_DIRS_DEBUG ${ARCH_PREBUILT_DIRS})
|
||||
elseif (DARWIN)
|
||||
set(ARCH_PREBUILT_DIRS_RELEASE ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib_release)
|
||||
set(ARCH_PREBUILT_DIRS ${ARCH_PREBUILT_DIRS_RELEASE})
|
||||
set(ARCH_PREBUILT_DIRS_DEBUG ${ARCH_PREBUILT_DIRS_RELEASE})
|
||||
set(ARCH_PREBUILT_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib)
|
||||
set(ARCH_PREBUILT_DIRS_RELEASE ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib/release)
|
||||
set(ARCH_PREBUILT_DIRS_DEBUG ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib/debug)
|
||||
endif (WINDOWS)
|
||||
endif (NOT STANDALONE)
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@ else (STANDALONE)
|
||||
set(OPENSSL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
|
||||
endif (STANDALONE)
|
||||
|
||||
if (LINUX)
|
||||
if (LINUX OR DARWIN)
|
||||
set(CRYPTO_LIBRARIES crypto)
|
||||
elseif (DARWIN)
|
||||
set(CRYPTO_LIBRARIES llcrypto)
|
||||
endif (LINUX)
|
||||
endif (LINUX OR DARWIN)
|
||||
|
||||
@@ -76,37 +76,36 @@ endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(DARWIN 1)
|
||||
|
||||
#SDK Compiler and Deployment targets for XCode
|
||||
if (${XCODE_VERSION} VERSION_LESS 4.0.0)
|
||||
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk)
|
||||
set(CMAKE_XCODE_ATTIBUTE_GCC_VERSION "4.2")
|
||||
else (${XCODE_VERSION} VERSION_LESS 4.0.0)
|
||||
if(${CMAKE_GENERATOR} MATCHES Xcode)
|
||||
#SDK Compiler and Deployment targets for XCode
|
||||
if (${XCODE_VERSION} VERSION_LESS 4.0.0)
|
||||
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5)
|
||||
set(CMAKE_XCODE_ATTIBUTE_GCC_VERSION "4.2")
|
||||
else (${XCODE_VERSION} VERSION_LESS 4.0.0)
|
||||
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.6.sdk)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42")
|
||||
endif (${XCODE_VERSION} VERSION_LESS 4.0.0)
|
||||
else()
|
||||
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.6.sdk)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42")
|
||||
endif (${XCODE_VERSION} VERSION_LESS 4.0.0)
|
||||
endif(${CMAKE_GENERATOR} MATCHES Xcode)
|
||||
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5)
|
||||
## We currently support only 32-bit i386 builds, so use these:
|
||||
set(CMAKE_OSX_ARCHITECTURES i386)
|
||||
set(ARCH i386)
|
||||
set(WORD_SIZE 32)
|
||||
|
||||
# NOTE: To attempt an i386/PPC Universal build, add this on the configure line:
|
||||
# -DCMAKE_OSX_ARCHITECTURES:STRING='i386;ppc'
|
||||
# Build only for i386 by default, system default on MacOSX 10.6 is x86_64
|
||||
if (NOT CMAKE_OSX_ARCHITECTURES)
|
||||
set(CMAKE_OSX_ARCHITECTURES i386)
|
||||
endif (NOT CMAKE_OSX_ARCHITECTURES)
|
||||
|
||||
if (CMAKE_OSX_ARCHITECTURES MATCHES "i386" AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc")
|
||||
set(ARCH universal)
|
||||
else (CMAKE_OSX_ARCHITECTURES MATCHES "i386" AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc")
|
||||
if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "ppc")
|
||||
set(ARCH ppc)
|
||||
else (${CMAKE_SYSTEM_PROCESSOR} MATCHES "ppc")
|
||||
set(ARCH i386)
|
||||
endif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "ppc")
|
||||
endif (CMAKE_OSX_ARCHITECTURES MATCHES "i386" AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc")
|
||||
## But if you want to compile for mixed 32/64 bit, try these:
|
||||
# set(CMAKE_OSX_ARCHITECTURES i386;x86_64)
|
||||
# set(ARCH universal)
|
||||
# set(WORD_SIZE 64)
|
||||
|
||||
## Finally, set up the build output directories
|
||||
set(LL_ARCH ${ARCH}_darwin)
|
||||
set(LL_ARCH_DIR universal-darwin)
|
||||
set(WORD_SIZE 32)
|
||||
endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
|
||||
|
||||
|
||||
@@ -173,6 +173,8 @@ void stop_recording_backtraces(void)
|
||||
channel_ct backtrace DDCN("BACKTRACE"); //!< This debug channel is used for backtraces.
|
||||
channel_ct statemachine DDCN("STATEMACHINE"); //!< This debug channel is used for output related to class AIStateMachine.
|
||||
channel_ct caps DDCN("CAPS"); //!< This debug channel is used for output related to Capabilities.
|
||||
channel_ct curl DDCN("CURL"); //!< This debug channel is used for output related to Curl.
|
||||
channel_ct curlio DDCN("CURLIO"); //!< This debug channel is used to print debug output of libcurl.
|
||||
|
||||
} // namespace dc
|
||||
} // namespace DEBUGCHANNELS
|
||||
|
||||
@@ -118,6 +118,8 @@ extern CWD_API channel_ct sdl;
|
||||
extern CWD_API channel_ct backtrace;
|
||||
extern CWD_API channel_ct statemachine;
|
||||
extern CWD_API channel_ct caps;
|
||||
extern CWD_API channel_ct curl;
|
||||
extern CWD_API channel_ct curlio;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -95,6 +95,28 @@ inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
|
||||
return true;
|
||||
}
|
||||
|
||||
void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr)
|
||||
{
|
||||
if(type & FMOD_MEMORY_STREAM_DECODE)
|
||||
{
|
||||
llinfos << "Decode buffer size: " << size << llendl;
|
||||
}
|
||||
else if(type & FMOD_MEMORY_STREAM_FILE)
|
||||
{
|
||||
llinfos << "Strean buffer size: " << size << llendl;
|
||||
}
|
||||
return new char[size];
|
||||
}
|
||||
void* F_STDCALL decode_realloc(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr)
|
||||
{
|
||||
memset(ptr,0,size);
|
||||
return ptr;
|
||||
}
|
||||
void F_STDCALL decode_dealloc(void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr)
|
||||
{
|
||||
delete[] (char*)ptr;
|
||||
}
|
||||
|
||||
bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
{
|
||||
|
||||
@@ -108,6 +130,10 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
|
||||
LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() initializing FMOD" << LL_ENDL;
|
||||
|
||||
result = FMOD::Memory_Initialize(NULL, 0, &decode_alloc, &decode_realloc, &decode_dealloc, FMOD_MEMORY_STREAM_DECODE | FMOD_MEMORY_STREAM_FILE);
|
||||
if(Check_FMOD_Error(result, "FMOD::Memory_Initialize"))
|
||||
return false;
|
||||
|
||||
result = FMOD::System_Create(&mSystem);
|
||||
if(Check_FMOD_Error(result, "FMOD::System_Create"))
|
||||
return false;
|
||||
@@ -124,54 +150,8 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
<< ")! You should be using FMOD Ex" << FMOD_VERSION << LL_ENDL;
|
||||
}
|
||||
|
||||
#if LL_WINDOWS
|
||||
int numdrivers;
|
||||
FMOD_SPEAKERMODE speakermode;
|
||||
FMOD_CAPS caps;
|
||||
char name[256];
|
||||
|
||||
//Is this block applicable to linux?
|
||||
{
|
||||
result = mSystem->getNumDrivers(&numdrivers);
|
||||
Check_FMOD_Error(result, "FMOD::System::getNumDrivers");
|
||||
if (numdrivers == 0)
|
||||
{
|
||||
result = mSystem->setOutput(FMOD_OUTPUTTYPE_NOSOUND);
|
||||
Check_FMOD_Error(result, "FMOD::System::setOutput");
|
||||
}
|
||||
else
|
||||
{
|
||||
result = mSystem->getDriverCaps(0, &caps, 0, &speakermode);
|
||||
Check_FMOD_Error(result,"FMOD::System::getDriverCaps");
|
||||
/*
|
||||
Set the user selected speaker mode.
|
||||
*/
|
||||
result = mSystem->setSpeakerMode(speakermode);
|
||||
Check_FMOD_Error(result, "FMOD::System::setSpeakerMode");
|
||||
if (caps & FMOD_CAPS_HARDWARE_EMULATED)
|
||||
{
|
||||
/*
|
||||
The user has the 'Acceleration' slider set to off! This is really bad
|
||||
for latency! You might want to warn the user about this.
|
||||
*/
|
||||
result = mSystem->setDSPBufferSize(1024, 10);
|
||||
Check_FMOD_Error(result, "FMOD::System::setDSPBufferSize");
|
||||
}
|
||||
result = mSystem->getDriverInfo(0, name, 256, 0);
|
||||
Check_FMOD_Error(result, "FMOD::System::getDriverInfo");
|
||||
|
||||
if (strstr(name, "SigmaTel"))
|
||||
{
|
||||
/*
|
||||
Sigmatel sound devices crackle for some reason if the format is PCM 16bit.
|
||||
PCM floating point output seems to solve it.
|
||||
*/
|
||||
result = mSystem->setSoftwareFormat(48000, FMOD_SOUND_FORMAT_PCMFLOAT, 0,0, FMOD_DSP_RESAMPLER_LINEAR);
|
||||
Check_FMOD_Error(result,"FMOD::System::setSoftwareFormat");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //LL_WINDOWS
|
||||
result = mSystem->setSoftwareFormat(44100, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR);
|
||||
Check_FMOD_Error(result,"FMOD::System::setSoftwareFormat");
|
||||
|
||||
// In this case, all sounds, PLUS wind and stream will be software.
|
||||
result = mSystem->setSoftwareChannels(num_channels + 2);
|
||||
@@ -297,6 +277,19 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
|
||||
LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init() FMOD Ex initialized correctly" << LL_ENDL;
|
||||
|
||||
int r_numbuffers, r_samplerate, r_channels, r_bits;
|
||||
unsigned int r_bufferlength;
|
||||
char r_name[256];
|
||||
mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers);
|
||||
mSystem->getSoftwareFormat(&r_samplerate, NULL, &r_channels, NULL, NULL, &r_bits);
|
||||
mSystem->getDriverInfo(0, r_name, 255, 0);
|
||||
r_name[255] = '\0';
|
||||
int latency = 1000.0 * r_bufferlength * r_numbuffers /r_samplerate;
|
||||
|
||||
LL_INFOS("AppInit") << "FMOD device: "<< r_name << "\n"
|
||||
<< "FMOD Ex parameters: " << r_samplerate << " Hz * " << r_channels << " * " <<r_bits <<" bit\n"
|
||||
<< "\tbuffer " << r_bufferlength << " * " << r_numbuffers << " (" << latency <<"ms)" << LL_ENDL;
|
||||
|
||||
mInited = true;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -58,6 +58,9 @@ class LLStreamingAudioInterface
|
||||
virtual const LLSD *getMetaData() = 0;
|
||||
virtual bool supportsWaveData() = 0;
|
||||
virtual bool getWaveData(float* arr, S32 count, S32 stride = 1) = 0;
|
||||
|
||||
virtual bool supportsAdjustableBufferSizes(){return false;}
|
||||
virtual void setBufferSizes(U32 streambuffertime, U32 decodebuffertime){};
|
||||
};
|
||||
|
||||
#endif // LL_STREAMINGAUDIO_H
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
|
||||
const std::string& getURL() { return mInternetStreamURL; }
|
||||
|
||||
FMOD_OPENSTATE getOpenState();
|
||||
FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL);
|
||||
protected:
|
||||
FMOD::System* mSystem;
|
||||
FMOD::Channel* mStreamChannel;
|
||||
@@ -74,7 +74,7 @@ LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) :
|
||||
{
|
||||
// Number of milliseconds of audio to buffer for the audio card.
|
||||
// Must be larger than the usual Second Life frame stutter time.
|
||||
const U32 buffer_seconds = 5; //sec
|
||||
const U32 buffer_seconds = 10; //sec
|
||||
const U32 estimated_bitrate = 128; //kbit/sec
|
||||
mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
|
||||
|
||||
@@ -145,7 +145,10 @@ void LLStreamingAudio_FMODEX::update()
|
||||
return;
|
||||
}
|
||||
|
||||
FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState();
|
||||
unsigned int progress;
|
||||
bool starving;
|
||||
bool diskbusy;
|
||||
FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy);
|
||||
|
||||
if (open_state == FMOD_OPENSTATE_READY)
|
||||
{
|
||||
@@ -158,6 +161,7 @@ void LLStreamingAudio_FMODEX::update()
|
||||
// Reset volume to previously set volume
|
||||
setGain(getGain());
|
||||
mFMODInternetStreamChannelp->setPaused(false);
|
||||
mLastStarved.stop();
|
||||
}
|
||||
}
|
||||
else if(open_state == FMOD_OPENSTATE_ERROR)
|
||||
@@ -168,6 +172,7 @@ void LLStreamingAudio_FMODEX::update()
|
||||
|
||||
if(mFMODInternetStreamChannelp)
|
||||
{
|
||||
//llinfos << "progress = " << progress << llendl;
|
||||
if(!mMetaData)
|
||||
mMetaData = new LLSD;
|
||||
|
||||
@@ -237,12 +242,29 @@ void LLStreamingAudio_FMODEX::update()
|
||||
}
|
||||
}
|
||||
}
|
||||
if(starving)
|
||||
{
|
||||
if(!mLastStarved.getStarted())
|
||||
{
|
||||
llinfos << "Stream starvation detected! Muting stream audio until it clears." << llendl;
|
||||
llinfos << " (diskbusy="<<diskbusy<<")" << llendl;
|
||||
llinfos << " (progress="<<progress<<")" << llendl;
|
||||
mFMODInternetStreamChannelp->setMute(true);
|
||||
}
|
||||
mLastStarved.start();
|
||||
}
|
||||
else if(mLastStarved.getStarted() && mLastStarved.getElapsedTimeF32() > 1.f)
|
||||
{
|
||||
mLastStarved.stop();
|
||||
mFMODInternetStreamChannelp->setMute(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODEX::stop()
|
||||
{
|
||||
mLastStarved.stop();
|
||||
if(mMetaData)
|
||||
{
|
||||
delete mMetaData;
|
||||
@@ -341,6 +363,11 @@ void LLStreamingAudio_FMODEX::setGain(F32 vol)
|
||||
if(!mFMODInternetStreamChannelp || !mCurrentInternetStreamp)
|
||||
return false;
|
||||
|
||||
bool muted=false;
|
||||
mFMODInternetStreamChannelp->getMute(&muted);
|
||||
if(muted)
|
||||
return false;
|
||||
|
||||
static std::vector<float> local_array(count); //Have to have an extra buffer to mix channels. Bleh.
|
||||
if(count > (S32)local_array.size()) //Expand the array if needed. Try to minimize allocation calls, so don't ever shrink.
|
||||
local_array.resize(count);
|
||||
@@ -442,9 +469,19 @@ bool LLAudioStreamManagerFMODEX::stopStream()
|
||||
}
|
||||
}
|
||||
|
||||
FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState()
|
||||
FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy)
|
||||
{
|
||||
FMOD_OPENSTATE state;
|
||||
mInternetStream->getOpenState(&state,NULL,NULL,NULL);
|
||||
mInternetStream->getOpenState(&state,percentbuffered,starving,diskbusy);
|
||||
return state;
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODEX::setBufferSizes(U32 streambuffertime, U32 decodebuffertime)
|
||||
{
|
||||
mSystem->setStreamBufferSize(streambuffertime/1000*128*128, FMOD_TIMEUNIT_RAWBYTES);
|
||||
FMOD_ADVANCEDSETTINGS settings;
|
||||
memset(&settings,0,sizeof(settings));
|
||||
settings.cbsize=sizeof(settings);
|
||||
settings.defaultDecodeBufferSize = decodebuffertime;//ms
|
||||
mSystem->setAdvancedSettings(&settings);
|
||||
}
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "stdtypes.h" // from llcommon
|
||||
|
||||
#include "llstreamingaudio.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
//Stubs
|
||||
class LLAudioStreamManagerFMODEX;
|
||||
@@ -66,6 +67,8 @@ class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface
|
||||
/*virtual*/ const LLSD *getMetaData(){return mMetaData;} //return NULL if not playing.
|
||||
/*virtual*/ bool supportsWaveData(){return true;}
|
||||
/*virtual*/ bool getWaveData(float* arr, S32 count, S32 stride = 1);
|
||||
/*virtual*/ bool supportsAdjustableBufferSizes(){return true;}
|
||||
/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime);
|
||||
private:
|
||||
FMOD::System *mSystem;
|
||||
|
||||
@@ -76,6 +79,8 @@ private:
|
||||
std::string mURL;
|
||||
F32 mGain;
|
||||
|
||||
LLTimer mLastStarved;
|
||||
|
||||
LLSD *mMetaData;
|
||||
};
|
||||
|
||||
|
||||
@@ -297,6 +297,20 @@ void LLApp::startErrorThread()
|
||||
}
|
||||
}
|
||||
|
||||
void LLApp::stopErrorThread()
|
||||
{
|
||||
LLApp::setStopped(); // Signal error thread that we stopped.
|
||||
int count = 0;
|
||||
while (mThreadErrorp && !mThreadErrorp->isStopped() && ++count < 100)
|
||||
{
|
||||
ms_sleep(10);
|
||||
}
|
||||
if (mThreadErrorp && !mThreadErrorp->isStopped())
|
||||
{
|
||||
llwarns << "Failed to stop Error Thread." << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
void LLApp::setErrorHandler(LLAppErrorHandler handler)
|
||||
{
|
||||
LLApp::sErrorHandler = handler;
|
||||
|
||||
@@ -43,10 +43,14 @@ template <typename Type> class LLAtomic32;
|
||||
typedef LLAtomic32<U32> LLAtomicU32;
|
||||
class LLErrorThread;
|
||||
class LLLiveFile;
|
||||
|
||||
|
||||
#if LL_LINUX
|
||||
typedef struct siginfo siginfo_t;
|
||||
#include <signal.h>
|
||||
//typedef struct siginfo siginfo_t; //Removed as per changes in glibc 2.16 - Drake Arconis
|
||||
#endif
|
||||
|
||||
|
||||
typedef void (*LLAppErrorHandler)();
|
||||
typedef void (*LLAppChildCallback)(int pid, bool exited, int status);
|
||||
|
||||
@@ -260,6 +264,10 @@ protected:
|
||||
* @ brief This method is called once as soon as logging is initialized.
|
||||
*/
|
||||
void startErrorThread();
|
||||
/**
|
||||
* @brief This method is called at the end, just prior to deinitializing curl.
|
||||
*/
|
||||
void stopErrorThread();
|
||||
|
||||
private:
|
||||
void setupErrorHandling(); // Do platform-specific error-handling setup (signals, structured exceptions)
|
||||
|
||||
@@ -114,7 +114,7 @@ const int LL_ERR_PRICE_MISMATCH = -23018;
|
||||
: liru_slashpos2 == std::string::npos ? std::string(__FILE__)/*Apparently, we're in / or perhaps the top of the drive, print as is*/\
|
||||
: std::string(__FILE__).substr(1+liru_slashpos2))/*print foo/bar.cpp or perhaps foo\bar.cpp*/
|
||||
|
||||
#define llassert_always(func) if (LL_UNLIKELY(!(func))) llerrs <<"\nASSERT(" #func ")\nfile:"<<liru_assert_strip<<" line:"<<__LINE__ << llendl;
|
||||
#define llassert_always(func) do { if (LL_UNLIKELY(!(func))) llerrs << "\nASSERT(" #func ")\nfile:" << liru_assert_strip << " line:" << std::dec << __LINE__ << llendl; } while(0)
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
#define llassert(func) llassert_always(func)
|
||||
|
||||
@@ -194,17 +194,17 @@ void LLErrorThread::run()
|
||||
if (LLApp::isError())
|
||||
{
|
||||
// The app is in an error state, run the application's error handler.
|
||||
//llinfos << "thread_error - An error has occurred, running error callback!" << llendl;
|
||||
Dout(dc::notice, "thread_error - An error has occurred, running error callback!");
|
||||
// Run the error handling callback
|
||||
LLApp::runErrorHandler();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Everything is okay, a clean exit.
|
||||
//llinfos << "thread_error - Application exited cleanly" << llendl;
|
||||
Dout(dc::notice, "thread_error - Application exited cleanly");
|
||||
}
|
||||
|
||||
//llinfos << "thread_error - Exiting" << llendl;
|
||||
Dout(dc::notice, "thread_error - Exiting");
|
||||
LLApp::sErrorThreadRunning = FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -251,7 +251,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)
|
||||
// MAIN thread
|
||||
bool LLQueuedThread::waitForResult(LLQueuedThread::handle_t handle, bool auto_complete)
|
||||
{
|
||||
llassert (handle != nullHandle())
|
||||
llassert (handle != nullHandle());
|
||||
bool res = false;
|
||||
bool waspaused = isPaused();
|
||||
bool done = false;
|
||||
|
||||
@@ -111,6 +111,8 @@ public:
|
||||
return mPriority > second.mPriority;
|
||||
}
|
||||
|
||||
virtual void deleteRequest(); // Only method to delete a request
|
||||
|
||||
protected:
|
||||
status_t setStatus(status_t newstatus)
|
||||
{
|
||||
@@ -130,7 +132,6 @@ public:
|
||||
|
||||
virtual bool processRequest() = 0; // Return true when request has completed
|
||||
virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted
|
||||
virtual void deleteRequest(); // Only method to delete a request
|
||||
|
||||
void setPriority(U32 pri)
|
||||
{
|
||||
|
||||
@@ -310,15 +310,27 @@ void LLThread::wakeLocked()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread.
|
||||
static apr_os_thread_t main_thread_id;
|
||||
LL_COMMON_API bool is_main_thread(void) { return apr_os_thread_equal(main_thread_id, apr_os_thread_current()); }
|
||||
#endif
|
||||
//static
|
||||
apr_os_thread_t LLThread::sMainThreadID;
|
||||
|
||||
void LLThread::set_main_thread_id(void)
|
||||
{
|
||||
sMainThreadID = apr_os_thread_current();
|
||||
}
|
||||
|
||||
// The thread private handle to access the LLThreadLocalData instance.
|
||||
apr_threadkey_t* LLThreadLocalData::sThreadLocalDataKey;
|
||||
|
||||
LLThreadLocalData::LLThreadLocalData(char const* name) : mCurlMultiHandle(NULL), mCurlErrorBuffer(NULL), mName(name)
|
||||
{
|
||||
}
|
||||
|
||||
LLThreadLocalData::~LLThreadLocalData()
|
||||
{
|
||||
delete mCurlMultiHandle;
|
||||
delete [] mCurlErrorBuffer;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLThreadLocalData::init(void)
|
||||
{
|
||||
@@ -336,10 +348,8 @@ void LLThreadLocalData::init(void)
|
||||
// Create the thread-local data for the main thread (this function is called by the main thread).
|
||||
LLThreadLocalData::create(NULL);
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
// This function is called by the main thread.
|
||||
main_thread_id = apr_os_thread_current();
|
||||
#endif
|
||||
LLThread::set_main_thread_id();
|
||||
}
|
||||
|
||||
// This is called once for every thread when the thread is destructed.
|
||||
@@ -352,7 +362,7 @@ void LLThreadLocalData::destroy(void* thread_local_data)
|
||||
//static
|
||||
void LLThreadLocalData::create(LLThread* threadp)
|
||||
{
|
||||
LLThreadLocalData* new_tld = new LLThreadLocalData;
|
||||
LLThreadLocalData* new_tld = new LLThreadLocalData(threadp ? threadp->mName.c_str() : "main thread");
|
||||
if (threadp)
|
||||
{
|
||||
threadp->mThreadLocalData = new_tld;
|
||||
|
||||
@@ -40,13 +40,6 @@
|
||||
#include "llaprpool.h"
|
||||
#include "llatomic.h"
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
extern LL_COMMON_API bool is_main_thread(void);
|
||||
#define ASSERT_SINGLE_THREAD do { static apr_os_thread_t first_thread_id = apr_os_thread_current(); llassert(apr_os_thread_equal(first_thread_id, apr_os_thread_current())); } while(0)
|
||||
#else
|
||||
#define ASSERT_SINGLE_THREAD do { } while(0)
|
||||
#endif
|
||||
|
||||
class LLThread;
|
||||
class LLMutex;
|
||||
class LLCondition;
|
||||
@@ -57,6 +50,12 @@ class LLCondition;
|
||||
#define ll_thread_local __thread
|
||||
#endif
|
||||
|
||||
class LL_COMMON_API LLThreadLocalDataMember
|
||||
{
|
||||
public:
|
||||
virtual ~LLThreadLocalDataMember() { };
|
||||
};
|
||||
|
||||
class LL_COMMON_API LLThreadLocalData
|
||||
{
|
||||
private:
|
||||
@@ -66,16 +65,24 @@ public:
|
||||
// Thread-local memory pool.
|
||||
LLAPRRootPool mRootPool;
|
||||
LLVolatileAPRPool mVolatileAPRPool;
|
||||
LLThreadLocalDataMember* mCurlMultiHandle; // Initialized by AICurlMultiHandle::getInstance
|
||||
char* mCurlErrorBuffer; // NULL, or pointing to a buffer used by libcurl.
|
||||
std::string mName; // "main thread", or a copy of LLThread::mName.
|
||||
|
||||
static void init(void);
|
||||
static void destroy(void* thread_local_data);
|
||||
static void create(LLThread* pthread);
|
||||
static LLThreadLocalData& tldata(void);
|
||||
|
||||
private:
|
||||
LLThreadLocalData(char const* name);
|
||||
~LLThreadLocalData();
|
||||
};
|
||||
|
||||
class LL_COMMON_API LLThread
|
||||
{
|
||||
private:
|
||||
static apr_os_thread_t sMainThreadID;
|
||||
static U32 sIDIter;
|
||||
static LLAtomicS32 sCount;
|
||||
static LLAtomicS32 sRunning;
|
||||
@@ -99,6 +106,7 @@ public:
|
||||
static S32 getCount() { return sCount; }
|
||||
static S32 getRunning() { return sRunning; }
|
||||
static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
|
||||
static bool is_main_thread(void) { return apr_os_thread_equal(LLThread::sMainThreadID, apr_os_thread_current()); }
|
||||
|
||||
public:
|
||||
// PAUSE / RESUME functionality. See source code for important usage notes.
|
||||
@@ -122,6 +130,9 @@ public:
|
||||
// Return thread-local data for the current thread.
|
||||
static LLThreadLocalData& tldata(void) { return LLThreadLocalData::tldata(); }
|
||||
|
||||
// Called once, from LLThreadLocalData::init().
|
||||
static void set_main_thread_id(void);
|
||||
|
||||
U32 getID() const { return mID; }
|
||||
|
||||
private:
|
||||
@@ -165,6 +176,13 @@ protected:
|
||||
// mRunCondition->unlock();
|
||||
};
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
LL_COMMON_API inline bool is_main_thread(void) { return LLThread::is_main_thread(); }
|
||||
#define ASSERT_SINGLE_THREAD do { static apr_os_thread_t first_thread_id = apr_os_thread_current(); llassert(apr_os_thread_equal(first_thread_id, apr_os_thread_current())); } while(0)
|
||||
#else
|
||||
#define ASSERT_SINGLE_THREAD do { } while(0)
|
||||
#endif
|
||||
|
||||
//============================================================================
|
||||
|
||||
#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
|
||||
@@ -206,6 +224,11 @@ protected:
|
||||
apr_thread_mutex_t* mAPRMutexp;
|
||||
mutable U32 mCount;
|
||||
mutable U32 mLockingThread;
|
||||
|
||||
private:
|
||||
// Disallow copy construction and assignment.
|
||||
LLMutexBase(LLMutexBase const&);
|
||||
LLMutexBase& operator=(LLMutexBase const&);
|
||||
};
|
||||
|
||||
class LL_COMMON_API LLMutex : public LLMutexBase
|
||||
@@ -225,10 +248,6 @@ public:
|
||||
|
||||
protected:
|
||||
LLAPRPool mPool;
|
||||
private:
|
||||
// Disable copy construction, as si teh bomb!!! -SG
|
||||
LLMutex(const LLMutex&);
|
||||
LLMutex& operator=(const LLMutex&);
|
||||
};
|
||||
|
||||
#if APR_HAS_THREADS
|
||||
|
||||
@@ -371,6 +371,9 @@ void LLCrashLogger::updateApplication(const std::string& message)
|
||||
|
||||
bool LLCrashLogger::init()
|
||||
{
|
||||
// Initialize curl
|
||||
AICurlInterface::initCurl();
|
||||
|
||||
// We assume that all the logs we're looking for reside on the current drive
|
||||
gDirUtilp->initAppDirs("SecondLife");
|
||||
|
||||
|
||||
@@ -29,7 +29,8 @@ set(llmessage_SOURCE_FILES
|
||||
llchainio.cpp
|
||||
llcircuit.cpp
|
||||
llclassifiedflags.cpp
|
||||
llcurl.cpp
|
||||
aicurl.cpp
|
||||
aicurlthread.cpp
|
||||
lldatapacker.cpp
|
||||
lldispatcher.cpp
|
||||
llfiltersd2xmlrpc.cpp
|
||||
@@ -66,8 +67,6 @@ set(llmessage_SOURCE_FILES
|
||||
llsdmessage.cpp
|
||||
llsdmessagebuilder.cpp
|
||||
llsdmessagereader.cpp
|
||||
llsdrpcclient.cpp
|
||||
llsdrpcserver.cpp
|
||||
llservicebuilder.cpp
|
||||
llservice.cpp
|
||||
llstoredmessage.cpp
|
||||
@@ -117,6 +116,9 @@ set(llmessage_HEADER_FILES
|
||||
llcircuit.h
|
||||
llclassifiedflags.h
|
||||
llcurl.h
|
||||
aicurl.h
|
||||
aicurlprivate.h
|
||||
aicurlthread.h
|
||||
lldatapacker.h
|
||||
lldbstrings.h
|
||||
lldispatcher.h
|
||||
@@ -164,8 +166,6 @@ set(llmessage_HEADER_FILES
|
||||
llsdmessage.h
|
||||
llsdmessagebuilder.h
|
||||
llsdmessagereader.h
|
||||
llsdrpcclient.h
|
||||
llsdrpcserver.h
|
||||
llservice.h
|
||||
llservicebuilder.h
|
||||
llstoredmessage.h
|
||||
|
||||
1363
indra/llmessage/aicurl.cpp
Normal file
1363
indra/llmessage/aicurl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
322
indra/llmessage/aicurl.h
Normal file
322
indra/llmessage/aicurl.h
Normal file
@@ -0,0 +1,322 @@
|
||||
/**
|
||||
* @file aicurl.h
|
||||
* @brief Thread safe wrapper for libcurl.
|
||||
*
|
||||
* Copyright (c) 2012, Aleric Inglewood.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution.
|
||||
*
|
||||
* CHANGELOG
|
||||
* and additional copyright holders.
|
||||
*
|
||||
* 17/03/2012
|
||||
* Initial version, written by Aleric Inglewood @ SL
|
||||
*/
|
||||
|
||||
#ifndef AICURL_H
|
||||
#define AICURL_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <curl/curl.h> // CURL, CURLM, CURLMcode, CURLoption, curl_*_callback
|
||||
|
||||
// Make sure we don't use this option: it is not thread-safe.
|
||||
#undef CURLOPT_DNS_USE_GLOBAL_CACHE
|
||||
|
||||
#include "stdtypes.h" // U32
|
||||
#include "lliopipe.h" // LLIOPipe::buffer_ptr_t
|
||||
#include "llatomic.h" // LLAtomicU32
|
||||
#include "aithreadsafe.h"
|
||||
|
||||
class LLSD;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exceptions.
|
||||
//
|
||||
|
||||
// A general curl exception.
|
||||
//
|
||||
class AICurlError : public std::runtime_error {
|
||||
public:
|
||||
AICurlError(std::string const& message) : std::runtime_error(message) { }
|
||||
};
|
||||
|
||||
class AICurlNoEasyHandle : public AICurlError {
|
||||
public:
|
||||
AICurlNoEasyHandle(std::string const& message) : AICurlError(message) { }
|
||||
};
|
||||
|
||||
class AICurlNoMultiHandle : public AICurlError {
|
||||
public:
|
||||
AICurlNoMultiHandle(std::string const& message) : AICurlError(message) { }
|
||||
};
|
||||
|
||||
// End Exceptions.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Things defined in this namespace are called from elsewhere in the viewer code.
|
||||
namespace AICurlInterface {
|
||||
|
||||
// Output parameter of AICurlPrivate::CurlEasyRequest::getResult.
|
||||
// Only used by LLXMLRPCTransaction::Impl.
|
||||
struct TransferInfo {
|
||||
TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) { }
|
||||
F64 mSizeDownload;
|
||||
F64 mTotalTime;
|
||||
F64 mSpeedDownload;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Global functions.
|
||||
|
||||
// Called once at start of application (from newview/llappviewer.cpp by main thread (before threads are created)),
|
||||
// with main purpose to initialize curl.
|
||||
void initCurl(void (*)(void) = NULL);
|
||||
|
||||
// Called once at start of application (from LLAppViewer::initThreads), starts AICurlThread.
|
||||
void startCurlThread(void);
|
||||
|
||||
// Called once at end of application (from newview/llappviewer.cpp by main thread),
|
||||
// with purpose to stop curl threads, free curl resources and deinitialize curl.
|
||||
void cleanupCurl(void);
|
||||
|
||||
// Called from indra/llmessage/llurlrequest.cpp to print debug output regarding
|
||||
// an error code returned by EasyRequest::getResult.
|
||||
// Just returns curl_easy_strerror(errorcode).
|
||||
std::string strerror(CURLcode errorcode);
|
||||
|
||||
// Called from indra/newview/llfloaterabout.cpp for the About floater, and
|
||||
// from newview/llappviewer.cpp in behalf of debug output.
|
||||
// Just returns curl_version().
|
||||
std::string getVersionString(void);
|
||||
|
||||
// Called from newview/llappviewer.cpp (and llcrashlogger/llcrashlogger.cpp) to set
|
||||
// the Certificate Authority file used to verify HTTPS certs.
|
||||
void setCAFile(std::string const& file);
|
||||
|
||||
// Not called from anywhere.
|
||||
// Can be used to set the path to the Certificate Authority file.
|
||||
void setCAPath(std::string const& file);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Global classes.
|
||||
|
||||
// Responder - base class for Request::get* and Request::post API.
|
||||
//
|
||||
// The life cycle of classes derived from this class is as follows:
|
||||
// They are allocated with new on the line where get(), getByteRange() or post() is called,
|
||||
// and the pointer to the allocated object is then put in a reference counting ResponderPtr.
|
||||
// This ResponderPtr is passed to CurlResponderBuffer::prepRequest which stores it in its
|
||||
// member mResponder. Hence, the life time of a Responder is never longer than its
|
||||
// associated CurlResponderBuffer, however, if everything works correctly, then normally a
|
||||
// responder is deleted in CurlResponderBuffer::removed_from_multi_handle by setting
|
||||
// mReponder to NULL.
|
||||
//
|
||||
// Note that the lifetime of CurlResponderBuffer is (a bit) shorter than the associated
|
||||
// CurlEasyRequest (because of the order of base classes of ThreadSafeBufferedCurlEasyRequest)
|
||||
// and the callbacks, as set by prepRequest, only use those two.
|
||||
// A callback locks the CurlEasyRequest before actually making the callback, and the
|
||||
// destruction of CurlResponderBuffer also first locks the CurlEasyRequest, and then revokes
|
||||
// the callbacks. This assures that a Responder is never used when the objects it uses are
|
||||
// destructed. Also, if any of those are destructed then the Responder is automatically
|
||||
// destructed too.
|
||||
//
|
||||
class Responder {
|
||||
protected:
|
||||
Responder(void);
|
||||
virtual ~Responder();
|
||||
|
||||
private:
|
||||
// Associated URL, used for debug output.
|
||||
std::string mURL;
|
||||
|
||||
public:
|
||||
// Called to set the URL of the current request for this Responder,
|
||||
// used only when printing debug output regarding activity of the Responder.
|
||||
void setURL(std::string const& url);
|
||||
|
||||
public:
|
||||
// Called from LLHTTPClientURLAdaptor::complete():
|
||||
|
||||
// Derived classes can override this to get the HTML header that was received, when the message is completed.
|
||||
// The default does nothing.
|
||||
virtual void completedHeader(U32 status, std::string const& reason, LLSD const& content);
|
||||
|
||||
// Derived classes can override this to get the raw data of the body of the HTML message that was received.
|
||||
// The default is to interpret the content as LLSD and call completed().
|
||||
virtual void completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, LLIOPipe::buffer_ptr_t const& buffer);
|
||||
|
||||
// Called from LLHTTPClient request calls, if an error occurs even before we can call one of the above.
|
||||
// It calls completed() with a fake status U32_MAX, as that is what some derived clients expect (bad design).
|
||||
// This means that if a derived class overrides completedRaw() it now STILL has to override completed() to catch this error.
|
||||
void fatalError(std::string const& reason);
|
||||
|
||||
// A derived class should return true if curl should follow redirections.
|
||||
// The default is not to follow redirections.
|
||||
virtual bool followRedir(void) { return false; }
|
||||
|
||||
protected:
|
||||
// ... or, derived classes can override this to get the LLSD content when the message is completed.
|
||||
// The default is to call result() (or errorWithContent() in case of a HTML status indicating an error).
|
||||
virtual void completed(U32 status, std::string const& reason, LLSD const& content);
|
||||
|
||||
// ... or, derived classes can override this to received the content of a body upon success.
|
||||
// The default does nothing.
|
||||
virtual void result(LLSD const& content);
|
||||
|
||||
// Derived classes can override this to get informed when a bad HTML status code is received.
|
||||
// The default calls error().
|
||||
virtual void errorWithContent(U32 status, std::string const& reason, LLSD const& content);
|
||||
|
||||
// ... or, derived classes can override this to get informed when a bad HTML statis code is received.
|
||||
// The default prints the error to llinfos.
|
||||
virtual void error(U32 status, std::string const& reason);
|
||||
|
||||
public:
|
||||
// Called from LLSDMessage::ResponderAdapter::listener.
|
||||
// LLSDMessage::ResponderAdapter is a hack, showing among others by fact that these functions need to be public.
|
||||
|
||||
void pubErrorWithContent(U32 status, std::string const& reason, LLSD const& content) { errorWithContent(status, reason, content); }
|
||||
void pubResult(LLSD const& content) { result(content); }
|
||||
|
||||
private:
|
||||
// Used by ResponderPtr. Object is deleted when reference count reaches zero.
|
||||
LLAtomicU32 mReferenceCount;
|
||||
|
||||
friend void intrusive_ptr_add_ref(Responder* p); // Called by boost::intrusive_ptr when a new copy of a boost::intrusive_ptr<Responder> is made.
|
||||
friend void intrusive_ptr_release(Responder* p); // Called by boost::intrusive_ptr when a boost::intrusive_ptr<Responder> is destroyed.
|
||||
// This function must delete the Responder object when the reference count reaches zero.
|
||||
};
|
||||
|
||||
// A Responder is passed around as ResponderPtr, which causes it to automatically
|
||||
// destruct when there are no pointers left pointing to it.
|
||||
typedef boost::intrusive_ptr<Responder> ResponderPtr;
|
||||
|
||||
} // namespace AICurlInterface
|
||||
|
||||
// Forward declaration (see aicurlprivate.h).
|
||||
namespace AICurlPrivate {
|
||||
class CurlEasyRequest;
|
||||
} // namespace AICurlPrivate
|
||||
|
||||
// Define access types (_crat = Const Read Access Type, _rat = Read Access Type, _wat = Write Access Type).
|
||||
// Typical usage is:
|
||||
// AICurlEasyRequest h1; // Create easy handle.
|
||||
// AICurlEasyRequest h2(h1); // Make lightweight copies.
|
||||
// AICurlEasyRequest_wat h2_w(*h2); // Lock and obtain write access to the easy handle.
|
||||
// Use *h2_w, which is a reference to the locked CurlEasyRequest instance.
|
||||
// Note: As it is not allowed to use curl easy handles in any way concurrently,
|
||||
// read access would at most give access to a CURL const*, which will turn out
|
||||
// to be completely useless; therefore it is sufficient and efficient to use
|
||||
// an AIThreadSafeSimple and it's unlikely that AICurlEasyRequest_rat will be used.
|
||||
typedef AIAccessConst<AICurlPrivate::CurlEasyRequest> AICurlEasyRequest_rat;
|
||||
typedef AIAccess<AICurlPrivate::CurlEasyRequest> AICurlEasyRequest_wat;
|
||||
|
||||
// Events generated by AICurlPrivate::CurlEasyHandle.
|
||||
struct AICurlEasyHandleEvents {
|
||||
// Events.
|
||||
virtual void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
|
||||
virtual void finished(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
|
||||
virtual void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
|
||||
// Avoid compiler warning.
|
||||
virtual ~AICurlEasyHandleEvents() { }
|
||||
};
|
||||
|
||||
#include "aicurlprivate.h"
|
||||
|
||||
// AICurlPrivate::CurlEasyRequestPtr, a boost::intrusive_ptr, is no more threadsafe than a
|
||||
// builtin type, but wrapping it in AIThreadSafe is obviously not going to help here.
|
||||
// Therefore we use the following trick: we wrap CurlEasyRequestPtr too, and only allow
|
||||
// read accesses on it.
|
||||
|
||||
// AICurlEasyRequest: a thread safe, reference counting, auto-cleaning curl easy handle.
|
||||
class AICurlEasyRequest {
|
||||
public:
|
||||
// Initial construction is allowed (thread-safe).
|
||||
// Note: If ThreadSafeCurlEasyRequest() throws then the memory allocated is still freed.
|
||||
// 'new' never returned however and neither the constructor nor destructor of mCurlEasyRequest is called in this case.
|
||||
// This might throw AICurlNoEasyHandle.
|
||||
AICurlEasyRequest(bool buffered) :
|
||||
mCurlEasyRequest(buffered ? new AICurlPrivate::ThreadSafeBufferedCurlEasyRequest : new AICurlPrivate::ThreadSafeCurlEasyRequest) { }
|
||||
AICurlEasyRequest(AICurlEasyRequest const& orig) : mCurlEasyRequest(orig.mCurlEasyRequest) { }
|
||||
|
||||
// For the rest, only allow read operations.
|
||||
AIThreadSafeSimple<AICurlPrivate::CurlEasyRequest>& operator*(void) const { llassert(mCurlEasyRequest.get()); return *mCurlEasyRequest; }
|
||||
AIThreadSafeSimple<AICurlPrivate::CurlEasyRequest>* operator->(void) const { llassert(mCurlEasyRequest.get()); return mCurlEasyRequest.get(); }
|
||||
AIThreadSafeSimple<AICurlPrivate::CurlEasyRequest>* get(void) const { return mCurlEasyRequest.get(); }
|
||||
|
||||
// Returns true if this object points to the same CurlEasyRequest object.
|
||||
bool operator==(AICurlEasyRequest const& cer) const { return mCurlEasyRequest == cer.mCurlEasyRequest; }
|
||||
|
||||
// Returns true if this object points to a different CurlEasyRequest object.
|
||||
bool operator!=(AICurlEasyRequest const& cer) const { return mCurlEasyRequest != cer.mCurlEasyRequest; }
|
||||
|
||||
// Queue this request for insertion in the multi session.
|
||||
void addRequest(void);
|
||||
|
||||
// Queue a command to remove this request from the multi session (or cancel a queued command to add it).
|
||||
void removeRequest(void);
|
||||
|
||||
// Returns true when this AICurlEasyRequest wraps a AICurlPrivate::ThreadSafeBufferedCurlEasyRequest.
|
||||
bool isBuffered(void) const { return mCurlEasyRequest->isBuffered(); }
|
||||
|
||||
private:
|
||||
// The actual pointer to the ThreadSafeCurlEasyRequest instance.
|
||||
AICurlPrivate::CurlEasyRequestPtr mCurlEasyRequest;
|
||||
|
||||
private:
|
||||
// Assignment would not be thread-safe; we may create this object and read from it.
|
||||
// Note: Destruction is implicitly assumed thread-safe, as it would be a logic error to
|
||||
// destruct it while another thread still needs it, concurrent or not.
|
||||
AICurlEasyRequest& operator=(AICurlEasyRequest const&) { return *this; }
|
||||
|
||||
public:
|
||||
// The more exotic member functions of this class, to deal with passing this class
|
||||
// as CURLOPT_PRIVATE pointer to a curl handle and afterwards restore it.
|
||||
// For "internal use" only; don't use things from AICurlPrivate yourself.
|
||||
|
||||
// It's thread-safe to give read access the underlaying boost::intrusive_ptr.
|
||||
// It's not OK to then call get() on that and store the AICurlPrivate::ThreadSafeCurlEasyRequest* separately.
|
||||
AICurlPrivate::CurlEasyRequestPtr const& get_ptr(void) const { return mCurlEasyRequest; }
|
||||
|
||||
// If we have a correct (with regard to reference counting) AICurlPrivate::CurlEasyRequestPtr,
|
||||
// then it's OK to construct a AICurlEasyRequest from it.
|
||||
// Note that the external AICurlPrivate::CurlEasyRequestPtr needs its own locking, because
|
||||
// it's not thread-safe in itself.
|
||||
AICurlEasyRequest(AICurlPrivate::CurlEasyRequestPtr const& ptr) : mCurlEasyRequest(ptr) { }
|
||||
|
||||
// This one is obviously dangerous. It's for use only in MultiHandle::check_run_count.
|
||||
// See also the long comment in CurlEasyRequest::finalizeRequest with regard to CURLOPT_PRIVATE.
|
||||
explicit AICurlEasyRequest(AICurlPrivate::ThreadSafeCurlEasyRequest* ptr) : mCurlEasyRequest(ptr) { }
|
||||
};
|
||||
|
||||
// Write Access Type for the buffer.
|
||||
struct AICurlResponderBuffer_wat : public AIAccess<AICurlPrivate::CurlResponderBuffer> {
|
||||
explicit AICurlResponderBuffer_wat(AICurlPrivate::ThreadSafeBufferedCurlEasyRequest& lockobj) :
|
||||
AIAccess<AICurlPrivate::CurlResponderBuffer>(lockobj) { }
|
||||
AICurlResponderBuffer_wat(AIThreadSafeSimple<AICurlPrivate::CurlEasyRequest>& lockobj) :
|
||||
AIAccess<AICurlPrivate::CurlResponderBuffer>(static_cast<AICurlPrivate::ThreadSafeBufferedCurlEasyRequest&>(lockobj)) { }
|
||||
};
|
||||
|
||||
#define AICurlPrivate DONTUSE_AICurlPrivate
|
||||
|
||||
#endif
|
||||
414
indra/llmessage/aicurlprivate.h
Normal file
414
indra/llmessage/aicurlprivate.h
Normal file
@@ -0,0 +1,414 @@
|
||||
/**
|
||||
* @file aicurlprivate.h
|
||||
* @brief Thread safe wrapper for libcurl.
|
||||
*
|
||||
* Copyright (c) 2012, Aleric Inglewood.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution.
|
||||
*
|
||||
* CHANGELOG
|
||||
* and additional copyright holders.
|
||||
*
|
||||
* 28/04/2012
|
||||
* Initial version, written by Aleric Inglewood @ SL
|
||||
*/
|
||||
|
||||
#ifndef AICURLPRIVATE_H
|
||||
#define AICURLPRIVATE_H
|
||||
|
||||
#include <sstream>
|
||||
#include "llatomic.h"
|
||||
|
||||
namespace AICurlPrivate {
|
||||
namespace curlthread { class MultiHandle; }
|
||||
|
||||
struct Stats {
|
||||
static LLAtomicU32 easy_calls;
|
||||
static LLAtomicU32 easy_errors;
|
||||
static LLAtomicU32 easy_init_calls;
|
||||
static LLAtomicU32 easy_init_errors;
|
||||
static LLAtomicU32 easy_cleanup_calls;
|
||||
static LLAtomicU32 multi_calls;
|
||||
static LLAtomicU32 multi_errors;
|
||||
|
||||
static void print(void);
|
||||
};
|
||||
|
||||
void handle_multi_error(CURLMcode code);
|
||||
inline CURLMcode check_multi_code(CURLMcode code) { Stats::multi_calls++; if (code != CURLM_OK) handle_multi_error(code); return code; }
|
||||
|
||||
bool curlThreadIsRunning(void);
|
||||
void wakeUpCurlThread(void);
|
||||
void stopCurlThread(void);
|
||||
|
||||
class ThreadSafeCurlEasyRequest;
|
||||
class ThreadSafeBufferedCurlEasyRequest;
|
||||
|
||||
// This class wraps CURL*'s.
|
||||
// It guarantees that a pointer is cleaned up when no longer needed, as required by libcurl.
|
||||
class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEvents {
|
||||
public:
|
||||
CurlEasyHandle(void);
|
||||
~CurlEasyHandle();
|
||||
|
||||
private:
|
||||
// Disallow assignment.
|
||||
CurlEasyHandle& operator=(CurlEasyHandle const*);
|
||||
|
||||
public:
|
||||
// Reset all options of a libcurl session handle.
|
||||
void reset(void) { llassert(!mActiveMultiHandle); curl_easy_reset(mEasyHandle); }
|
||||
|
||||
// Set options for a curl easy handle.
|
||||
template<typename BUILTIN>
|
||||
CURLcode setopt(CURLoption option, BUILTIN parameter);
|
||||
|
||||
// Clone a libcurl session handle using all the options previously set.
|
||||
//CurlEasyHandle(CurlEasyHandle const& orig);
|
||||
|
||||
// URL encode/decode the given string.
|
||||
char* escape(char* url, int length);
|
||||
char* unescape(char* url, int inlength , int* outlength);
|
||||
|
||||
// Extract information from a curl handle.
|
||||
CURLcode getinfo(CURLINFO info, void* data);
|
||||
#if _WIN64 || __x86_64__ || __ppc64__
|
||||
// Overload for integer types that are too small (libcurl demands a long).
|
||||
CURLcode getinfo(CURLINFO info, S32* data) { long ldata; CURLcode res = getinfo(info, &ldata); *data = static_cast<S32>(ldata); return res; }
|
||||
CURLcode getinfo(CURLINFO info, U32* data) { long ldata; CURLcode res = getinfo(info, &ldata); *data = static_cast<U32>(ldata); return res; }
|
||||
#endif
|
||||
|
||||
// Perform a file transfer (blocking).
|
||||
CURLcode perform(void);
|
||||
// Pause and unpause a connection.
|
||||
CURLcode pause(int bitmask);
|
||||
|
||||
// Called when a request is queued for removal. In that case a race between the actual removal
|
||||
// and revoking of the callbacks is harmless (and happens for the raw non-statemachine version).
|
||||
void remove_queued(void) { mQueuedForRemoval = true; }
|
||||
// In case it's added after being removed.
|
||||
void add_queued(void) { mQueuedForRemoval = false; }
|
||||
|
||||
private:
|
||||
CURL* mEasyHandle;
|
||||
CURLM* mActiveMultiHandle;
|
||||
char* mErrorBuffer;
|
||||
bool mQueuedForRemoval; // Set if the easy handle is (probably) added to the multi handle, but is queued for removal.
|
||||
#ifdef SHOW_ASSERT
|
||||
public:
|
||||
bool mRemovedPerCommand; // Set if mActiveMultiHandle was reset as per command from the main thread.
|
||||
#endif
|
||||
|
||||
private:
|
||||
// This should only be called from MultiHandle; add/remove an easy handle to/from a multi handle.
|
||||
friend class curlthread::MultiHandle;
|
||||
CURLMcode add_handle_to_multi(AICurlEasyRequest_wat& curl_easy_request_w, CURLM* multi_handle);
|
||||
CURLMcode remove_handle_from_multi(AICurlEasyRequest_wat& curl_easy_request_w, CURLM* multi_handle);
|
||||
|
||||
public:
|
||||
// Returns true if this easy handle was added to a curl multi handle.
|
||||
bool active(void) const { return mActiveMultiHandle; }
|
||||
|
||||
// If there was an error code as result, then this returns a human readable error string.
|
||||
// Only valid when setErrorBuffer was called and the curl_easy function returned an error.
|
||||
std::string getErrorString(void) const { return mErrorBuffer ? mErrorBuffer : "(null)"; }
|
||||
|
||||
// Returns true when it is expected that the parent will revoke callbacks before the curl
|
||||
// easy handle is removed from the multi handle; that usually happens when an external
|
||||
// error demands termination of the request (ie, an expiration).
|
||||
bool no_warning(void) const { return mQueuedForRemoval || LLApp::isExiting(); }
|
||||
|
||||
// Used for debugging purposes.
|
||||
bool operator==(CURL* easy_handle) const { return mEasyHandle == easy_handle; }
|
||||
|
||||
private:
|
||||
// Call this prior to every curl_easy function whose return value is passed to check_easy_code.
|
||||
void setErrorBuffer(void);
|
||||
|
||||
static void handle_easy_error(CURLcode code);
|
||||
|
||||
// Always first call setErrorBuffer()!
|
||||
static inline CURLcode check_easy_code(CURLcode code)
|
||||
{
|
||||
Stats::easy_calls++;
|
||||
if (code != CURLE_OK)
|
||||
handle_easy_error(code);
|
||||
return code;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Return the underlying curl easy handle.
|
||||
CURL* getEasyHandle(void) const { return mEasyHandle; }
|
||||
|
||||
private:
|
||||
// Return, and possibly create, the curl (easy) error buffer used by the current thread.
|
||||
static char* getTLErrorBuffer(void);
|
||||
};
|
||||
|
||||
template<typename BUILTIN>
|
||||
CURLcode CurlEasyHandle::setopt(CURLoption option, BUILTIN parameter)
|
||||
{
|
||||
llassert(!mActiveMultiHandle);
|
||||
setErrorBuffer();
|
||||
return check_easy_code(curl_easy_setopt(mEasyHandle, option, parameter));
|
||||
}
|
||||
|
||||
// CurlEasyRequest adds a slightly more powerful interface that can be used
|
||||
// to set the options on a curl easy handle.
|
||||
//
|
||||
// Calling sendRequest() will then connect to the given URL and perform
|
||||
// the data exchange. If an error occurs related to this handle, it can
|
||||
// be read by calling getErrorString().
|
||||
//
|
||||
// Note that the life cycle of a CurlEasyRequest is controlled by AICurlEasyRequest:
|
||||
// a CurlEasyRequest is only ever created as base class of a ThreadSafeCurlEasyRequest,
|
||||
// which is only created by creating a AICurlEasyRequest. When the last copy of such
|
||||
// AICurlEasyRequest is deleted, then also the ThreadSafeCurlEasyRequest is deleted
|
||||
// and the CurlEasyRequest destructed.
|
||||
class CurlEasyRequest : public CurlEasyHandle {
|
||||
public:
|
||||
void setoptString(CURLoption option, std::string const& value);
|
||||
void setPost(char const* postdata, S32 size);
|
||||
void addHeader(char const* str);
|
||||
|
||||
private:
|
||||
// Callback stubs.
|
||||
static size_t headerCallback(char* ptr, size_t size, size_t nmemb, void* userdata);
|
||||
static size_t writeCallback(char* ptr, size_t size, size_t nmemb, void* userdata);
|
||||
static size_t readCallback(char* ptr, size_t size, size_t nmemb, void* userdata);
|
||||
static CURLcode SSLCtxCallback(CURL* curl, void* sslctx, void* userdata);
|
||||
|
||||
curl_write_callback mHeaderCallback;
|
||||
void* mHeaderCallbackUserData;
|
||||
curl_write_callback mWriteCallback;
|
||||
void* mWriteCallbackUserData;
|
||||
curl_read_callback mReadCallback;
|
||||
void* mReadCallbackUserData;
|
||||
curl_ssl_ctx_callback mSSLCtxCallback;
|
||||
void* mSSLCtxCallbackUserData;
|
||||
|
||||
public:
|
||||
void setHeaderCallback(curl_write_callback callback, void* userdata);
|
||||
void setWriteCallback(curl_write_callback callback, void* userdata);
|
||||
void setReadCallback(curl_read_callback callback, void* userdata);
|
||||
void setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata);
|
||||
|
||||
// Call this if the set callbacks are about to be invalidated.
|
||||
void revokeCallbacks(void);
|
||||
|
||||
// Reset everything to the state it was in when this object was just created.
|
||||
void resetState(void);
|
||||
|
||||
private:
|
||||
// Called from applyDefaultOptions.
|
||||
void applyProxySettings(void);
|
||||
|
||||
public:
|
||||
// Set default options that we want applied to all curl easy handles.
|
||||
void applyDefaultOptions(void);
|
||||
|
||||
// Prepare the request for adding it to a multi session, or calling perform.
|
||||
// This actually adds the headers that were collected with addHeader.
|
||||
void finalizeRequest(std::string const& url);
|
||||
|
||||
// Store result code that is returned by getResult.
|
||||
void store_result(CURLcode result) { mResult = result; }
|
||||
|
||||
// Called when the curl easy handle is done.
|
||||
void done(AICurlEasyRequest_wat& curl_easy_request_w) { finished(curl_easy_request_w); }
|
||||
|
||||
// Fill info with the transfer info.
|
||||
void getTransferInfo(AICurlInterface::TransferInfo* info);
|
||||
|
||||
// If result != CURLE_FAILED_INIT then also info was filled.
|
||||
void getResult(CURLcode* result, AICurlInterface::TransferInfo* info = NULL);
|
||||
|
||||
private:
|
||||
curl_slist* mHeaders;
|
||||
bool mRequestFinalized;
|
||||
AICurlEasyHandleEvents* mEventsTarget;
|
||||
CURLcode mResult;
|
||||
|
||||
private:
|
||||
// This class may only be created by constructing a ThreadSafeCurlEasyRequest.
|
||||
friend class ThreadSafeCurlEasyRequest;
|
||||
// Throws AICurlNoEasyHandle.
|
||||
CurlEasyRequest(void) :
|
||||
mHeaders(NULL), mRequestFinalized(false), mEventsTarget(NULL), mResult(CURLE_FAILED_INIT)
|
||||
{ applyDefaultOptions(); }
|
||||
public:
|
||||
~CurlEasyRequest();
|
||||
|
||||
public:
|
||||
// Post-initialization, set the parent to pass the events to.
|
||||
void send_events_to(AICurlEasyHandleEvents* target) { mEventsTarget = target; }
|
||||
|
||||
// For debugging purposes
|
||||
bool is_finalized(void) const { return mRequestFinalized; }
|
||||
|
||||
// Return pointer to the ThreadSafe (wrapped) version of this object.
|
||||
ThreadSafeCurlEasyRequest* get_lockobj(void);
|
||||
|
||||
protected:
|
||||
// Pass events to parent.
|
||||
/*virtual*/ void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
/*virtual*/ void finished(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
/*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
};
|
||||
|
||||
// Buffers used by the AICurlInterface::Request API.
|
||||
// Curl callbacks write into and read from these buffers.
|
||||
// The interface with the rest of the code is through AICurlInterface::Responder.
|
||||
//
|
||||
// The lifetime of a CurlResponderBuffer is slightly shorter than its
|
||||
// associated CurlEasyRequest; this class can only be created as base class
|
||||
// of ThreadSafeBufferedCurlEasyRequest, and is therefore constructed after
|
||||
// the construction of the associated CurlEasyRequest and destructed before it.
|
||||
// Hence, it's safe to use get_lockobj() and through that access the CurlEasyRequest
|
||||
// object at all times.
|
||||
//
|
||||
// A CurlResponderBuffer is thus created when a ThreadSafeBufferedCurlEasyRequest
|
||||
// is created which only happens by creating a AICurlEasyRequest(true) instance,
|
||||
// and when the last AICurlEasyRequest is deleted, then the ThreadSafeBufferedCurlEasyRequest
|
||||
// is deleted and the CurlResponderBuffer destructed.
|
||||
class CurlResponderBuffer : protected AICurlEasyHandleEvents {
|
||||
public:
|
||||
void resetState(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
void prepRequest(AICurlEasyRequest_wat& buffered_curl_easy_request_w, std::vector<std::string> const& headers, AICurlInterface::ResponderPtr responder, S32 time_out = 0, bool post = false);
|
||||
|
||||
std::stringstream& getInput() { return mInput; }
|
||||
std::stringstream& getHeaderOutput() { return mHeaderOutput; }
|
||||
LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; }
|
||||
|
||||
// Called if libcurl doesn't deliver within CurlRequestTimeOut seconds.
|
||||
void timed_out(void);
|
||||
|
||||
// Called after removed_from_multi_handle was called.
|
||||
void processOutput(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
|
||||
protected:
|
||||
/*virtual*/ void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
/*virtual*/ void finished(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
/*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
|
||||
private:
|
||||
std::stringstream mInput;
|
||||
std::stringstream mHeaderOutput;
|
||||
LLIOPipe::buffer_ptr_t mOutput;
|
||||
AICurlInterface::ResponderPtr mResponder;
|
||||
|
||||
public:
|
||||
static LLChannelDescriptors const sChannels; // Channel object for mOutput: we ONLY use channel 0, so this can be a constant.
|
||||
|
||||
private:
|
||||
// This class may only be created by constructing a ThreadSafeBufferedCurlEasyRequest.
|
||||
friend class ThreadSafeBufferedCurlEasyRequest;
|
||||
CurlResponderBuffer(void);
|
||||
public:
|
||||
~CurlResponderBuffer();
|
||||
|
||||
private:
|
||||
static size_t curlWriteCallback(char* data, size_t size, size_t nmemb, void* user_data);
|
||||
static size_t curlReadCallback(char* data, size_t size, size_t nmemb, void* user_data);
|
||||
static size_t curlHeaderCallback(char* data, size_t size, size_t nmemb, void* user_data);
|
||||
|
||||
public:
|
||||
// Return pointer to the ThreadSafe (wrapped) version of this object.
|
||||
ThreadSafeBufferedCurlEasyRequest* get_lockobj(void);
|
||||
|
||||
// Return true when prepRequest was already called and the object has not been
|
||||
// invalidated as a result of calling timed_out().
|
||||
bool isValid(void) const { return mResponder; }
|
||||
};
|
||||
|
||||
// This class wraps CurlEasyRequest for thread-safety and adds a reference counter so we can
|
||||
// copy it around cheaply and it gets destructed automatically when the last instance is deleted.
|
||||
// It guarantees that the CURL* handle is never used concurrently, which is not allowed by libcurl.
|
||||
// As AIThreadSafeSimpleDC contains a mutex, it cannot be copied. Therefore we need a reference counter for this object.
|
||||
class ThreadSafeCurlEasyRequest : public AIThreadSafeSimple<CurlEasyRequest> {
|
||||
public:
|
||||
// Throws AICurlNoEasyHandle.
|
||||
ThreadSafeCurlEasyRequest(void) : mReferenceCount(0)
|
||||
{ new (ptr()) CurlEasyRequest;
|
||||
Dout(dc::curl, "Creating ThreadSafeCurlEasyRequest with this = " << (void*)this); }
|
||||
virtual ~ThreadSafeCurlEasyRequest()
|
||||
{ Dout(dc::curl, "Destructing ThreadSafeCurlEasyRequest with this = " << (void*)this); }
|
||||
|
||||
// Returns true if this is a base class of ThreadSafeBufferedCurlEasyRequest.
|
||||
virtual bool isBuffered(void) const { return false; }
|
||||
|
||||
private:
|
||||
LLAtomicU32 mReferenceCount;
|
||||
|
||||
friend void intrusive_ptr_add_ref(ThreadSafeCurlEasyRequest* p); // Called by boost::intrusive_ptr when a new copy of a boost::intrusive_ptr<ThreadSafeCurlEasyRequest> is made.
|
||||
friend void intrusive_ptr_release(ThreadSafeCurlEasyRequest* p); // Called by boost::intrusive_ptr when a boost::intrusive_ptr<ThreadSafeCurlEasyRequest> is destroyed.
|
||||
};
|
||||
|
||||
// Same as the above but adds a CurlResponderBuffer. The latter has its own locking in order to
|
||||
// allow casting the underlying CurlEasyRequest to ThreadSafeCurlEasyRequest, independent of
|
||||
// what class it is part of: ThreadSafeCurlEasyRequest or ThreadSafeBufferedCurlEasyRequest.
|
||||
// The virtual destructor of ThreadSafeCurlEasyRequest allows to treat each easy handle transparently
|
||||
// as a ThreadSafeCurlEasyRequest object, or optionally dynamic_cast it to a ThreadSafeBufferedCurlEasyRequest.
|
||||
// Note: the order of these base classes is important: AIThreadSafeSimple<CurlResponderBuffer> is now
|
||||
// destructed before ThreadSafeCurlEasyRequest is.
|
||||
class ThreadSafeBufferedCurlEasyRequest : public ThreadSafeCurlEasyRequest, public AIThreadSafeSimple<CurlResponderBuffer> {
|
||||
public:
|
||||
// Throws AICurlNoEasyHandle.
|
||||
ThreadSafeBufferedCurlEasyRequest(void) { new (AIThreadSafeSimple<CurlResponderBuffer>::ptr()) CurlResponderBuffer; }
|
||||
|
||||
/*virtual*/ bool isBuffered(void) const { return true; }
|
||||
};
|
||||
|
||||
// The curl easy request type wrapped in a reference counting pointer.
|
||||
typedef boost::intrusive_ptr<AICurlPrivate::ThreadSafeCurlEasyRequest> CurlEasyRequestPtr;
|
||||
|
||||
// This class wraps CURLM*'s.
|
||||
// It guarantees that a pointer is cleaned up when no longer needed, as required by libcurl.
|
||||
class CurlMultiHandle : public boost::noncopyable {
|
||||
public:
|
||||
CurlMultiHandle(void);
|
||||
~CurlMultiHandle();
|
||||
|
||||
private:
|
||||
// Disallow assignment.
|
||||
CurlMultiHandle& operator=(CurlMultiHandle const*);
|
||||
|
||||
private:
|
||||
static LLAtomicU32 sTotalMultiHandles;
|
||||
|
||||
protected:
|
||||
CURLM* mMultiHandle;
|
||||
|
||||
public:
|
||||
// Set options for a curl multi handle.
|
||||
template<typename BUILTIN>
|
||||
CURLMcode setopt(CURLMoption option, BUILTIN parameter);
|
||||
|
||||
// Returns total number of existing CURLM* handles (excluding ones created outside this class).
|
||||
static U32 getTotalMultiHandles(void) { return sTotalMultiHandles; }
|
||||
};
|
||||
|
||||
template<typename BUILTIN>
|
||||
CURLMcode CurlMultiHandle::setopt(CURLMoption option, BUILTIN parameter)
|
||||
{
|
||||
return check_multi_code(curl_multi_setopt(mMultiHandle, option, parameter));
|
||||
}
|
||||
|
||||
} // namespace AICurlPrivate
|
||||
|
||||
#endif
|
||||
1561
indra/llmessage/aicurlthread.cpp
Normal file
1561
indra/llmessage/aicurlthread.cpp
Normal file
File diff suppressed because it is too large
Load Diff
128
indra/llmessage/aicurlthread.h
Normal file
128
indra/llmessage/aicurlthread.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* @file aicurlthread.h
|
||||
* @brief Thread safe wrapper for libcurl.
|
||||
*
|
||||
* Copyright (c) 2012, Aleric Inglewood.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution.
|
||||
*
|
||||
* CHANGELOG
|
||||
* and additional copyright holders.
|
||||
*
|
||||
* 28/04/2012
|
||||
* Initial version, written by Aleric Inglewood @ SL
|
||||
*/
|
||||
|
||||
#ifndef AICURLTHREAD_H
|
||||
#define AICURLTHREAD_H
|
||||
|
||||
#include "aicurl.h"
|
||||
#include <vector>
|
||||
|
||||
#undef AICurlPrivate
|
||||
|
||||
namespace AICurlPrivate {
|
||||
namespace curlthread {
|
||||
|
||||
class PollSet;
|
||||
|
||||
// For ordering a std::set with AICurlEasyRequest objects.
|
||||
struct AICurlEasyRequestCompare {
|
||||
bool operator()(AICurlEasyRequest const& h1, AICurlEasyRequest const& h2) { return h1.get() < h2.get(); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MultiHandle
|
||||
|
||||
// This class adds member functions that will only be called from the AICurlThread thread.
|
||||
// This class guarantees that all added easy handles will be removed from the multi handle
|
||||
// before the multi handle is cleaned up, as is required by libcurl.
|
||||
class MultiHandle : public CurlMultiHandle
|
||||
{
|
||||
public:
|
||||
MultiHandle(void);
|
||||
~MultiHandle();
|
||||
|
||||
// Add/remove an easy handle to/from a multi session.
|
||||
CURLMcode add_easy_request(AICurlEasyRequest const& easy_request);
|
||||
CURLMcode remove_easy_request(AICurlEasyRequest const& easy_request, bool as_per_command = false);
|
||||
|
||||
// Reads/writes available data from a particular socket (non-blocking).
|
||||
CURLMcode socket_action(curl_socket_t sockfd, int ev_bitmask);
|
||||
|
||||
// Set data to association with an internal socket.
|
||||
CURLMcode assign(curl_socket_t sockfd, void* sockptr);
|
||||
|
||||
// Read multi stack informationals.
|
||||
CURLMsg const* info_read(int* msgs_in_queue) const;
|
||||
|
||||
private:
|
||||
typedef std::set<AICurlEasyRequest, AICurlEasyRequestCompare> addedEasyRequests_type;
|
||||
addedEasyRequests_type mAddedEasyRequests;
|
||||
|
||||
bool mHandleAddedOrRemoved; // Set when an easy handle was added or removed, reset in check_run_count().
|
||||
int mPrevRunningHandles; // The last value of mRunningHandles that check_run_count() was called with.
|
||||
int mRunningHandles; // The last value returned by curl_multi_socket_action.
|
||||
long mTimeOut; // The last time out in ms as set by the callback CURLMOPT_TIMERFUNCTION.
|
||||
|
||||
private:
|
||||
static int socket_callback(CURL* easy, curl_socket_t s, int action, void* userp, void* socketp);
|
||||
static int timer_callback(CURLM* multi, long timeout_ms, void* userp);
|
||||
|
||||
public:
|
||||
// Returns the number of active easy handles as reported by the last call to curl_multi_socket_action.
|
||||
int getRunningHandles(void) const { return mRunningHandles; }
|
||||
|
||||
// Returns how long to wait for socket action before calling socket_action(CURL_SOCKET_TIMEOUT, 0), in ms.
|
||||
int getTimeOut(void) const { return mTimeOut; }
|
||||
|
||||
// This is called before sleeping, after calling (one or more times) socket_action.
|
||||
void check_run_count(void);
|
||||
|
||||
public:
|
||||
//-----------------------------------------------------------------------------
|
||||
// Curl socket administration:
|
||||
|
||||
PollSet* mReadPollSet;
|
||||
PollSet* mWritePollSet;
|
||||
};
|
||||
|
||||
} // namespace curlthread
|
||||
} // namespace AICurlPrivate
|
||||
|
||||
// Thread safe, noncopyable curl multi handle.
|
||||
// This class wraps MultiHandle for thread-safety.
|
||||
// AIThreadSafeSingleThreadDC cannot be copied, but that is OK as we don't need that (or want that);
|
||||
// this class provides a thread-local singleton (exactly one instance per thread), and because it
|
||||
// can't be copied, that guarantees that the CURLM* handle is never used concurrently, which is
|
||||
// not allowed by libcurl.
|
||||
class AICurlMultiHandle : public AIThreadSafeSingleThreadDC<AICurlPrivate::curlthread::MultiHandle>, public LLThreadLocalDataMember {
|
||||
public:
|
||||
static AICurlMultiHandle& getInstance(void);
|
||||
static void destroyInstance(void);
|
||||
private:
|
||||
// Use getInstance().
|
||||
AICurlMultiHandle(void) { }
|
||||
};
|
||||
|
||||
typedef AISTAccessConst<AICurlPrivate::curlthread::MultiHandle> AICurlMultiHandle_rat;
|
||||
typedef AISTAccess<AICurlPrivate::curlthread::MultiHandle> AICurlMultiHandle_wat;
|
||||
|
||||
#define AICurlPrivate DONTUSE_AICurlPrivate
|
||||
|
||||
#endif
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llares.h"
|
||||
#include "llscopedvolatileaprpool.h"
|
||||
|
||||
#include <ares_dns.h>
|
||||
#include <ares_version.h>
|
||||
|
||||
@@ -401,7 +401,7 @@ bool LLAssetStorage::findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAsse
|
||||
if (user_data)
|
||||
{
|
||||
// The *user_data should not be passed without a callback to clean it up.
|
||||
llassert(callback != NULL)
|
||||
llassert(callback != NULL);
|
||||
}
|
||||
|
||||
BOOL exists = mStaticVFS->getExists(uuid, type);
|
||||
@@ -441,7 +441,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, LL
|
||||
if (user_data)
|
||||
{
|
||||
// The *user_data should not be passed without a callback to clean it up.
|
||||
llassert(callback != NULL)
|
||||
llassert(callback != NULL);
|
||||
}
|
||||
|
||||
if (mShutDown)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,457 +1,39 @@
|
||||
/**
|
||||
/**
|
||||
* @file llcurl.h
|
||||
* @author Zero / Donovan
|
||||
* @date 2006-10-15
|
||||
* @brief A wrapper around libcurl.
|
||||
* @brief Drop in replacement for old llcurl.h.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* Copyright (c) 2012, Aleric Inglewood.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution.
|
||||
*
|
||||
* CHANGELOG
|
||||
* and additional copyright holders.
|
||||
*
|
||||
* 22/06/2012
|
||||
* Initial version, written by Aleric Inglewood @ SL
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LL_LLCURL_H
|
||||
#define LL_LLCURL_H
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "aicurl.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <curl/curl.h> // TODO: remove dependency
|
||||
|
||||
#include "llbuffer.h"
|
||||
#include "lliopipe.h"
|
||||
#include "llsd.h"
|
||||
#include "llthread.h"
|
||||
#include "llqueuedthread.h"
|
||||
#include "llframetimer.h"
|
||||
|
||||
class LLMutex;
|
||||
class LLCurlThread;
|
||||
|
||||
// For whatever reason, this is not typedef'd in curl.h
|
||||
typedef size_t (*curl_header_callback)(void *ptr, size_t size, size_t nmemb, void *stream);
|
||||
|
||||
class LLCurl
|
||||
{
|
||||
LOG_CLASS(LLCurl);
|
||||
|
||||
public:
|
||||
class Easy;
|
||||
class Multi;
|
||||
|
||||
struct TransferInfo
|
||||
{
|
||||
TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {}
|
||||
F64 mSizeDownload;
|
||||
F64 mTotalTime;
|
||||
F64 mSpeedDownload;
|
||||
};
|
||||
|
||||
class Responder
|
||||
{
|
||||
//LOG_CLASS(Responder);
|
||||
public:
|
||||
|
||||
Responder();
|
||||
virtual ~Responder();
|
||||
|
||||
/**
|
||||
* @brief return true if the status code indicates success.
|
||||
*/
|
||||
static bool isGoodStatus(U32 status)
|
||||
{
|
||||
return((200 <= status) && (status < 300));
|
||||
}
|
||||
|
||||
virtual void errorWithContent(
|
||||
U32 status,
|
||||
const std::string& reason,
|
||||
const LLSD& content);
|
||||
//< called by completed() on bad status
|
||||
|
||||
virtual void error(U32 status, const std::string& reason);
|
||||
//< called by default error(status, reason, content)
|
||||
|
||||
virtual void result(const LLSD& content);
|
||||
//< called by completed for good status codes.
|
||||
|
||||
virtual void completedRaw(
|
||||
U32 status,
|
||||
const std::string& reason,
|
||||
const LLChannelDescriptors& channels,
|
||||
const LLIOPipe::buffer_ptr_t& buffer);
|
||||
/**< Override point for clients that may want to use this
|
||||
class when the response is some other format besides LLSD
|
||||
*/
|
||||
|
||||
virtual void completed(
|
||||
U32 status,
|
||||
const std::string& reason,
|
||||
const LLSD& content);
|
||||
/**< The default implemetnation calls
|
||||
either:
|
||||
* result(), or
|
||||
* error()
|
||||
*/
|
||||
|
||||
// Override to handle parsing of the header only. Note: this is the only place where the contents
|
||||
// of the header can be parsed. In the ::completed call above only the body is contained in the LLSD.
|
||||
virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content);
|
||||
|
||||
// Used internally to set the url for debugging later.
|
||||
void setURL(const std::string& url);
|
||||
|
||||
virtual bool followRedir()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public: /* but not really -- don't touch this */
|
||||
U32 mReferenceCount;
|
||||
|
||||
private:
|
||||
std::string mURL;
|
||||
};
|
||||
typedef boost::intrusive_ptr<Responder> ResponderPtr;
|
||||
|
||||
|
||||
/**
|
||||
* @ brief Set certificate authority file used to verify HTTPS certs.
|
||||
*/
|
||||
static void setCAFile(const std::string& file);
|
||||
|
||||
/**
|
||||
* @ brief Set certificate authority path used to verify HTTPS certs.
|
||||
*/
|
||||
static void setCAPath(const std::string& path);
|
||||
|
||||
/**
|
||||
* @ brief Return human-readable string describing libcurl version.
|
||||
*/
|
||||
static std::string getVersionString();
|
||||
|
||||
/**
|
||||
* @ brief Get certificate authority file used to verify HTTPS certs.
|
||||
*/
|
||||
static const std::string& getCAFile() { return sCAFile; }
|
||||
|
||||
/**
|
||||
* @ brief Get certificate authority path used to verify HTTPS certs.
|
||||
*/
|
||||
static const std::string& getCAPath() { return sCAPath; }
|
||||
|
||||
/**
|
||||
* @ brief Initialize LLCurl class
|
||||
*/
|
||||
static void initClass(F32 curl_reuest_timeout = 120.f, S32 max_number_handles = 256, bool multi_threaded = false);
|
||||
|
||||
/**
|
||||
* @ brief Cleanup LLCurl class
|
||||
*/
|
||||
static void cleanupClass();
|
||||
|
||||
/**
|
||||
* @ brief curl error code -> string
|
||||
*/
|
||||
static std::string strerror(CURLcode errorcode);
|
||||
|
||||
// For OpenSSL callbacks
|
||||
static std::vector<LLMutex*> sSSLMutex;
|
||||
|
||||
// OpenSSL callbacks
|
||||
static void ssl_locking_callback(int mode, int type, const char *file, int line);
|
||||
static unsigned long ssl_thread_id(void);
|
||||
|
||||
static LLCurlThread* getCurlThread() { return sCurlThread ;}
|
||||
|
||||
static CURLM* newMultiHandle() ;
|
||||
static CURLMcode deleteMultiHandle(CURLM* handle) ;
|
||||
static CURL* newEasyHandle() ;
|
||||
static void deleteEasyHandle(CURL* handle) ;
|
||||
|
||||
private:
|
||||
static std::string sCAPath;
|
||||
static std::string sCAFile;
|
||||
static const unsigned int MAX_REDIRECTS;
|
||||
static LLCurlThread* sCurlThread;
|
||||
|
||||
static LLMutex* sHandleMutexp ;
|
||||
static S32 sTotalHandles ;
|
||||
static S32 sMaxHandles;
|
||||
public:
|
||||
static bool sNotQuitting;
|
||||
static F32 sCurlRequestTimeOut;
|
||||
};
|
||||
|
||||
class LLCurl::Easy
|
||||
{
|
||||
LOG_CLASS(Easy);
|
||||
|
||||
private:
|
||||
Easy();
|
||||
|
||||
public:
|
||||
static Easy* getEasy();
|
||||
~Easy();
|
||||
|
||||
CURL* getCurlHandle() const { return mCurlEasyHandle; }
|
||||
|
||||
void setErrorBuffer();
|
||||
void setCA();
|
||||
|
||||
void setopt(CURLoption option, S32 value);
|
||||
// These assume the setter does not free value!
|
||||
void setopt(CURLoption option, void* value);
|
||||
void setopt(CURLoption option, char* value);
|
||||
// Copies the string so that it is guaranteed to stick around
|
||||
void setoptString(CURLoption option, const std::string& value);
|
||||
|
||||
void slist_append(const char* str);
|
||||
void setHeaders();
|
||||
|
||||
U32 report(CURLcode);
|
||||
void getTransferInfo(LLCurl::TransferInfo* info);
|
||||
|
||||
void prepRequest(const std::string& url, const std::vector<std::string>& headers, LLCurl::ResponderPtr, S32 time_out = 0, bool post = false);
|
||||
|
||||
const char* getErrorBuffer();
|
||||
|
||||
std::stringstream& getInput() { return mInput; }
|
||||
std::stringstream& getHeaderOutput() { return mHeaderOutput; }
|
||||
LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; }
|
||||
const LLChannelDescriptors& getChannels() { return mChannels; }
|
||||
|
||||
void resetState();
|
||||
|
||||
static CURL* allocEasyHandle();
|
||||
static void releaseEasyHandle(CURL* handle);
|
||||
|
||||
private:
|
||||
friend class LLCurl;
|
||||
friend class LLCurl::Multi;
|
||||
|
||||
CURL* mCurlEasyHandle;
|
||||
struct curl_slist* mHeaders;
|
||||
|
||||
std::stringstream mRequest;
|
||||
LLChannelDescriptors mChannels;
|
||||
LLIOPipe::buffer_ptr_t mOutput;
|
||||
std::stringstream mInput;
|
||||
std::stringstream mHeaderOutput;
|
||||
char mErrorBuffer[CURL_ERROR_SIZE];
|
||||
|
||||
// Note: char*'s not strings since we pass pointers to curl
|
||||
std::vector<char*> mStrings;
|
||||
|
||||
LLCurl::ResponderPtr mResponder;
|
||||
|
||||
static std::set<CURL*> sFreeHandles;
|
||||
static std::set<CURL*> sActiveHandles;
|
||||
static LLMutex* sHandleMutexp ;
|
||||
};
|
||||
|
||||
class LLCurl::Multi
|
||||
{
|
||||
LOG_CLASS(Multi);
|
||||
|
||||
friend class LLCurlThread ;
|
||||
|
||||
private:
|
||||
~Multi();
|
||||
|
||||
void markDead() ;
|
||||
bool doPerform();
|
||||
|
||||
public:
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STATE_READY=0,
|
||||
STATE_PERFORMING=1,
|
||||
STATE_COMPLETED=2
|
||||
} ePerformState;
|
||||
|
||||
Multi(F32 idle_time_out = 0.f);
|
||||
|
||||
LLCurl::Easy* allocEasy();
|
||||
bool addEasy(LLCurl::Easy* easy);
|
||||
void removeEasy(LLCurl::Easy* easy);
|
||||
|
||||
void lock() ;
|
||||
void unlock() ;
|
||||
|
||||
void setState(ePerformState state) ;
|
||||
ePerformState getState() ;
|
||||
|
||||
bool isCompleted() ;
|
||||
bool isValid() {return mCurlMultiHandle != NULL && mValid;}
|
||||
bool isDead() {return mDead;}
|
||||
|
||||
bool waitToComplete() ;
|
||||
|
||||
S32 process();
|
||||
|
||||
CURLMsg* info_read(S32* msgs_in_queue);
|
||||
|
||||
S32 mQueued;
|
||||
S32 mErrorCount;
|
||||
|
||||
private:
|
||||
void easyFree(LLCurl::Easy*);
|
||||
void cleanup(bool deleted = false);
|
||||
|
||||
CURLM* mCurlMultiHandle;
|
||||
|
||||
typedef std::set<LLCurl::Easy*> easy_active_list_t;
|
||||
easy_active_list_t mEasyActiveList;
|
||||
typedef std::map<CURL*, LLCurl::Easy*> easy_active_map_t;
|
||||
easy_active_map_t mEasyActiveMap;
|
||||
typedef std::set<LLCurl::Easy*> easy_free_list_t;
|
||||
easy_free_list_t mEasyFreeList;
|
||||
|
||||
LLQueuedThread::handle_t mHandle ;
|
||||
ePerformState mState;
|
||||
|
||||
BOOL mDead ;
|
||||
BOOL mValid ;
|
||||
LLMutex* mMutexp ;
|
||||
LLMutex* mDeletionMutexp ;
|
||||
LLMutex* mEasyMutexp ;
|
||||
LLFrameTimer mIdleTimer ;
|
||||
F32 mIdleTimeOut;
|
||||
};
|
||||
|
||||
class LLCurlThread : public LLQueuedThread
|
||||
{
|
||||
public:
|
||||
|
||||
class CurlRequest : public LLQueuedThread::QueuedRequest
|
||||
{
|
||||
protected:
|
||||
virtual ~CurlRequest(); // use deleteRequest()
|
||||
|
||||
public:
|
||||
CurlRequest(handle_t handle, LLCurl::Multi* multi, LLCurlThread* curl_thread);
|
||||
|
||||
/*virtual*/ bool processRequest();
|
||||
/*virtual*/ void finishRequest(bool completed);
|
||||
|
||||
private:
|
||||
// input
|
||||
LLCurl::Multi* mMulti;
|
||||
LLCurlThread* mCurlThread;
|
||||
};
|
||||
friend class CurlRequest;
|
||||
|
||||
public:
|
||||
LLCurlThread(bool threaded = true) ;
|
||||
virtual ~LLCurlThread() ;
|
||||
|
||||
S32 update(F32 max_time_ms);
|
||||
|
||||
void addMulti(LLCurl::Multi* multi) ;
|
||||
void killMulti(LLCurl::Multi* multi) ;
|
||||
|
||||
private:
|
||||
bool doMultiPerform(LLCurl::Multi* multi) ;
|
||||
void deleteMulti(LLCurl::Multi* multi) ;
|
||||
void cleanupMulti(LLCurl::Multi* multi) ;
|
||||
} ;
|
||||
|
||||
//namespace boost
|
||||
//{
|
||||
void intrusive_ptr_add_ref(LLCurl::Responder* p);
|
||||
void intrusive_ptr_release(LLCurl::Responder* p);
|
||||
//};
|
||||
|
||||
|
||||
class LLCurlRequest
|
||||
{
|
||||
public:
|
||||
typedef std::vector<std::string> headers_t;
|
||||
|
||||
LLCurlRequest();
|
||||
~LLCurlRequest();
|
||||
|
||||
void get(const std::string& url, LLCurl::ResponderPtr responder);
|
||||
bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder);
|
||||
bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder, S32 time_out = 0);
|
||||
bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder, S32 time_out = 0);
|
||||
|
||||
S32 process();
|
||||
S32 getQueued();
|
||||
|
||||
private:
|
||||
void addMulti();
|
||||
LLCurl::Easy* allocEasy();
|
||||
bool addEasy(LLCurl::Easy* easy);
|
||||
|
||||
private:
|
||||
typedef std::set<LLCurl::Multi*> curlmulti_set_t;
|
||||
curlmulti_set_t mMultiSet;
|
||||
LLCurl::Multi* mActiveMulti;
|
||||
S32 mActiveRequestCount;
|
||||
BOOL mProcessing;
|
||||
};
|
||||
|
||||
class LLCurlEasyRequest
|
||||
{
|
||||
public:
|
||||
LLCurlEasyRequest();
|
||||
~LLCurlEasyRequest();
|
||||
void setopt(CURLoption option, S32 value);
|
||||
void setoptString(CURLoption option, const std::string& value);
|
||||
void setPost(char* postdata, S32 size);
|
||||
void setHeaderCallback(curl_header_callback callback, void* userdata);
|
||||
void setWriteCallback(curl_write_callback callback, void* userdata);
|
||||
void setReadCallback(curl_read_callback callback, void* userdata);
|
||||
void setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata);
|
||||
void slist_append(const char* str);
|
||||
void sendRequest(const std::string& url);
|
||||
void requestComplete();
|
||||
bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL);
|
||||
std::string getErrorString();
|
||||
bool isCompleted() {return mMulti->isCompleted() ;}
|
||||
bool wait() { return mMulti->waitToComplete(); }
|
||||
bool isValid() {return mMulti && mMulti->isValid(); }
|
||||
|
||||
LLCurl::Easy* getEasy() const { return mEasy; }
|
||||
|
||||
private:
|
||||
CURLMsg* info_read(S32* queue, LLCurl::TransferInfo* info);
|
||||
|
||||
private:
|
||||
LLCurl::Multi* mMulti;
|
||||
LLCurl::Easy* mEasy;
|
||||
bool mRequestSent;
|
||||
bool mResultReturned;
|
||||
};
|
||||
|
||||
// Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace.
|
||||
namespace LLCurlFF
|
||||
{
|
||||
void check_easy_code(CURLcode code);
|
||||
void check_multi_code(CURLMcode code);
|
||||
}
|
||||
// Map interface to old LLCurl names so this can be used as a drop-in replacement.
|
||||
namespace LLCurl = AICurlInterface;
|
||||
|
||||
#endif // LL_LLCURL_H
|
||||
|
||||
@@ -220,17 +220,28 @@ static void request(
|
||||
const LLSD& headers = LLSD()
|
||||
)
|
||||
{
|
||||
if (responder)
|
||||
{
|
||||
// For possible debug output from within the responder.
|
||||
responder->setURL(url);
|
||||
}
|
||||
|
||||
if (!LLHTTPClient::hasPump())
|
||||
{
|
||||
responder->completed(U32_MAX, "No pump", LLSD());
|
||||
responder->fatalError("No pump");
|
||||
return;
|
||||
}
|
||||
LLPumpIO::chain_t chain;
|
||||
|
||||
LLURLRequest* req = new LLURLRequest(method, url);
|
||||
if(!req->isValid())//failed
|
||||
LLURLRequest* req;
|
||||
try
|
||||
{
|
||||
delete req ;
|
||||
req = new LLURLRequest(method, url);
|
||||
}
|
||||
catch(AICurlNoEasyHandle& error)
|
||||
{
|
||||
llwarns << "Failed to create LLURLRequest: " << error.what() << llendl;
|
||||
// This is what the old LL code did: no recovery whatsoever (but also no leaks or crash).
|
||||
return ;
|
||||
}
|
||||
|
||||
@@ -282,11 +293,6 @@ static void request(
|
||||
}
|
||||
}
|
||||
|
||||
if (responder)
|
||||
{
|
||||
responder->setURL(url);
|
||||
}
|
||||
|
||||
req->setCallback(new LLHTTPClientURLAdaptor(responder));
|
||||
|
||||
if (method == LLURLRequest::HTTP_POST && gMessageSystem)
|
||||
@@ -333,7 +339,7 @@ void LLHTTPClient::getByteRange(
|
||||
std::string range = llformat("bytes=%d-%d", offset, offset+bytes-1);
|
||||
headers["Range"] = range;
|
||||
}
|
||||
request(url,LLURLRequest::HTTP_GET, NULL, responder, timeout, headers);
|
||||
request(url, LLURLRequest::HTTP_GET, NULL, responder, timeout, headers);
|
||||
}
|
||||
|
||||
void LLHTTPClient::head(
|
||||
@@ -372,12 +378,12 @@ class LLHTTPBuffer
|
||||
public:
|
||||
LLHTTPBuffer() { }
|
||||
|
||||
static size_t curl_write( void *ptr, size_t size, size_t nmemb, void *user_data)
|
||||
static size_t curl_write(char* ptr, size_t size, size_t nmemb, void* user_data)
|
||||
{
|
||||
LLHTTPBuffer* self = (LLHTTPBuffer*)user_data;
|
||||
|
||||
size_t bytes = (size * nmemb);
|
||||
self->mBuffer.append((char*)ptr,bytes);
|
||||
self->mBuffer.append(ptr,bytes);
|
||||
return nmemb;
|
||||
}
|
||||
|
||||
@@ -428,104 +434,91 @@ static LLSD blocking_request(
|
||||
)
|
||||
{
|
||||
lldebugs << "blockingRequest of " << url << llendl;
|
||||
char curl_error_buffer[CURL_ERROR_SIZE] = "\0";
|
||||
CURL* curlp = LLCurl::newEasyHandle();
|
||||
llassert_always(curlp != NULL) ;
|
||||
|
||||
LLHTTPBuffer http_buffer;
|
||||
std::string body_str;
|
||||
|
||||
// other request method checks root cert first, we skip?
|
||||
S32 http_status = 499;
|
||||
LLSD response = LLSD::emptyMap();
|
||||
|
||||
// Apply configured proxy settings
|
||||
LLProxy::getInstance()->applyProxySettings(curlp);
|
||||
|
||||
// * Set curl handle options
|
||||
curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts
|
||||
curl_easy_setopt(curlp, CURLOPT_TIMEOUT, timeout); // seconds, see warning at top of function.
|
||||
curl_easy_setopt(curlp, CURLOPT_WRITEFUNCTION, LLHTTPBuffer::curl_write);
|
||||
curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer);
|
||||
curl_easy_setopt(curlp, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer);
|
||||
|
||||
// * Setup headers (don't forget to free them after the call!)
|
||||
curl_slist* headers_list = NULL;
|
||||
if (headers.isMap())
|
||||
try
|
||||
{
|
||||
LLSD::map_const_iterator iter = headers.beginMap();
|
||||
LLSD::map_const_iterator end = headers.endMap();
|
||||
for (; iter != end; ++iter)
|
||||
AICurlEasyRequest easy_request(false);
|
||||
AICurlEasyRequest_wat curlEasyRequest_w(*easy_request);
|
||||
|
||||
LLHTTPBuffer http_buffer;
|
||||
std::string body_str;
|
||||
|
||||
// * Set curl handle options
|
||||
curlEasyRequest_w->setopt(CURLOPT_TIMEOUT, timeout); // seconds, see warning at top of function.
|
||||
curlEasyRequest_w->setWriteCallback(&LLHTTPBuffer::curl_write, &http_buffer);
|
||||
|
||||
// * Setup headers.
|
||||
if (headers.isMap())
|
||||
{
|
||||
std::ostringstream header;
|
||||
header << iter->first << ": " << iter->second.asString() ;
|
||||
lldebugs << "header = " << header.str() << llendl;
|
||||
headers_list = curl_slist_append(headers_list, header.str().c_str());
|
||||
LLSD::map_const_iterator iter = headers.beginMap();
|
||||
LLSD::map_const_iterator end = headers.endMap();
|
||||
for (; iter != end; ++iter)
|
||||
{
|
||||
std::ostringstream header;
|
||||
header << iter->first << ": " << iter->second.asString() ;
|
||||
lldebugs << "header = " << header.str() << llendl;
|
||||
curlEasyRequest_w->addHeader(header.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// * Setup specific method / "verb" for the URI (currently only GET and POST supported + poppy)
|
||||
if (method == LLURLRequest::HTTP_GET)
|
||||
{
|
||||
curlEasyRequest_w->setopt(CURLOPT_HTTPGET, 1);
|
||||
}
|
||||
else if (method == LLURLRequest::HTTP_POST)
|
||||
{
|
||||
curlEasyRequest_w->setopt(CURLOPT_POST, 1);
|
||||
//serialize to ostr then copy to str - need to because ostr ptr is unstable :(
|
||||
std::ostringstream ostr;
|
||||
LLSDSerialize::toXML(body, ostr);
|
||||
body_str = ostr.str();
|
||||
curlEasyRequest_w->setopt(CURLOPT_POSTFIELDS, body_str.c_str());
|
||||
//copied from PHP libs, correct?
|
||||
curlEasyRequest_w->addHeader("Content-Type: application/llsd+xml");
|
||||
|
||||
// copied from llurlrequest.cpp
|
||||
// it appears that apache2.2.3 or django in etch is busted. If
|
||||
// we do not clear the expect header, we get a 500. May be
|
||||
// limited to django/mod_wsgi.
|
||||
curlEasyRequest_w->addHeader("Expect:");
|
||||
}
|
||||
|
||||
// * Do the action using curl, handle results
|
||||
lldebugs << "HTTP body: " << body_str << llendl;
|
||||
curlEasyRequest_w->addHeader("Accept: application/llsd+xml");
|
||||
curlEasyRequest_w->finalizeRequest(url);
|
||||
|
||||
S32 curl_success = curlEasyRequest_w->perform();
|
||||
curlEasyRequest_w->getinfo(CURLINFO_RESPONSE_CODE, &http_status);
|
||||
// if we get a non-404 and it's not a 200 OR maybe it is but you have error bits,
|
||||
if ( http_status != 404 && (http_status != 200 || curl_success != 0) )
|
||||
{
|
||||
// We expect 404s, don't spam for them.
|
||||
llwarns << "CURL REQ URL: " << url << llendl;
|
||||
llwarns << "CURL REQ METHOD TYPE: " << method << llendl;
|
||||
llwarns << "CURL REQ HEADERS: " << headers.asString() << llendl;
|
||||
llwarns << "CURL REQ BODY: " << body_str << llendl;
|
||||
llwarns << "CURL HTTP_STATUS: " << http_status << llendl;
|
||||
llwarns << "CURL ERROR: " << curlEasyRequest_w->getErrorString() << llendl;
|
||||
llwarns << "CURL ERROR BODY: " << http_buffer.asString() << llendl;
|
||||
response["body"] = http_buffer.asString();
|
||||
}
|
||||
else
|
||||
{
|
||||
response["body"] = http_buffer.asLLSD();
|
||||
lldebugs << "CURL response: " << http_buffer.asString() << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
// * Setup specific method / "verb" for the URI (currently only GET and POST supported + poppy)
|
||||
if (method == LLURLRequest::HTTP_GET)
|
||||
catch(AICurlNoEasyHandle const& error)
|
||||
{
|
||||
curl_easy_setopt(curlp, CURLOPT_HTTPGET, 1);
|
||||
}
|
||||
else if (method == LLURLRequest::HTTP_POST)
|
||||
{
|
||||
curl_easy_setopt(curlp, CURLOPT_POST, 1);
|
||||
//serialize to ostr then copy to str - need to because ostr ptr is unstable :(
|
||||
std::ostringstream ostr;
|
||||
LLSDSerialize::toXML(body, ostr);
|
||||
body_str = ostr.str();
|
||||
curl_easy_setopt(curlp, CURLOPT_POSTFIELDS, body_str.c_str());
|
||||
//copied from PHP libs, correct?
|
||||
headers_list = curl_slist_append(headers_list, "Content-Type: application/llsd+xml");
|
||||
|
||||
// copied from llurlrequest.cpp
|
||||
// it appears that apache2.2.3 or django in etch is busted. If
|
||||
// we do not clear the expect header, we get a 500. May be
|
||||
// limited to django/mod_wsgi.
|
||||
headers_list = curl_slist_append(headers_list, "Expect:");
|
||||
}
|
||||
|
||||
// * Do the action using curl, handle results
|
||||
lldebugs << "HTTP body: " << body_str << llendl;
|
||||
headers_list = curl_slist_append(headers_list, "Accept: application/llsd+xml");
|
||||
CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, headers_list);
|
||||
if ( curl_result != CURLE_OK )
|
||||
{
|
||||
llinfos << "Curl is hosed - can't add headers" << llendl;
|
||||
response["body"] = error.what();
|
||||
}
|
||||
|
||||
LLSD response = LLSD::emptyMap();
|
||||
S32 curl_success = curl_easy_perform(curlp);
|
||||
S32 http_status = 499;
|
||||
curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &http_status);
|
||||
response["status"] = http_status;
|
||||
// if we get a non-404 and it's not a 200 OR maybe it is but you have error bits,
|
||||
if ( http_status != 404 && (http_status != 200 || curl_success != 0) )
|
||||
{
|
||||
// We expect 404s, don't spam for them.
|
||||
llwarns << "CURL REQ URL: " << url << llendl;
|
||||
llwarns << "CURL REQ METHOD TYPE: " << method << llendl;
|
||||
llwarns << "CURL REQ HEADERS: " << headers.asString() << llendl;
|
||||
llwarns << "CURL REQ BODY: " << body_str << llendl;
|
||||
llwarns << "CURL HTTP_STATUS: " << http_status << llendl;
|
||||
llwarns << "CURL ERROR: " << curl_error_buffer << llendl;
|
||||
llwarns << "CURL ERROR BODY: " << http_buffer.asString() << llendl;
|
||||
response["body"] = http_buffer.asString();
|
||||
}
|
||||
else
|
||||
{
|
||||
response["body"] = http_buffer.asLLSD();
|
||||
lldebugs << "CURL response: " << http_buffer.asString() << llendl;
|
||||
}
|
||||
|
||||
if(headers_list)
|
||||
{ // free the header list
|
||||
curl_slist_free_all(headers_list);
|
||||
}
|
||||
|
||||
// * Cleanup
|
||||
LLCurl::deleteEasyHandle(curlp);
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,9 @@ public:
|
||||
typedef LLCurl::Responder Responder;
|
||||
typedef LLCurl::ResponderPtr ResponderPtr;
|
||||
|
||||
|
||||
// The default actually already ignores responses.
|
||||
class ResponderIgnore : public Responder { };
|
||||
|
||||
/** @name non-blocking API */
|
||||
//@{
|
||||
static void head(
|
||||
|
||||
@@ -76,7 +76,14 @@ LLIOPipe::~LLIOPipe()
|
||||
}
|
||||
|
||||
//virtual
|
||||
bool LLIOPipe::isValid()
|
||||
bool LLIOPipe::hasExpiration(void) const
|
||||
{
|
||||
// LLIOPipe::hasNotExpired always returns true.
|
||||
return false;
|
||||
}
|
||||
|
||||
//virtual
|
||||
bool LLIOPipe::hasNotExpired(void) const
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public:
|
||||
// The connection was lost.
|
||||
STATUS_LOST_CONNECTION = -5,
|
||||
|
||||
// The totoal process time has exceeded the timeout.
|
||||
// The total process time has exceeded the timeout.
|
||||
STATUS_EXPIRED = -6,
|
||||
|
||||
// Keep track of the count of codes here.
|
||||
@@ -231,7 +231,16 @@ public:
|
||||
*/
|
||||
virtual ~LLIOPipe();
|
||||
|
||||
virtual bool isValid() ;
|
||||
/**
|
||||
* @brief External expiration facility.
|
||||
*
|
||||
* If hasExpiration() returns true, then we need to check hasNotExpired()
|
||||
* to see if the LLIOPipe is still valid. In the legacy LL code the
|
||||
* latter was called isValid() and was overloaded for two purposes:
|
||||
* either expiration or failure to initialize.
|
||||
*/
|
||||
virtual bool hasExpiration(void) const;
|
||||
virtual bool hasNotExpired(void) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
||||
@@ -47,23 +47,22 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou
|
||||
static LLSocket::ptr_t tcp_open_channel(LLHost host); // Open a TCP channel to a given host
|
||||
static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP channel
|
||||
|
||||
LLProxy::LLProxy():
|
||||
mHTTPProxyEnabled(false),
|
||||
mProxyMutex(),
|
||||
mUDPProxy(),
|
||||
mTCPProxy(),
|
||||
mHTTPProxy(),
|
||||
ProxyShared::ProxyShared(void):
|
||||
mProxyType(LLPROXY_SOCKS),
|
||||
mAuthMethodSelected(METHOD_NOAUTH),
|
||||
mSocksUsername(),
|
||||
mSocksPassword()
|
||||
mAuthMethodSelected(METHOD_NOAUTH)
|
||||
{
|
||||
}
|
||||
|
||||
LLProxy::LLProxy():
|
||||
mHTTPProxyEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
LLProxy::~LLProxy()
|
||||
{
|
||||
stopSOCKSProxy();
|
||||
disableHTTPProxy();
|
||||
Shared_wat shared_w(mShared);
|
||||
disableHTTPProxy(shared_w);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,15 +77,18 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
||||
{
|
||||
S32 result;
|
||||
|
||||
Unshared_rat unshared_r(mUnshared);
|
||||
Shared_rat shared_r(mShared);
|
||||
|
||||
/* SOCKS 5 Auth request */
|
||||
socks_auth_request_t socks_auth_request;
|
||||
socks_auth_response_t socks_auth_response;
|
||||
|
||||
socks_auth_request.version = SOCKS_VERSION; // SOCKS version 5
|
||||
socks_auth_request.num_methods = 1; // Sending 1 method.
|
||||
socks_auth_request.methods = getSelectedAuthMethod(); // Send only the selected method.
|
||||
socks_auth_request.methods = getSelectedAuthMethod(shared_r); // Send only the selected method.
|
||||
|
||||
result = tcp_blocking_handshake(mProxyControlChannel,
|
||||
result = tcp_blocking_handshake(unshared_r->mProxyControlChannel,
|
||||
static_cast<char*>(static_cast<void*>(&socks_auth_request)),
|
||||
sizeof(socks_auth_request),
|
||||
static_cast<char*>(static_cast<void*>(&socks_auth_response)),
|
||||
@@ -109,8 +111,8 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
||||
if (socks_auth_response.method == METHOD_PASSWORD)
|
||||
{
|
||||
// The server has requested a username/password combination
|
||||
std::string socks_username(getSocksUser());
|
||||
std::string socks_password(getSocksPwd());
|
||||
std::string socks_username(getSocksUser(shared_r));
|
||||
std::string socks_password(getSocksPwd(shared_r));
|
||||
U32 request_size = socks_username.size() + socks_password.size() + 3;
|
||||
char * password_auth = new char[request_size];
|
||||
password_auth[0] = 0x01;
|
||||
@@ -121,7 +123,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
||||
|
||||
authmethod_password_reply_t password_reply;
|
||||
|
||||
result = tcp_blocking_handshake(mProxyControlChannel,
|
||||
result = tcp_blocking_handshake(unshared_r->mProxyControlChannel,
|
||||
password_auth,
|
||||
request_size,
|
||||
static_cast<char*>(static_cast<void*>(&password_reply)),
|
||||
@@ -157,7 +159,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
||||
// "If the client is not in possession of the information at the time of the UDP ASSOCIATE,
|
||||
// the client MUST use a port number and address of all zeros. RFC 1928"
|
||||
|
||||
result = tcp_blocking_handshake(mProxyControlChannel,
|
||||
result = tcp_blocking_handshake(unshared_r->mProxyControlChannel,
|
||||
static_cast<char*>(static_cast<void*>(&connect_request)),
|
||||
sizeof(connect_request),
|
||||
static_cast<char*>(static_cast<void*>(&connect_reply)),
|
||||
@@ -176,10 +178,14 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
||||
return SOCKS_UDP_FWD_NOT_GRANTED;
|
||||
}
|
||||
|
||||
mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order
|
||||
mUDPProxy.setAddress(proxy.getAddress());
|
||||
{
|
||||
// Write access type and read access type are really the same, so unshared_w must be simply a reference.
|
||||
Unshared_wat& unshared_w = unshared_r;
|
||||
unshared_w->mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order
|
||||
unshared_w->mUDPProxy.setAddress(proxy.getAddress());
|
||||
}
|
||||
// The connection was successful. We now have the UDP port to send requests that need forwarding to.
|
||||
LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << mUDPProxy << LL_ENDL;
|
||||
LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << unshared_r->mUDPProxy << LL_ENDL;
|
||||
|
||||
return SOCKS_OK;
|
||||
}
|
||||
@@ -197,9 +203,11 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
||||
*/
|
||||
S32 LLProxy::startSOCKSProxy(LLHost host)
|
||||
{
|
||||
Unshared_wat unshared_w(mUnshared);
|
||||
|
||||
if (host.isOk())
|
||||
{
|
||||
mTCPProxy = host;
|
||||
unshared_w->mTCPProxy = host;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -209,13 +217,13 @@ S32 LLProxy::startSOCKSProxy(LLHost host)
|
||||
// Close any running SOCKS connection.
|
||||
stopSOCKSProxy();
|
||||
|
||||
mProxyControlChannel = tcp_open_channel(mTCPProxy);
|
||||
if (!mProxyControlChannel)
|
||||
unshared_w->mProxyControlChannel = tcp_open_channel(unshared_w->mTCPProxy);
|
||||
if (!unshared_w->mProxyControlChannel)
|
||||
{
|
||||
return SOCKS_HOST_CONNECT_FAILED;
|
||||
}
|
||||
|
||||
S32 status = proxyHandshake(mTCPProxy);
|
||||
S32 status = proxyHandshake(unshared_w->mTCPProxy);
|
||||
|
||||
if (status != SOCKS_OK)
|
||||
{
|
||||
@@ -246,14 +254,16 @@ void LLProxy::stopSOCKSProxy()
|
||||
// then we must shut down any HTTP proxy operations. But it is allowable if web
|
||||
// proxy is being used to continue proxying HTTP.
|
||||
|
||||
if (LLPROXY_SOCKS == getHTTPProxyType())
|
||||
Shared_rat shared_r(mShared);
|
||||
if (LLPROXY_SOCKS == getHTTPProxyType(shared_r))
|
||||
{
|
||||
disableHTTPProxy();
|
||||
Shared_wat shared_w(shared_r);
|
||||
disableHTTPProxy(shared_w);
|
||||
}
|
||||
|
||||
if (mProxyControlChannel)
|
||||
Unshared_wat unshared_w(mUnshared);
|
||||
if (unshared_w->mProxyControlChannel)
|
||||
{
|
||||
tcp_close_channel(&mProxyControlChannel);
|
||||
tcp_close_channel(&unshared_w->mProxyControlChannel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,9 +272,7 @@ void LLProxy::stopSOCKSProxy()
|
||||
*/
|
||||
void LLProxy::setAuthNone()
|
||||
{
|
||||
LLMutexLock lock(&mProxyMutex);
|
||||
|
||||
mAuthMethodSelected = METHOD_NOAUTH;
|
||||
Shared_wat(mShared)->mAuthMethodSelected = METHOD_NOAUTH;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -288,11 +296,10 @@ bool LLProxy::setAuthPassword(const std::string &username, const std::string &pa
|
||||
return false;
|
||||
}
|
||||
|
||||
LLMutexLock lock(&mProxyMutex);
|
||||
|
||||
mAuthMethodSelected = METHOD_PASSWORD;
|
||||
mSocksUsername = username;
|
||||
mSocksPassword = password;
|
||||
Shared_wat shared_w(mShared);
|
||||
shared_w->mAuthMethodSelected = METHOD_PASSWORD;
|
||||
shared_w->mSocksUsername = username;
|
||||
shared_w->mSocksPassword = password;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -314,12 +321,10 @@ bool LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type)
|
||||
return false;
|
||||
}
|
||||
|
||||
LLMutexLock lock(&mProxyMutex);
|
||||
|
||||
mHTTPProxy = httpHost;
|
||||
mProxyType = type;
|
||||
|
||||
Shared_wat shared_w(mShared);
|
||||
mHTTPProxyEnabled = true;
|
||||
shared_w->mHTTPProxy = httpHost;
|
||||
shared_w->mProxyType = type;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -335,9 +340,8 @@ bool LLProxy::enableHTTPProxy()
|
||||
{
|
||||
bool ok;
|
||||
|
||||
LLMutexLock lock(&mProxyMutex);
|
||||
|
||||
ok = (mHTTPProxy.isOk());
|
||||
Shared_rat shared_r(mShared);
|
||||
ok = (shared_r->mHTTPProxy.isOk());
|
||||
if (ok)
|
||||
{
|
||||
mHTTPProxyEnabled = true;
|
||||
@@ -346,54 +350,6 @@ bool LLProxy::enableHTTPProxy()
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the HTTP proxy.
|
||||
*/
|
||||
void LLProxy::disableHTTPProxy()
|
||||
{
|
||||
LLMutexLock lock(&mProxyMutex);
|
||||
|
||||
mHTTPProxyEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the currently selected HTTP proxy type
|
||||
*/
|
||||
LLHttpProxyType LLProxy::getHTTPProxyType() const
|
||||
{
|
||||
LLMutexLock lock(&mProxyMutex);
|
||||
return mProxyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the SOCKS 5 password.
|
||||
*/
|
||||
std::string LLProxy::getSocksPwd() const
|
||||
{
|
||||
LLMutexLock lock(&mProxyMutex);
|
||||
return mSocksPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the SOCKS 5 username.
|
||||
*/
|
||||
std::string LLProxy::getSocksUser() const
|
||||
{
|
||||
LLMutexLock lock(&mProxyMutex);
|
||||
return mSocksUsername;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the currently selected SOCKS 5 authentication method.
|
||||
*
|
||||
* @return Returns either none or password.
|
||||
*/
|
||||
LLSocks5AuthType LLProxy::getSelectedAuthMethod() const
|
||||
{
|
||||
LLMutexLock lock(&mProxyMutex);
|
||||
return mAuthMethodSelected;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the LLProxy and make certain that any APR pools and classes are deleted before terminating APR.
|
||||
*
|
||||
@@ -406,57 +362,6 @@ void LLProxy::cleanupClass()
|
||||
deleteSingleton();
|
||||
}
|
||||
|
||||
void LLProxy::applyProxySettings(LLCurlEasyRequest* handle)
|
||||
{
|
||||
applyProxySettings(handle->getEasy());
|
||||
}
|
||||
|
||||
void LLProxy::applyProxySettings(LLCurl::Easy* handle)
|
||||
{
|
||||
applyProxySettings(handle->getCurlHandle());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Apply proxy settings to a CuRL request if an HTTP proxy is enabled.
|
||||
*
|
||||
* This method has been designed to be safe to call from
|
||||
* any thread in the viewer. This allows requests in the
|
||||
* texture fetch thread to be aware of the proxy settings.
|
||||
* When the HTTP proxy is enabled, the proxy mutex will
|
||||
* be locked every time this method is called.
|
||||
*
|
||||
* @param handle A pointer to a valid CURL request, before it has been performed.
|
||||
*/
|
||||
void LLProxy::applyProxySettings(CURL* handle)
|
||||
{
|
||||
// Do a faster unlocked check to see if we are supposed to proxy.
|
||||
if (mHTTPProxyEnabled)
|
||||
{
|
||||
// We think we should proxy, lock the proxy mutex.
|
||||
LLMutexLock lock(&mProxyMutex);
|
||||
// Now test again to verify that the proxy wasn't disabled between the first check and the lock.
|
||||
if (mHTTPProxyEnabled)
|
||||
{
|
||||
LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str()));
|
||||
LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort()));
|
||||
|
||||
if (mProxyType == LLPROXY_SOCKS)
|
||||
{
|
||||
LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5));
|
||||
if (mAuthMethodSelected == METHOD_PASSWORD)
|
||||
{
|
||||
std::string auth_string = mSocksUsername + ":" + mSocksPassword;
|
||||
LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send one TCP packet and receive one in return.
|
||||
*
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "llmemory.h"
|
||||
#include "llsingleton.h"
|
||||
#include "llthread.h"
|
||||
#include "aithreadsafe.h"
|
||||
#include <string>
|
||||
|
||||
// SOCKS error codes returned from the StartProxy method
|
||||
@@ -206,41 +207,92 @@ enum LLSocks5AuthType
|
||||
* The implementation of HTTP proxying is handled by libcurl. LLProxy
|
||||
* is responsible for managing the HTTP proxy options and provides a
|
||||
* thread-safe method to apply those options to a curl request
|
||||
* (LLProxy::applyProxySettings()). This method is overloaded
|
||||
* to accommodate the various abstraction libcurl layers that exist
|
||||
* throughout the viewer (LLCurlEasyRequest, LLCurl::Easy, and CURL).
|
||||
*
|
||||
* If you are working with LLCurl or LLCurlEasyRequest objects,
|
||||
* the configured proxy settings will be applied in the constructors
|
||||
* of those request handles. If you are working with CURL objects
|
||||
* directly, you will need to pass the handle of the request to
|
||||
* applyProxySettings() before issuing the request.
|
||||
* (LLProxy::applyProxySettings()).
|
||||
*
|
||||
* To ensure thread safety, all LLProxy members that relate to the HTTP
|
||||
* proxy require the LLProxyMutex to be locked before accessing.
|
||||
*/
|
||||
|
||||
struct ProxyUnshared
|
||||
{
|
||||
/*###########################################################################################
|
||||
MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD.
|
||||
###########################################################################################*/
|
||||
|
||||
// UDP proxy address and port
|
||||
LLHost mUDPProxy;
|
||||
|
||||
// TCP proxy control channel address and port
|
||||
LLHost mTCPProxy;
|
||||
|
||||
// socket handle to proxy TCP control channel
|
||||
LLSocket::ptr_t mProxyControlChannel;
|
||||
|
||||
/*###########################################################################################
|
||||
END OF UNSHARED MEMBERS
|
||||
###########################################################################################*/
|
||||
};
|
||||
|
||||
struct ProxyShared
|
||||
{
|
||||
ProxyShared(void);
|
||||
|
||||
/*###########################################################################################
|
||||
MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD.
|
||||
###########################################################################################*/
|
||||
|
||||
// HTTP proxy address and port
|
||||
LLHost mHTTPProxy;
|
||||
|
||||
// Currently selected HTTP proxy type. Can be web or SOCKS.
|
||||
LLHttpProxyType mProxyType;
|
||||
|
||||
// SOCKS 5 selected authentication method.
|
||||
LLSocks5AuthType mAuthMethodSelected;
|
||||
|
||||
// SOCKS 5 username
|
||||
std::string mSocksUsername;
|
||||
// SOCKS 5 password
|
||||
std::string mSocksPassword;
|
||||
|
||||
/*###########################################################################################
|
||||
END OF SHARED MEMBERS
|
||||
###########################################################################################*/
|
||||
};
|
||||
|
||||
class LLProxy: public LLSingleton<LLProxy>
|
||||
{
|
||||
LOG_CLASS(LLProxy);
|
||||
|
||||
public:
|
||||
typedef AISTAccessConst<ProxyUnshared> Unshared_crat; // Constant Read Access Type for Unshared (cannot be converted to write access).
|
||||
typedef AISTAccess<ProxyUnshared> Unshared_rat; // Read Access Type for Unshared (same as write access type, since we don't lock at all).
|
||||
typedef AISTAccess<ProxyUnshared> Unshared_wat; // Write Access Type, for Unshared.
|
||||
typedef AIReadAccessConst<ProxyShared> Shared_crat; // Constant Read Access Type for Shared (cannot be converted to write access).
|
||||
typedef AIReadAccess<ProxyShared> Shared_rat; // Read Access Type for Shared.
|
||||
typedef AIWriteAccess<ProxyShared> Shared_wat; // Write Access Type for Shared.
|
||||
|
||||
/*###########################################################################################
|
||||
METHODS THAT DO NOT LOCK mProxyMutex!
|
||||
Public methods that only access variables not shared between threads.
|
||||
###########################################################################################*/
|
||||
// Constructor, cannot have parameters due to LLSingleton parent class. Call from main thread only.
|
||||
LLProxy();
|
||||
|
||||
// Static check for enabled status for UDP packets. Call from main thread only.
|
||||
static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; }
|
||||
// Static check for enabled status for UDP packets. Called from main thread only.
|
||||
static bool isSOCKSProxyEnabled(void) { llassert(is_main_thread()); return sUDPProxyEnabled; }
|
||||
|
||||
// Get the UDP proxy address and port. Call from main thread only.
|
||||
LLHost getUDPProxy() const { return mUDPProxy; }
|
||||
// Get the UDP proxy address and port. Called from main thread only.
|
||||
LLHost getUDPProxy(void) const { return Unshared_crat(mUnshared)->mUDPProxy; }
|
||||
|
||||
/*###########################################################################################
|
||||
END OF NON-LOCKING METHODS
|
||||
End of methods that only access variables not shared between threads.
|
||||
###########################################################################################*/
|
||||
|
||||
// Return true if there is a good chance that the HTTP proxy is currently enabled.
|
||||
bool HTTPProxyEnabled(void) const { return mHTTPProxyEnabled; }
|
||||
|
||||
/*###########################################################################################
|
||||
METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
|
||||
Public methods that access variables shared between threads.
|
||||
###########################################################################################*/
|
||||
// Destructor, closes open connections. Do not call directly, use cleanupClass().
|
||||
~LLProxy();
|
||||
@@ -251,9 +303,7 @@ public:
|
||||
|
||||
// Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false.
|
||||
// Safe to call from any thread.
|
||||
void applyProxySettings(CURL* handle);
|
||||
void applyProxySettings(LLCurl::Easy* handle);
|
||||
void applyProxySettings(LLCurlEasyRequest* handle);
|
||||
void applyProxySettings(AICurlEasyRequest_wat const& curlEasyRequest_w);
|
||||
|
||||
// Start a connection to the SOCKS 5 proxy. Call from main thread only.
|
||||
S32 startSOCKSProxy(LLHost host);
|
||||
@@ -273,30 +323,37 @@ public:
|
||||
bool enableHTTPProxy();
|
||||
|
||||
// Stop proxying HTTP packets. Call from main thread only.
|
||||
void disableHTTPProxy();
|
||||
// Note that this needs shared_w to be passed because we want the shared members to be locked when this is reset to false.
|
||||
void disableHTTPProxy(Shared_wat const& shared_w) { mHTTPProxyEnabled = false; }
|
||||
void disableHTTPProxy(void) { disableHTTPProxy(Shared_wat(mShared)); }
|
||||
|
||||
// Get the currently selected HTTP proxy address and port
|
||||
LLHost const& getHTTPProxy(Shared_crat const& shared_r) const { return shared_r->mHTTPProxy; }
|
||||
|
||||
// Get the currently selected HTTP proxy type
|
||||
LLHttpProxyType getHTTPProxyType(Shared_crat const& shared_r) const { return shared_r->mProxyType; }
|
||||
|
||||
// Get the currently selected auth method.
|
||||
LLSocks5AuthType getSelectedAuthMethod(Shared_crat const& shared_r) const { return shared_r->mAuthMethodSelected; }
|
||||
|
||||
// SOCKS 5 username and password accessors.
|
||||
std::string getSocksUser(Shared_crat const& shared_r) const { return shared_r->mSocksUsername; }
|
||||
std::string getSocksPwd(Shared_crat const& shared_r) const { return shared_r->mSocksPassword; }
|
||||
|
||||
/*###########################################################################################
|
||||
END OF LOCKING METHODS
|
||||
End of methods that access variables shared between threads.
|
||||
###########################################################################################*/
|
||||
|
||||
private:
|
||||
/*###########################################################################################
|
||||
METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
|
||||
Private methods that access variables shared between threads.
|
||||
###########################################################################################*/
|
||||
|
||||
// Perform a SOCKS 5 authentication and UDP association with the proxy server.
|
||||
S32 proxyHandshake(LLHost proxy);
|
||||
|
||||
// Get the currently selected auth method.
|
||||
LLSocks5AuthType getSelectedAuthMethod() const;
|
||||
|
||||
// Get the currently selected HTTP proxy type
|
||||
LLHttpProxyType getHTTPProxyType() const;
|
||||
|
||||
std::string getSocksPwd() const;
|
||||
std::string getSocksUser() const;
|
||||
|
||||
/*###########################################################################################
|
||||
END OF LOCKING METHODS
|
||||
End of methods that access variables shared between threads.
|
||||
###########################################################################################*/
|
||||
|
||||
private:
|
||||
@@ -304,49 +361,16 @@ private:
|
||||
// Instead use enableHTTPProxy() and disableHTTPProxy() instead.
|
||||
mutable LLAtomic32<bool> mHTTPProxyEnabled;
|
||||
|
||||
// Mutex to protect shared members in non-main thread calls to applyProxySettings().
|
||||
mutable LLMutex mProxyMutex;
|
||||
|
||||
/*###########################################################################################
|
||||
MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE!
|
||||
###########################################################################################*/
|
||||
|
||||
// Is the UDP proxy enabled?
|
||||
static bool sUDPProxyEnabled;
|
||||
|
||||
// UDP proxy address and port
|
||||
LLHost mUDPProxy;
|
||||
// TCP proxy control channel address and port
|
||||
LLHost mTCPProxy;
|
||||
AIThreadSafeSingleThreadDC<ProxyUnshared> mUnshared;
|
||||
AIThreadSafeDC<ProxyShared> mShared;
|
||||
|
||||
// socket handle to proxy TCP control channel
|
||||
LLSocket::ptr_t mProxyControlChannel;
|
||||
|
||||
/*###########################################################################################
|
||||
END OF UNSHARED MEMBERS
|
||||
###########################################################################################*/
|
||||
|
||||
/*###########################################################################################
|
||||
MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex!
|
||||
###########################################################################################*/
|
||||
|
||||
// HTTP proxy address and port
|
||||
LLHost mHTTPProxy;
|
||||
|
||||
// Currently selected HTTP proxy type. Can be web or socks.
|
||||
LLHttpProxyType mProxyType;
|
||||
|
||||
// SOCKS 5 selected authentication method.
|
||||
LLSocks5AuthType mAuthMethodSelected;
|
||||
|
||||
// SOCKS 5 username
|
||||
std::string mSocksUsername;
|
||||
// SOCKS 5 password
|
||||
std::string mSocksPassword;
|
||||
|
||||
/*###########################################################################################
|
||||
END OF SHARED MEMBERS
|
||||
###########################################################################################*/
|
||||
public:
|
||||
// For thread-safe read access. Use the _crat access types with these.
|
||||
AIThreadSafeSingleThreadDC<ProxyUnshared> const& unshared_lockobj(void) const { return mUnshared; }
|
||||
AIThreadSafeDC<ProxyShared> const& shared_lockobj(void) const { return mShared; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -198,19 +198,17 @@ LLPumpIO::~LLPumpIO()
|
||||
}
|
||||
}
|
||||
|
||||
bool LLPumpIO::addChain(const chain_t& chain, F32 timeout, bool has_curl_request)
|
||||
bool LLPumpIO::addChain(chain_t const& chain, F32 timeout)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
|
||||
if(chain.empty()) return false;
|
||||
|
||||
#if LL_THREADS_APR
|
||||
LLScopedLock lock(mChainsMutex);
|
||||
#endif
|
||||
chain_t::const_iterator it = chain.begin();
|
||||
chain_t::const_iterator const end = chain.end();
|
||||
if (it == end) return false;
|
||||
|
||||
LLChainInfo info;
|
||||
info.mHasCurlRequest = has_curl_request;
|
||||
info.setTimeoutSeconds(timeout);
|
||||
info.mData = LLIOPipe::buffer_ptr_t(new LLBufferArray);
|
||||
info.mData->setThreaded(has_curl_request);
|
||||
LLLinkInfo link;
|
||||
#if LL_DEBUG_PIPE_TYPE_IN_PUMP
|
||||
lldebugs << "LLPumpIO::addChain() " << chain[0] << " '"
|
||||
@@ -218,14 +216,17 @@ bool LLPumpIO::addChain(const chain_t& chain, F32 timeout, bool has_curl_request
|
||||
#else
|
||||
lldebugs << "LLPumpIO::addChain() " << chain[0] <<llendl;
|
||||
#endif
|
||||
chain_t::const_iterator it = chain.begin();
|
||||
chain_t::const_iterator end = chain.end();
|
||||
for(; it != end; ++it)
|
||||
{
|
||||
info.mHasExpiration = info.mHasExpiration || (*it)->hasExpiration();
|
||||
link.mPipe = (*it);
|
||||
link.mChannels = info.mData->nextChannel();
|
||||
info.mChainLinks.push_back(link);
|
||||
}
|
||||
|
||||
#if LL_THREADS_APR
|
||||
LLScopedLock lock(mChainsMutex);
|
||||
#endif
|
||||
mPendingChains.push_back(info);
|
||||
return true;
|
||||
}
|
||||
@@ -242,11 +243,10 @@ bool LLPumpIO::addChain(
|
||||
// description, we need to have that description matched to a
|
||||
// particular buffer.
|
||||
if(!data) return false;
|
||||
if(links.empty()) return false;
|
||||
links_t::const_iterator link = links.begin();
|
||||
links_t::const_iterator const end = links.end();
|
||||
if (link == end) return false;
|
||||
|
||||
#if LL_THREADS_APR
|
||||
LLScopedLock lock(mChainsMutex);
|
||||
#endif
|
||||
#if LL_DEBUG_PIPE_TYPE_IN_PUMP
|
||||
lldebugs << "LLPumpIO::addChain() " << links[0].mPipe << " '"
|
||||
<< typeid(*(links[0].mPipe)).name() << "'" << llendl;
|
||||
@@ -258,6 +258,17 @@ bool LLPumpIO::addChain(
|
||||
info.mChainLinks = links;
|
||||
info.mData = data;
|
||||
info.mContext = context;
|
||||
for (; link != end; ++link)
|
||||
{
|
||||
if (link->mPipe->hasExpiration())
|
||||
{
|
||||
info.mHasExpiration = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if LL_THREADS_APR
|
||||
LLScopedLock lock(mChainsMutex);
|
||||
#endif
|
||||
mPendingChains.push_back(info);
|
||||
return true;
|
||||
}
|
||||
@@ -1086,14 +1097,14 @@ void LLPumpIO::processChain(LLChainInfo& chain)
|
||||
|
||||
bool LLPumpIO::isChainExpired(LLChainInfo& chain)
|
||||
{
|
||||
if(!chain.mHasCurlRequest)
|
||||
if(!chain.mHasExpiration)
|
||||
{
|
||||
return false ;
|
||||
}
|
||||
|
||||
for(links_t::iterator iter = chain.mChainLinks.begin(); iter != chain.mChainLinks.end(); ++iter)
|
||||
{
|
||||
if(!(*iter).mPipe->isValid())
|
||||
if(!(*iter).mPipe->hasNotExpired())
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
@@ -1106,6 +1117,8 @@ bool LLPumpIO::handleChainError(
|
||||
LLChainInfo& chain,
|
||||
LLIOPipe::EStatus error)
|
||||
{
|
||||
DoutEntering(dc::notice, "LLPumpIO::handleChainError(" << (void*)&chain << ", " << LLIOPipe::lookupStatusString(error) << ")");
|
||||
|
||||
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
|
||||
links_t::reverse_iterator rit;
|
||||
if(chain.mHead == chain.mChainLinks.end())
|
||||
@@ -1168,7 +1181,7 @@ LLPumpIO::LLChainInfo::LLChainInfo() :
|
||||
mInit(false),
|
||||
mLock(0),
|
||||
mEOS(false),
|
||||
mHasCurlRequest(false),
|
||||
mHasExpiration(false),
|
||||
mDescriptorsPool(new LLAPRPool(LLThread::tldata().mRootPool))
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
|
||||
@@ -1180,9 +1193,7 @@ void LLPumpIO::LLChainInfo::setTimeoutSeconds(F32 timeout)
|
||||
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
|
||||
if(timeout > 0.0f)
|
||||
{
|
||||
mTimer.start();
|
||||
mTimer.reset();
|
||||
mTimer.setTimerExpirySec(timeout);
|
||||
mTimer.start(timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -100,10 +100,9 @@ public:
|
||||
* @param chain The pipes for the chain
|
||||
* @param timeout The number of seconds in the future to
|
||||
* expire. Pass in 0.0f to never expire.
|
||||
* @param has_curl_request The chain contains LLURLRequest if true.
|
||||
* @return Returns true if anything was added to the pump.
|
||||
*/
|
||||
bool addChain(const chain_t& chain, F32 timeout, bool has_curl_request = false);
|
||||
bool addChain(const chain_t& chain, F32 timeout);
|
||||
|
||||
/**
|
||||
* @brief Struct to associate a pipe with it's buffer io indexes.
|
||||
@@ -347,7 +346,7 @@ protected:
|
||||
// basic member data
|
||||
bool mInit;
|
||||
bool mEOS;
|
||||
bool mHasCurlRequest;
|
||||
bool mHasExpiration;
|
||||
S32 mLock;
|
||||
LLFrameTimer mTimer;
|
||||
links_t::iterator mHead;
|
||||
|
||||
@@ -151,11 +151,11 @@ bool LLSDMessage::ResponderAdapter::listener(const LLSD& payload, bool success)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
mResponder->result(payload);
|
||||
mResponder->pubResult(payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
mResponder->errorWithContent(payload["status"].asInteger(), payload["reason"], payload["content"]);
|
||||
mResponder->pubErrorWithContent(payload["status"].asInteger(), payload["reason"], payload["content"]);
|
||||
}
|
||||
|
||||
/*---------------- MUST BE LAST STATEMENT BEFORE RETURN ----------------*/
|
||||
|
||||
@@ -1,255 +0,0 @@
|
||||
/**
|
||||
* @file llsdrpcclient.cpp
|
||||
* @author Phoenix
|
||||
* @date 2005-11-05
|
||||
* @brief Implementation of the llsd client classes.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llsdrpcclient.h"
|
||||
|
||||
#include "llbufferstream.h"
|
||||
#include "llfasttimer.h"
|
||||
#include "llfiltersd2xmlrpc.h"
|
||||
#include "llmemtype.h"
|
||||
#include "llpumpio.h"
|
||||
#include "llsd.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llurlrequest.h"
|
||||
|
||||
/**
|
||||
* String constants
|
||||
*/
|
||||
static std::string LLSDRPC_RESPONSE_NAME("response");
|
||||
static std::string LLSDRPC_FAULT_NAME("fault");
|
||||
|
||||
/**
|
||||
* LLSDRPCResponse
|
||||
*/
|
||||
LLSDRPCResponse::LLSDRPCResponse() :
|
||||
mIsError(false),
|
||||
mIsFault(false)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLSDRPCResponse::~LLSDRPCResponse()
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
||||
}
|
||||
|
||||
bool LLSDRPCResponse::extractResponse(const LLSD& sd)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
||||
bool rv = true;
|
||||
if(sd.has(LLSDRPC_RESPONSE_NAME))
|
||||
{
|
||||
mReturnValue = sd[LLSDRPC_RESPONSE_NAME];
|
||||
mIsFault = false;
|
||||
}
|
||||
else if(sd.has(LLSDRPC_FAULT_NAME))
|
||||
{
|
||||
mReturnValue = sd[LLSDRPC_FAULT_NAME];
|
||||
mIsFault = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mReturnValue.clear();
|
||||
mIsError = true;
|
||||
rv = false;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_SDRPC_RESPONSE("SDRPC Response");
|
||||
|
||||
// virtual
|
||||
LLIOPipe::EStatus LLSDRPCResponse::process_impl(
|
||||
const LLChannelDescriptors& channels,
|
||||
buffer_ptr_t& buffer,
|
||||
bool& eos,
|
||||
LLSD& context,
|
||||
LLPumpIO* pump)
|
||||
{
|
||||
LLFastTimer t(FTM_SDRPC_RESPONSE);
|
||||
PUMP_DEBUG;
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
||||
if(mIsError)
|
||||
{
|
||||
error(pump);
|
||||
}
|
||||
else if(mIsFault)
|
||||
{
|
||||
fault(pump);
|
||||
}
|
||||
else
|
||||
{
|
||||
response(pump);
|
||||
}
|
||||
PUMP_DEBUG;
|
||||
return STATUS_DONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* LLSDRPCClient
|
||||
*/
|
||||
|
||||
LLSDRPCClient::LLSDRPCClient() :
|
||||
mState(STATE_NONE),
|
||||
mQueue(EPBQ_PROCESS)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLSDRPCClient::~LLSDRPCClient()
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
||||
}
|
||||
|
||||
bool LLSDRPCClient::call(
|
||||
const std::string& uri,
|
||||
const std::string& method,
|
||||
const LLSD& parameter,
|
||||
LLSDRPCResponse* response,
|
||||
EPassBackQueue queue)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
||||
//llinfos << "RPC: " << uri << "." << method << "(" << *parameter << ")"
|
||||
// << llendl;
|
||||
if(method.empty() || !response)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
mState = STATE_READY;
|
||||
mURI.assign(uri);
|
||||
std::stringstream req;
|
||||
req << LLSDRPC_REQUEST_HEADER_1 << method
|
||||
<< LLSDRPC_REQUEST_HEADER_2;
|
||||
LLSDSerialize::toNotation(parameter, req);
|
||||
req << LLSDRPC_REQUEST_FOOTER;
|
||||
mRequest = req.str();
|
||||
mQueue = queue;
|
||||
mResponse = response;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLSDRPCClient::call(
|
||||
const std::string& uri,
|
||||
const std::string& method,
|
||||
const std::string& parameter,
|
||||
LLSDRPCResponse* response,
|
||||
EPassBackQueue queue)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
||||
//llinfos << "RPC: " << uri << "." << method << "(" << parameter << ")"
|
||||
// << llendl;
|
||||
if(method.empty() || parameter.empty() || !response)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
mState = STATE_READY;
|
||||
mURI.assign(uri);
|
||||
std::stringstream req;
|
||||
req << LLSDRPC_REQUEST_HEADER_1 << method
|
||||
<< LLSDRPC_REQUEST_HEADER_2 << parameter
|
||||
<< LLSDRPC_REQUEST_FOOTER;
|
||||
mRequest = req.str();
|
||||
mQueue = queue;
|
||||
mResponse = response;
|
||||
return true;
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_PROCESS_SDRPC_CLIENT("SDRPC Client");
|
||||
|
||||
// virtual
|
||||
LLIOPipe::EStatus LLSDRPCClient::process_impl(
|
||||
const LLChannelDescriptors& channels,
|
||||
buffer_ptr_t& buffer,
|
||||
bool& eos,
|
||||
LLSD& context,
|
||||
LLPumpIO* pump)
|
||||
{
|
||||
LLFastTimer t(FTM_PROCESS_SDRPC_CLIENT);
|
||||
PUMP_DEBUG;
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
||||
if((STATE_NONE == mState) || (!pump))
|
||||
{
|
||||
// You should have called the call() method already.
|
||||
return STATUS_PRECONDITION_NOT_MET;
|
||||
}
|
||||
EStatus rv = STATUS_DONE;
|
||||
switch(mState)
|
||||
{
|
||||
case STATE_READY:
|
||||
{
|
||||
PUMP_DEBUG;
|
||||
// lldebugs << "LLSDRPCClient::process_impl STATE_READY" << llendl;
|
||||
buffer->append(
|
||||
channels.out(),
|
||||
(U8*)mRequest.c_str(),
|
||||
mRequest.length());
|
||||
context[CONTEXT_DEST_URI_SD_LABEL] = mURI;
|
||||
mState = STATE_WAITING_FOR_RESPONSE;
|
||||
break;
|
||||
}
|
||||
case STATE_WAITING_FOR_RESPONSE:
|
||||
{
|
||||
PUMP_DEBUG;
|
||||
// The input channel has the sd response in it.
|
||||
//lldebugs << "LLSDRPCClient::process_impl STATE_WAITING_FOR_RESPONSE"
|
||||
// << llendl;
|
||||
LLBufferStream resp(channels, buffer.get());
|
||||
LLSD sd;
|
||||
LLSDSerialize::fromNotation(sd, resp, buffer->count(channels.in()));
|
||||
LLSDRPCResponse* response = (LLSDRPCResponse*)mResponse.get();
|
||||
if (!response)
|
||||
{
|
||||
mState = STATE_DONE;
|
||||
break;
|
||||
}
|
||||
response->extractResponse(sd);
|
||||
if(EPBQ_PROCESS == mQueue)
|
||||
{
|
||||
LLPumpIO::chain_t chain;
|
||||
chain.push_back(mResponse);
|
||||
pump->addChain(chain, DEFAULT_CHAIN_EXPIRY_SECS);
|
||||
}
|
||||
else
|
||||
{
|
||||
pump->respond(mResponse.get());
|
||||
}
|
||||
mState = STATE_DONE;
|
||||
break;
|
||||
}
|
||||
case STATE_DONE:
|
||||
default:
|
||||
PUMP_DEBUG;
|
||||
llinfos << "invalid state to process" << llendl;
|
||||
rv = STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
/**
|
||||
* @file llsdrpcclient.h
|
||||
* @author Phoenix
|
||||
* @date 2005-11-05
|
||||
* @brief Implementation and helpers for structure data RPC clients.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLSDRPCCLIENT_H
|
||||
#define LL_LLSDRPCCLIENT_H
|
||||
|
||||
/**
|
||||
* This file declares classes to encapsulate a basic structured data
|
||||
* remote procedure client.
|
||||
*/
|
||||
|
||||
#include "llchainio.h"
|
||||
#include "llfiltersd2xmlrpc.h"
|
||||
#include "lliopipe.h"
|
||||
#include "llurlrequest.h"
|
||||
|
||||
/**
|
||||
* @class LLSDRPCClientResponse
|
||||
* @brief Abstract base class to represent a response from an SD server.
|
||||
*
|
||||
* This is used as a base class for callbacks generated from an
|
||||
* structured data remote procedure call. The
|
||||
* <code>extractResponse</code> method will deal with the llsdrpc method
|
||||
* call overhead, and keep track of what to call during the next call
|
||||
* into <code>process</code>. If you use this as a base class, you
|
||||
* need to implement <code>response</code>, <code>fault</code>, and
|
||||
* <code>error</code> to do something useful. When in those methods,
|
||||
* you can parse and utilize the mReturnValue member data.
|
||||
*/
|
||||
class LLSDRPCResponse : public LLIOPipe
|
||||
{
|
||||
public:
|
||||
LLSDRPCResponse();
|
||||
virtual ~LLSDRPCResponse();
|
||||
|
||||
/**
|
||||
* @brief This method extracts the response out of the sd passed in
|
||||
*
|
||||
* Any appropriate data found in the sd passed in will be
|
||||
* extracted and managed by this object - not copied or cloned. It
|
||||
* will still be up to the caller to delete the pointer passed in.
|
||||
* @param sd The raw structured data response from the remote server.
|
||||
* @return Returns true if this was able to parse the structured data.
|
||||
*/
|
||||
bool extractResponse(const LLSD& sd);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Method called when the response is ready.
|
||||
*/
|
||||
virtual bool response(LLPumpIO* pump) = 0;
|
||||
|
||||
/**
|
||||
* @brief Method called when a fault is generated by the remote server.
|
||||
*/
|
||||
virtual bool fault(LLPumpIO* pump) = 0;
|
||||
|
||||
/**
|
||||
* @brief Method called when there was an error
|
||||
*/
|
||||
virtual bool error(LLPumpIO* pump) = 0;
|
||||
|
||||
protected:
|
||||
/* @name LLIOPipe virtual implementations
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* @brief Process the data in buffer
|
||||
*/
|
||||
virtual EStatus process_impl(
|
||||
const LLChannelDescriptors& channels,
|
||||
buffer_ptr_t& buffer,
|
||||
bool& eos,
|
||||
LLSD& context,
|
||||
LLPumpIO* pump);
|
||||
//@}
|
||||
|
||||
protected:
|
||||
LLSD mReturnValue;
|
||||
bool mIsError;
|
||||
bool mIsFault;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLSDRPCClient
|
||||
* @brief Client class for a structured data remote procedure call.
|
||||
*
|
||||
* This class helps deal with making structured data calls to a remote
|
||||
* server. You can visualize the calls as:
|
||||
* <code>
|
||||
* response = uri.method(parameter)
|
||||
* </code>
|
||||
* where you pass in everything to <code>call</code> and this class
|
||||
* takes care of the rest of the details.
|
||||
* In typical usage, you will derive a class from this class and
|
||||
* provide an API more useful for the specific application at
|
||||
* hand. For example, if you were writing a service to send an instant
|
||||
* message, you could create an API for it to send the messsage, and
|
||||
* that class would do the work of translating it into the method and
|
||||
* parameter, find the destination, and invoke <code>call</call> with
|
||||
* a useful implementation of LLSDRPCResponse passed in to handle the
|
||||
* response from the network.
|
||||
*/
|
||||
class LLSDRPCClient : public LLIOPipe
|
||||
{
|
||||
public:
|
||||
LLSDRPCClient();
|
||||
virtual ~LLSDRPCClient();
|
||||
|
||||
/**
|
||||
* @brief Enumeration for tracking which queue to process the
|
||||
* response.
|
||||
*/
|
||||
enum EPassBackQueue
|
||||
{
|
||||
EPBQ_PROCESS,
|
||||
EPBQ_CALLBACK,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Call a method on a remote LLSDRPCServer
|
||||
*
|
||||
* @param uri The remote object to call, eg,
|
||||
* http://localhost/usher. If you are using a factory with a fixed
|
||||
* url, the uri passed in will probably be ignored.
|
||||
* @param method The method to call on the remote object
|
||||
* @param parameter The parameter to pass into the remote
|
||||
* object. It is up to the caller to delete the value passed in.
|
||||
* @param response The object which gets the response.
|
||||
* @param queue Specifies to call the response on the process or
|
||||
* callback queue.
|
||||
* @return Returns true if this object will be able to make the RPC call.
|
||||
*/
|
||||
bool call(
|
||||
const std::string& uri,
|
||||
const std::string& method,
|
||||
const LLSD& parameter,
|
||||
LLSDRPCResponse* response,
|
||||
EPassBackQueue queue);
|
||||
|
||||
/**
|
||||
* @brief Call a method on a remote LLSDRPCServer
|
||||
*
|
||||
* @param uri The remote object to call, eg,
|
||||
* http://localhost/usher. If you are using a factory with a fixed
|
||||
* url, the uri passed in will probably be ignored.
|
||||
* @param method The method to call on the remote object
|
||||
* @param parameter The seriailized parameter to pass into the
|
||||
* remote object.
|
||||
* @param response The object which gets the response.
|
||||
* @param queue Specifies to call the response on the process or
|
||||
* callback queue.
|
||||
* @return Returns true if this object will be able to make the RPC call.
|
||||
*/
|
||||
bool call(
|
||||
const std::string& uri,
|
||||
const std::string& method,
|
||||
const std::string& parameter,
|
||||
LLSDRPCResponse* response,
|
||||
EPassBackQueue queue);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Enumeration for tracking client state.
|
||||
*/
|
||||
enum EState
|
||||
{
|
||||
STATE_NONE,
|
||||
STATE_READY,
|
||||
STATE_WAITING_FOR_RESPONSE,
|
||||
STATE_DONE
|
||||
};
|
||||
|
||||
/* @name LLIOPipe virtual implementations
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* @brief Process the data in buffer
|
||||
*/
|
||||
virtual EStatus process_impl(
|
||||
const LLChannelDescriptors& channels,
|
||||
buffer_ptr_t& buffer,
|
||||
bool& eos,
|
||||
LLSD& context,
|
||||
LLPumpIO* pump);
|
||||
//@}
|
||||
|
||||
protected:
|
||||
EState mState;
|
||||
std::string mURI;
|
||||
std::string mRequest;
|
||||
EPassBackQueue mQueue;
|
||||
LLIOPipe::ptr_t mResponse;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLSDRPCClientFactory
|
||||
* @brief Basic implementation for making an SD RPC client factory
|
||||
*
|
||||
* This class eases construction of a basic sd rpc client. Here is an
|
||||
* example of it's use:
|
||||
* <code>
|
||||
* class LLUsefulService : public LLService { ... }
|
||||
* LLService::registerCreator(
|
||||
* "useful",
|
||||
* LLService::creator_t(new LLSDRPCClientFactory<LLUsefulService>))
|
||||
* </code>
|
||||
*/
|
||||
template<class Client>
|
||||
class LLSDRPCClientFactory : public LLChainIOFactory
|
||||
{
|
||||
public:
|
||||
LLSDRPCClientFactory() {}
|
||||
LLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {}
|
||||
virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
|
||||
{
|
||||
lldebugs << "LLSDRPCClientFactory::build" << llendl;
|
||||
LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST));
|
||||
if(!http->isValid())
|
||||
{
|
||||
llwarns << "Creating LLURLRequest failed." << llendl ;
|
||||
delete http;
|
||||
return false;
|
||||
}
|
||||
|
||||
LLIOPipe::ptr_t service(new Client);
|
||||
chain.push_back(service);
|
||||
LLIOPipe::ptr_t http_pipe(http);
|
||||
http->addHeader("Content-Type: text/llsd");
|
||||
if(mURL.empty())
|
||||
{
|
||||
chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
|
||||
}
|
||||
else
|
||||
{
|
||||
http->setURL(mURL);
|
||||
}
|
||||
chain.push_back(http_pipe);
|
||||
chain.push_back(service);
|
||||
return true;
|
||||
}
|
||||
protected:
|
||||
std::string mURL;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLXMLSDRPCClientFactory
|
||||
* @brief Basic implementation for making an XMLRPC to SD RPC client factory
|
||||
*
|
||||
* This class eases construction of a basic sd rpc client which uses
|
||||
* xmlrpc as a serialization grammar. Here is an example of it's use:
|
||||
* <code>
|
||||
* class LLUsefulService : public LLService { ... }
|
||||
* LLService::registerCreator(
|
||||
* "useful",
|
||||
* LLService::creator_t(new LLXMLSDRPCClientFactory<LLUsefulService>))
|
||||
* </code>
|
||||
*/
|
||||
template<class Client>
|
||||
class LLXMLSDRPCClientFactory : public LLChainIOFactory
|
||||
{
|
||||
public:
|
||||
LLXMLSDRPCClientFactory() {}
|
||||
LLXMLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {}
|
||||
virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
|
||||
{
|
||||
lldebugs << "LLXMLSDRPCClientFactory::build" << llendl;
|
||||
|
||||
LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST));
|
||||
if(!http->isValid())
|
||||
{
|
||||
llwarns << "Creating LLURLRequest failed." << llendl ;
|
||||
delete http;
|
||||
return false ;
|
||||
}
|
||||
LLIOPipe::ptr_t service(new Client);
|
||||
chain.push_back(service);
|
||||
LLIOPipe::ptr_t http_pipe(http);
|
||||
http->addHeader("Content-Type: text/xml");
|
||||
if(mURL.empty())
|
||||
{
|
||||
chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
|
||||
}
|
||||
else
|
||||
{
|
||||
http->setURL(mURL);
|
||||
}
|
||||
chain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCRequest(NULL)));
|
||||
chain.push_back(http_pipe);
|
||||
chain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCResponse2LLSD));
|
||||
chain.push_back(service);
|
||||
return true;
|
||||
}
|
||||
protected:
|
||||
std::string mURL;
|
||||
};
|
||||
|
||||
#endif // LL_LLSDRPCCLIENT_H
|
||||
@@ -1,347 +0,0 @@
|
||||
/**
|
||||
* @file llsdrpcserver.cpp
|
||||
* @author Phoenix
|
||||
* @date 2005-10-11
|
||||
* @brief Implementation of the LLSDRPCServer and related classes.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llsdrpcserver.h"
|
||||
|
||||
#include "llbuffer.h"
|
||||
#include "llbufferstream.h"
|
||||
#include "llfasttimer.h"
|
||||
#include "llmemtype.h"
|
||||
#include "llpumpio.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llstl.h"
|
||||
|
||||
static const char FAULT_PART_1[] = "{'fault':{'code':i";
|
||||
static const char FAULT_PART_2[] = ", 'description':'";
|
||||
static const char FAULT_PART_3[] = "'}}";
|
||||
|
||||
static const char RESPONSE_PART_1[] = "{'response':";
|
||||
static const char RESPONSE_PART_2[] = "}";
|
||||
|
||||
static const S32 FAULT_GENERIC = 1000;
|
||||
static const S32 FAULT_METHOD_NOT_FOUND = 1001;
|
||||
|
||||
static const std::string LLSDRPC_METHOD_SD_NAME("method");
|
||||
static const std::string LLSDRPC_PARAMETER_SD_NAME("parameter");
|
||||
|
||||
|
||||
/**
|
||||
* LLSDRPCServer
|
||||
*/
|
||||
LLSDRPCServer::LLSDRPCServer() :
|
||||
mState(LLSDRPCServer::STATE_NONE),
|
||||
mPump(NULL),
|
||||
mLock(0)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
||||
}
|
||||
|
||||
LLSDRPCServer::~LLSDRPCServer()
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
||||
std::for_each(
|
||||
mMethods.begin(),
|
||||
mMethods.end(),
|
||||
llcompose1(
|
||||
DeletePointerFunctor<LLSDRPCMethodCallBase>(),
|
||||
llselect2nd<method_map_t::value_type>()));
|
||||
std::for_each(
|
||||
mCallbackMethods.begin(),
|
||||
mCallbackMethods.end(),
|
||||
llcompose1(
|
||||
DeletePointerFunctor<LLSDRPCMethodCallBase>(),
|
||||
llselect2nd<method_map_t::value_type>()));
|
||||
}
|
||||
|
||||
|
||||
// virtual
|
||||
ESDRPCSStatus LLSDRPCServer::deferredResponse(
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* data) {
|
||||
// subclass should provide a sane implementation
|
||||
return ESDRPCS_DONE;
|
||||
}
|
||||
|
||||
void LLSDRPCServer::clearLock()
|
||||
{
|
||||
if(mLock && mPump)
|
||||
{
|
||||
mPump->clearLock(mLock);
|
||||
mPump = NULL;
|
||||
mLock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_PROCESS_SDRPC_SERVER("SDRPC Server");
|
||||
|
||||
// virtual
|
||||
LLIOPipe::EStatus LLSDRPCServer::process_impl(
|
||||
const LLChannelDescriptors& channels,
|
||||
buffer_ptr_t& buffer,
|
||||
bool& eos,
|
||||
LLSD& context,
|
||||
LLPumpIO* pump)
|
||||
{
|
||||
LLFastTimer t(FTM_PROCESS_SDRPC_SERVER);
|
||||
PUMP_DEBUG;
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
||||
// lldebugs << "LLSDRPCServer::process_impl" << llendl;
|
||||
// Once we have all the data, We need to read the sd on
|
||||
// the the in channel, and respond on the out channel
|
||||
if(!eos) return STATUS_BREAK;
|
||||
if(!pump || !buffer) return STATUS_PRECONDITION_NOT_MET;
|
||||
|
||||
std::string method_name;
|
||||
LLIOPipe::EStatus status = STATUS_DONE;
|
||||
|
||||
switch(mState)
|
||||
{
|
||||
case STATE_DEFERRED:
|
||||
PUMP_DEBUG;
|
||||
if(ESDRPCS_DONE != deferredResponse(channels, buffer.get()))
|
||||
{
|
||||
buildFault(
|
||||
channels,
|
||||
buffer.get(),
|
||||
FAULT_GENERIC,
|
||||
"deferred response failed.");
|
||||
}
|
||||
mState = STATE_DONE;
|
||||
return STATUS_DONE;
|
||||
|
||||
case STATE_DONE:
|
||||
// lldebugs << "STATE_DONE" << llendl;
|
||||
break;
|
||||
case STATE_CALLBACK:
|
||||
// lldebugs << "STATE_CALLBACK" << llendl;
|
||||
PUMP_DEBUG;
|
||||
method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
|
||||
if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
|
||||
{
|
||||
if(ESDRPCS_DONE != callbackMethod(
|
||||
method_name,
|
||||
mRequest[LLSDRPC_PARAMETER_SD_NAME],
|
||||
channels,
|
||||
buffer.get()))
|
||||
{
|
||||
buildFault(
|
||||
channels,
|
||||
buffer.get(),
|
||||
FAULT_GENERIC,
|
||||
"Callback method call failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// this should never happen, since we should not be in
|
||||
// this state unless we originally found a method and
|
||||
// params during the first call to process.
|
||||
buildFault(
|
||||
channels,
|
||||
buffer.get(),
|
||||
FAULT_GENERIC,
|
||||
"Invalid LLSDRPC sever state - callback without method.");
|
||||
}
|
||||
pump->clearLock(mLock);
|
||||
mLock = 0;
|
||||
mState = STATE_DONE;
|
||||
break;
|
||||
case STATE_NONE:
|
||||
// lldebugs << "STATE_NONE" << llendl;
|
||||
default:
|
||||
{
|
||||
// First time we got here - process the SD request, and call
|
||||
// the method.
|
||||
PUMP_DEBUG;
|
||||
LLBufferStream istr(channels, buffer.get());
|
||||
mRequest.clear();
|
||||
LLSDSerialize::fromNotation(
|
||||
mRequest,
|
||||
istr,
|
||||
buffer->count(channels.in()));
|
||||
|
||||
// { 'method':'...', 'parameter': ... }
|
||||
method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
|
||||
if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
|
||||
{
|
||||
ESDRPCSStatus rv = callMethod(
|
||||
method_name,
|
||||
mRequest[LLSDRPC_PARAMETER_SD_NAME],
|
||||
channels,
|
||||
buffer.get());
|
||||
switch(rv)
|
||||
{
|
||||
case ESDRPCS_DEFERRED:
|
||||
mPump = pump;
|
||||
mLock = pump->setLock();
|
||||
mState = STATE_DEFERRED;
|
||||
status = STATUS_BREAK;
|
||||
break;
|
||||
|
||||
case ESDRPCS_CALLBACK:
|
||||
{
|
||||
mState = STATE_CALLBACK;
|
||||
LLPumpIO::LLLinkInfo link;
|
||||
link.mPipe = LLIOPipe::ptr_t(this);
|
||||
link.mChannels = channels;
|
||||
LLPumpIO::links_t links;
|
||||
links.push_back(link);
|
||||
pump->respond(links, buffer, context);
|
||||
mLock = pump->setLock();
|
||||
status = STATUS_BREAK;
|
||||
break;
|
||||
}
|
||||
case ESDRPCS_DONE:
|
||||
mState = STATE_DONE;
|
||||
break;
|
||||
case ESDRPCS_ERROR:
|
||||
default:
|
||||
buildFault(
|
||||
channels,
|
||||
buffer.get(),
|
||||
FAULT_GENERIC,
|
||||
"Method call failed.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// send a fault
|
||||
buildFault(
|
||||
channels,
|
||||
buffer.get(),
|
||||
FAULT_GENERIC,
|
||||
"Unable to find method and parameter in request.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PUMP_DEBUG;
|
||||
return status;
|
||||
}
|
||||
|
||||
// virtual
|
||||
ESDRPCSStatus LLSDRPCServer::callMethod(
|
||||
const std::string& method,
|
||||
const LLSD& params,
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* response)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
||||
// Try to find the method in the method table.
|
||||
ESDRPCSStatus rv = ESDRPCS_DONE;
|
||||
method_map_t::iterator it = mMethods.find(method);
|
||||
if(it != mMethods.end())
|
||||
{
|
||||
rv = (*it).second->call(params, channels, response);
|
||||
}
|
||||
else
|
||||
{
|
||||
it = mCallbackMethods.find(method);
|
||||
if(it == mCallbackMethods.end())
|
||||
{
|
||||
// method not found.
|
||||
std::ostringstream message;
|
||||
message << "rpc server unable to find method: " << method;
|
||||
buildFault(
|
||||
channels,
|
||||
response,
|
||||
FAULT_METHOD_NOT_FOUND,
|
||||
message.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// we found it in the callback methods - tell the process
|
||||
// to coordinate calling on the pump callback.
|
||||
return ESDRPCS_CALLBACK;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// virtual
|
||||
ESDRPCSStatus LLSDRPCServer::callbackMethod(
|
||||
const std::string& method,
|
||||
const LLSD& params,
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* response)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
||||
// Try to find the method in the callback method table.
|
||||
ESDRPCSStatus rv = ESDRPCS_DONE;
|
||||
method_map_t::iterator it = mCallbackMethods.find(method);
|
||||
if(it != mCallbackMethods.end())
|
||||
{
|
||||
rv = (*it).second->call(params, channels, response);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "pcserver unable to find callback method: " << method;
|
||||
buildFault(
|
||||
channels,
|
||||
response,
|
||||
FAULT_METHOD_NOT_FOUND,
|
||||
message.str());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// static
|
||||
void LLSDRPCServer::buildFault(
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* data,
|
||||
S32 code,
|
||||
const std::string& msg)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
||||
LLBufferStream ostr(channels, data);
|
||||
ostr << FAULT_PART_1 << code << FAULT_PART_2 << msg << FAULT_PART_3;
|
||||
llinfos << "LLSDRPCServer::buildFault: " << code << ", " << msg << llendl;
|
||||
}
|
||||
|
||||
// static
|
||||
void LLSDRPCServer::buildResponse(
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* data,
|
||||
const LLSD& response)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
||||
LLBufferStream ostr(channels, data);
|
||||
ostr << RESPONSE_PART_1;
|
||||
LLSDSerialize::toNotation(response, ostr);
|
||||
ostr << RESPONSE_PART_2;
|
||||
#if LL_DEBUG
|
||||
std::ostringstream debug_ostr;
|
||||
debug_ostr << "LLSDRPCServer::buildResponse: ";
|
||||
LLSDSerialize::toNotation(response, debug_ostr);
|
||||
llinfos << debug_ostr.str() << llendl;
|
||||
#endif
|
||||
}
|
||||
@@ -1,360 +0,0 @@
|
||||
/**
|
||||
* @file llsdrpcserver.h
|
||||
* @author Phoenix
|
||||
* @date 2005-10-11
|
||||
* @brief Declaration of the structured data remote procedure call server.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLSDRPCSERVER_H
|
||||
#define LL_LLSDRPCSERVER_H
|
||||
|
||||
/**
|
||||
* I've set this up to be pretty easy to use when you want to make a
|
||||
* structured data rpc server which responds to methods by
|
||||
* name. Derive a class from the LLSDRPCServer, and during
|
||||
* construction (or initialization if you have the luxury) map method
|
||||
* names to pointers to member functions. This will look a lot like:
|
||||
*
|
||||
* <code>
|
||||
* class LLMessageAgents : public LLSDRPCServer {<br>
|
||||
* public:<br>
|
||||
* typedef LLSDRPCServer<LLUsher> mem_fn_t;<br>
|
||||
* LLMessageAgents() {<br>
|
||||
* mMethods["message"] = new mem_fn_t(this, &LLMessageAgents::rpc_IM);<br>
|
||||
* mMethods["alert"] = new mem_fn_t(this, &LLMessageAgents::rpc_Alrt);<br>
|
||||
* }<br>
|
||||
* protected:<br>
|
||||
* rpc_IM(const LLSD& params,
|
||||
* const LLChannelDescriptors& channels,
|
||||
* LLBufferArray* data)
|
||||
* {...}<br>
|
||||
* rpc_Alert(const LLSD& params,
|
||||
* const LLChannelDescriptors& channels,
|
||||
* LLBufferArray* data)
|
||||
* {...}<br>
|
||||
* };<br>
|
||||
* </code>
|
||||
*
|
||||
* The params are an array where each element in the array is a single
|
||||
* parameter in the call.
|
||||
*
|
||||
* It is up to you to pack a valid serialized llsd response into the
|
||||
* data object passed into the method, but you can use the helper
|
||||
* methods below to help.
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include "lliopipe.h"
|
||||
#include "lliohttpserver.h"
|
||||
#include "llfiltersd2xmlrpc.h"
|
||||
|
||||
class LLSD;
|
||||
|
||||
/**
|
||||
* @brief Enumeration for specifying server method call status. This
|
||||
* enumeration controls how the server class will manage the pump
|
||||
* process/callback mechanism.
|
||||
*/
|
||||
enum ESDRPCSStatus
|
||||
{
|
||||
// The call went ok, but the response is not yet ready. The
|
||||
// method will arrange for the clearLock() call to be made at
|
||||
// a later date, after which, once the chain is being pumped
|
||||
// again, deferredResponse() will be called to gather the result
|
||||
ESDRPCS_DEFERRED,
|
||||
|
||||
// The LLSDRPCServer would like to handle the method on the
|
||||
// callback queue of the pump.
|
||||
ESDRPCS_CALLBACK,
|
||||
|
||||
// The method call finished and generated output.
|
||||
ESDRPCS_DONE,
|
||||
|
||||
// Method failed for some unspecified reason - you should avoid
|
||||
// this. A generic fault will be sent to the output.
|
||||
ESDRPCS_ERROR,
|
||||
|
||||
ESDRPCS_COUNT,
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLSDRPCMethodCallBase
|
||||
* @brief Base class for calling a member function in an sd rpcserver
|
||||
* implementation.
|
||||
*/
|
||||
class LLSDRPCMethodCallBase
|
||||
{
|
||||
public:
|
||||
LLSDRPCMethodCallBase() {}
|
||||
virtual ~LLSDRPCMethodCallBase() {}
|
||||
|
||||
virtual ESDRPCSStatus call(
|
||||
const LLSD& params,
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* response) = 0;
|
||||
protected:
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLSDRPCMethodCall
|
||||
* @brief Class which implements member function calls.
|
||||
*/
|
||||
template<class Server>
|
||||
class LLSDRPCMethodCall : public LLSDRPCMethodCallBase
|
||||
{
|
||||
public:
|
||||
typedef ESDRPCSStatus (Server::*mem_fn)(
|
||||
const LLSD& params,
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* data);
|
||||
LLSDRPCMethodCall(Server* s, mem_fn fn) :
|
||||
mServer(s),
|
||||
mMemFn(fn)
|
||||
{
|
||||
}
|
||||
virtual ~LLSDRPCMethodCall() {}
|
||||
virtual ESDRPCSStatus call(
|
||||
const LLSD& params,
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* data)
|
||||
{
|
||||
return (*mServer.*mMemFn)(params, channels, data);
|
||||
}
|
||||
|
||||
protected:
|
||||
Server* mServer;
|
||||
mem_fn mMemFn;
|
||||
//bool (Server::*mMemFn)(const LLSD& params, LLBufferArray& data);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class LLSDRPCServer
|
||||
* @brief Basic implementation of a structure data rpc server
|
||||
*
|
||||
* The rpc server is also designed to appropriately straddle the pump
|
||||
* <code>process()</code> and <code>callback()</code> to specify which
|
||||
* thread you want to work on when handling a method call. The
|
||||
* <code>mMethods</code> methods are called from
|
||||
* <code>process()</code>, while the <code>mCallbackMethods</code> are
|
||||
* called when a pump is in a <code>callback()</code> cycle.
|
||||
*/
|
||||
class LLSDRPCServer : public LLIOPipe
|
||||
{
|
||||
public:
|
||||
LLSDRPCServer();
|
||||
virtual ~LLSDRPCServer();
|
||||
|
||||
/**
|
||||
* enumeration for generic fault codes
|
||||
*/
|
||||
enum
|
||||
{
|
||||
FAULT_BAD_REQUEST = 2000,
|
||||
FAULT_NO_RESPONSE = 2001,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Call this method to return an rpc fault.
|
||||
*
|
||||
* @param channel The channel for output on the data buffer
|
||||
* @param data buffer which will recieve the final output
|
||||
* @param code The fault code
|
||||
* @param msg The fault message
|
||||
*/
|
||||
static void buildFault(
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* data,
|
||||
S32 code,
|
||||
const std::string& msg);
|
||||
|
||||
/**
|
||||
* @brief Call this method to build an rpc response.
|
||||
*
|
||||
* @param channel The channel for output on the data buffer
|
||||
* @param data buffer which will recieve the final output
|
||||
* @param response The return value from the method call
|
||||
*/
|
||||
static void buildResponse(
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* data,
|
||||
const LLSD& response);
|
||||
|
||||
protected:
|
||||
/* @name LLIOPipe virtual implementations
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* @brief Process the data in buffer
|
||||
*/
|
||||
virtual EStatus process_impl(
|
||||
const LLChannelDescriptors& channels,
|
||||
buffer_ptr_t& buffer,
|
||||
bool& eos,
|
||||
LLSD& context,
|
||||
LLPumpIO* pump);
|
||||
//@}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief Enumeration to track the state of the rpc server instance
|
||||
*/
|
||||
enum EState
|
||||
{
|
||||
STATE_NONE,
|
||||
STATE_CALLBACK,
|
||||
STATE_DEFERRED,
|
||||
STATE_DONE
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This method is called when an http post comes in.
|
||||
*
|
||||
* The default behavior is to look at the method name, look up the
|
||||
* method in the method table, and call it. If the method is not
|
||||
* found, this function will build a fault response. You can
|
||||
* implement your own version of this function if you want to hard
|
||||
* wire some behavior or optimize things a bit.
|
||||
* @param method The method name being called
|
||||
* @param params The parameters
|
||||
* @param channel The channel for output on the data buffer
|
||||
* @param data The http data
|
||||
* @return Returns the status of the method call, done/deferred/etc
|
||||
*/
|
||||
virtual ESDRPCSStatus callMethod(
|
||||
const std::string& method,
|
||||
const LLSD& params,
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* data);
|
||||
|
||||
/**
|
||||
* @brief This method is called when a pump callback is processed.
|
||||
*
|
||||
* The default behavior is to look at the method name, look up the
|
||||
* method in the callback method table, and call it. If the method
|
||||
* is not found, this function will build a fault response. You
|
||||
* can implement your own version of this function if you want to
|
||||
* hard wire some behavior or optimize things a bit.
|
||||
* @param method The method name being called
|
||||
* @param params The parameters
|
||||
* @param channel The channel for output on the data buffer
|
||||
* @param data The http data
|
||||
* @return Returns the status of the method call, done/deferred/etc
|
||||
*/
|
||||
virtual ESDRPCSStatus callbackMethod(
|
||||
const std::string& method,
|
||||
const LLSD& params,
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* data);
|
||||
|
||||
/**
|
||||
* @brief Called after a deferred service is unlocked
|
||||
*
|
||||
* If a method returns ESDRPCS_DEFERRED, then the service chain
|
||||
* will be locked and not processed until some other system calls
|
||||
* clearLock() on the service instance again. At that point,
|
||||
* once the pump starts processing the chain again, this method
|
||||
* will be called so the service can output the final result
|
||||
* into the buffers.
|
||||
*/
|
||||
virtual ESDRPCSStatus deferredResponse(
|
||||
const LLChannelDescriptors& channels,
|
||||
LLBufferArray* data);
|
||||
|
||||
// donovan put this public here 7/27/06
|
||||
public:
|
||||
/**
|
||||
* @brief unlock a service that as ESDRPCS_DEFERRED
|
||||
*/
|
||||
void clearLock();
|
||||
|
||||
protected:
|
||||
EState mState;
|
||||
LLSD mRequest;
|
||||
LLPumpIO* mPump;
|
||||
S32 mLock;
|
||||
typedef std::map<std::string, LLSDRPCMethodCallBase*> method_map_t;
|
||||
method_map_t mMethods;
|
||||
method_map_t mCallbackMethods;
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Helper Templates for making LLHTTPNodes
|
||||
*
|
||||
* These templates help in creating nodes for handing a service from
|
||||
* either SDRPC or XMLRPC, given a single implementation of LLSDRPCServer.
|
||||
*
|
||||
* To use it:
|
||||
* \code
|
||||
* class LLUsefulServer : public LLSDRPCServer { ... }
|
||||
*
|
||||
* LLHTTPNode& root = LLCreateHTTPWireServer(...);
|
||||
* root.addNode("llsdrpc/useful", new LLSDRPCNode<LLUsefulServer>);
|
||||
* root.addNode("xmlrpc/useful", new LLXMLRPCNode<LLUsefulServer>);
|
||||
* \endcode
|
||||
*/
|
||||
//@{
|
||||
|
||||
template<class Server>
|
||||
class LLSDRPCServerFactory : public LLChainIOFactory
|
||||
{
|
||||
public:
|
||||
virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
|
||||
{
|
||||
lldebugs << "LLXMLSDRPCServerFactory::build" << llendl;
|
||||
chain.push_back(LLIOPipe::ptr_t(new Server));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Server>
|
||||
class LLSDRPCNode : public LLHTTPNodeForFactory<
|
||||
LLSDRPCServerFactory<Server> >
|
||||
{
|
||||
};
|
||||
|
||||
template<class Server>
|
||||
class LLXMLRPCServerFactory : public LLChainIOFactory
|
||||
{
|
||||
public:
|
||||
virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
|
||||
{
|
||||
lldebugs << "LLXMLSDRPCServerFactory::build" << llendl;
|
||||
chain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCRequest2LLSD));
|
||||
chain.push_back(LLIOPipe::ptr_t(new Server));
|
||||
chain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCResponse));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Server>
|
||||
class LLXMLRPCNode : public LLHTTPNodeForFactory<
|
||||
LLXMLRPCServerFactory<Server> >
|
||||
{
|
||||
};
|
||||
|
||||
//@}
|
||||
|
||||
#endif // LL_LLSDRPCSERVER_H
|
||||
@@ -29,6 +29,10 @@
|
||||
#include "linden_common.h"
|
||||
#include "llurlrequest.h"
|
||||
|
||||
#ifdef CWDEBUG
|
||||
#include <libcwd/buf2str.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <openssl/x509_vfy.h>
|
||||
#include <openssl/ssl.h>
|
||||
@@ -48,13 +52,10 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;
|
||||
/**
|
||||
* String constants
|
||||
*/
|
||||
const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
|
||||
const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
|
||||
|
||||
|
||||
static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
|
||||
|
||||
|
||||
static size_t headerCallback(char* data, size_t size, size_t nmemb, void* user);
|
||||
|
||||
/**
|
||||
* class LLURLRequestDetail
|
||||
@@ -65,7 +66,7 @@ public:
|
||||
LLURLRequestDetail();
|
||||
~LLURLRequestDetail();
|
||||
std::string mURL;
|
||||
LLCurlEasyRequest* mCurlRequest;
|
||||
AICurlEasyRequest mCurlEasyRequest;
|
||||
LLIOPipe::buffer_ptr_t mResponseBuffer;
|
||||
LLChannelDescriptors mChannels;
|
||||
U8* mLastRead;
|
||||
@@ -76,36 +77,28 @@ public:
|
||||
};
|
||||
|
||||
LLURLRequestDetail::LLURLRequestDetail() :
|
||||
mCurlRequest(NULL),
|
||||
mCurlEasyRequest(false),
|
||||
mLastRead(NULL),
|
||||
mBodyLimit(0),
|
||||
mByteAccumulator(0),
|
||||
mIsBodyLimitSet(false),
|
||||
mSSLVerifyCallback(NULL)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
||||
mCurlRequest = new LLCurlEasyRequest();
|
||||
|
||||
if(!mCurlRequest->isValid()) //failed.
|
||||
{
|
||||
delete mCurlRequest ;
|
||||
mCurlRequest = NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
LLURLRequestDetail::~LLURLRequestDetail()
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
||||
delete mCurlRequest;
|
||||
mLastRead = NULL;
|
||||
}
|
||||
|
||||
void LLURLRequest::setSSLVerifyCallback(SSLCertVerifyCallback callback, void *param)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
||||
mDetail->mSSLVerifyCallback = callback;
|
||||
mDetail->mCurlRequest->setSSLCtxCallback(LLURLRequest::_sslCtxCallback, (void *)this);
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, true);
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, 2);
|
||||
AICurlEasyRequest_wat curlEasyRequest_w(*mDetail->mCurlEasyRequest);
|
||||
curlEasyRequest_w->setSSLCtxCallback(LLURLRequest::_sslCtxCallback, (void *)this);
|
||||
curlEasyRequest_w->setopt(CURLOPT_SSL_VERIFYPEER, true);
|
||||
curlEasyRequest_w->setopt(CURLOPT_SSL_VERIFYHOST, 2);
|
||||
}
|
||||
|
||||
|
||||
@@ -159,6 +152,7 @@ LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action) :
|
||||
mAction(action)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
||||
// This might throw AICurlNoEasyHandle.
|
||||
initialize();
|
||||
}
|
||||
|
||||
@@ -168,6 +162,7 @@ LLURLRequest::LLURLRequest(
|
||||
mAction(action)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
||||
// This might throw AICurlNoEasyHandle.
|
||||
initialize();
|
||||
setURL(url);
|
||||
}
|
||||
@@ -175,13 +170,16 @@ LLURLRequest::LLURLRequest(
|
||||
LLURLRequest::~LLURLRequest()
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
||||
{
|
||||
AICurlEasyRequest_wat curl_easy_request_w(*mDetail->mCurlEasyRequest);
|
||||
curl_easy_request_w->revokeCallbacks();
|
||||
curl_easy_request_w->send_events_to(NULL);
|
||||
}
|
||||
delete mDetail;
|
||||
mDetail = NULL ;
|
||||
}
|
||||
|
||||
void LLURLRequest::setURL(const std::string& url)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
||||
mDetail->mURL = url;
|
||||
}
|
||||
|
||||
@@ -193,7 +191,8 @@ std::string LLURLRequest::getURL() const
|
||||
void LLURLRequest::addHeader(const char* header)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
||||
mDetail->mCurlRequest->slist_append(header);
|
||||
AICurlEasyRequest_wat curlEasyRequest_w(*mDetail->mCurlEasyRequest);
|
||||
curlEasyRequest_w->addHeader(header);
|
||||
}
|
||||
|
||||
void LLURLRequest::setBodyLimit(U32 size)
|
||||
@@ -206,7 +205,8 @@ void LLURLRequest::setCallback(LLURLRequestComplete* callback)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
||||
mCompletionCallback = callback;
|
||||
mDetail->mCurlRequest->setHeaderCallback(&headerCallback, (void*)callback);
|
||||
AICurlEasyRequest_wat curlEasyRequest_w(*mDetail->mCurlEasyRequest);
|
||||
curlEasyRequest_w->setHeaderCallback(&headerCallback, (void*)callback);
|
||||
}
|
||||
|
||||
// Added to mitigate the effect of libcurl looking
|
||||
@@ -242,30 +242,39 @@ void LLURLRequest::useProxy(bool use_proxy)
|
||||
|
||||
lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = \"" << env_proxy << "\"" << llendl;
|
||||
|
||||
if (use_proxy)
|
||||
{
|
||||
mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy);
|
||||
}
|
||||
else
|
||||
{
|
||||
mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, "");
|
||||
}
|
||||
AICurlEasyRequest_wat curlEasyRequest_w(*mDetail->mCurlEasyRequest);
|
||||
curlEasyRequest_w->setoptString(CURLOPT_PROXY, use_proxy ? env_proxy : std::string(""));
|
||||
}
|
||||
|
||||
void LLURLRequest::useProxy(const std::string &proxy)
|
||||
{
|
||||
mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, proxy);
|
||||
AICurlEasyRequest_wat curlEasyRequest_w(*mDetail->mCurlEasyRequest);
|
||||
curlEasyRequest_w->setoptString(CURLOPT_PROXY, proxy);
|
||||
}
|
||||
|
||||
void LLURLRequest::allowCookies()
|
||||
{
|
||||
mDetail->mCurlRequest->setoptString(CURLOPT_COOKIEFILE, "");
|
||||
AICurlEasyRequest_wat curlEasyRequest_w(*mDetail->mCurlEasyRequest);
|
||||
curlEasyRequest_w->setoptString(CURLOPT_COOKIEFILE, "");
|
||||
}
|
||||
|
||||
//virtual
|
||||
bool LLURLRequest::isValid()
|
||||
bool LLURLRequest::hasExpiration(void) const
|
||||
{
|
||||
return mDetail->mCurlRequest && mDetail->mCurlRequest->isValid();
|
||||
// Currently, this ALWAYS returns false -- because only AICurlEasyRequestStateMachine uses buffered
|
||||
// AICurlEasyRequest objects, and LLURLRequest uses (unbuffered) AICurlEasyRequest directly, which
|
||||
// have no expiration facility.
|
||||
return mDetail->mCurlEasyRequest.isBuffered();
|
||||
}
|
||||
|
||||
//virtual
|
||||
bool LLURLRequest::hasNotExpired(void) const
|
||||
{
|
||||
if (!mDetail->mCurlEasyRequest.isBuffered())
|
||||
return true;
|
||||
AICurlEasyRequest_wat buffered_easy_request_w(*mDetail->mCurlEasyRequest);
|
||||
AICurlResponderBuffer_wat buffer_w(*mDetail->mCurlEasyRequest);
|
||||
return buffer_w->isValid();
|
||||
}
|
||||
|
||||
// virtual
|
||||
@@ -273,10 +282,24 @@ LLIOPipe::EStatus LLURLRequest::handleError(
|
||||
LLIOPipe::EStatus status,
|
||||
LLPumpIO* pump)
|
||||
{
|
||||
DoutEntering(dc::curl, "LLURLRequest::handleError(" << LLIOPipe::lookupStatusString(status) << ", " << (void*)pump << ")");
|
||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
||||
|
||||
if(!isValid())
|
||||
|
||||
if (LL_LIKELY(!mDetail->mCurlEasyRequest.isBuffered())) // Currently always true.
|
||||
{
|
||||
// The last reference will be deleted when the pump that this chain belongs to
|
||||
// is removed from the running chains vector, upon returning from this function.
|
||||
// This keeps the CurlEasyRequest object alive until the curl thread cleanly removed it.
|
||||
Dout(dc::curl, "Calling mDetail->mCurlEasyRequest.removeRequest()");
|
||||
mDetail->mCurlEasyRequest.removeRequest();
|
||||
}
|
||||
else if (!hasNotExpired())
|
||||
{
|
||||
// The buffered version has it's own time out handling, and that already expired,
|
||||
// so we can ignore the expiration of this timer (currently never happens).
|
||||
// I left it here because it's what LL did (in the form if (!isValid() ...),
|
||||
// and it would be relevant if this characteristic of mDetail->mCurlEasyRequest
|
||||
// would change. --Aleric
|
||||
return STATUS_EXPIRED ;
|
||||
}
|
||||
|
||||
@@ -294,6 +317,19 @@ LLIOPipe::EStatus LLURLRequest::handleError(
|
||||
return status;
|
||||
}
|
||||
|
||||
void LLURLRequest::added_to_multi_handle(AICurlEasyRequest_wat&)
|
||||
{
|
||||
}
|
||||
|
||||
void LLURLRequest::finished(AICurlEasyRequest_wat&)
|
||||
{
|
||||
}
|
||||
|
||||
void LLURLRequest::removed_from_multi_handle(AICurlEasyRequest_wat&)
|
||||
{
|
||||
mRemoved = true;
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST("URL Request");
|
||||
|
||||
// virtual
|
||||
@@ -310,7 +346,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
|
||||
//llinfos << "LLURLRequest::process_impl()" << llendl;
|
||||
if (!buffer) return STATUS_ERROR;
|
||||
|
||||
// we're still waiting or prcessing, check how many
|
||||
// we're still waiting or processing, check how many
|
||||
// bytes we have accumulated.
|
||||
const S32 MIN_ACCUMULATION = 100000;
|
||||
if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
|
||||
@@ -354,44 +390,36 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
|
||||
{
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
mRemoved = false;
|
||||
mState = STATE_WAITING_FOR_RESPONSE;
|
||||
mDetail->mCurlEasyRequest.addRequest(); // Add easy handle to multi handle.
|
||||
|
||||
// *FIX: Maybe we should just go to the next state now...
|
||||
return STATUS_BREAK;
|
||||
}
|
||||
case STATE_WAITING_FOR_RESPONSE:
|
||||
case STATE_PROCESSING_RESPONSE:
|
||||
{
|
||||
PUMP_DEBUG;
|
||||
LLIOPipe::EStatus status = STATUS_BREAK;
|
||||
static LLFastTimer::DeclareTimer FTM_URL_PERFORM("Perform");
|
||||
if (!mRemoved) // Not removed from multi handle yet?
|
||||
{
|
||||
LLFastTimer t(FTM_URL_PERFORM);
|
||||
if(!mDetail->mCurlRequest->wait())
|
||||
{
|
||||
return status ;
|
||||
}
|
||||
// Easy handle is still being processed.
|
||||
return STATUS_BREAK;
|
||||
}
|
||||
// Curl thread finished with this easy handle.
|
||||
mState = STATE_CURL_FINISHED;
|
||||
}
|
||||
case STATE_CURL_FINISHED:
|
||||
{
|
||||
PUMP_DEBUG;
|
||||
LLIOPipe::EStatus status = STATUS_NO_CONNECTION; // Catch-all failure code.
|
||||
|
||||
while(1)
|
||||
// Left braces in order not to change indentation.
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST_GET_RESULT("Get Result");
|
||||
|
||||
bool newmsg = false;
|
||||
{
|
||||
LLFastTimer t(FTM_PROCESS_URL_REQUEST_GET_RESULT);
|
||||
newmsg = mDetail->mCurlRequest->getResult(&result);
|
||||
}
|
||||
AICurlEasyRequest_wat(*mDetail->mCurlEasyRequest)->getResult(&result);
|
||||
|
||||
if(!newmsg)
|
||||
{
|
||||
// keep processing
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
mState = STATE_HAVE_RESPONSE;
|
||||
context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
|
||||
context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
|
||||
@@ -423,6 +451,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
|
||||
}
|
||||
mCompletionCallback = NULL;
|
||||
}
|
||||
status = STATUS_BREAK; // This is what the old code returned. Does it make sense?
|
||||
break;
|
||||
case CURLE_FAILED_INIT:
|
||||
case CURLE_COULDNT_CONNECT:
|
||||
@@ -464,16 +493,15 @@ void LLURLRequest::initialize()
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
||||
mState = STATE_INITIALIZED;
|
||||
// This might throw AICurlNoEasyHandle.
|
||||
mDetail = new LLURLRequestDetail;
|
||||
|
||||
if(!isValid())
|
||||
{
|
||||
return ;
|
||||
AICurlEasyRequest_wat curlEasyRequest_w(*mDetail->mCurlEasyRequest);
|
||||
curlEasyRequest_w->setWriteCallback(&downCallback, (void*)this);
|
||||
curlEasyRequest_w->setReadCallback(&upCallback, (void*)this);
|
||||
}
|
||||
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
|
||||
mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);
|
||||
mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this);
|
||||
mRequestTransferedBytes = 0;
|
||||
mResponseTransferedBytes = 0;
|
||||
}
|
||||
@@ -488,70 +516,74 @@ bool LLURLRequest::configure()
|
||||
S32 bytes = mDetail->mResponseBuffer->countAfter(
|
||||
mDetail->mChannels.in(),
|
||||
NULL);
|
||||
switch(mAction)
|
||||
{
|
||||
case HTTP_HEAD:
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_HEADER, 1);
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_NOBODY, 1);
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
|
||||
rv = true;
|
||||
break;
|
||||
case HTTP_GET:
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_HTTPGET, 1);
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
|
||||
AICurlEasyRequest_wat curlEasyRequest_w(*mDetail->mCurlEasyRequest);
|
||||
switch(mAction)
|
||||
{
|
||||
case HTTP_HEAD:
|
||||
curlEasyRequest_w->setopt(CURLOPT_HEADER, 1);
|
||||
curlEasyRequest_w->setopt(CURLOPT_NOBODY, 1);
|
||||
curlEasyRequest_w->setopt(CURLOPT_FOLLOWLOCATION, 1);
|
||||
rv = true;
|
||||
break;
|
||||
case HTTP_GET:
|
||||
curlEasyRequest_w->setopt(CURLOPT_HTTPGET, 1);
|
||||
curlEasyRequest_w->setopt(CURLOPT_FOLLOWLOCATION, 1);
|
||||
|
||||
// Set Accept-Encoding to allow response compression
|
||||
mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, "");
|
||||
rv = true;
|
||||
break;
|
||||
// Set Accept-Encoding to allow response compression
|
||||
curlEasyRequest_w->setoptString(CURLOPT_ENCODING, "");
|
||||
rv = true;
|
||||
break;
|
||||
|
||||
case HTTP_PUT:
|
||||
// Disable the expect http 1.1 extension. POST and PUT default
|
||||
// to turning this on, and I am not too sure what it means.
|
||||
addHeader("Expect:");
|
||||
case HTTP_PUT:
|
||||
// Disable the expect http 1.1 extension. POST and PUT default
|
||||
// to turning this on, and I am not too sure what it means.
|
||||
addHeader("Expect:");
|
||||
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_UPLOAD, 1);
|
||||
mDetail->mCurlRequest->setopt(CURLOPT_INFILESIZE, bytes);
|
||||
rv = true;
|
||||
break;
|
||||
curlEasyRequest_w->setopt(CURLOPT_UPLOAD, 1);
|
||||
curlEasyRequest_w->setopt(CURLOPT_INFILESIZE, bytes);
|
||||
rv = true;
|
||||
break;
|
||||
|
||||
case HTTP_POST:
|
||||
// Disable the expect http 1.1 extension. POST and PUT default
|
||||
// to turning this on, and I am not too sure what it means.
|
||||
addHeader("Expect:");
|
||||
case HTTP_POST:
|
||||
// Disable the expect http 1.1 extension. POST and PUT default
|
||||
// to turning this on, and I am not too sure what it means.
|
||||
addHeader("Expect:");
|
||||
|
||||
// Disable the content type http header.
|
||||
// *FIX: what should it be?
|
||||
addHeader("Content-Type:");
|
||||
// Disable the content type http header.
|
||||
// *FIX: what should it be?
|
||||
addHeader("Content-Type:");
|
||||
|
||||
// Set the handle for an http post
|
||||
mDetail->mCurlRequest->setPost(NULL, bytes);
|
||||
// Set the handle for an http post
|
||||
curlEasyRequest_w->setPost(NULL, bytes);
|
||||
|
||||
// Set Accept-Encoding to allow response compression
|
||||
mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, "");
|
||||
rv = true;
|
||||
break;
|
||||
// Set Accept-Encoding to allow response compression
|
||||
curlEasyRequest_w->setoptString(CURLOPT_ENCODING, "");
|
||||
rv = true;
|
||||
break;
|
||||
|
||||
case HTTP_DELETE:
|
||||
// Set the handle for an http post
|
||||
mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "DELETE");
|
||||
rv = true;
|
||||
break;
|
||||
case HTTP_DELETE:
|
||||
// Set the handle for an http post
|
||||
curlEasyRequest_w->setoptString(CURLOPT_CUSTOMREQUEST, "DELETE");
|
||||
rv = true;
|
||||
break;
|
||||
|
||||
case HTTP_MOVE:
|
||||
// Set the handle for an http post
|
||||
mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "MOVE");
|
||||
// *NOTE: should we check for the Destination header?
|
||||
rv = true;
|
||||
break;
|
||||
case HTTP_MOVE:
|
||||
// Set the handle for an http post
|
||||
curlEasyRequest_w->setoptString(CURLOPT_CUSTOMREQUEST, "MOVE");
|
||||
// *NOTE: should we check for the Destination header?
|
||||
rv = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
llwarns << "Unhandled URLRequest action: " << mAction << llendl;
|
||||
break;
|
||||
}
|
||||
if(rv)
|
||||
{
|
||||
mDetail->mCurlRequest->sendRequest(mDetail->mURL);
|
||||
default:
|
||||
llwarns << "Unhandled URLRequest action: " << mAction << llendl;
|
||||
break;
|
||||
}
|
||||
if(rv)
|
||||
{
|
||||
curlEasyRequest_w->finalizeRequest(mDetail->mURL);
|
||||
curlEasyRequest_w->send_events_to(this);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -615,9 +647,8 @@ size_t LLURLRequest::upCallback(
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user)
|
||||
static size_t headerCallback(char* header_line, size_t size, size_t nmemb, void* user)
|
||||
{
|
||||
const char* header_line = (const char*)data;
|
||||
size_t header_len = size * nmemb;
|
||||
LLURLRequestComplete* complete = (LLURLRequestComplete*)user;
|
||||
|
||||
@@ -683,42 +714,6 @@ static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user)
|
||||
return header_len;
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_PROCESS_URL_EXTRACTOR("URL Extractor");
|
||||
/**
|
||||
* LLContextURLExtractor
|
||||
*/
|
||||
// virtual
|
||||
LLIOPipe::EStatus LLContextURLExtractor::process_impl(
|
||||
const LLChannelDescriptors& channels,
|
||||
buffer_ptr_t& buffer,
|
||||
bool& eos,
|
||||
LLSD& context,
|
||||
LLPumpIO* pump)
|
||||
{
|
||||
LLFastTimer t(FTM_PROCESS_URL_EXTRACTOR);
|
||||
PUMP_DEBUG;
|
||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
||||
// The destination host is in the context.
|
||||
if(context.isUndefined() || !mRequest)
|
||||
{
|
||||
return STATUS_PRECONDITION_NOT_MET;
|
||||
}
|
||||
|
||||
// copy in to out, since this just extract the URL and does not
|
||||
// actually change the data.
|
||||
LLChangeChannel change(channels.in(), channels.out());
|
||||
std::for_each(buffer->beginSegment(), buffer->endSegment(), change);
|
||||
|
||||
// find the context url
|
||||
if(context.has(CONTEXT_DEST_URI_SD_LABEL))
|
||||
{
|
||||
mRequest->setURL(context[CONTEXT_DEST_URI_SD_LABEL].asString());
|
||||
return STATUS_DONE;
|
||||
}
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* LLURLRequestComplete
|
||||
*/
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
|
||||
|
||||
extern const std::string CONTEXT_REQUEST;
|
||||
extern const std::string CONTEXT_DEST_URI_SD_LABEL;
|
||||
extern const std::string CONTEXT_RESPONSE;
|
||||
extern const std::string CONTEXT_TRANSFERED_BYTES;
|
||||
|
||||
@@ -66,7 +65,7 @@ typedef struct x509_store_ctx_st X509_STORE_CTX;
|
||||
* worth the time and effort to eventually port this to a raw client
|
||||
* socket.
|
||||
*/
|
||||
class LLURLRequest : public LLIOPipe
|
||||
class LLURLRequest : public LLIOPipe, protected AICurlEasyHandleEvents
|
||||
{
|
||||
LOG_CLASS(LLURLRequest);
|
||||
public:
|
||||
@@ -190,7 +189,8 @@ public:
|
||||
*/
|
||||
void allowCookies();
|
||||
|
||||
/*virtual*/ bool isValid() ;
|
||||
/*virtual*/ bool hasExpiration(void) const;
|
||||
/*virtual*/ bool hasNotExpired(void) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -217,6 +217,7 @@ protected:
|
||||
STATE_INITIALIZED,
|
||||
STATE_WAITING_FOR_RESPONSE,
|
||||
STATE_PROCESSING_RESPONSE,
|
||||
STATE_CURL_FINISHED,
|
||||
STATE_HAVE_RESPONSE,
|
||||
};
|
||||
EState mState;
|
||||
@@ -228,6 +229,14 @@ protected:
|
||||
|
||||
static CURLcode _sslCtxCallback(CURL * curl, void *sslctx, void *param);
|
||||
|
||||
// mRemoved is used instead of changing mState directly, because I'm not convinced the latter is atomic.
|
||||
// Set to false before adding curl request and then only tested.
|
||||
// Reset in removed_from_multi_handle (by another thread), this is thread-safe.
|
||||
bool mRemoved;
|
||||
/*virtual*/ void added_to_multi_handle(AICurlEasyRequest_wat&);
|
||||
/*virtual*/ void finished(AICurlEasyRequest_wat&);
|
||||
/*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat&);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Initialize the object. Called during construction.
|
||||
@@ -266,42 +275,6 @@ private:
|
||||
LLURLRequest(const LLURLRequest&);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class LLContextURLExtractor
|
||||
* @brief This class unpacks the url out of a agent usher service so
|
||||
* it can be packed into a LLURLRequest object.
|
||||
* @see LLIOPipe
|
||||
*
|
||||
* This class assumes that the context is a map that contains an entry
|
||||
* named CONTEXT_DEST_URI_SD_LABEL.
|
||||
*/
|
||||
class LLContextURLExtractor : public LLIOPipe
|
||||
{
|
||||
public:
|
||||
LLContextURLExtractor(LLURLRequest* req) : mRequest(req) {}
|
||||
~LLContextURLExtractor() {}
|
||||
|
||||
protected:
|
||||
/* @name LLIOPipe virtual implementations
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* @brief Process the data in buffer
|
||||
*/
|
||||
virtual EStatus process_impl(
|
||||
const LLChannelDescriptors& channels,
|
||||
buffer_ptr_t& buffer,
|
||||
bool& eos,
|
||||
LLSD& context,
|
||||
LLPumpIO* pump);
|
||||
//@}
|
||||
|
||||
protected:
|
||||
LLURLRequest* mRequest;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class LLURLRequestComplete
|
||||
* @brief Class which can optionally be used with an LLURLRequest to
|
||||
@@ -374,11 +347,4 @@ protected:
|
||||
EStatus mRequestStatus;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* External constants
|
||||
*/
|
||||
extern const std::string CONTEXT_DEST_URI_SD_LABEL;
|
||||
|
||||
#endif // LL_LLURLREQUEST_H
|
||||
|
||||
@@ -55,7 +55,6 @@ set_target_properties(SLPlugin
|
||||
)
|
||||
|
||||
target_link_libraries(SLPlugin
|
||||
${GOOGLE_PERFTOOLS_LIBRARIES}
|
||||
${LLPLUGIN_LIBRARIES}
|
||||
${LLMESSAGE_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
@@ -82,11 +81,4 @@ if (DARWIN)
|
||||
)
|
||||
endif (DARWIN)
|
||||
|
||||
if (WINDOWS)
|
||||
set_target_properties(SLPlugin
|
||||
PROPERTIES
|
||||
LINK_FLAGS "${GOOGLE_PERFTOOLS_LINKER_FLAGS}"
|
||||
)
|
||||
endif (WINDOWS)
|
||||
|
||||
#ll_deploy_sharedlibs_command(SLPlugin)
|
||||
|
||||
@@ -435,11 +435,7 @@ LLGLManager::LLGLManager() :
|
||||
mHasPointParameters(FALSE),
|
||||
mHasDrawBuffers(FALSE),
|
||||
mHasTextureRectangle(FALSE),
|
||||
mHasTextureMultisample(FALSE),
|
||||
mHasTransformFeedback(FALSE),
|
||||
mMaxSampleMaskWords(0),
|
||||
mMaxColorTextureSamples(0),
|
||||
mMaxDepthTextureSamples(0),
|
||||
mMaxIntegerSamples(0),
|
||||
|
||||
mHasAnisotropic(FALSE),
|
||||
@@ -732,12 +728,10 @@ bool LLGLManager::initGL()
|
||||
|
||||
stop_glerror();
|
||||
|
||||
if (mHasTextureMultisample)
|
||||
if (mHasFramebufferMultisample)
|
||||
{
|
||||
glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples);
|
||||
glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples);
|
||||
glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
|
||||
glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
|
||||
glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
@@ -749,24 +743,12 @@ bool LLGLManager::initGL()
|
||||
}
|
||||
#endif
|
||||
stop_glerror();
|
||||
mHasTextureMultisample = FALSE;
|
||||
#if LL_WINDOWS
|
||||
if (mIsATI)
|
||||
{ //using multisample textures on ATI results in black screen for some reason
|
||||
mHasTextureMultisample = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mIsIntel && mGLVersion <= 3.f)
|
||||
{ //never try to use framebuffer objects on older intel drivers (crashy)
|
||||
mHasFramebufferObject = FALSE;
|
||||
}
|
||||
|
||||
if (mHasFramebufferObject)
|
||||
{
|
||||
glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
|
||||
setToDebugGPU();
|
||||
@@ -847,14 +829,6 @@ std::string LLGLManager::getRawGLString()
|
||||
return gl_string;
|
||||
}
|
||||
|
||||
U32 LLGLManager::getNumFBOFSAASamples(U32 samples)
|
||||
{
|
||||
samples = llmin(samples, (U32) mMaxColorTextureSamples);
|
||||
samples = llmin(samples, (U32) mMaxDepthTextureSamples);
|
||||
samples = llmin(samples, (U32) 4);
|
||||
return samples;
|
||||
}
|
||||
|
||||
void LLGLManager::shutdownGL()
|
||||
{
|
||||
if (mInited)
|
||||
@@ -956,11 +930,10 @@ void LLGLManager::initExtensions()
|
||||
mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts);
|
||||
|
||||
mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f;
|
||||
|
||||
|
||||
mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
|
||||
mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
|
||||
mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
|
||||
mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
|
||||
mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts);
|
||||
mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE;
|
||||
#if !LL_DARWIN
|
||||
@@ -1198,13 +1171,6 @@ void LLGLManager::initExtensions()
|
||||
{
|
||||
glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT");
|
||||
}
|
||||
if (mHasTextureMultisample)
|
||||
{
|
||||
glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage2DMultisample");
|
||||
glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample");
|
||||
glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");
|
||||
glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");
|
||||
}
|
||||
if (mHasTransformFeedback)
|
||||
{
|
||||
glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glBeginTransformFeedback");
|
||||
|
||||
@@ -104,11 +104,7 @@ public:
|
||||
BOOL mHasDrawBuffers;
|
||||
BOOL mHasDepthClamp;
|
||||
BOOL mHasTextureRectangle;
|
||||
BOOL mHasTextureMultisample;
|
||||
BOOL mHasTransformFeedback;
|
||||
S32 mMaxSampleMaskWords;
|
||||
S32 mMaxColorTextureSamples;
|
||||
S32 mMaxDepthTextureSamples;
|
||||
S32 mMaxIntegerSamples;
|
||||
|
||||
// Other extensions.
|
||||
@@ -155,7 +151,6 @@ public:
|
||||
void printGLInfoString();
|
||||
void getGLInfo(LLSD& info);
|
||||
|
||||
U32 getNumFBOFSAASamples(U32 desired_samples = 32);
|
||||
// In ALL CAPS
|
||||
std::string mGLVendor;
|
||||
std::string mGLVendorShort;
|
||||
@@ -521,4 +516,5 @@ extern BOOL gGLActive;
|
||||
#ifndef GL_DEPTH24_STENCIL8
|
||||
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_EXT
|
||||
#endif
|
||||
|
||||
#endif // LL_LLGL_H
|
||||
|
||||
@@ -278,7 +278,7 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;
|
||||
# include "GL/glh_extensions.h"
|
||||
# undef __APPLE__
|
||||
|
||||
#elif LL_LINUX
|
||||
#elif LL_LINUX
|
||||
//----------------------------------------------------------------------------
|
||||
// Linux, MESA headers, but not necessarily assuming MESA runtime.
|
||||
// quotes so we get libraries/.../GL/ version
|
||||
@@ -783,6 +783,7 @@ extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB;
|
||||
extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB;
|
||||
extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
|
||||
extern PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB;
|
||||
|
||||
#elif LL_DARWIN
|
||||
//----------------------------------------------------------------------------
|
||||
// LL_DARWIN
|
||||
@@ -825,6 +826,7 @@ extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_A
|
||||
#define glGenerateMipmap glGenerateMipmapEXT
|
||||
#define GL_MAX_SAMPLES 0x8D57
|
||||
#endif
|
||||
|
||||
// GL_ARB_draw_buffers
|
||||
extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
|
||||
|
||||
@@ -997,7 +999,7 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <AGL/gl.h>
|
||||
#include <OpenGL/gl.h>
|
||||
|
||||
#endif // LL_MESA / LL_WINDOWS / LL_DARWIN
|
||||
|
||||
@@ -1029,4 +1031,5 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
|
||||
#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
|
||||
#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
|
||||
#endif
|
||||
|
||||
#endif // LL_LLGLHEADERS_H
|
||||
|
||||
@@ -330,7 +330,6 @@ S32 LLImageGL::updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 categ
|
||||
//static
|
||||
void LLImageGL::destroyGL(BOOL save_state)
|
||||
{
|
||||
deleteDeadTextures(); //Dump unimportant textures.
|
||||
for (S32 stage = 0; stage < gGLManager.mNumTextureUnits; stage++)
|
||||
{
|
||||
gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
@@ -364,7 +363,6 @@ void LLImageGL::destroyGL(BOOL save_state)
|
||||
}
|
||||
llinfos << "Storing " << stored_count << " images..." << llendl;
|
||||
sAllowReadBackRaw = false ;
|
||||
deleteDeadTextures();//Now, actually call glDeleteTextures for everything.
|
||||
}
|
||||
|
||||
//static
|
||||
@@ -1528,7 +1526,7 @@ void LLImageGL::deleteDeadTextures()
|
||||
{
|
||||
bool reset = false;
|
||||
|
||||
for(U32 i=0;i<LLTexUnit::TT_NONE;++i)
|
||||
/*for(U32 i=0;i<LLTexUnit::TT_NONE;++i)
|
||||
{
|
||||
for(dead_texturelist_t::iterator it=sDeadTextureList[i].begin();it!=sDeadTextureList[i].end();++it)
|
||||
{
|
||||
@@ -1554,7 +1552,7 @@ void LLImageGL::deleteDeadTextures()
|
||||
stop_glerror();
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (reset)
|
||||
{
|
||||
|
||||
@@ -699,6 +699,28 @@ bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth
|
||||
release();
|
||||
stop_glerror();
|
||||
|
||||
if (!gGLManager.mHasFramebufferMultisample || !gGLManager.mHasFramebufferObject || !(sUseFBO || use_fbo))
|
||||
return false;
|
||||
|
||||
if(color_fmt != GL_RGBA)
|
||||
{
|
||||
llwarns << "Unsupported color format: " << color_fmt << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
//Restrict to valid sample count
|
||||
{
|
||||
mSamples = samples;
|
||||
mSamples = llmin(mSamples, (U32)4); //Cap to prevent memory bloat.
|
||||
mSamples = llmin(mSamples, (U32) gGLManager.mMaxIntegerSamples);//GL_RGBA
|
||||
|
||||
if(depth && !stencil)
|
||||
mSamples = llmin(mSamples, (U32) gGLManager.mMaxSamples); //GL_DEPTH_COMPONENT16_ARB
|
||||
}
|
||||
|
||||
if (mSamples <= 1)
|
||||
return false;
|
||||
|
||||
mResX = resx;
|
||||
mResY = resy;
|
||||
|
||||
@@ -706,30 +728,16 @@ bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth
|
||||
mUseDepth = depth;
|
||||
mStencil = stencil;
|
||||
|
||||
if (!gGLManager.mHasFramebufferMultisample)
|
||||
{
|
||||
llerrs << "Attempting to allocate unsupported render target type!" << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
mSamples = gGLManager.getNumFBOFSAASamples(samples);
|
||||
|
||||
if (mSamples <= 1)
|
||||
{
|
||||
llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
|
||||
if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
|
||||
{
|
||||
|
||||
if (depth)
|
||||
{
|
||||
stop_glerror();
|
||||
if(!allocateDepth())
|
||||
{
|
||||
release();
|
||||
return false;
|
||||
}
|
||||
stop_glerror();
|
||||
}
|
||||
glGenFramebuffers(1, (GLuint *) &mFBO);
|
||||
@@ -779,6 +787,7 @@ bool LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
|
||||
if (glGetError() != GL_NO_ERROR)
|
||||
{
|
||||
llwarns << "Unable to allocate color buffer for multisample render target." << llendl;
|
||||
release();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +231,6 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
|
||||
|
||||
if (features->hasLighting)
|
||||
{
|
||||
|
||||
if (features->hasWaterFog)
|
||||
{
|
||||
if (features->disableTextureIndex)
|
||||
@@ -308,7 +307,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
|
||||
}
|
||||
shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE order of shader object attaching is VERY IMPORTANT!!!
|
||||
@@ -571,7 +570,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
|
||||
return 0;
|
||||
}
|
||||
|
||||
//we can't have any lines longer than 1024 characters
|
||||
//we can't have any lines longer than 1024 characters
|
||||
//or any shaders longer than 4096 lines... deal - DaveP
|
||||
GLcharARB buff[1024];
|
||||
GLcharARB* text[4096];
|
||||
|
||||
@@ -45,17 +45,20 @@ class LLMouseHandler
|
||||
public:
|
||||
LLMouseHandler() {}
|
||||
virtual ~LLMouseHandler() {}
|
||||
|
||||
typedef enum {
|
||||
SHOW_NEVER,
|
||||
SHOW_IF_NOT_BLOCKED,
|
||||
SHOW_ALWAYS,
|
||||
} EShowToolTip;
|
||||
|
||||
typedef enum {
|
||||
CLICK_LEFT,
|
||||
CLICK_MIDDLE,
|
||||
CLICK_RIGHT,
|
||||
CLICK_DOUBLELEFT
|
||||
} EClickType;
|
||||
|
||||
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
|
||||
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) = 0;
|
||||
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) = 0;
|
||||
|
||||
@@ -113,6 +113,7 @@ LLWindow::LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags)
|
||||
mSupportedResolutions(NULL),
|
||||
mNumSupportedResolutions(0),
|
||||
mCurrentCursor(UI_CURSOR_ARROW),
|
||||
mNextCursor(UI_CURSOR_ARROW),
|
||||
mCursorHidden(FALSE),
|
||||
mBusyCount(0),
|
||||
mIsMouseClipping(FALSE),
|
||||
@@ -125,7 +126,6 @@ LLWindow::LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags)
|
||||
|
||||
LLWindow::~LLWindow()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//virtual
|
||||
@@ -139,6 +139,7 @@ BOOL LLWindow::canDelete()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLWindow::incBusyCount()
|
||||
{
|
||||
|
||||
@@ -104,12 +104,14 @@ public:
|
||||
virtual S32 getBusyCount() const;
|
||||
|
||||
// Sets cursor, may set to arrow+hourglass
|
||||
virtual void setCursor(ECursorType cursor) = 0;
|
||||
virtual void setCursor(ECursorType cursor) { mNextCursor = cursor; };
|
||||
virtual ECursorType getCursor() const;
|
||||
virtual void updateCursor() = 0;
|
||||
|
||||
virtual void captureMouse() = 0;
|
||||
virtual void releaseMouse() = 0;
|
||||
virtual void setMouseClipping( BOOL b ) = 0;
|
||||
|
||||
virtual BOOL isClipboardTextAvailable() = 0;
|
||||
virtual BOOL pasteTextFromClipboard(LLWString &dst) = 0;
|
||||
virtual BOOL copyTextToClipboard(const LLWString &src) = 0;
|
||||
@@ -196,6 +198,7 @@ protected:
|
||||
LLWindowResolution* mSupportedResolutions;
|
||||
S32 mNumSupportedResolutions;
|
||||
ECursorType mCurrentCursor;
|
||||
ECursorType mNextCursor;
|
||||
BOOL mCursorHidden;
|
||||
S32 mBusyCount; // how deep is the "cursor busy" stack?
|
||||
BOOL mIsMouseClipping; // Is this window currently clipping the mouse
|
||||
|
||||
@@ -91,5 +91,4 @@ public:
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
/*virtual*/ void showCursorFromMouseMove() {};
|
||||
/*virtual*/ void hideCursorUntilMouseMove() {};
|
||||
/*virtual*/ BOOL isCursorHidden() {return FALSE;};
|
||||
/*virtual*/ void setCursor(ECursorType cursor) {};
|
||||
/*virtual*/ void updateCursor() {};
|
||||
//virtual ECursorType getCursor() { return mCurrentCursor; };
|
||||
/*virtual*/ void captureMouse() {};
|
||||
/*virtual*/ void releaseMouse() {};
|
||||
|
||||
@@ -50,6 +50,11 @@ void setupCocoa()
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents.
|
||||
// ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr'
|
||||
// when init'ing the Cocoa App window.
|
||||
[[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
|
||||
|
||||
// This is a bit of voodoo taken from the Apple sample code "CarbonCocoa_PictureCursor":
|
||||
// http://developer.apple.com/samplecode/CarbonCocoa_PictureCursor/index.html
|
||||
|
||||
@@ -60,6 +65,8 @@ void setupCocoa()
|
||||
[[[NSWindow alloc] init] release];
|
||||
|
||||
[pool release];
|
||||
|
||||
inited = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -226,10 +226,10 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
|
||||
// Route them to a dummy callback structure until the end of constructor.
|
||||
LLWindowCallbacks null_callbacks;
|
||||
mCallbacks = &null_callbacks;
|
||||
|
||||
|
||||
// Voodoo for calling cocoa from carbon (see llwindowmacosx-objc.mm).
|
||||
setupCocoa();
|
||||
|
||||
|
||||
// Initialize the keyboard
|
||||
gKeyboard = new LLKeyboardMacOSX();
|
||||
gKeyboard->setCallbacks(callbacks);
|
||||
@@ -260,10 +260,10 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
|
||||
mRawKeyEvent = NULL;
|
||||
mFSAASamples = fsaa_samples;
|
||||
mForceRebuild = FALSE;
|
||||
|
||||
|
||||
// For reasons that aren't clear to me, LLTimers seem to be created in the "started" state.
|
||||
// Since the started state of this one is used to track whether the NMRec has been installed, it wants to start out in the "stopped" state.
|
||||
mBounceTimer.stop();
|
||||
mBounceTimer.stop();
|
||||
|
||||
// Get the original aspect ratio of the main device.
|
||||
mOriginalAspectRatio = (double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay);
|
||||
@@ -276,7 +276,7 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
|
||||
mMoveEventCampartorUPP = NewEventComparatorUPP(staticMoveEventComparator);
|
||||
mGlobalHandlerRef = NULL;
|
||||
mWindowHandlerRef = NULL;
|
||||
|
||||
|
||||
mDragOverrideCursor = -1;
|
||||
|
||||
// We're not clipping yet
|
||||
@@ -451,7 +451,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
|
||||
mFullscreenBits = -1;
|
||||
mFullscreenRefresh = -1;
|
||||
|
||||
std::string error= llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height);
|
||||
std::string error= llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height);
|
||||
OSMessageBox(error, "Error", OSMB_OK);
|
||||
}
|
||||
}
|
||||
@@ -484,7 +484,6 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
|
||||
true,
|
||||
(long)this);
|
||||
|
||||
|
||||
if (!mWindow)
|
||||
{
|
||||
setupFailure("Window creation error", "Error", OSMB_OK);
|
||||
@@ -500,7 +499,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
|
||||
InstallStandardEventHandler(GetWindowEventTarget(mWindow));
|
||||
InstallWindowEventHandler(mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler
|
||||
#if LL_OS_DRAGDROP_ENABLED
|
||||
InstallTrackingHandler( dragTrackingHandler, mWindow, (void*)this );
|
||||
InstallTrackingHandler( dragTrackingHandler, mWindow, (void*)this );
|
||||
InstallReceiveHandler( dragReceiveHandler, mWindow, (void*)this );
|
||||
#endif // LL_OS_DRAGDROP_ENABLED
|
||||
}
|
||||
@@ -581,16 +580,16 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
|
||||
AGL_NO_RECOVERY,
|
||||
AGL_DOUBLEBUFFER,
|
||||
AGL_CLOSEST_POLICY,
|
||||
AGL_ACCELERATED,
|
||||
AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0,
|
||||
AGL_SAMPLES_ARB, mFSAASamples,
|
||||
AGL_RED_SIZE, 8,
|
||||
AGL_GREEN_SIZE, 8,
|
||||
AGL_BLUE_SIZE, 8,
|
||||
AGL_ALPHA_SIZE, 8,
|
||||
AGL_DEPTH_SIZE, 24,
|
||||
AGL_STENCIL_SIZE, 8,
|
||||
AGL_NONE
|
||||
AGL_ACCELERATED,
|
||||
AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0,
|
||||
AGL_SAMPLES_ARB, mFSAASamples,
|
||||
AGL_RED_SIZE, 8,
|
||||
AGL_GREEN_SIZE, 8,
|
||||
AGL_BLUE_SIZE, 8,
|
||||
AGL_ALPHA_SIZE, 8,
|
||||
AGL_DEPTH_SIZE, 24,
|
||||
AGL_STENCIL_SIZE, 8,
|
||||
AGL_NONE
|
||||
};
|
||||
|
||||
LL_DEBUGS("Window") << "createContext: creating windowed pixelformat" << LL_ENDL;
|
||||
@@ -797,7 +796,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
|
||||
LL_DEBUGS("GLinit") << "Keeping vertical sync" << LL_ENDL;
|
||||
frames_per_swap = 1;
|
||||
}
|
||||
aglSetInteger(mContext, AGL_SWAP_INTERVAL, &frames_per_swap);
|
||||
aglSetInteger(mContext, AGL_SWAP_INTERVAL, &frames_per_swap);
|
||||
|
||||
//enable multi-threaded OpenGL
|
||||
if (sUseMultGL)
|
||||
@@ -810,7 +809,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
|
||||
if (cgl_err != kCGLNoError )
|
||||
{
|
||||
LL_DEBUGS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL;
|
||||
@@ -1042,6 +1041,7 @@ void LLWindowMacOSX::hide()
|
||||
HideWindow(mWindow);
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLWindowMacOSX::minimize()
|
||||
{
|
||||
setMouseClipping(FALSE);
|
||||
@@ -1049,6 +1049,7 @@ void LLWindowMacOSX::minimize()
|
||||
CollapseWindow(mWindow, true);
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLWindowMacOSX::restore()
|
||||
{
|
||||
show();
|
||||
@@ -1114,7 +1115,7 @@ BOOL LLWindowMacOSX::maximize()
|
||||
{
|
||||
ZoomWindow(mWindow, inContent, true);
|
||||
}
|
||||
|
||||
|
||||
return mMaximized;
|
||||
}
|
||||
|
||||
@@ -1169,6 +1170,8 @@ void LLWindowMacOSX::gatherInput()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
updateCursor();
|
||||
}
|
||||
|
||||
BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position)
|
||||
@@ -1437,11 +1440,11 @@ static void fixOrigin(void)
|
||||
GrafPtr port;
|
||||
Rect portrect;
|
||||
|
||||
::GetPort(&port);
|
||||
::GetPort(&port);
|
||||
::GetPortBounds(port, &portrect);
|
||||
if((portrect.left != 0) || (portrect.top != 0))
|
||||
{
|
||||
// Mozilla sometimes changes our port origin. Fuckers.
|
||||
// Mozilla sometimes changes our port origin.
|
||||
::SetOrigin(0,0);
|
||||
}
|
||||
}
|
||||
@@ -1451,17 +1454,17 @@ BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position)
|
||||
Point cursor_point;
|
||||
LLCoordScreen screen_pos;
|
||||
GrafPtr save;
|
||||
|
||||
|
||||
if(mWindow == NULL)
|
||||
return FALSE;
|
||||
|
||||
|
||||
::GetPort(&save);
|
||||
::SetPort(GetWindowPort(mWindow));
|
||||
fixOrigin();
|
||||
|
||||
// gets the mouse location in local coordinates
|
||||
::GetMouse(&cursor_point);
|
||||
|
||||
|
||||
// lldebugs << "getCursorPosition(): cursor is at " << cursor_point.h << ", " << cursor_point.v << " port origin: " << portrect.left << ", " << portrect.top << llendl;
|
||||
|
||||
::SetPort(save);
|
||||
@@ -1526,7 +1529,7 @@ F32 LLWindowMacOSX::getNativeAspectRatio()
|
||||
{
|
||||
// The constructor for this class grabs the aspect ratio of the monitor before doing any resolution
|
||||
// switching, and stashes it in mOriginalAspectRatio. Here, we just return it.
|
||||
|
||||
|
||||
if (mOverrideAspectRatio > 0.f)
|
||||
{
|
||||
return mOverrideAspectRatio;
|
||||
@@ -2001,7 +2004,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
if (mPreeditor
|
||||
&& (result = GetEventParameter(event, kEventParamTextInputSendFixLen,
|
||||
typeLongInteger, ¶m_type, sizeof(fix_len), NULL, &fix_len)) == noErr
|
||||
&& typeLongInteger == param_type
|
||||
&& typeLongInteger == param_type
|
||||
&& (result = GetEventParameter(event, kEventParamTextInputSendText,
|
||||
typeUnicodeText, ¶m_type, 0, &text_len, NULL)) == noErr
|
||||
&& typeUnicodeText == param_type)
|
||||
@@ -2021,7 +2024,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
mPreeditor->markAsPreedit(location, length);
|
||||
}
|
||||
mPreeditor->resetPreedit();
|
||||
|
||||
|
||||
// Receive the text from input method.
|
||||
U16 *const text = new U16[text_len / sizeof(U16)];
|
||||
GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText, NULL, text_len, NULL, text);
|
||||
@@ -2060,11 +2063,11 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray,
|
||||
NULL, text_range_array_size, NULL, text_range_array);
|
||||
|
||||
// WARNING: We assume ranges are in ascending order,
|
||||
// WARNING: We assume ranges are in ascending order,
|
||||
// although the condition is undocumented. It seems
|
||||
// OK to assume this. I also assumed
|
||||
// the ranges are contiguous in previous versions, but I
|
||||
// have heard a rumore that older versions os ATOK may
|
||||
// have heard a rumore that older versions os ATOK may
|
||||
// return ranges with some _gap_. I don't know whether
|
||||
// it is true, but I'm preparing my code for the case.
|
||||
|
||||
@@ -2128,15 +2131,16 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case kEventTextInputUnicodeForKeyEvent:
|
||||
{
|
||||
UInt32 modifiers = 0;
|
||||
|
||||
|
||||
// First, process the raw event.
|
||||
{
|
||||
EventRef rawEvent = NULL;
|
||||
|
||||
|
||||
// Get the original event and extract the modifier keys, so we can ignore command-key events.
|
||||
if (GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent) == noErr)
|
||||
{
|
||||
@@ -2145,7 +2149,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
|
||||
// and call this function recursively to handle the raw key event.
|
||||
eventHandler (myHandler, rawEvent);
|
||||
|
||||
|
||||
// save the raw event until we're done processing the unicode input as well.
|
||||
mRawKeyEvent = rawEvent;
|
||||
}
|
||||
@@ -2176,7 +2180,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
else
|
||||
{
|
||||
MASK mask = LLWindowMacOSX::modifiersToMask(modifiers);
|
||||
|
||||
|
||||
llassert( actualType == typeUnicodeText );
|
||||
|
||||
// The result is a UTF16 buffer. Pass the characters in turn to handleUnicodeChar.
|
||||
@@ -2202,7 +2206,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
result = err;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case kEventTextInputOffsetToPos:
|
||||
{
|
||||
EventParamType param_type;
|
||||
@@ -2215,7 +2219,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
S32 preedit, preedit_length;
|
||||
mPreeditor->getPreeditRange(&preedit, &preedit_length);
|
||||
const LLWString & text = mPreeditor->getPreeditString();
|
||||
|
||||
|
||||
LLCoordGL caret_coord;
|
||||
LLRect preedit_bounds;
|
||||
if (0 <= offset
|
||||
@@ -2229,10 +2233,10 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
qd_point.h = caret_base_coord_screen.mX;
|
||||
qd_point.v = caret_base_coord_screen.mY;
|
||||
SetEventParameter(event, kEventParamTextInputReplyPoint, typeQDPoint, sizeof(qd_point), &qd_point);
|
||||
|
||||
|
||||
short line_height = (short) preedit_bounds.getHeight();
|
||||
SetEventParameter(event, kEventParamTextInputReplyLineHeight, typeShortInteger, sizeof(line_height), &line_height);
|
||||
|
||||
|
||||
result = noErr;
|
||||
}
|
||||
else
|
||||
@@ -2285,7 +2289,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
case kEventRawKeyRepeat:
|
||||
if (gDebugWindowProc)
|
||||
{
|
||||
printf("key down, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n",
|
||||
printf("key down, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n",
|
||||
(unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers);
|
||||
fflush(stdout);
|
||||
}
|
||||
@@ -2296,7 +2300,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
case kEventRawKeyUp:
|
||||
if (gDebugWindowProc)
|
||||
{
|
||||
printf("key up, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n",
|
||||
printf("key up, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n",
|
||||
(unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers);
|
||||
fflush(stdout);
|
||||
}
|
||||
@@ -2354,7 +2358,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
}
|
||||
|
||||
// When the state of the 'Fn' key (the one that changes some of the mappings on a powerbook/macbook keyboard
|
||||
// to an embedded keypad) changes, it may subsequently cause a key up event to be lost, which may lead to
|
||||
// to an embedded keypad) changes, it may subsequently cause a key up event to be lost, which may lead to
|
||||
// a movement key getting "stuck" down. This is bad.
|
||||
// This is an OS bug -- even the GetKeys() API doesn't tell you the key has been released.
|
||||
// This workaround causes all held-down keys to be reset whenever the state of the Fn key changes. This isn't
|
||||
@@ -2364,14 +2368,14 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
if (gDebugWindowProc) printf("Fn key state change event\n");
|
||||
gKeyboard->resetKeys();
|
||||
}
|
||||
|
||||
|
||||
if (gDebugWindowProc) fflush(stdout);
|
||||
|
||||
mLastModifiers = modifiers;
|
||||
result = eventNotHandledErr;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
mRawKeyEvent = NULL;
|
||||
}
|
||||
break;
|
||||
@@ -2466,7 +2470,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
case kEventMouseButtonSecondary:
|
||||
mCallbacks->handleRightMouseDown(this, outCoords, mask);
|
||||
break;
|
||||
|
||||
|
||||
case kEventMouseButtonTertiary:
|
||||
mCallbacks->handleMiddleMouseDown(this, outCoords, mask);
|
||||
break;
|
||||
@@ -2528,7 +2532,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
|
||||
case kEventClassWindow:
|
||||
switch(evtKind)
|
||||
{
|
||||
{
|
||||
case kEventWindowActivated:
|
||||
if (mTSMDocument)
|
||||
{
|
||||
@@ -2543,7 +2547,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
}
|
||||
mCallbacks->handleFocusLost(this);
|
||||
break;
|
||||
|
||||
|
||||
case kEventWindowBoundsChanging:
|
||||
{
|
||||
// This is where we would constrain move/resize to a particular screen
|
||||
@@ -2553,7 +2557,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
|
||||
GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds);
|
||||
GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &previousBounds);
|
||||
|
||||
|
||||
// Put an offset into window un-maximize operation since the kEventWindowGetIdealSize
|
||||
// event only allows the specification of size and not position.
|
||||
if (mMaximized)
|
||||
@@ -2561,7 +2565,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
short leftOffset = mPreviousWindowRect.left - currentBounds.left;
|
||||
currentBounds.left += leftOffset;
|
||||
currentBounds.right += leftOffset;
|
||||
|
||||
|
||||
short topOffset = mPreviousWindowRect.top - currentBounds.top;
|
||||
currentBounds.top += topOffset;
|
||||
currentBounds.bottom += topOffset;
|
||||
@@ -2581,7 +2585,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
{
|
||||
currentBounds.bottom = currentBounds.top + MIN_WINDOW_HEIGHT;
|
||||
}
|
||||
|
||||
|
||||
SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), ¤tBounds);
|
||||
result = noErr;
|
||||
}
|
||||
@@ -2592,38 +2596,38 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
// Get new window bounds
|
||||
Rect newBounds;
|
||||
GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &newBounds);
|
||||
|
||||
|
||||
// Get previous window bounds
|
||||
Rect oldBounds;
|
||||
GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &oldBounds);
|
||||
|
||||
|
||||
// Determine if the new size is larger than the old
|
||||
bool newBoundsLarger = ((newBounds.right - newBounds.left) >= (oldBounds.right - oldBounds.left));
|
||||
newBoundsLarger &= ((newBounds.bottom - newBounds.top) >= (oldBounds.bottom - oldBounds.top));
|
||||
|
||||
|
||||
// Check to see if this is a zoom event (+ button on window pane)
|
||||
unsigned int eventParams;
|
||||
GetEventParameter(event, kEventParamAttributes, typeUInt32, NULL, sizeof(int), NULL, &eventParams);
|
||||
bool isZoomEvent = ((eventParams & kWindowBoundsChangeZoom) != 0);
|
||||
|
||||
|
||||
// Maximized flag is if zoom event and increasing window size
|
||||
mMaximized = (isZoomEvent && newBoundsLarger);
|
||||
|
||||
|
||||
aglUpdateContext(mContext);
|
||||
|
||||
|
||||
mCallbacks->handleResize(this, newBounds.right - newBounds.left, newBounds.bottom - newBounds.top);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case kEventWindowGetIdealSize:
|
||||
// Only recommend a new ideal size when un-maximizing
|
||||
if (mMaximized == TRUE)
|
||||
{
|
||||
Point nonMaximizedSize;
|
||||
|
||||
|
||||
nonMaximizedSize.v = mPreviousWindowRect.bottom - mPreviousWindowRect.top;
|
||||
nonMaximizedSize.h = mPreviousWindowRect.right - mPreviousWindowRect.left;
|
||||
|
||||
|
||||
SetEventParameter(event, kEventParamDimensions, typeQDPoint, sizeof(Point), &nonMaximizedSize);
|
||||
result = noErr;
|
||||
}
|
||||
@@ -2678,7 +2682,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
if (mPreeditor)
|
||||
{
|
||||
switch(evtKind)
|
||||
{
|
||||
{
|
||||
|
||||
case kEventTSMDocumentAccessGetLength:
|
||||
{
|
||||
@@ -2697,14 +2701,14 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
{
|
||||
// Return the selected range, excluding preedit.
|
||||
// In our preeditor, preedit and selection are exclusive, so,
|
||||
// when it has a preedit, there is no selection and the
|
||||
// when it has a preedit, there is no selection and the
|
||||
// insertion point is on the preedit that corrupses into the
|
||||
// beginning of the preedit when the preedit was removed.
|
||||
|
||||
S32 preedit, preedit_length;
|
||||
mPreeditor->getPreeditRange(&preedit, &preedit_length);
|
||||
const LLWString & text = mPreeditor->getPreeditString();
|
||||
|
||||
|
||||
CFRange range;
|
||||
if (preedit_length)
|
||||
{
|
||||
@@ -2768,7 +2772,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
memcpy(target_pointer, text_utf16.c_str() + range.location, range.length * sizeof(UniChar));
|
||||
|
||||
// Note that result has already been set above.
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2815,7 +2819,7 @@ const char* cursorIDToName(int id)
|
||||
case UI_CURSOR_TOOLPLAY: return "UI_CURSOR_TOOLPLAY";
|
||||
case UI_CURSOR_TOOLPAUSE: return "UI_CURSOR_TOOLPAUSE";
|
||||
case UI_CURSOR_TOOLMEDIAOPEN: return "UI_CURSOR_TOOLMEDIAOPEN";
|
||||
case UI_CURSOR_PIPETTE: return "UI_CURSOR_PIPETTE";
|
||||
case UI_CURSOR_PIPETTE: return "UI_CURSOR_PIPETTE";
|
||||
case UI_CURSOR_TOOLSIT: return "UI_CURSOR_TOOLSIT";
|
||||
case UI_CURSOR_TOOLBUY: return "UI_CURSOR_TOOLBUY";
|
||||
case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN";
|
||||
@@ -2823,7 +2827,7 @@ const char* cursorIDToName(int id)
|
||||
}
|
||||
|
||||
llerrs << "cursorIDToName: unknown cursor id" << id << llendl;
|
||||
|
||||
|
||||
return "UI_CURSOR_ARROW";
|
||||
}
|
||||
|
||||
@@ -2839,42 +2843,42 @@ static void initPixmapCursor(int cursorid, int hotspotX, int hotspotY)
|
||||
fullpath += gDirUtilp->getDirDelimiter();
|
||||
fullpath += cursorIDToName(cursorid);
|
||||
fullpath += ".tif";
|
||||
|
||||
|
||||
gCursors[cursorid] = createImageCursor(fullpath.c_str(), hotspotX, hotspotY);
|
||||
}
|
||||
|
||||
void LLWindowMacOSX::setCursor(ECursorType cursor)
|
||||
void LLWindowMacOSX::updateCursor()
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
|
||||
if (mDragOverrideCursor != -1)
|
||||
if (mDragOverrideCursor != -1)
|
||||
{
|
||||
// A drag is in progress...remember the requested cursor and we'll
|
||||
// restore it when it is done
|
||||
mCurrentCursor = cursor;
|
||||
mCurrentCursor = mNextCursor;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cursor == UI_CURSOR_ARROW
|
||||
if (mNextCursor == UI_CURSOR_ARROW
|
||||
&& mBusyCount > 0)
|
||||
{
|
||||
cursor = UI_CURSOR_WORKING;
|
||||
mNextCursor = UI_CURSOR_WORKING;
|
||||
}
|
||||
|
||||
if(mCurrentCursor == cursor)
|
||||
if(mCurrentCursor == mNextCursor)
|
||||
return;
|
||||
|
||||
// RN: replace multi-drag cursors with single versions
|
||||
if (cursor == UI_CURSOR_ARROWDRAGMULTI)
|
||||
if (mNextCursor == UI_CURSOR_ARROWDRAGMULTI)
|
||||
{
|
||||
cursor = UI_CURSOR_ARROWDRAG;
|
||||
mNextCursor = UI_CURSOR_ARROWDRAG;
|
||||
}
|
||||
else if (cursor == UI_CURSOR_ARROWCOPYMULTI)
|
||||
else if (mNextCursor == UI_CURSOR_ARROWCOPYMULTI)
|
||||
{
|
||||
cursor = UI_CURSOR_ARROWCOPY;
|
||||
mNextCursor = UI_CURSOR_ARROWCOPY;
|
||||
}
|
||||
|
||||
switch(cursor)
|
||||
switch(mNextCursor)
|
||||
{
|
||||
default:
|
||||
case UI_CURSOR_ARROW:
|
||||
@@ -2926,7 +2930,7 @@ void LLWindowMacOSX::setCursor(ECursorType cursor)
|
||||
case UI_CURSOR_TOOLBUY:
|
||||
case UI_CURSOR_TOOLOPEN:
|
||||
case UI_CURSOR_TOOLPAY:
|
||||
result = setImageCursor(gCursors[cursor]);
|
||||
result = setImageCursor(gCursors[mNextCursor]);
|
||||
break;
|
||||
|
||||
}
|
||||
@@ -2936,7 +2940,7 @@ void LLWindowMacOSX::setCursor(ECursorType cursor)
|
||||
InitCursor();
|
||||
}
|
||||
|
||||
mCurrentCursor = cursor;
|
||||
mCurrentCursor = mNextCursor;
|
||||
}
|
||||
|
||||
ECursorType LLWindowMacOSX::getCursor() const
|
||||
@@ -2967,9 +2971,9 @@ void LLWindowMacOSX::initCursors()
|
||||
initPixmapCursor(UI_CURSOR_TOOLPLAY, 1, 1);
|
||||
initPixmapCursor(UI_CURSOR_TOOLPAUSE, 1, 1);
|
||||
initPixmapCursor(UI_CURSOR_TOOLMEDIAOPEN, 1, 1);
|
||||
initPixmapCursor(UI_CURSOR_TOOLSIT, 1, 1);
|
||||
initPixmapCursor(UI_CURSOR_TOOLBUY, 1, 1);
|
||||
initPixmapCursor(UI_CURSOR_TOOLOPEN, 1, 1);
|
||||
initPixmapCursor(UI_CURSOR_TOOLSIT, 20, 15);
|
||||
initPixmapCursor(UI_CURSOR_TOOLBUY, 20, 15);
|
||||
initPixmapCursor(UI_CURSOR_TOOLOPEN, 20, 15);
|
||||
initPixmapCursor(UI_CURSOR_TOOLPAY, 1, 1);
|
||||
|
||||
initPixmapCursor(UI_CURSOR_SIZENWSE, 10, 10);
|
||||
@@ -3281,14 +3285,14 @@ void LLWindowMacOSX::setTitle(const std::string &title)
|
||||
LLSD LLWindowMacOSX::getNativeKeyData()
|
||||
{
|
||||
LLSD result = LLSD::emptyMap();
|
||||
|
||||
|
||||
if(mRawKeyEvent)
|
||||
{
|
||||
char char_code = 0;
|
||||
UInt32 key_code = 0;
|
||||
UInt32 modifiers = 0;
|
||||
UInt32 keyboard_type = 0;
|
||||
|
||||
|
||||
GetEventParameter (mRawKeyEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &char_code);
|
||||
GetEventParameter (mRawKeyEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &key_code);
|
||||
GetEventParameter (mRawKeyEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
|
||||
@@ -3298,7 +3302,7 @@ LLSD LLWindowMacOSX::getNativeKeyData()
|
||||
result["key_code"] = (S32)key_code;
|
||||
result["modifiers"] = (S32)modifiers;
|
||||
result["keyboard_type"] = (S32)keyboard_type;
|
||||
|
||||
|
||||
#if 0
|
||||
// This causes trouble for control characters -- apparently character codes less than 32 (escape, control-A, etc)
|
||||
// cause llsd serialization to create XML that the llsd deserializer won't parse!
|
||||
@@ -3307,7 +3311,7 @@ LLSD LLWindowMacOSX::getNativeKeyData()
|
||||
EventParamType actualType = typeUTF8Text;
|
||||
UInt32 actualSize = 0;
|
||||
char *buffer = NULL;
|
||||
|
||||
|
||||
err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, 0, &actualSize, NULL);
|
||||
if(err == noErr)
|
||||
{
|
||||
@@ -3320,7 +3324,7 @@ LLSD LLWindowMacOSX::getNativeKeyData()
|
||||
}
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
|
||||
result["unicode"] = unicode;
|
||||
#endif
|
||||
|
||||
@@ -3328,7 +3332,7 @@ LLSD LLWindowMacOSX::getNativeKeyData()
|
||||
|
||||
|
||||
lldebugs << "native key data is: " << result << llendl;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -3375,17 +3379,17 @@ void *LLWindowMacOSX::getPlatformWindow()
|
||||
|
||||
void *LLWindowMacOSX::getMediaWindow()
|
||||
{
|
||||
/*
|
||||
Mozilla needs to be initialized with a WindowRef to function properly.
|
||||
/*
|
||||
Mozilla needs to be initialized with a WindowRef to function properly.
|
||||
(There's no good reason for this, since it shouldn't be interacting with our window in any way, but that's another issue.)
|
||||
If we're in windowed mode, we _could_ hand it our actual window pointer, but a subsequent switch to fullscreen will destroy that window,
|
||||
If we're in windowed mode, we _could_ hand it our actual window pointer, but a subsequent switch to fullscreen will destroy that window,
|
||||
which trips up Mozilla.
|
||||
Instead of using our actual window, we create an invisible window which will persist for the lifetime of the application and pass that to Mozilla.
|
||||
This satisfies its deep-seated need to latch onto a WindowRef and solves the issue with switching between fullscreen and windowed modes.
|
||||
|
||||
Note that we will never destroy this window (by design!), but since only one will ever be created per run of the application, that's okay.
|
||||
*/
|
||||
|
||||
|
||||
if(sMediaWindow == NULL)
|
||||
{
|
||||
Rect window_rect = {100, 100, 200, 200};
|
||||
@@ -3394,13 +3398,13 @@ void *LLWindowMacOSX::getMediaWindow()
|
||||
NULL,
|
||||
&window_rect,
|
||||
(ConstStr255Param) "\p",
|
||||
false, // Create the window invisible.
|
||||
false, // Create the window invisible.
|
||||
zoomDocProc, // Window with a grow box and a zoom box
|
||||
kLastWindowOfClass, // create it behind other windows
|
||||
false, // no close box
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
return (void*)sMediaWindow;
|
||||
}
|
||||
|
||||
@@ -3450,7 +3454,7 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
|
||||
}
|
||||
|
||||
UseInputWindow(mTSMDocument, !b);
|
||||
|
||||
|
||||
// Take care of old and new preeditors.
|
||||
if (preeditor != mPreeditor || !b)
|
||||
{
|
||||
@@ -3469,7 +3473,7 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
|
||||
return;
|
||||
}
|
||||
mLanguageTextInputAllowed = b;
|
||||
|
||||
|
||||
if (b)
|
||||
{
|
||||
if (mTSMScriptCode != smRoman)
|
||||
@@ -3518,7 +3522,7 @@ MASK LLWindowMacOSX::modifiersToMask(SInt16 modifiers)
|
||||
if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; }
|
||||
if(modifiers & optionKey) { mask |= MASK_ALT; }
|
||||
return mask;
|
||||
}
|
||||
}
|
||||
|
||||
#if LL_OS_DRAGDROP_ENABLED
|
||||
|
||||
@@ -3529,53 +3533,53 @@ OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef
|
||||
LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
|
||||
|
||||
lldebugs << "drag tracking handler, message = " << message << llendl;
|
||||
|
||||
|
||||
switch(message)
|
||||
{
|
||||
case kDragTrackingInWindow:
|
||||
result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_TRACK);
|
||||
break;
|
||||
|
||||
|
||||
case kDragTrackingEnterHandler:
|
||||
result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_START_TRACKING);
|
||||
break;
|
||||
|
||||
|
||||
case kDragTrackingLeaveHandler:
|
||||
result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_STOP_TRACKING);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon,
|
||||
OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon,
|
||||
DragRef drag)
|
||||
{
|
||||
{
|
||||
LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
|
||||
return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED);
|
||||
|
||||
}
|
||||
|
||||
OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDropAction action)
|
||||
{
|
||||
{
|
||||
OSErr result = dragNotAcceptedErr; // overall function result
|
||||
OSErr err = noErr; // for local error handling
|
||||
|
||||
|
||||
// Get the mouse position and modifiers of this drag.
|
||||
SInt16 modifiers, mouseDownModifiers, mouseUpModifiers;
|
||||
::GetDragModifiers(drag, &modifiers, &mouseDownModifiers, &mouseUpModifiers);
|
||||
MASK mask = LLWindowMacOSX::modifiersToMask(modifiers);
|
||||
|
||||
|
||||
Point mouse_point;
|
||||
// This will return the mouse point in global screen coords
|
||||
::GetDragMouse(drag, &mouse_point, NULL);
|
||||
LLCoordScreen screen_coords(mouse_point.h, mouse_point.v);
|
||||
LLCoordGL gl_pos;
|
||||
convertCoords(screen_coords, &gl_pos);
|
||||
|
||||
|
||||
// Look at the pasteboard and try to extract an URL from it
|
||||
PasteboardRef pasteboard;
|
||||
if(GetDragPasteboard(drag, &pasteboard) == noErr)
|
||||
@@ -3583,22 +3587,22 @@ OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDrop
|
||||
ItemCount num_items = 0;
|
||||
// Treat an error here as an item count of 0
|
||||
(void)PasteboardGetItemCount(pasteboard, &num_items);
|
||||
|
||||
|
||||
// Only deal with single-item drags.
|
||||
if(num_items == 1)
|
||||
{
|
||||
PasteboardItemID item_id = NULL;
|
||||
CFArrayRef flavors = NULL;
|
||||
CFDataRef data = NULL;
|
||||
|
||||
|
||||
err = PasteboardGetItemIdentifier(pasteboard, 1, &item_id); // Yes, this really is 1-based.
|
||||
|
||||
|
||||
// Try to extract an URL from the pasteboard
|
||||
if(err == noErr)
|
||||
{
|
||||
err = PasteboardCopyItemFlavors( pasteboard, item_id, &flavors);
|
||||
}
|
||||
|
||||
|
||||
if(err == noErr)
|
||||
{
|
||||
if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeURL))
|
||||
@@ -3611,9 +3615,9 @@ OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDrop
|
||||
// This is a string that might be an URL.
|
||||
err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeUTF8PlainText, &data);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(flavors != NULL)
|
||||
{
|
||||
CFRelease(flavors);
|
||||
@@ -3624,12 +3628,12 @@ OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDrop
|
||||
std::string url;
|
||||
url.assign((char*)CFDataGetBytePtr(data), CFDataGetLength(data));
|
||||
CFRelease(data);
|
||||
|
||||
|
||||
if(!url.empty())
|
||||
{
|
||||
LLWindowCallbacks::DragNDropResult res =
|
||||
LLWindowCallbacks::DragNDropResult res =
|
||||
mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url);
|
||||
|
||||
|
||||
switch (res) {
|
||||
case LLWindowCallbacks::DND_NONE: // No drop allowed
|
||||
if (action == LLWindowCallbacks::DNDA_TRACK)
|
||||
@@ -3664,7 +3668,7 @@ OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDrop
|
||||
// Restore the cursor
|
||||
ECursorType temp_cursor = mCurrentCursor;
|
||||
// get around the "setting the same cursor" code in setCursor()
|
||||
mCurrentCursor = UI_CURSOR_COUNT;
|
||||
mCurrentCursor = UI_CURSOR_COUNT;
|
||||
setCursor(temp_cursor);
|
||||
}
|
||||
else {
|
||||
@@ -3676,7 +3680,7 @@ OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDrop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
/*virtual*/ void showCursorFromMouseMove();
|
||||
/*virtual*/ void hideCursorUntilMouseMove();
|
||||
/*virtual*/ BOOL isCursorHidden();
|
||||
/*virtual*/ void setCursor(ECursorType cursor);
|
||||
/*virtual*/ void updateCursor();
|
||||
/*virtual*/ ECursorType getCursor() const;
|
||||
/*virtual*/ void captureMouse();
|
||||
/*virtual*/ void releaseMouse();
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
/*virtual*/ void showCursorFromMouseMove() {};
|
||||
/*virtual*/ void hideCursorUntilMouseMove() {};
|
||||
/*virtual*/ BOOL isCursorHidden() {return FALSE;};
|
||||
/*virtual*/ void setCursor(ECursorType cursor) {};
|
||||
/*virtual*/ void updateCursor() {};
|
||||
//virtual ECursorType getCursor() { return mCurrentCursor; };
|
||||
/*virtual*/ void captureMouse() {};
|
||||
/*virtual*/ void releaseMouse() {};
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "llwindowcallbacks.h"
|
||||
#include "llkeyboardsdl.h"
|
||||
|
||||
#include "llerror.h"
|
||||
#include "llgl.h"
|
||||
#include "llstring.h"
|
||||
@@ -221,15 +222,14 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
|
||||
#endif // LL_X11
|
||||
|
||||
#if LL_GTK
|
||||
// We MUST be the first to initialize GTK, i.e. we have to beat
|
||||
// our embedded Mozilla to the punch so that GTK doesn't get badly
|
||||
// We MUST be the first to initialize GTK so that GTK doesn't get badly
|
||||
// initialized with a non-C locale and cause lots of serious random
|
||||
// weirdness.
|
||||
ll_try_gtk_init();
|
||||
#endif // LL_GTK
|
||||
|
||||
// Get the original aspect ratio of the main device.
|
||||
mOriginalAspectRatio = 1024.0 / 768.0; // !!! *FIX: ? //(double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay);
|
||||
// Assume 4:3 aspect ratio until we know better
|
||||
mOriginalAspectRatio = 1024.0 / 768.0;
|
||||
|
||||
if (title.empty())
|
||||
mWindowTitle = "SDL Window"; // *FIX: (???)
|
||||
@@ -425,7 +425,6 @@ static int x11_detect_VRAM_kb()
|
||||
BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync)
|
||||
{
|
||||
//bool glneedsinit = false;
|
||||
// const char *gllibname = null;
|
||||
|
||||
llinfos << "createContext, fullscreen=" << fullscreen <<
|
||||
" size=" << width << "x" << height << llendl;
|
||||
@@ -856,11 +855,13 @@ void LLWindowSDL::hide()
|
||||
// *FIX: What to do with SDL?
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLWindowSDL::minimize()
|
||||
{
|
||||
// *FIX: What to do with SDL?
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLWindowSDL::restore()
|
||||
{
|
||||
// *FIX: What to do with SDL?
|
||||
@@ -1680,12 +1681,13 @@ void check_vm_bloat()
|
||||
}
|
||||
#endif // LL_LINUX
|
||||
}
|
||||
|
||||
|
||||
// virtual
|
||||
void LLWindowSDL::processMiscNativeEvents()
|
||||
{
|
||||
#if LL_GTK
|
||||
// Pump GTK events to avoid starvation for:
|
||||
// * Embedded Gecko
|
||||
// * DBUS servicing
|
||||
// * Anything else which quietly hooks into the default glib/GTK loop
|
||||
if (ll_try_gtk_init())
|
||||
@@ -1721,7 +1723,7 @@ void LLWindowSDL::processMiscNativeEvents()
|
||||
|
||||
void LLWindowSDL::gatherInput()
|
||||
{
|
||||
const Uint32 CLICK_THRESHOLD = 500; // milliseconds
|
||||
const Uint32 CLICK_THRESHOLD = 500; // milliseconds
|
||||
static int leftClick = 0;
|
||||
static int rightClick = 0;
|
||||
static Uint32 lastLeftDown = 0;
|
||||
@@ -1747,16 +1749,17 @@ void LLWindowSDL::gatherInput()
|
||||
mKeyScanCode = event.key.keysym.scancode;
|
||||
mKeyVirtualKey = event.key.keysym.unicode;
|
||||
mKeyModifiers = event.key.keysym.mod;
|
||||
gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod);
|
||||
// part of the fix for SL-13243
|
||||
if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0)
|
||||
SDLReallyCaptureInput(TRUE);
|
||||
|
||||
if (event.key.keysym.unicode)
|
||||
{
|
||||
handleUnicodeUTF16(event.key.keysym.unicode,
|
||||
gKeyboard->currentMask(FALSE));
|
||||
}
|
||||
gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod);
|
||||
// part of the fix for SL-13243
|
||||
if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0)
|
||||
SDLReallyCaptureInput(TRUE);
|
||||
|
||||
if (event.key.keysym.unicode)
|
||||
{
|
||||
handleUnicodeUTF16(event.key.keysym.unicode,
|
||||
gKeyboard->currentMask(FALSE));
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_KEYUP:
|
||||
@@ -1767,8 +1770,8 @@ void LLWindowSDL::gatherInput()
|
||||
if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0)
|
||||
SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243
|
||||
|
||||
gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod);
|
||||
break;
|
||||
gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
{
|
||||
@@ -1878,7 +1881,7 @@ void LLWindowSDL::gatherInput()
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
mCallbacks->handleResize(this, width, height);
|
||||
break;
|
||||
}
|
||||
@@ -1932,6 +1935,8 @@ void LLWindowSDL::gatherInput()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateCursor();
|
||||
|
||||
#if LL_X11
|
||||
// This is a good time to stop flashing the icon if our mFlashTimer has
|
||||
@@ -2018,7 +2023,7 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty
|
||||
return sdlcursor;
|
||||
}
|
||||
|
||||
void LLWindowSDL::setCursor(ECursorType cursor)
|
||||
void LLWindowSDL::updateCursor()
|
||||
{
|
||||
if (ATIbug) {
|
||||
// cursor-updating is very flaky when this bug is
|
||||
@@ -2026,11 +2031,11 @@ void LLWindowSDL::setCursor(ECursorType cursor)
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCurrentCursor != cursor)
|
||||
if (mCurrentCursor != mNextCursor)
|
||||
{
|
||||
if (cursor < UI_CURSOR_COUNT)
|
||||
if (mNextCursor < UI_CURSOR_COUNT)
|
||||
{
|
||||
SDL_Cursor *sdlcursor = mSDLCursors[cursor];
|
||||
SDL_Cursor *sdlcursor = mSDLCursors[mNextCursor];
|
||||
// Try to default to the arrow for any cursors that
|
||||
// did not load correctly.
|
||||
if (!sdlcursor && mSDLCursors[UI_CURSOR_ARROW])
|
||||
@@ -2038,9 +2043,9 @@ void LLWindowSDL::setCursor(ECursorType cursor)
|
||||
if (sdlcursor)
|
||||
SDL_SetCursor(sdlcursor);
|
||||
} else {
|
||||
llwarns << "Tried to set invalid cursor number " << cursor << llendl;
|
||||
llwarns << "Tried to set invalid cursor number " << mNextCursor << llendl;
|
||||
}
|
||||
mCurrentCursor = cursor;
|
||||
mCurrentCursor = mNextCursor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
/*virtual*/ void showCursorFromMouseMove();
|
||||
/*virtual*/ void hideCursorUntilMouseMove();
|
||||
/*virtual*/ BOOL isCursorHidden();
|
||||
/*virtual*/ void setCursor(ECursorType cursor);
|
||||
/*virtual*/ void updateCursor();
|
||||
/*virtual*/ void captureMouse();
|
||||
/*virtual*/ void releaseMouse();
|
||||
/*virtual*/ void setMouseClipping( BOOL b );
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
/*virtual*/ void gatherInput();
|
||||
/*virtual*/ void swapBuffers();
|
||||
|
||||
/*virtual*/ void delayInputProcessing() { };
|
||||
/*virtual*/ void delayInputProcessing() { };
|
||||
|
||||
// handy coordinate space conversion routines
|
||||
/*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to);
|
||||
|
||||
@@ -677,6 +677,7 @@ void LLWindowWin32::hide()
|
||||
ShowWindow(mWindowHandle, SW_HIDE);
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLWindowWin32::minimize()
|
||||
{
|
||||
setMouseClipping(FALSE);
|
||||
@@ -684,7 +685,7 @@ void LLWindowWin32::minimize()
|
||||
ShowWindow(mWindowHandle, SW_MINIMIZE);
|
||||
}
|
||||
|
||||
|
||||
//virtual
|
||||
void LLWindowWin32::restore()
|
||||
{
|
||||
ShowWindow(mWindowHandle, SW_RESTORE);
|
||||
@@ -1019,6 +1020,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
|
||||
dw_style = WS_OVERLAPPEDWINDOW;
|
||||
}
|
||||
|
||||
|
||||
// don't post quit messages when destroying old windows
|
||||
mPostQuit = FALSE;
|
||||
|
||||
@@ -1070,6 +1072,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LL_INFOS("Window") << "Device context retrieved." << llendl ;
|
||||
|
||||
if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd)))
|
||||
{
|
||||
close();
|
||||
@@ -1078,6 +1082,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LL_INFOS("Window") << "Pixel format chosen." << llendl ;
|
||||
|
||||
// Verify what pixel format we actually received.
|
||||
if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
|
||||
&pfd))
|
||||
@@ -1653,13 +1659,13 @@ void LLWindowWin32::initCursors()
|
||||
mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE"));
|
||||
|
||||
// Color cursors
|
||||
mCursor[UI_CURSOR_TOOLSIT] = loadColorCursor(TEXT("TOOLSIT"));
|
||||
mCursor[UI_CURSOR_TOOLBUY] = loadColorCursor(TEXT("TOOLBUY"));
|
||||
mCursor[UI_CURSOR_TOOLPAY] = loadColorCursor(TEXT("TOOLPAY"));
|
||||
mCursor[UI_CURSOR_TOOLOPEN] = loadColorCursor(TEXT("TOOLOPEN"));
|
||||
mCursor[UI_CURSOR_TOOLPLAY] = loadColorCursor(TEXT("TOOLPLAY"));
|
||||
mCursor[UI_CURSOR_TOOLPAUSE] = loadColorCursor(TEXT("TOOLPAUSE"));
|
||||
mCursor[UI_CURSOR_TOOLMEDIAOPEN] = loadColorCursor(TEXT("TOOLMEDIAOPEN"));
|
||||
mCursor[ UI_CURSOR_TOOLSIT ] = loadColorCursor(TEXT("TOOLSIT"));
|
||||
mCursor[ UI_CURSOR_TOOLBUY ] = loadColorCursor(TEXT("TOOLBUY"));
|
||||
mCursor[ UI_CURSOR_TOOLPAY ] = loadColorCursor(TEXT("TOOLPAY"));
|
||||
mCursor[ UI_CURSOR_TOOLOPEN ] = loadColorCursor(TEXT("TOOLOPEN"));
|
||||
mCursor[ UI_CURSOR_TOOLPLAY ] = loadColorCursor(TEXT("TOOLPLAY"));
|
||||
mCursor[ UI_CURSOR_TOOLPAUSE ] = loadColorCursor(TEXT("TOOLPAUSE"));
|
||||
mCursor[ UI_CURSOR_TOOLMEDIAOPEN ] = loadColorCursor(TEXT("TOOLMEDIAOPEN"));
|
||||
|
||||
// Note: custom cursors that are not found make LoadCursor() return NULL.
|
||||
for( S32 i = 0; i < UI_CURSOR_COUNT; i++ )
|
||||
@@ -1673,18 +1679,18 @@ void LLWindowWin32::initCursors()
|
||||
|
||||
|
||||
|
||||
void LLWindowWin32::setCursor(ECursorType cursor)
|
||||
void LLWindowWin32::updateCursor()
|
||||
{
|
||||
if (cursor == UI_CURSOR_ARROW
|
||||
if (mNextCursor == UI_CURSOR_ARROW
|
||||
&& mBusyCount > 0)
|
||||
{
|
||||
cursor = UI_CURSOR_WORKING;
|
||||
mNextCursor = UI_CURSOR_WORKING;
|
||||
}
|
||||
|
||||
if( mCurrentCursor != cursor )
|
||||
if( mCurrentCursor != mNextCursor )
|
||||
{
|
||||
mCurrentCursor = cursor;
|
||||
SetCursor( mCursor[cursor] );
|
||||
mCurrentCursor = mNextCursor;
|
||||
SetCursor( mCursor[mNextCursor] );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1764,6 +1770,8 @@ void LLWindowWin32::gatherInput()
|
||||
|
||||
mInputProcessingPaused = FALSE;
|
||||
|
||||
updateCursor();
|
||||
|
||||
// clear this once we've processed all mouse messages that might have occurred after
|
||||
// we slammed the mouse position
|
||||
mMousePositionModified = FALSE;
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
/*virtual*/ void showCursorFromMouseMove();
|
||||
/*virtual*/ void hideCursorUntilMouseMove();
|
||||
/*virtual*/ BOOL isCursorHidden();
|
||||
/*virtual*/ void setCursor(ECursorType cursor);
|
||||
/*virtual*/ void updateCursor();
|
||||
/*virtual*/ ECursorType getCursor() const;
|
||||
/*virtual*/ void captureMouse();
|
||||
/*virtual*/ void releaseMouse();
|
||||
|
||||
@@ -152,6 +152,7 @@ set(viewer_SOURCE_FILES
|
||||
llconfirmationmanager.cpp
|
||||
llconsole.cpp
|
||||
llcontainerview.cpp
|
||||
llcurlrequest.cpp
|
||||
llcurrencyuimanager.cpp
|
||||
llcylinder.cpp
|
||||
lldebugmessagebox.cpp
|
||||
@@ -474,8 +475,6 @@ set(viewer_SOURCE_FILES
|
||||
llviewerfoldertype.cpp
|
||||
llviewergenericmessage.cpp
|
||||
llviewergesture.cpp
|
||||
#llviewerimage.cpp
|
||||
#llviewerimagelist.cpp
|
||||
llviewerinventory.cpp
|
||||
llviewerjoint.cpp
|
||||
llviewerjointattachment.cpp
|
||||
@@ -649,6 +648,7 @@ set(viewer_HEADER_FILES
|
||||
llconfirmationmanager.h
|
||||
llconsole.h
|
||||
llcontainerview.h
|
||||
llcurlrequest.h
|
||||
llcurrencyuimanager.h
|
||||
llcylinder.h
|
||||
lldebugmessagebox.h
|
||||
@@ -976,8 +976,6 @@ set(viewer_HEADER_FILES
|
||||
llviewerfoldertype.h
|
||||
llviewergenericmessage.h
|
||||
llviewergesture.h
|
||||
#llviewerimage.h
|
||||
#llviewerimagelist.h
|
||||
llviewerinventory.h
|
||||
llviewerjoint.h
|
||||
llviewerjointattachment.h
|
||||
@@ -1372,23 +1370,28 @@ if (FMOD OR FMODEX)
|
||||
endif (FMOD)
|
||||
|
||||
if (DARWIN)
|
||||
set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp)
|
||||
add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES})
|
||||
if (FMODEX)
|
||||
set(fmodwrapper_needed_LIBRARIES ${FMODEX_LIBRARY} ${CARBON_LIBRARY})
|
||||
endif (FMODEX)
|
||||
if (FMOD)
|
||||
set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY})
|
||||
endif (FMOD)
|
||||
set_target_properties(
|
||||
fmodwrapper
|
||||
PROPERTIES
|
||||
BUILD_WITH_INSTALL_RPATH 1
|
||||
INSTALL_NAME_DIR "@executable_path/../Resources"
|
||||
LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp"
|
||||
)
|
||||
set(FMODWRAPPER_LIBRARY fmodwrapper)
|
||||
target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES})
|
||||
if(FMOD)
|
||||
set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp)
|
||||
add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES})
|
||||
if (FMODEX)
|
||||
set(fmodwrapper_needed_LIBRARIES ${FMODEX_LIBRARY} ${CARBON_LIBRARY})
|
||||
endif (FMODEX)
|
||||
if (FMOD)
|
||||
set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY})
|
||||
endif (FMOD)
|
||||
set_target_properties(
|
||||
fmodwrapper
|
||||
PROPERTIES
|
||||
BUILD_WITH_INSTALL_RPATH 1
|
||||
INSTALL_NAME_DIR "@executable_path/../Resources"
|
||||
LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp"
|
||||
)
|
||||
set(FMODWRAPPER_LIBRARY fmodwrapper)
|
||||
target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES})
|
||||
endif(FMOD)
|
||||
if(FMODEX)
|
||||
set(FMODWRAPPER_LIBRARY ${FMODEX_LIBRARY})
|
||||
endif(FMODEX)
|
||||
else (DARWIN)
|
||||
# fmodwrapper unnecessary on linux or windows, for fmod and fmodex
|
||||
if (FMODEX)
|
||||
@@ -1798,7 +1801,7 @@ endif (WINDOWS)
|
||||
if (DARWIN)
|
||||
# Don't do this here -- it's taken care of by viewer_manifest.py
|
||||
# add_custom_command(TARGET ${VIEWER_BINARY_NAME} POST_BUILD
|
||||
# COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin/
|
||||
# DEPENDS ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib
|
||||
# COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib/release/libllqtwebkit.dylib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin/
|
||||
# DEPENDS ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib/release/libllqtwebkit.dylib
|
||||
# )
|
||||
endif (DARWIN)
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
CFBundleName = "Singularity";
|
||||
|
||||
CFBundleShortVersionString = "Singularity Viewer 1.5.0.0";
|
||||
CFBundleGetInfoString = "Singularity Viewer 1.5.0.0, Copyright 2010 Siana Gearz";
|
||||
CFBundleShortVersionString = "Singularity Viewer 1.7.0.0";
|
||||
CFBundleGetInfoString = "Singularity Viewer 1.7.0.0, Copyright 2012 Siana Gearz";
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>singularity.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.secondlife.indra.viewer</string>
|
||||
<string>org.singularityviewer.singularity</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
|
||||
@@ -786,6 +786,18 @@
|
||||
<real>0.7843137254902</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
</map>
|
||||
<key>5886ec80-cf56-11e1-9b23-0800200c9a66</key>
|
||||
<map>
|
||||
<key>name</key>
|
||||
<string>Voodoo</string>
|
||||
<key>color</key>
|
||||
<array>
|
||||
<real>0.70588235294118</real>
|
||||
<real>0.7843137254902</real>
|
||||
<real>0.7843137254902</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
</map>
|
||||
<key>734bae36-a197-b087-ee2d-a098d58fed55</key>
|
||||
<map>
|
||||
|
||||
@@ -4006,17 +4006,6 @@
|
||||
<key>Value</key>
|
||||
<real>120.0</real>
|
||||
</map>
|
||||
<key>CurlUseMultipleThreads</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Use background threads for executing curl_multi_perform (requires restart)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>Cursor3D</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
||||
@@ -214,6 +214,8 @@
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.5</real>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>BuildPrefs_Ysize</key>
|
||||
<map>
|
||||
@@ -225,6 +227,8 @@
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.5</real>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>BuildPrefs_Zsize</key>
|
||||
<map>
|
||||
@@ -236,6 +240,8 @@
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.5</real>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EmeraldBuildPrefs_Phantom</key>
|
||||
<map>
|
||||
@@ -247,6 +253,8 @@
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EmeraldBuildPrefs_Temporary</key>
|
||||
<map>
|
||||
@@ -258,6 +266,8 @@
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EmeraldBuildPrefs_Physical</key>
|
||||
<map>
|
||||
@@ -269,6 +279,8 @@
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EmeraldBuildPrefs_EmbedItem</key>
|
||||
<map>
|
||||
@@ -280,6 +292,8 @@
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>BuildPrefs_Material</key>
|
||||
<map>
|
||||
@@ -291,6 +305,8 @@
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>Wood</string>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EmeraldBuildPrefs_Color</key>
|
||||
<map>
|
||||
@@ -307,6 +323,8 @@
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EmeraldBuildPrefs_Texture</key>
|
||||
<map>
|
||||
@@ -318,6 +336,8 @@
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>89556747-24cb-43ed-920b-47caed15465f</string>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EmeraldBuildPrefs_Alpha</key>
|
||||
<map>
|
||||
@@ -329,6 +349,8 @@
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EmeraldBuildPrefs_Glow</key>
|
||||
<map>
|
||||
@@ -340,6 +362,8 @@
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EmeraldBuildPrefs_FullBright</key>
|
||||
<map>
|
||||
@@ -351,6 +375,8 @@
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EmeraldBuildPrefs_Shiny</key>
|
||||
<map>
|
||||
@@ -362,6 +388,21 @@
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>None</string>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>LiruEnableBuildPrefs</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When false, disables all defaults set in the building preferences panel, without resetting them.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<string>1</string>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
</map>
|
||||
</llsd>
|
||||
|
||||
@@ -40,6 +40,28 @@
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SHFMODExStreamBufferSize</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Sets the streaming buffer size (in milliseconds)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>7000</integer>
|
||||
</map>
|
||||
<key>SHFMODExDecodeBufferSize</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Sets the streaming decode buffer size (in milliseconds)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>1000</integer>
|
||||
</map>
|
||||
<key>SHAllowScriptCommands</key>
|
||||
<map>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<real>0.24652767181396484</real>
|
||||
<string>[Tarnix] Ultrabright Night</string>
|
||||
</array>
|
||||
<array>
|
||||
<real>0.24999989569187164</real>
|
||||
<string>[Tarnix] Ultrabright Morning</string>
|
||||
</array>
|
||||
<array>
|
||||
<real>0.49652755260467529</real>
|
||||
<string>[Tarnix] Ultrabright Day</string>
|
||||
</array>
|
||||
<array>
|
||||
<real>0.90277743339538574</real>
|
||||
<string>[Tarnix] Ultrabright Night</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
@@ -0,0 +1,36 @@
|
||||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<string>Realistic Night</string>
|
||||
</array>
|
||||
<array>
|
||||
<real>0.12499994784593582</real>
|
||||
<string>Realistic 3AM</string>
|
||||
</array>
|
||||
<array>
|
||||
<real>0.24652767181396484</real>
|
||||
<string>Realistic 6AM</string>
|
||||
</array>
|
||||
<array>
|
||||
<real>0.37499985098838806</real>
|
||||
<string>A-9AM</string>
|
||||
</array>
|
||||
<array>
|
||||
<real>0.49999979138374329</real>
|
||||
<string>Realistic</string>
|
||||
</array>
|
||||
<array>
|
||||
<real>0.62499970197677612</real>
|
||||
<string>A-3PM</string>
|
||||
</array>
|
||||
<array>
|
||||
<real>0.74999970197677612</real>
|
||||
<string>Realistic 6PM</string>
|
||||
</array>
|
||||
<array>
|
||||
<real>0.87499958276748657</real>
|
||||
<string>Realistic 9PM</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.0462114512920379638671875</real>
|
||||
<real>0.05376493558287620544433594</real>
|
||||
<real>0.0709760487079620361328125</real>
|
||||
<real>0.02365868352353572845458984</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.1467447141720501502248908</real>
|
||||
<real>0.4041820112504588280444295</real>
|
||||
<real>0.8083723277382617311559443</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.2301578534514239215980069</real>
|
||||
<real>0.3007703710769140670322486</real>
|
||||
<real>0.3251373821004301944981307</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.2784517256901799520107943</real>
|
||||
<real>0.2784517256901799520107943</real>
|
||||
<real>0.2784517256901799520107943</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>1.6884100437164306640625</real>
|
||||
<real>0.526096999645233154296875</real>
|
||||
<real>0.9492304265646138716761016</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>1.6884100437164306640625</real>
|
||||
<real>0.526096999645233154296875</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.3682807419706036755613354</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.69985902430791213646444</real>
|
||||
<real>10.50173369741952456024592</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.269999980926513671875</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.0004900000058114528656005859</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>12.90000057220458984375</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>2.45044231414794921875</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>0.87999999523162841796875</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>0.799999237060546875</real>
|
||||
<real>0.001000000047497451305389404</real>
|
||||
<real>-1.19999992847442626953125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>3.5</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.199999988079071044921875</real>
|
||||
<real>0.1991560012102127075195312</real>
|
||||
<real>0.1991560012102127075195312</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>-0.529998958110809326171875</real>
|
||||
<real>0.555569469928741455078125</real>
|
||||
<real>-0.640658795833587646484375</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>1333</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>22</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>0.589999973773956298828125</real>
|
||||
<key>sun_angle</key>
|
||||
<real>0.5890476703643798828125</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>1.397439671540726457976689</real>
|
||||
<real>1.479949096350015480538787</real>
|
||||
<real>2.570202271922596537478967</real>
|
||||
<real>0.9015665961795940042122766</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.01848458126187324523925781</real>
|
||||
<real>0.02150597609579563140869141</real>
|
||||
<real>0.02839041873812675476074219</real>
|
||||
<real>0.009463473223149776458740234</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.1467447141720501502248908</real>
|
||||
<real>0.4041820112504588280444295</real>
|
||||
<real>0.8083723277382617311559443</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.2301578534514239215980069</real>
|
||||
<real>0.3007703710769140670322486</real>
|
||||
<real>0.3251373821004301944981307</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.2784517256901799520107943</real>
|
||||
<real>0.2784517256901799520107943</real>
|
||||
<real>0.2784517256901799520107943</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>1.6884100437164306640625</real>
|
||||
<real>0.526096999645233154296875</real>
|
||||
<real>0.9492304265646138716761016</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>1.6884100437164306640625</real>
|
||||
<real>0.526096999645233154296875</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.3682807419706036755613354</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.69985902430791213646444</real>
|
||||
<real>10.50173369741952456024592</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.269999980926513671875</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.0004900000058114528656005859</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>12.90000057220458984375</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>2.19911479949951171875</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1.09000003337860107421875</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>4.867557667375535856990609</real>
|
||||
<real>0.001000000047497451305389404</real>
|
||||
<real>-0.4737372158712260805657479</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>3.5</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.199999988079071044921875</real>
|
||||
<real>0.1991560012102127075195312</real>
|
||||
<real>0.1991560012102127075195312</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>-0.6726734638214111328125</real>
|
||||
<real>0.555569469928741455078125</real>
|
||||
<real>-0.4887258112430572509765625</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>1333</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>22</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>0.589999973773956298828125</real>
|
||||
<key>sun_angle</key>
|
||||
<real>0.5890476703643798828125</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>1.397439671540726457976689</real>
|
||||
<real>1.479949096350015480538787</real>
|
||||
<real>2.570202271922596537478967</real>
|
||||
<real>0.9015665961795940042122766</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.22705078125</real>
|
||||
<real>0.0897216796875</real>
|
||||
<real>0.00732421875</real>
|
||||
<real>0.07568359375</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.171875</real>
|
||||
<real>0.171875</real>
|
||||
<real>0.171875</real>
|
||||
<real>0.0859375</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.31999999284744263</real>
|
||||
<real>0.31999999284744263</real>
|
||||
<real>0.31999999284744263</real>
|
||||
<real>0.15999999642372131</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.50999999046325684</real>
|
||||
<real>0.50999999046325684</real>
|
||||
<real>0.50999999046325684</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>1</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.079999998211860657</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.49940013885498</real>
|
||||
<real>10.01099967956543</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.25999999046325684</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.00060999998822808266</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>46.900001525878906</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>5.1522121429443359</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>0.26999998092651367</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>12.799999237060547</real>
|
||||
<real>0.0010000000474974513</real>
|
||||
<real>-0.99999994039535522</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>1.8899999856948853</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.23999999463558197</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>-0.86294835805892944</real>
|
||||
<real>0.30070748925209045</real>
|
||||
<real>-0.40607285499572754</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>427</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>21</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>0.81000000238418579</real>
|
||||
<key>sun_angle</key>
|
||||
<real>2.836158275604248</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>1.08233642578125</real>
|
||||
<real>1.07391357421875</real>
|
||||
<real>1.07391357421875</real>
|
||||
<real>0.36077880859375</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.50390625</real>
|
||||
<real>0.50390625</real>
|
||||
<real>0.50390625</real>
|
||||
<real>0.16796875</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.97999995946884155</real>
|
||||
<real>0.97999995946884155</real>
|
||||
<real>0.97999995946884155</real>
|
||||
<real>0.48999997973442078</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.47999998927116394</real>
|
||||
<real>0.53999996185302734</real>
|
||||
<real>0.45999997854232788</real>
|
||||
<real>0.53999996185302734</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.50999999046325684</real>
|
||||
<real>0.50999999046325684</real>
|
||||
<real>0.50999999046325684</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>1</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.079999998211860657</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.49940013885498</real>
|
||||
<real>10.01099967956543</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.25999999046325684</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.00013000000035390258</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>24.30000114440918</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>3.958406925201416</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1.6899999380111694</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>15.59999942779541</real>
|
||||
<real>0.0010000000474974513</real>
|
||||
<real>-0.59999996423721313</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>1.2699999809265137</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.26999998092651367</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>-0.29358875751495361</real>
|
||||
<real>0.91531205177307129</real>
|
||||
<real>0.27569809556007385</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>483</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>21</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>0</real>
|
||||
<key>sun_angle</key>
|
||||
<real>1.9853105545043945</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>1.3799998760223389</real>
|
||||
<real>1.3799998760223389</real>
|
||||
<real>1.3799998760223389</real>
|
||||
<real>0.45999997854232788</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.0099999997764825821</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0.0099999997764825821</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.68000000715255737</real>
|
||||
<real>0.49999505281448364</real>
|
||||
<real>1</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.070000000298023224</real>
|
||||
<real>0.85394656658172607</real>
|
||||
<real>1</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.53962135314941406</real>
|
||||
<real>0.53962135314941406</real>
|
||||
<real>0.53962135314941406</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>0.69569224119186401</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.10999999195337296</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.49940013885498</real>
|
||||
<real>10.01099967956543</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.3765256404876709</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.0004099999787285924</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>12.800000190734863</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>2.1991147994995117</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1.0199999809265137</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>5.3999996185302734</real>
|
||||
<real>0.0010000000474974513</real>
|
||||
<real>-0.39999997615814209</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>2.9500000476837158</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.45999997854232788</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>-0.68231838941574097</real>
|
||||
<real>0.53729885816574097</real>
|
||||
<real>-0.49573326110839844</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>1352.0999755859375</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>10</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>0</real>
|
||||
<key>sun_angle</key>
|
||||
<real>0.56723111867904663</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>0.77999997138977051</real>
|
||||
<real>1.2300000190734863</real>
|
||||
<real>1.2300000190734863</real>
|
||||
<real>0.40999999642372131</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0.05468752607703208923339844</real>
|
||||
<real>0.109375</real>
|
||||
<real>0.0546875</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>2</real>
|
||||
<real>2</real>
|
||||
<real>2</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.5396213531494140625</real>
|
||||
<real>0.5396213531494140625</real>
|
||||
<real>0.5396213531494140625</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>0.695692241191864013671875</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.1099999919533729553222656</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.49940013885498046875</real>
|
||||
<real>10.0109996795654296875</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.3765256404876708984375</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.0004099999787285923957824707</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>12.80000019073486328125</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>5.026547908782958984375</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>0.819999992847442626953125</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>17.799999237060546875</real>
|
||||
<real>0.001000000047497451305389404</real>
|
||||
<real>-0.4999999701976776123046875</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>2.9500000476837158203125</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.459999978542327880859375</real>
|
||||
<real>0.1991560012102127075195312</real>
|
||||
<real>0.1991560012102127075195312</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>0.79077517986297607421875</real>
|
||||
<real>0.555569469928741455078125</real>
|
||||
<real>0.2569381296634674072265625</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>1352.0999755859375</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>10</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>0</real>
|
||||
<key>sun_angle</key>
|
||||
<real>0.5890476703643798828125</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>2.8857421875</real>
|
||||
<real>1.8592071533203125</real>
|
||||
<real>0.8642578125</real>
|
||||
<real>0.9619140625</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.21194984018802643</real>
|
||||
<real>0.25700280070304871</real>
|
||||
<real>0.25999999046325684</real>
|
||||
<real>0.25999999046325684</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.10031381994485855</real>
|
||||
<real>0.2849995493888855</real>
|
||||
<real>0.56999999284744263</real>
|
||||
<real>0.56999999284744263</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.15806557238101959</real>
|
||||
<real>0.31211116909980774</real>
|
||||
<real>0.52999997138977051</real>
|
||||
<real>0.52999997138977051</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.62000000476837158</real>
|
||||
<real>0.72737622261047363</real>
|
||||
<real>0.73626559972763062</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>0.89999997615814209</real>
|
||||
<real>0.93999999761581421</real>
|
||||
<real>0.74000000953674316</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>0.11999999731779099</real>
|
||||
<real>0.20999999344348907</real>
|
||||
<real>0.029999999329447746</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.25999999046325684</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>9.993240904292179</real>
|
||||
<real>10.010000228881836</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.29999998211860657</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.00013000000035390258</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>10.100000381469727</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>3.8955750465393066</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1.4699999094009399</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>11.200000762939453</real>
|
||||
<real>0.0010000000474974513</real>
|
||||
<real>-0.64999997615814209</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>0.35999998450279236</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.11999999731779099</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>0.66304093599319458</real>
|
||||
<real>0.24868990480899811</real>
|
||||
<real>-0.70606660842895508</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>789</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>24</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>0.18999999761581421</real>
|
||||
<key>sun_angle</key>
|
||||
<real>0.25132742524147034</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>2.25</real>
|
||||
<real>1.2599999904632568</real>
|
||||
<real>0.59999996423721313</real>
|
||||
<real>2.25</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.36328125</real>
|
||||
<real>0.321533203125</real>
|
||||
<real>0.22265625</real>
|
||||
<real>0.12109375</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.97999995946884155</real>
|
||||
<real>0.97999995946884155</real>
|
||||
<real>0.97999995946884155</real>
|
||||
<real>0.48999997973442078</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.31999999284744263</real>
|
||||
<real>0.31999999284744263</real>
|
||||
<real>0.31999999284744263</real>
|
||||
<real>0.15999999642372131</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.50999999046325684</real>
|
||||
<real>0.50999999046325684</real>
|
||||
<real>0.50999999046325684</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>1</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.079999998211860657</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.49940013885498</real>
|
||||
<real>10.01099967956543</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.25999999046325684</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.00031000000308267772</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>6.8000001907348633</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>4.2725663185119629</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>5</real>
|
||||
<real>0.0010000000474974513</real>
|
||||
<real>-0.33000001311302185</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>1.8899999856948853</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.23999999463558197</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>-0.46939900517463684</real>
|
||||
<real>0.85491263866424561</real>
|
||||
<real>0.22088223695755005</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>752</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>21</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>0</real>
|
||||
<key>sun_angle</key>
|
||||
<real>2.1162102222442627</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>2.4300000667572021</real>
|
||||
<real>2.0399999618530273</real>
|
||||
<real>1.8600000143051147</real>
|
||||
<real>2.4300000667572021</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.5859375</real>
|
||||
<real>0.5859375</real>
|
||||
<real>0.5859375</real>
|
||||
<real>0.1953125</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.2447581589221954345703125</real>
|
||||
<real>0.4487232863903045654296875</real>
|
||||
<real>0.7599999904632568359375</real>
|
||||
<real>0.37999999523162841796875</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.6136362552642822265625</real>
|
||||
<real>0.6136362552642822265625</real>
|
||||
<real>0.8549020290374755859375</real>
|
||||
<real>0.42745101451873779296875</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.4099999964237213134765625</real>
|
||||
<real>0.4099999964237213134765625</real>
|
||||
<real>0.4099999964237213134765625</real>
|
||||
<real>0.4099999964237213134765625</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>1.6884100437164306640625</real>
|
||||
<real>0.526096999645233154296875</real>
|
||||
<real>1</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>1.6884100437164306640625</real>
|
||||
<real>0.526096999645233154296875</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.4199999868869781494140625</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.19999980926513671875</real>
|
||||
<real>10.0109996795654296875</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.269999980926513671875</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>9.999999747378751635551453e-05</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>0.4000000059604644775390625</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>3.1415927410125732421875</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>0.769999980926513671875</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>5</real>
|
||||
<real>0.001000000047497451305389404</real>
|
||||
<real>-1.10000002384185791015625</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>0.88999998569488525390625</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.1599999964237213134765625</real>
|
||||
<real>0.1991560012102127075195312</real>
|
||||
<real>0.1991560012102127075195312</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>1.003947020460603523073218e-13</real>
|
||||
<real>1</real>
|
||||
<real>-1.148381556959066074341536e-06</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>1493</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>22</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>0</real>
|
||||
<key>sun_angle</key>
|
||||
<real>1.57079517841339111328125</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>2.1299998760223388671875</real>
|
||||
<real>1.8660809993743896484375</real>
|
||||
<real>1.490999698638916015625</real>
|
||||
<real>0.709999978542327880859375</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.24475815892219543</real>
|
||||
<real>0.44872328639030457</real>
|
||||
<real>0.75999999046325684</real>
|
||||
<real>0.37999999523162842</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.49548381567001343</real>
|
||||
<real>0.49548381567001343</real>
|
||||
<real>0.63999998569488525</real>
|
||||
<real>0.31999999284744263</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.40999999642372131</real>
|
||||
<real>0.40999999642372131</real>
|
||||
<real>0.40999999642372131</real>
|
||||
<real>0.40999999642372131</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>1.6884100437164307</real>
|
||||
<real>0.52609699964523315</real>
|
||||
<real>1</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>1</real>
|
||||
<real>0.96999996900558472</real>
|
||||
<real>0.08999999612569809</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.40999996662139893</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.359999656677246</real>
|
||||
<real>10.340000152587891</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.2800000011920929</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>9.9999997473787516e-006</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>0</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1.1000000238418579</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>5</real>
|
||||
<real>0.0010000000474974513</real>
|
||||
<real>-1.1000000238418579</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>3.5</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.15999999642372131</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>-0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>667</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>22</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>1.1299999952316284</real>
|
||||
<key>sun_angle</key>
|
||||
<real>6.2395515441894531</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>1.6986236572265625</real>
|
||||
<real>1.1374046802520752</real>
|
||||
<real>0.4810638427734375</real>
|
||||
<real>0.5662078857421875</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.3486154782113272121435443</real>
|
||||
<real>0.449369331229434954000368</real>
|
||||
<real>0.603132514577153000523424</real>
|
||||
<real>0.6937349534321981536777457</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.3662028399132433720275515</real>
|
||||
<real>0.3662028399731497851909978</real>
|
||||
<real>0.4375903419326376275755308</real>
|
||||
<real>0.6640963995887574355947436</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.3169694886788358978435554</real>
|
||||
<real>0.3169694886788358978435554</real>
|
||||
<real>0.3169694886788358978435554</real>
|
||||
<real>0.7085542303539185127192468</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>1.6884100437164306640625</real>
|
||||
<real>0.526096999645233154296875</real>
|
||||
<real>0.9392771101574294290159628</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>1.6884100437164306640625</real>
|
||||
<real>0.526096999645233154296875</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.4199999868869781494140625</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.35150370716937828774462</real>
|
||||
<real>10.01099989455784466940713</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.269999980926513671875</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.0002012048324333540389764752</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>0.1975903555777060727205452</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>0</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>5</real>
|
||||
<real>0.00100000003430226265706271</real>
|
||||
<real>-0.4799999904774563952436495</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>2.463735011225950621849279</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.07903613876588544417955973</real>
|
||||
<real>0.199156002811505972172057</real>
|
||||
<real>0.199156002811505972172057</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0.59130990505218505859375</real>
|
||||
<real>-0.8064444065093994140625</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>1196.065065097033084384748</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>22</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>2</real>
|
||||
<key>sun_angle</key>
|
||||
<real>5.6505031585693359375</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>0.08699999749660491943359375</real>
|
||||
<real>0.118706881999969482421875</real>
|
||||
<real>0.2129999846220016479492188</real>
|
||||
<real>0.07099999487400054931640625</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
141
indra/newview/app_settings/windlight/skies/Realistic%203AM.xml
Normal file
141
indra/newview/app_settings/windlight/skies/Realistic%203AM.xml
Normal file
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.22259476780891418</real>
|
||||
<real>0.26450252532958984</real>
|
||||
<real>0.35999998450279236</real>
|
||||
<real>0.11999999731779099</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.23999616268583132</real>
|
||||
<real>0.239999227803052</real>
|
||||
<real>0.24000028550619668</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.22615400241566114</real>
|
||||
<real>0.22615400241566114</real>
|
||||
<real>0.22615400241566114</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>1.6884100437164307</real>
|
||||
<real>0.52609699964523315</real>
|
||||
<real>0.88000000953681223</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>1.6884100437164307</real>
|
||||
<real>0.52609699964523315</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.41999998688697815</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.499400354105791</real>
|
||||
<real>10.011000104419489</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.0003000046529240592</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>7</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>0</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>5.0000000000023022</real>
|
||||
<real>0.0010000000214220922</real>
|
||||
<real>-0.47999999165507345</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>4</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>4.6348559691012062e-006</real>
|
||||
<real>0.19915600437461423</real>
|
||||
<real>0.19915600437461423</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>-0</real>
|
||||
<real>1</real>
|
||||
<real>2.3722609512333293e-006</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>906.19008370909478</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>22</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>1.9999420642852783</real>
|
||||
<key>sun_angle</key>
|
||||
<real>4.7123866081237793</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>0.11344550549983978</real>
|
||||
<real>0.11571422964334488</real>
|
||||
<real>0.21467949450016022</real>
|
||||
<real>0.071559831500053406</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
141
indra/newview/app_settings/windlight/skies/Realistic%206AM.xml
Normal file
141
indra/newview/app_settings/windlight/skies/Realistic%206AM.xml
Normal file
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.80999994277954102</real>
|
||||
<real>0.46289783716201782</real>
|
||||
<real>0.62999993562698364</real>
|
||||
<real>0.26999998092651367</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.30247950553894043</real>
|
||||
<real>0.83312696218490601</real>
|
||||
<real>1.6662704944610596</real>
|
||||
<real>0.83313524723052979</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.20673196017742157</real>
|
||||
<real>0.40988314151763916</real>
|
||||
<real>0.47999998927116394</real>
|
||||
<real>0.47999998927116394</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.22616604226328718</real>
|
||||
<real>0.22616604226328718</real>
|
||||
<real>0.22616604226328718</real>
|
||||
<real>0.99997219085526012</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>1.6884100437164307</real>
|
||||
<real>0.52609699964523315</real>
|
||||
<real>0.88000025272481253</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>1.6884100437164307</real>
|
||||
<real>0.52609699964523315</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.41999998688697815</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.49940013883861</real>
|
||||
<real>10.010999679576344</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.26999998092651367</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.00056000001495704055</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>0.69999998807907104</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>0</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>4.6000003814697266</real>
|
||||
<real>0.0010000000474974513</real>
|
||||
<real>-0.94999998807907104</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>0.66999995708465576</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.15999999642372131</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>-0</real>
|
||||
<real>0.094108223915100098</real>
|
||||
<real>0.99556195735931396</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>877</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>22</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>0</real>
|
||||
<key>sun_angle</key>
|
||||
<real>0.094247691333293915</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>2.8055419921875</real>
|
||||
<real>2.5958919525146484</real>
|
||||
<real>2.3507080078125</real>
|
||||
<real>0.9351806640625</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
141
indra/newview/app_settings/windlight/skies/Realistic%206PM.xml
Normal file
141
indra/newview/app_settings/windlight/skies/Realistic%206PM.xml
Normal file
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.58785861730575562</real>
|
||||
<real>0.46682888269424438</real>
|
||||
<real>0.46682891249656677</real>
|
||||
<real>0.1959528774023056</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.18964982032775879</real>
|
||||
<real>0.52235734462738037</real>
|
||||
<real>1.0447251796722412</real>
|
||||
<real>0.52236258983612061</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.11289128661155701</real>
|
||||
<real>0.22382725775241852</real>
|
||||
<real>0.26210871338844299</real>
|
||||
<real>0.1310543566942215</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.22615399956703186</real>
|
||||
<real>0.22615399956703186</real>
|
||||
<real>0.22615399956703186</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>1.6884100437164307</real>
|
||||
<real>0.52609699964523315</real>
|
||||
<real>0.87999999523162842</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>1.6884100437164307</real>
|
||||
<real>0.52609699964523315</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.41999998688697815</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.49940013885498</real>
|
||||
<real>10.01099967956543</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.26999998092651367</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.00052999996114522219</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>0.69999998807907104</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>0</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>1.8000006675720215</real>
|
||||
<real>0.0010000000474974513</real>
|
||||
<real>-0.29999998211860657</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>2.1150000095367432</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.17600001394748688</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0.23768773674964905</real>
|
||||
<real>-0.97134160995483398</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>767</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>22</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>0</real>
|
||||
<key>sun_angle</key>
|
||||
<real>2.9016079902648926</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>1.9921875</real>
|
||||
<real>1.9921875</real>
|
||||
<real>1.9921875</real>
|
||||
<real>0.6640625</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
141
indra/newview/app_settings/windlight/skies/Realistic%209PM.xml
Normal file
141
indra/newview/app_settings/windlight/skies/Realistic%209PM.xml
Normal file
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.20404692765200849</real>
|
||||
<real>0.24246276689169122</real>
|
||||
<real>0.33000383615406292</real>
|
||||
<real>0.1100123608103587</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0.070311017334461212</real>
|
||||
<real>0.070312172174453735</real>
|
||||
<real>0.070313982665538788</real>
|
||||
<real>0.035156991332769394</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.23999616268583132</real>
|
||||
<real>0.239999227803052</real>
|
||||
<real>0.24000028550619668</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.22615400241566114</real>
|
||||
<real>0.22615400241566114</real>
|
||||
<real>0.22615400241566114</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>1.6884100437164307</real>
|
||||
<real>0.52609699964523315</real>
|
||||
<real>0.88000000953681223</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>1.6884100437164307</real>
|
||||
<real>0.52609699964523315</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.41999998688697815</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.499400354105791</real>
|
||||
<real>10.011000104419489</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.00023999999393709004</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>4.2000002861022949</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>0</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>5.0000000000023022</real>
|
||||
<real>0.0010000000214220922</real>
|
||||
<real>-0.47999999165507345</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>4</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>-0</real>
|
||||
<real>0.70710688829421997</real>
|
||||
<real>0.70710664987564087</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>1534</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>22</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>1.9999420642852783</real>
|
||||
<key>sun_angle</key>
|
||||
<real>3.9269909858703613</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>0.16206490993499756</real>
|
||||
<real>0.16530600190162659</real>
|
||||
<real>0.30668509006500244</real>
|
||||
<real>0.10222836583852768</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
141
indra/newview/app_settings/windlight/skies/Realistic%20Night.xml
Normal file
141
indra/newview/app_settings/windlight/skies/Realistic%20Night.xml
Normal file
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.080595135688781738</real>
|
||||
<real>0.095768749713897705</real>
|
||||
<real>0.13034236431121826</real>
|
||||
<real>0.043447453528642654</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.1181640625</real>
|
||||
<real>0.14753724634647369</real>
|
||||
<real>0.2255859375</real>
|
||||
<real>0.11279296875</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.1328125</real>
|
||||
<real>0.1328125</real>
|
||||
<real>0.1328125</real>
|
||||
<real>0.1328125</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>0.88000000953711155</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.41999998688697815</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.49940035411295</real>
|
||||
<real>10.011000104431371</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>5.999999848427251e-005</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>75.5</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>0</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>5</real>
|
||||
<real>0.0010000000474974513</real>
|
||||
<real>-0.44999998807907104</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>0.34999999403953552</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>-0</real>
|
||||
<real>1</real>
|
||||
<real>3.0028815672267228e-005</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>438</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>26</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>2</real>
|
||||
<key>sun_angle</key>
|
||||
<real>4.7123589515686035</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>0.092010498046875</real>
|
||||
<real>0.11404039710760117</real>
|
||||
<real>0.142364501953125</real>
|
||||
<real>0.047454833984375</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
141
indra/newview/app_settings/windlight/skies/Realistic.xml
Normal file
141
indra/newview/app_settings/windlight/skies/Realistic.xml
Normal file
@@ -0,0 +1,141 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>ambient</key>
|
||||
<array>
|
||||
<real>0.9140625</real>
|
||||
<real>0.9140625</real>
|
||||
<real>0.9140625</real>
|
||||
<real>0.3046875</real>
|
||||
</array>
|
||||
<key>blue_density</key>
|
||||
<array>
|
||||
<real>1.3854242563247681</real>
|
||||
<real>1.5503612756729126</real>
|
||||
<real>1.8020757436752319</real>
|
||||
<real>0.90103787183761597</real>
|
||||
</array>
|
||||
<key>blue_horizon</key>
|
||||
<array>
|
||||
<real>0.174346923828125</real>
|
||||
<real>0.20045472681522369</real>
|
||||
<real>0.278778076171875</real>
|
||||
<real>0.1393890380859375</real>
|
||||
</array>
|
||||
<key>cloud_color</key>
|
||||
<array>
|
||||
<real>0.236663818359375</real>
|
||||
<real>0.26210832595825195</real>
|
||||
<real>0.278961181640625</real>
|
||||
<real>0.278961181640625</real>
|
||||
</array>
|
||||
<key>cloud_pos_density1</key>
|
||||
<array>
|
||||
<real>0.32999998331069946</real>
|
||||
<real>0.52999997138977051</real>
|
||||
<real>1</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_pos_density2</key>
|
||||
<array>
|
||||
<real>1.6884100437164307</real>
|
||||
<real>0.48999997973442078</real>
|
||||
<real>0.125</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scale</key>
|
||||
<array>
|
||||
<real>0.47999998927116394</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>cloud_scroll_rate</key>
|
||||
<array>
|
||||
<real>10.069999694824219</real>
|
||||
<real>10.01099967956543</real>
|
||||
</array>
|
||||
<key>cloud_shadow</key>
|
||||
<array>
|
||||
<real>0.25</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>density_multiplier</key>
|
||||
<array>
|
||||
<real>0.00017999998817685992</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>distance_multiplier</key>
|
||||
<array>
|
||||
<real>3</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>east_angle</key>
|
||||
<real>0</real>
|
||||
<key>enable_cloud_scroll</key>
|
||||
<array>
|
||||
<boolean>1</boolean>
|
||||
<boolean>1</boolean>
|
||||
</array>
|
||||
<key>gamma</key>
|
||||
<array>
|
||||
<real>1</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>glow</key>
|
||||
<array>
|
||||
<real>5.5999994277954102</real>
|
||||
<real>0.0010000000474974513</real>
|
||||
<real>-0.49999997019767761</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_density</key>
|
||||
<array>
|
||||
<real>0.42999997735023499</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>haze_horizon</key>
|
||||
<array>
|
||||
<real>0.68000000715255737</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>0.19915600121021271</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>lightnorm</key>
|
||||
<array>
|
||||
<real>0</real>
|
||||
<real>0.91269159317016602</real>
|
||||
<real>-0.40864911675453186</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
<key>max_y</key>
|
||||
<array>
|
||||
<real>1342</real>
|
||||
<real>0</real>
|
||||
<real>0</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>preset_num</key>
|
||||
<integer>22</integer>
|
||||
<key>star_brightness</key>
|
||||
<real>0</real>
|
||||
<key>sun_angle</key>
|
||||
<real>1.9917697906494141</real>
|
||||
<key>sunlight_color</key>
|
||||
<array>
|
||||
<real>1.210693359375</real>
|
||||
<real>1.2674446105957031</real>
|
||||
<real>1.461181640625</real>
|
||||
<real>0.487060546875</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
@@ -0,0 +1,43 @@
|
||||
<llsd>
|
||||
<map>
|
||||
<key>blurMultiplier</key>
|
||||
<real>0.05800000205636024475097656</real>
|
||||
<key>fresnelOffset</key>
|
||||
<real>0.4299999773502349853515625</real>
|
||||
<key>fresnelScale</key>
|
||||
<real>0.1400000005960464477539062</real>
|
||||
<key>normScale</key>
|
||||
<array>
|
||||
<real>2.2000000476837158203125</real>
|
||||
<real>1.10000002384185791015625</real>
|
||||
<real>0.800000011920928955078125</real>
|
||||
</array>
|
||||
<key>normalMap</key>
|
||||
<uuid>822ded49-9a6c-f61c-cb89-6df54f42cdf4</uuid>
|
||||
<key>scaleAbove</key>
|
||||
<real>0.03999999910593032836914062</real>
|
||||
<key>scaleBelow</key>
|
||||
<real>0.329999983310699462890625</real>
|
||||
<key>underWaterFogMod</key>
|
||||
<real>0</real>
|
||||
<key>waterFogColor</key>
|
||||
<array>
|
||||
<real>0.234375</real>
|
||||
<real>1.00000011920928955078125</real>
|
||||
<real>0.999999940395355224609375</real>
|
||||
<real>1</real>
|
||||
</array>
|
||||
<key>waterFogDensity</key>
|
||||
<real>12.9960384368896484375</real>
|
||||
<key>wave1Dir</key>
|
||||
<array>
|
||||
<real>-0.2000000476837158203125</real>
|
||||
<real>-0.2400000095367431640625</real>
|
||||
</array>
|
||||
<key>wave2Dir</key>
|
||||
<array>
|
||||
<real>-0.190000057220458984375</real>
|
||||
<real>0</real>
|
||||
</array>
|
||||
</map>
|
||||
</llsd>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user