From ef490e308ccce8e6df85144784a0f4580f5ac6a1 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sat, 5 Feb 2011 15:58:07 +0100 Subject: Introduces a LLThreadLocalData class that can be accessed through the static LLThread::tldata(). Currently this object contains two (public) thread-local objects: a LLAPRRootPool and a LLVolatileAPRPool. The first is the general memory pool used by this thread (and this thread alone), while the second is intended for short lived memory allocations (needed for APR). The advantages of not mixing those two is that the latter is used most frequently, and as a result of it's nature can be destroyed and reconstructed on a "regular" basis. This patch adds LLAPRPool (completely replacing the old one), which is a wrapper around apr_pool_t* and has complete thread-safity checking. Whenever an apr call requires memory for some resource, a memory pool in the form of an LLAPRPool object can be created with the same life-time as this resource; assuring clean up of the memory no sooner, but also not much later than the life-time of the resource that needs the memory. Many, many function calls and constructors had the pool parameter simply removed (it is no longer the concern of the developer, if you don't write code that actually does an libapr call then you are no longer bothered with memory pools at all). However, I kept the notion of short-lived and long-lived allocations alive (see my remark in the jira here: https://jira.secondlife.com/browse/STORM-864?focusedCommentId=235356&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-235356 which requires that the LLAPRFile API needs to allow the user to specify how long they think a file will stay open. By choosing 'short_lived' as default for the constructor that immediately opens a file, the number of instances where this needs to be specified is drastically reduced however (obviously, any automatic LLAPRFile is short lived). *** Addressed Boroondas remarks in https://codereview.secondlife.com/r/99/ regarding (doxygen) comments. This patch effectively only changes comments. Includes some 'merge' stuff that ended up in llvocache.cpp (while starting as a bug fix, now only resulting in a cleanup). *** Added comment 'The use of apr_pool_t is OK here'. Added this comment on every line where apr_pool_t is correctly being used. This should make it easier to spot (future) errors where someone started to use apr_pool_t; you can just grep all sources for 'apr_pool_t' and immediately see where it's being used while LLAPRPool should have been used. Note that merging this patch is very easy: If there are no other uses of apr_pool_t in the code (one grep) and it compiles, then it will work. *** Second Merge (needed to remove 'delete mCreationMutex' from LLImageDecodeThread::~LLImageDecodeThread). *** Added back #include . Apparently that is needed on libapr version 1.2.8., the version used by Linden Lab, for calls to apr_queue_*. This is a bug in libapr (we also include , that is fixed in (at least) 1.3.7. Note that 1.2.8 is VERY old. Even 1.3.x is old. *** License fixes (GPL -> LGPL). And typo in comments. Addresses merov's comments on the review board. *** Added Merov's compile fixes for windows. --- indra/llmessage/llares.cpp | 17 ++----- indra/llmessage/llcurl.cpp | 2 +- indra/llmessage/lliohttpserver.cpp | 10 ++-- indra/llmessage/lliohttpserver.h | 2 +- indra/llmessage/lliosocket.cpp | 99 ++++++++++++++------------------------ indra/llmessage/lliosocket.h | 33 ++++--------- indra/llmessage/llmail.cpp | 17 ++++--- indra/llmessage/llmail.h | 4 +- indra/llmessage/llpumpio.cpp | 74 ++++++++++------------------ indra/llmessage/llpumpio.h | 31 ++++-------- indra/llmessage/llurlrequest.cpp | 25 ++++++---- indra/llmessage/message.cpp | 17 +++---- indra/llmessage/tests/networkio.h | 9 +--- 13 files changed, 122 insertions(+), 218 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp index 5a67035ed1..fab9858b69 100644 --- a/indra/llmessage/llares.cpp +++ b/indra/llmessage/llares.cpp @@ -28,6 +28,7 @@ #include "linden_common.h" #include "llares.h" +#include "llscopedvolatileaprpool.h" #include #include @@ -464,11 +465,6 @@ void LLAres::search(const std::string &query, LLResType type, bool LLAres::process(U64 timeout) { - if (!gAPRPoolp) - { - ll_init_apr(); - } - ares_socket_t socks[ARES_GETSOCK_MAXNUM]; apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM]; apr_int32_t nsds = 0; @@ -482,10 +478,7 @@ bool LLAres::process(U64 timeout) return nsds > 0; } - apr_status_t status; - LLAPRPool pool; - status = pool.getStatus() ; - ll_apr_assert_status(status); + LLScopedVolatileAPRPool scoped_pool; for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++) { @@ -502,7 +495,7 @@ bool LLAres::process(U64 timeout) apr_socket_t *aprSock = NULL; - status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool.getAPRPool()); + apr_status_t status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], scoped_pool); if (status != APR_SUCCESS) { ll_apr_warn_status(status); @@ -511,7 +504,7 @@ bool LLAres::process(U64 timeout) aprFds[nactive].desc.s = aprSock; aprFds[nactive].desc_type = APR_POLL_SOCKET; - aprFds[nactive].p = pool.getAPRPool(); + aprFds[nactive].p = scoped_pool; aprFds[nactive].rtnevents = 0; aprFds[nactive].client_data = &socks[i]; @@ -520,7 +513,7 @@ bool LLAres::process(U64 timeout) if (nactive > 0) { - status = apr_poll(aprFds, nactive, &nsds, timeout); + apr_status_t status = apr_poll(aprFds, nactive, &nsds, timeout); if (status != APR_SUCCESS && status != APR_TIMEUP) { diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index a485fa0160..4d3b382f7a 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -1039,7 +1039,7 @@ void LLCurl::initClass() S32 mutex_count = CRYPTO_num_locks(); for (S32 i=0; i factory_ptr(factory); - LLIOServerSocket* server = new LLIOServerSocket(pool, socket, factory_ptr); + LLIOServerSocket* server = new LLIOServerSocket(socket, factory_ptr); LLPumpIO::chain_t chain; chain.push_back(LLIOPipe::ptr_t(server)); diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h index 5c1b0531ff..2294e4b8ae 100644 --- a/indra/llmessage/lliohttpserver.h +++ b/indra/llmessage/lliohttpserver.h @@ -50,7 +50,7 @@ class LLIOHTTPServer public: typedef void (*timing_callback_t)(const char* hashed_name, F32 time, void* data); - static LLHTTPNode& create(apr_pool_t* pool, LLPumpIO& pump, U16 port); + static LLHTTPNode& create(LLPumpIO& pump, U16 port); /**< Creates an HTTP wire server on the pump for the given TCP port. * * Returns the root node of the new server. Add LLHTTPNode instances diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index ca84fa8bb8..e802d9b3a6 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -35,6 +35,7 @@ #include "llhost.h" #include "llmemtype.h" #include "llpumpio.h" +#include "llthread.h" // // constants @@ -98,51 +99,31 @@ void ll_debug_socket(const char* msg, apr_socket_t* apr_sock) /// // static -LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) +LLSocket::ptr_t LLSocket::create(EType type, U16 port) { LLMemType m1(LLMemType::MTYPE_IO_TCP); - LLSocket::ptr_t rv; - apr_socket_t* socket = NULL; - apr_pool_t* new_pool = NULL; apr_status_t status = APR_EGENERAL; - - // create a pool for the socket - status = apr_pool_create(&new_pool, pool); - if(ll_apr_warn_status(status)) - { - if(new_pool) apr_pool_destroy(new_pool); - return rv; - } + LLSocket::ptr_t rv(new LLSocket); if(STREAM_TCP == type) { - status = apr_socket_create( - &socket, - APR_INET, - SOCK_STREAM, - APR_PROTO_TCP, - new_pool); + status = apr_socket_create(&rv->mSocket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, rv->mPool()); } else if(DATAGRAM_UDP == type) { - status = apr_socket_create( - &socket, - APR_INET, - SOCK_DGRAM, - APR_PROTO_UDP, - new_pool); + status = apr_socket_create(&rv->mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, rv->mPool()); } else { - if(new_pool) apr_pool_destroy(new_pool); + rv.reset(); return rv; } if(ll_apr_warn_status(status)) { - if(new_pool) apr_pool_destroy(new_pool); + rv->mSocket = NULL; + rv.reset(); return rv; } - rv = ptr_t(new LLSocket(socket, new_pool)); if(port > 0) { apr_sockaddr_t* sa = NULL; @@ -152,7 +133,7 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) APR_UNSPEC, port, 0, - new_pool); + rv->mPool()); if(ll_apr_warn_status(status)) { rv.reset(); @@ -160,8 +141,8 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) } // This allows us to reuse the address on quick down/up. This // is unlikely to create problems. - ll_apr_warn_status(apr_socket_opt_set(socket, APR_SO_REUSEADDR, 1)); - status = apr_socket_bind(socket, sa); + ll_apr_warn_status(apr_socket_opt_set(rv->mSocket, APR_SO_REUSEADDR, 1)); + status = apr_socket_bind(rv->mSocket, sa); if(ll_apr_warn_status(status)) { rv.reset(); @@ -175,7 +156,7 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) // to keep a queue of incoming connections for ACCEPT. lldebugs << "Setting listen state for socket." << llendl; status = apr_socket_listen( - socket, + rv->mSocket, LL_DEFAULT_LISTEN_BACKLOG); if(ll_apr_warn_status(status)) { @@ -196,21 +177,28 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) } // static -LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool) +LLSocket::ptr_t LLSocket::create(apr_status_t& status, LLSocket::ptr_t& listen_socket) { LLMemType m1(LLMemType::MTYPE_IO_TCP); - LLSocket::ptr_t rv; - if(!socket) + if (!listen_socket->getSocket()) + { + status = APR_ENOSOCKET; + return LLSocket::ptr_t(); + } + LLSocket::ptr_t rv(new LLSocket); + lldebugs << "accepting socket" << llendl; + status = apr_socket_accept(&rv->mSocket, listen_socket->getSocket(), rv->mPool()); + if (status != APR_SUCCESS) { + rv->mSocket = NULL; + rv.reset(); return rv; } - rv = ptr_t(new LLSocket(socket, pool)); rv->mPort = PORT_EPHEMERAL; rv->setOptions(); return rv; } - bool LLSocket::blockingConnect(const LLHost& host) { if(!mSocket) return false; @@ -223,7 +211,7 @@ bool LLSocket::blockingConnect(const LLHost& host) APR_UNSPEC, host.getPort(), 0, - mPool))) + mPool()))) { return false; } @@ -234,13 +222,11 @@ bool LLSocket::blockingConnect(const LLHost& host) return true; } -LLSocket::LLSocket(apr_socket_t* socket, apr_pool_t* pool) : - mSocket(socket), - mPool(pool), +LLSocket::LLSocket() : + mSocket(NULL), + mPool(LLThread::tldata().mRootPool), mPort(PORT_INVALID) { - ll_debug_socket("Constructing wholely formed socket", mSocket); - LLMemType m1(LLMemType::MTYPE_IO_TCP); } LLSocket::~LLSocket() @@ -252,10 +238,6 @@ LLSocket::~LLSocket() ll_debug_socket("Destroying socket", mSocket); apr_socket_close(mSocket); } - if(mPool) - { - apr_pool_destroy(mPool); - } } void LLSocket::setOptions() @@ -516,10 +498,8 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl( /// LLIOServerSocket::LLIOServerSocket( - apr_pool_t* pool, LLIOServerSocket::socket_t listener, factory_t factory) : - mPool(pool), mListenSocket(listener), mReactor(factory), mInitialized(false), @@ -579,21 +559,15 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( lldebugs << "accepting socket" << llendl; PUMP_DEBUG; - apr_pool_t* new_pool = NULL; - apr_status_t status = apr_pool_create(&new_pool, mPool); - apr_socket_t* socket = NULL; - status = apr_socket_accept( - &socket, - mListenSocket->getSocket(), - new_pool); - LLSocket::ptr_t llsocket(LLSocket::create(socket, new_pool)); + apr_status_t status; + LLSocket::ptr_t llsocket(LLSocket::create(status, mListenSocket)); //EStatus rv = STATUS_ERROR; - if(llsocket) + if(llsocket && status == APR_SUCCESS) { PUMP_DEBUG; apr_sockaddr_t* remote_addr; - apr_socket_addr_get(&remote_addr, APR_REMOTE, socket); + apr_socket_addr_get(&remote_addr, APR_REMOTE, llsocket->getSocket()); char* remote_host_string; apr_sockaddr_ip_get(&remote_host_string, remote_addr); @@ -608,7 +582,6 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( { chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket))); pump->addChain(chain, mResponseTimeout); - status = STATUS_OK; } else { @@ -617,7 +590,8 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( } else { - llwarns << "Unable to create linden socket." << llendl; + char buf[256]; + llwarns << "Unable to accept linden socket: " << apr_strerror(status, buf, sizeof(buf)) << llendl; } PUMP_DEBUG; @@ -630,11 +604,10 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( #if 0 LLIODataSocket::LLIODataSocket( U16 suggested_port, - U16 start_discovery_port, - apr_pool_t* pool) : + U16 start_discovery_port) : mSocket(NULL) { - if(!pool || (PORT_INVALID == suggested_port)) return; + if(PORT_INVALID == suggested_port) return; if(ll_apr_warn_status(apr_socket_create(&mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, pool))) return; apr_sockaddr_t* sa = NULL; if(ll_apr_warn_status(apr_sockaddr_info_get(&sa, APR_ANYADDR, APR_UNSPEC, suggested_port, 0, pool))) return; diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h index 6806e5084a..1e35225512 100644 --- a/indra/llmessage/lliosocket.h +++ b/indra/llmessage/lliosocket.h @@ -38,7 +38,6 @@ */ #include "lliopipe.h" -#include "apr_pools.h" #include "apr_network_io.h" #include "llchainio.h" @@ -88,34 +87,22 @@ public: * socket. If you intend the socket to be known to external * clients without prior port notification, do not use * PORT_EPHEMERAL. - * @param pool The apr pool to use. A child pool will be created - * and associated with the socket. * @param type The type of socket to create * @param port The port for the socket * @return A valid socket shared pointer if the call worked. */ static ptr_t create( - apr_pool_t* pool, EType type, U16 port = PORT_EPHEMERAL); /** - * @brief Create a LLSocket when you already have an apr socket. + * @brief Create a LLSocket by accepting a connection from a listen socket. * - * This method assumes an ephemeral port. This is typically used - * by calls which spawn a socket such as a call to - * accept() as in the server socket. This call should - * not fail if you have a valid apr socket. - * Because of the nature of how accept() works, you are expected - * to create a new pool for the socket, use that pool for the - * accept, and pass it in here where it will be bound with the - * socket and destroyed at the same time. - * @param socket The apr socket to use - * @param pool The pool used to create the socket. *NOTE: The pool - * passed in will be DESTROYED. + * @param status Output. Status of the accept if a valid listen socket was passed. + * @param listen_socket The listen socket to use. * @return A valid socket shared pointer if the call worked. */ - static ptr_t create(apr_socket_t* socket, apr_pool_t* pool); + static ptr_t create(apr_status_t& status, ptr_t& listen_socket); /** * @brief Perform a blocking connect to a host. Do not use in production. @@ -150,7 +137,7 @@ protected: * @brief Protected constructor since should only make sockets * with one of the two create() calls. */ - LLSocket(apr_socket_t* socket, apr_pool_t* pool); + LLSocket(void); /** * @brief Set default socket options. @@ -167,8 +154,8 @@ protected: // The apr socket. apr_socket_t* mSocket; - // our memory pool - apr_pool_t* mPool; + // Our memory pool. + LLAPRPool mPool; // The port if we know it. U16 mPort; @@ -293,7 +280,7 @@ class LLIOServerSocket : public LLIOPipe public: typedef LLSocket::ptr_t socket_t; typedef boost::shared_ptr factory_t; - LLIOServerSocket(apr_pool_t* pool, socket_t listener, factory_t reactor); + LLIOServerSocket(socket_t listener, factory_t reactor); virtual ~LLIOServerSocket(); /** @@ -325,7 +312,6 @@ protected: //@} protected: - apr_pool_t* mPool; socket_t mListenSocket; factory_t mReactor; bool mInitialized; @@ -359,8 +345,7 @@ public: */ LLIODataSocket( U16 suggested_port, - U16 start_discovery_port, - apr_pool_t* pool); + U16 start_discovery_port); virtual ~LLIODataSocket(); protected: diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp index 08b31e9c7a..8a898ab1b0 100644 --- a/indra/llmessage/llmail.cpp +++ b/indra/llmessage/llmail.cpp @@ -50,6 +50,7 @@ #include "llstring.h" #include "lluuid.h" #include "net.h" +#include "llaprpool.h" // // constants @@ -57,7 +58,7 @@ const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE = 4096; static bool gMailEnabled = true; -static apr_pool_t* gMailPool; +static LLAPRPool gMailPool; static apr_sockaddr_t* gSockAddr; static apr_socket_t* gMailSocket; @@ -82,7 +83,7 @@ bool connect_smtp() gSockAddr->sa.sin.sin_family, SOCK_STREAM, APR_PROTO_TCP, - gMailPool); + gMailPool()); if(ll_apr_warn_status(status)) return false; status = apr_socket_connect(gMailSocket, gSockAddr); if(ll_apr_warn_status(status)) @@ -139,19 +140,19 @@ BOOL LLMail::send( } // static -void LLMail::init(const std::string& hostname, apr_pool_t* pool) +void LLMail::init(const std::string& hostname) { gMailSocket = NULL; - if(hostname.empty() || !pool) + if (hostname.empty()) { - gMailPool = NULL; gSockAddr = NULL; + gMailPool.destroy(); } else { - gMailPool = pool; + gMailPool.create(); - // collect all the information into a socaddr sturcture. the + // Collect all the information into a sockaddr structure. the // documentation is a bit unclear, but I either have to // specify APR_UNSPEC or not specify any flags. I am not sure // which option is better. @@ -161,7 +162,7 @@ void LLMail::init(const std::string& hostname, apr_pool_t* pool) APR_UNSPEC, 25, APR_IPV4_ADDR_OK, - gMailPool); + gMailPool()); ll_apr_warn_status(status); } } diff --git a/indra/llmessage/llmail.h b/indra/llmessage/llmail.h index 3791714363..0a5c532088 100644 --- a/indra/llmessage/llmail.h +++ b/indra/llmessage/llmail.h @@ -27,15 +27,13 @@ #ifndef LL_LLMAIL_H #define LL_LLMAIL_H -typedef struct apr_pool_t apr_pool_t; - #include "llsd.h" class LLMail { public: // if hostname is NULL, then the host is resolved as 'mail' - static void init(const std::string& hostname, apr_pool_t* pool); + static void init(const std::string& hostname); // Allow all email transmission to be disabled/enabled. static void enable(bool mail_enabled); diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index a8d2a0a224..89cfd66e1b 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -37,6 +37,7 @@ #include "llmemtype.h" #include "llstl.h" #include "llstat.h" +#include "llthread.h" // These should not be enabled in production, but they can be // intensely useful during development for finding certain kinds of @@ -162,14 +163,12 @@ struct ll_delete_apr_pollset_fd_client_data /** * LLPumpIO */ -LLPumpIO::LLPumpIO(apr_pool_t* pool) : +LLPumpIO::LLPumpIO(void) : mState(LLPumpIO::NORMAL), mRebuildPollset(false), mPollset(NULL), mPollsetClientID(0), mNextLock(0), - mPool(NULL), - mCurrentPool(NULL), mCurrentPoolReallocCount(0), mChainsMutex(NULL), mCallbackMutex(NULL), @@ -178,21 +177,24 @@ LLPumpIO::LLPumpIO(apr_pool_t* pool) : mCurrentChain = mRunningChains.end(); LLMemType m1(LLMemType::MTYPE_IO_PUMP); - initialize(pool); + initialize(); } LLPumpIO::~LLPumpIO() { LLMemType m1(LLMemType::MTYPE_IO_PUMP); - cleanup(); -} - -bool LLPumpIO::prime(apr_pool_t* pool) -{ - LLMemType m1(LLMemType::MTYPE_IO_PUMP); - cleanup(); - initialize(pool); - return ((pool == NULL) ? false : true); +#if LL_THREADS_APR + if (mChainsMutex) apr_thread_mutex_destroy(mChainsMutex); + if (mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex); +#endif + mChainsMutex = NULL; + mCallbackMutex = NULL; + if(mPollset) + { +// lldebugs << "cleaning up pollset" << llendl; + apr_pollset_destroy(mPollset); + mPollset = NULL; + } } bool LLPumpIO::addChain(const chain_t& chain, F32 timeout) @@ -352,8 +354,7 @@ bool LLPumpIO::setConditional(LLIOPipe* pipe, const apr_pollfd_t* poll) { // each fd needs a pool to work with, so if one was // not specified, use this pool. - // *FIX: Should it always be this pool? - value.second.p = mPool; + value.second.p = (*mCurrentChain).mDescriptorsPool->operator()(); } value.second.client_data = new S32(++mPollsetClientID); (*mCurrentChain).mDescriptors.push_back(value); @@ -825,39 +826,15 @@ void LLPumpIO::control(LLPumpIO::EControl op) } } -void LLPumpIO::initialize(apr_pool_t* pool) +void LLPumpIO::initialize(void) { LLMemType m1(LLMemType::MTYPE_IO_PUMP); - if(!pool) return; + mPool.create(); #if LL_THREADS_APR // SJB: Windows defaults to NESTED and OSX defaults to UNNESTED, so use UNNESTED explicitly. - apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, pool); - apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, pool); -#endif - mPool = pool; -} - -void LLPumpIO::cleanup() -{ - LLMemType m1(LLMemType::MTYPE_IO_PUMP); -#if LL_THREADS_APR - if(mChainsMutex) apr_thread_mutex_destroy(mChainsMutex); - if(mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex); + apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, mPool()); + apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, mPool()); #endif - mChainsMutex = NULL; - mCallbackMutex = NULL; - if(mPollset) - { -// lldebugs << "cleaning up pollset" << llendl; - apr_pollset_destroy(mPollset); - mPollset = NULL; - } - if(mCurrentPool) - { - apr_pool_destroy(mCurrentPool); - mCurrentPool = NULL; - } - mPool = NULL; } void LLPumpIO::rebuildPollset() @@ -885,21 +862,19 @@ void LLPumpIO::rebuildPollset() if(mCurrentPool && (0 == (++mCurrentPoolReallocCount % POLLSET_POOL_RECYCLE_COUNT))) { - apr_pool_destroy(mCurrentPool); - mCurrentPool = NULL; + mCurrentPool.destroy(); mCurrentPoolReallocCount = 0; } if(!mCurrentPool) { - apr_status_t status = apr_pool_create(&mCurrentPool, mPool); - (void)ll_apr_warn_status(status); + mCurrentPool.create(mPool); } // add all of the file descriptors run_it = mRunningChains.begin(); LLChainInfo::conditionals_t::iterator fd_it; LLChainInfo::conditionals_t::iterator fd_end; - apr_pollset_create(&mPollset, size, mCurrentPool, 0); + apr_pollset_create(&mPollset, size, mCurrentPool(), 0); for(; run_it != run_end; ++run_it) { fd_it = (*run_it).mDescriptors.begin(); @@ -1157,7 +1132,8 @@ bool LLPumpIO::handleChainError( LLPumpIO::LLChainInfo::LLChainInfo() : mInit(false), mLock(0), - mEOS(false) + mEOS(false), + mDescriptorsPool(new LLAPRPool(LLThread::tldata().mRootPool)) { LLMemType m1(LLMemType::MTYPE_IO_PUMP); mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS); diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h index 9303c9d7fc..75c35ae7ab 100644 --- a/indra/llmessage/llpumpio.h +++ b/indra/llmessage/llpumpio.h @@ -30,11 +30,12 @@ #define LL_LLPUMPIO_H #include +#include #if LL_LINUX // needed for PATH_MAX in APR. #include #endif -#include "apr_pools.h" +#include "llaprpool.h" #include "llbuffer.h" #include "llframetimer.h" #include "lliopipe.h" @@ -58,9 +59,8 @@ extern const F32 NEVER_CHAIN_EXPIRY_SECS; * pump() on a thread used for IO and call * respond() on a thread that is expected to do higher * level processing. You can call almost any other method from any - * thread - see notes for each method for details. In order for the - * threading abstraction to work, you need to call prime() - * with a valid apr pool. + * thread - see notes for each method for details. + * * A pump instance manages much of the state for the pipe, including * the list of pipes in the chain, the channel for each element in the * chain, the buffer, and if any pipe has marked the stream or process @@ -79,24 +79,13 @@ public: /** * @brief Constructor. */ - LLPumpIO(apr_pool_t* pool); + LLPumpIO(void); /** * @brief Destructor. */ ~LLPumpIO(); - /** - * @brief Prepare this pump for usage. - * - * If you fail to call this method prior to use, the pump will - * try to work, but will not come with any thread locking - * mechanisms. - * @param pool The apr pool to use. - * @return Returns true if the pump is primed. - */ - bool prime(apr_pool_t* pool); - /** * @brief Typedef for having a chain of pipes. */ @@ -368,6 +357,7 @@ protected: typedef std::pair pipe_conditional_t; typedef std::vector conditionals_t; conditionals_t mDescriptors; + boost::shared_ptr mDescriptorsPool; }; // All the running chains & info @@ -386,9 +376,9 @@ protected: callbacks_t mPendingCallbacks; callbacks_t mCallbacks; - // memory allocator for pollsets & mutexes. - apr_pool_t* mPool; - apr_pool_t* mCurrentPool; + // Memory pool for pollsets & mutexes. + LLAPRPool mPool; + LLAPRPool mCurrentPool; S32 mCurrentPoolReallocCount; #if LL_THREADS_APR @@ -400,8 +390,7 @@ protected: #endif protected: - void initialize(apr_pool_t* pool); - void cleanup(); + void initialize(); /** * @brief Given the internal state of the chains, rebuild the pollset diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index cb9d1c3731..83b6f7cf71 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -40,6 +40,7 @@ #include "llstring.h" #include "apr_env.h" #include "llapr.h" +#include "llscopedvolatileaprpool.h" static const U32 HTTP_STATUS_PIPE_ERROR = 499; /** @@ -210,27 +211,31 @@ void LLURLRequest::setCallback(LLURLRequestComplete* callback) // is called with use_proxy = FALSE void LLURLRequest::useProxy(bool use_proxy) { - static char *env_proxy; + static std::string env_proxy; - if (use_proxy && (env_proxy == NULL)) + if (use_proxy && env_proxy.empty()) { - apr_status_t status; - LLAPRPool pool; - status = apr_env_get(&env_proxy, "ALL_PROXY", pool.getAPRPool()); + char* env_proxy_str; + LLScopedVolatileAPRPool scoped_pool; + apr_status_t status = apr_env_get(&env_proxy_str, "ALL_PROXY", scoped_pool); if (status != APR_SUCCESS) { - status = apr_env_get(&env_proxy, "http_proxy", pool.getAPRPool()); + status = apr_env_get(&env_proxy_str, "http_proxy", scoped_pool); } if (status != APR_SUCCESS) { - use_proxy = FALSE; + use_proxy = false; } + else + { + // env_proxy_str is stored in the scoped_pool, so we have to make a copy. + env_proxy = env_proxy_str; + } } + lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = \"" << env_proxy << "\"" << llendl; - lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl; - - if (env_proxy && use_proxy) + if (use_proxy) { mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy); } diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 2f0d815be5..302cfc7ca2 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -97,8 +97,10 @@ std::string get_shared_secret(); class LLMessagePollInfo { public: + LLMessagePollInfo(void) : mPool(LLThread::tldata().mRootPool) { } apr_socket_t *mAPRSocketp; apr_pollfd_t mPollFD; + LLAPRPool mPool; }; namespace @@ -287,20 +289,13 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port, } // LL_DEBUGS("Messaging") << << "*** port: " << mPort << llendl; - // - // Create the data structure that we can poll on - // - if (!gAPRPoolp) - { - LL_ERRS("Messaging") << "No APR pool before message system initialization!" << llendl; - ll_init_apr(); - } + mPollInfop = new LLMessagePollInfo; + apr_socket_t *aprSocketp = NULL; - apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, gAPRPoolp); + apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, mPollInfop->mPool()); - mPollInfop = new LLMessagePollInfo; mPollInfop->mAPRSocketp = aprSocketp; - mPollInfop->mPollFD.p = gAPRPoolp; + mPollInfop->mPollFD.p = mPollInfop->mPool(); mPollInfop->mPollFD.desc_type = APR_POLL_SOCKET; mPollInfop->mPollFD.reqevents = APR_POLLIN; mPollInfop->mPollFD.rtnevents = 0; diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h index 2aff90ca1e..23e1c791f4 100644 --- a/indra/llmessage/tests/networkio.h +++ b/indra/llmessage/tests/networkio.h @@ -30,7 +30,6 @@ #define LL_NETWORKIO_H #include "llmemory.h" // LLSingleton -#include "llapr.h" #include "llares.h" #include "llpumpio.h" #include "llhttpclient.h" @@ -48,14 +47,8 @@ public: mServicePump(NULL), mDone(false) { - ll_init_apr(); - if (! gAPRPoolp) - { - throw std::runtime_error("Can't initialize APR"); - } - // Create IO Pump to use for HTTP Requests. - mServicePump = new LLPumpIO(gAPRPoolp); + mServicePump = new LLPumpIO; LLHTTPClient::setPump(*mServicePump); if (ll_init_ares() == NULL || !gAres->isInitialized()) { -- cgit v1.3 From 74d9bf0d5525426feae4ea21e2a81034ddcf4d7f Mon Sep 17 00:00:00 2001 From: Robin Cornelius Date: Mon, 28 Mar 2011 11:20:06 +0100 Subject: VWR-20801 Implement SOCKS 5 Proxy for the viewer --- indra/llmessage/CMakeLists.txt | 2 + indra/llmessage/llcurl.cpp | 44 ++++ indra/llmessage/llpacketring.cpp | 60 ++++- indra/llmessage/llpacketring.h | 3 + indra/llmessage/llsocks5.cpp | 224 +++++++++++++++++ indra/llmessage/llsocks5.h | 243 ++++++++++++++++++ indra/llmessage/net.cpp | 156 ++++++++++++ indra/llmessage/net.h | 5 + indra/newview/app_settings/settings.xml | 77 ++++++ indra/newview/llfloaterpreference.cpp | 171 +++++++++++++ indra/newview/llfloaterpreference.h | 30 +++ indra/newview/llstartup.cpp | 123 ++++++++- indra/newview/llstartup.h | 2 + indra/newview/llviewerfloaterreg.cpp | 1 + indra/newview/llxmlrpctransaction.cpp | 21 +- .../default/xui/en/floater_preferences_proxy.xml | 274 +++++++++++++++++++++ .../newview/skins/default/xui/en/notifications.xml | 70 ++++++ .../default/xui/en/panel_preferences_setup.xml | 85 +++---- 18 files changed, 1525 insertions(+), 66 deletions(-) create mode 100644 indra/llmessage/llsocks5.cpp create mode 100644 indra/llmessage/llsocks5.h create mode 100644 indra/newview/skins/default/xui/en/floater_preferences_proxy.xml (limited to 'indra/llmessage') diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 1cad0f6d22..8c68d38926 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -74,6 +74,7 @@ set(llmessage_SOURCE_FILES llsdrpcserver.cpp llservicebuilder.cpp llservice.cpp + llsocks5.cpp llstoredmessage.cpp lltemplatemessagebuilder.cpp lltemplatemessagedispatcher.cpp @@ -172,6 +173,7 @@ set(llmessage_HEADER_FILES llsdrpcserver.h llservice.h llservicebuilder.h + llsocks5.h llstoredmessage.h lltaskname.h llteleportflags.h diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index a485fa0160..020c0d6a4a 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -50,6 +50,8 @@ #include "llsdserialize.h" #include "llthread.h" +#include "llsocks5.h" + ////////////////////////////////////////////////////////////////////////////// /* The trick to getting curl to do keep-alives is to reuse the @@ -273,6 +275,28 @@ LLCurl::Easy* LLCurl::Easy::getEasy() // set no DMS caching as default for all easy handles. This prevents them adopting a // multi handles cache if they are added to one. curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); + + //Set the CURL options for either Socks or HTTP proxy + if (LLSocks::getInstance()->isHttpProxyEnabled()) + { + std::string address = LLSocks::getInstance()->getHTTPProxy().getIPString(); + U16 port = LLSocks::getInstance()->getHTTPProxy().getPort(); + curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXY,address.c_str()); + curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXYPORT,port); + if (LLSocks::getInstance()->getHttpProxyType() == LLPROXY_SOCKS) + { + curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + if(LLSocks::getInstance()->getSelectedAuthMethod()==METHOD_PASSWORD) + { + curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXYUSERPWD,LLSocks::getInstance()->getProxyUserPwd().c_str()); + } + } + else + { + curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + } + } + ++gCurlEasyCount; return easy; } @@ -446,6 +470,26 @@ void LLCurl::Easy::prepRequest(const std::string& url, // setopt(CURLOPT_VERBOSE, 1); // usefull for debugging setopt(CURLOPT_NOSIGNAL, 1); + if (LLSocks::getInstance()->isHttpProxyEnabled()) + { + std::string address = LLSocks::getInstance()->getHTTPProxy().getIPString(); + U16 port = LLSocks::getInstance()->getHTTPProxy().getPort(); + setoptString(CURLOPT_PROXY, address.c_str()); + setopt(CURLOPT_PROXYPORT, port); + if (LLSocks::getInstance()->getHttpProxyType() == LLPROXY_SOCKS) + { + setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + if(LLSocks::getInstance()->getSelectedAuthMethod()==METHOD_PASSWORD) + { + setoptString(CURLOPT_PROXYUSERPWD,LLSocks::getInstance()->getProxyUserPwd()); + } + } + else + { + setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + } + } + mOutput.reset(new LLBufferArray); setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback); setopt(CURLOPT_WRITEDATA, (void*)this); diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index 8999dec64a..0c8c5f763c 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -35,6 +35,17 @@ #include "llrand.h" #include "u64.h" +#include "llsocks5.h" +#include "message.h" + +#if LL_WINDOWS + #include +#else + #include + #include +#endif + + /////////////////////////////////////////////////////////// LLPacketRing::LLPacketRing () : mUseInThrottle(FALSE), @@ -216,8 +227,31 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap) else { // no delay, pull straight from net + if (LLSocks::isEnabled()) + { + U8 buffer[MAX_BUFFER_SIZE]; + packet_size = receive_packet(socket, (char*)buffer); + + if (packet_size > 10) + { + memcpy(datap,buffer+10,packet_size-10); + } + else + { + packet_size=0; + } + + proxywrap_t * header; + header = (proxywrap_t *)buffer; + mLastSender.setAddress(header->addr); + mLastSender.setPort(ntohs(header->port)); + } + else + { packet_size = receive_packet(socket, datap); mLastSender = ::get_sender(); + } + mLastReceivingIF = ::get_receiving_interface(); if (packet_size) // did we actually get a packet? @@ -243,7 +277,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL BOOL status = TRUE; if (!mUseOutThrottle) { - return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() ); + return doSendPacket(h_socket, send_buffer, buf_size, host ); } else { @@ -264,7 +298,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL mOutBufferLength -= packetp->getSize(); packet_size = packetp->getSize(); - status = send_packet(h_socket, packetp->getData(), packet_size, packetp->getHost().getAddress(), packetp->getHost().getPort()); + status = doSendPacket(h_socket, packetp->getData(), packet_size, packetp->getHost()); delete packetp; // Update the throttle @@ -273,7 +307,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL else { // If the queue's empty, we can just send this packet right away. - status = send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() ); + status = doSendPacket(h_socket, send_buffer, buf_size, host ); packet_size = buf_size; // Update the throttle @@ -311,3 +345,23 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL return status; } + +BOOL LLPacketRing::doSendPacket(int h_socket, const char * send_buffer, S32 buf_size, LLHost host) +{ + + if (!LLSocks::isEnabled()) + { + return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort()); + } + + proxywrap_t *socks_header = (proxywrap_t *)&mProxyWrappedSendBuffer; + socks_header->rsv = 0; + socks_header->addr = host.getAddress(); + socks_header->port = htons(host.getPort()); + socks_header->atype = ADDRESS_IPV4; + socks_header->frag = 0; + + memcpy(mProxyWrappedSendBuffer+10, send_buffer, buf_size); + + return send_packet(h_socket,(const char*) mProxyWrappedSendBuffer, buf_size+10, LLSocks::getInstance()->getUDPProxy().getAddress(), LLSocks::getInstance()->getUDPProxy().getPort()); +} diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h index e6409d2048..2fe2f8e1e9 100644 --- a/indra/llmessage/llpacketring.h +++ b/indra/llmessage/llpacketring.h @@ -82,6 +82,9 @@ protected: LLHost mLastSender; LLHost mLastReceivingIF; + + BOOL doSendPacket(int h_socket, const char * send_buffer, S32 buf_size, LLHost host); + U8 mProxyWrappedSendBuffer[NET_BUFFER_SIZE]; }; diff --git a/indra/llmessage/llsocks5.cpp b/indra/llmessage/llsocks5.cpp new file mode 100644 index 0000000000..1f458a007c --- /dev/null +++ b/indra/llmessage/llsocks5.cpp @@ -0,0 +1,224 @@ +/** + * @file llsocks5.cpp + * @brief Socks 5 implementation + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * 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, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include + +#include "linden_common.h" +#include "net.h" +#include "llhost.h" +#include "message.h" +#include "llsocks5.h" + +// Static class variable instances + +// We want this to be static to avoid excessive indirection on every +// incomming packet just to do a simple bool test. The getter for this +// member is also static +bool LLSocks::sUdpProxyEnabled; +bool LLSocks::sHttpProxyEnabled; + +LLSocks::LLSocks() +{ + sUdpProxyEnabled = false; + sHttpProxyEnabled = false; + hProxyControlChannel = 0; + mProxyType = LLPROXY_SOCKS; +} + +// Perform a Socks5 authentication and UDP assioacation to the proxy +// specified by proxy, and assiocate UDP port message_port +int LLSocks::proxyHandshake(LLHost proxy, U32 message_port) +{ + int result; + + /* 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 = mAuthMethodSelected; // send only the selected metho + + result = tcp_handshake(hProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request_t), (char*)&socks_auth_response, sizeof(socks_auth_response_t)); + if (result != 0) + { + llwarns << "Socks authentication request failed, error on TCP control channel : " << result << llendl; + stopProxy(); + return SOCKS_CONNECT_ERROR; + } + + if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE) + { + llwarns << "Socks5 server refused all our authentication methods" << llendl; + stopProxy(); + return SOCKS_NOT_ACCEPTABLE; + } + + // SOCKS5 USERNAME/PASSWORD authentication + if (socks_auth_response.method == METHOD_PASSWORD) + { + // The server has requested a username/password combination + U32 request_size = mSocksUsername.size() + mSocksPassword.size() + 3; + char * password_auth = (char *)malloc(request_size); + password_auth[0] = 0x01; + password_auth[1] = mSocksUsername.size(); + memcpy(&password_auth[2],mSocksUsername.c_str(), mSocksUsername.size()); + password_auth[mSocksUsername.size()+2] = mSocksPassword.size(); + memcpy(&password_auth[mSocksUsername.size()+3], mSocksPassword.c_str(), mSocksPassword.size()); + + authmethod_password_reply_t password_reply; + + result = tcp_handshake(hProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(authmethod_password_reply_t)); + free (password_auth); + + if (result != 0) + { + llwarns << "Socks authentication failed, error on TCP control channel : " << result << llendl; + stopProxy(); + return SOCKS_CONNECT_ERROR; + } + + if (password_reply.status != AUTH_SUCCESS) + { + llwarns << "Socks authentication failed" << llendl; + stopProxy(); + return SOCKS_AUTH_FAIL; + } + } + + /* SOCKS5 connect request */ + + socks_command_request_t connect_request; + socks_command_response_t connect_reply; + + connect_request.version = SOCKS_VERSION; //Socks V5 + connect_request.command = COMMAND_UDP_ASSOCIATE; // Associate UDP + connect_request.flag = FIELD_RESERVED; + connect_request.atype = ADDRESS_IPV4; + connect_request.address = 0; // 0.0.0.0 We are not fussy about address + // UDP is promiscious receive for our protocol + connect_request.port = 0; // Port must be 0 if you ever want to connect via NAT and your router does port rewrite for you + + result = tcp_handshake(hProxyControlChannel, (char*)&connect_request, sizeof(socks_command_request_t), (char*)&connect_reply, sizeof(socks_command_response_t)); + if (result != 0) + { + llwarns << "Socks connect request failed, error on TCP control channel : " << result << llendl; + stopProxy(); + return SOCKS_CONNECT_ERROR; + } + + if (connect_reply.reply != REPLY_REQUEST_GRANTED) + { + //Something went wrong + llwarns << "Connection to SOCKS5 server failed, UDP forward request not granted" << llendl; + stopProxy(); + return SOCKS_UDP_FWD_NOT_GRANTED; + } + + mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order + mUDPProxy.setAddress(proxy.getAddress()); + // All good now we have been given the UDP port to send requests that need forwarding. + llinfos << "Socks 5 UDP proxy connected on " << mUDPProxy << llendl; + return SOCKS_OK; +} + +int LLSocks::startProxy(LLHost proxy, U32 message_port) +{ + int status; + + mTCPProxy = proxy; + + if (hProxyControlChannel) + { + tcp_close_channel(hProxyControlChannel); + hProxyControlChannel=0; + } + + hProxyControlChannel = tcp_open_channel(proxy); + if (hProxyControlChannel == -1) + { + return SOCKS_HOST_CONNECT_FAILED; + } + + status = proxyHandshake(proxy, message_port); + if (status == SOCKS_OK) + { + sUdpProxyEnabled=true; + } + return status; +} + +int LLSocks::startProxy(std::string host, U32 port) +{ + mTCPProxy.setHostByName(host); + mTCPProxy.setPort(port); + return startProxy(mTCPProxy, (U32)gMessageSystem->mPort); +} + +void LLSocks::stopProxy() +{ + sUdpProxyEnabled = false; + + // If the Socks proxy is requested to stop and we are using that for http as well + // 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 == mProxyType) + { + sHttpProxyEnabled = false; + } + + if (hProxyControlChannel) + { + tcp_close_channel(hProxyControlChannel); + hProxyControlChannel=0; + } +} + +void LLSocks::setAuthNone() +{ + mAuthMethodSelected = METHOD_NOAUTH; +} + +void LLSocks::setAuthPassword(std::string username, std::string password) +{ + mAuthMethodSelected = METHOD_PASSWORD; + mSocksUsername = username; + mSocksPassword = password; +} + +void LLSocks::EnableHttpProxy(LLHost httpHost, LLHttpProxyType type) +{ + sHttpProxyEnabled = true; + mHTTPProxy = httpHost; + mProxyType = type; +} diff --git a/indra/llmessage/llsocks5.h b/indra/llmessage/llsocks5.h new file mode 100644 index 0000000000..83e311a962 --- /dev/null +++ b/indra/llmessage/llsocks5.h @@ -0,0 +1,243 @@ +/** + * @file llsocks5.h + * @brief Socks 5 implementation + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * 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, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_SOCKS5_H +#define LL_SOCKS5_H + +#include "llhost.h" +#include "llmemory.h" +#include "llsingleton.h" +#include + +// Error codes returned from the StartProxy method + +#define SOCKS_OK 0 +#define SOCKS_CONNECT_ERROR -1 +#define SOCKS_NOT_PERMITTED -2 +#define SOCKS_NOT_ACCEPTABLE -3 +#define SOCKS_AUTH_FAIL -4 +#define SOCKS_UDP_FWD_NOT_GRANTED -5 +#define SOCKS_HOST_CONNECT_FAILED -6 + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */ +#endif + +#define SOCKS_VERSION 0x05 // we are using socks 5 + +// socks 5 address/hostname types +#define ADDRESS_IPV4 0x01 +#define ADDRESS_HOSTNAME 0x03 +#define ADDRESS_IPV6 0x04 + +// Lets just use our own ipv4 struct rather than dragging in system +// specific headers +union ipv4_address_t { + unsigned char octects[4]; + U32 addr32; +}; + +// Socks 5 control channel commands +#define COMMAND_TCP_STREAM 0x01 +#define COMMAND_TCP_BIND 0x02 +#define COMMAND_UDP_ASSOCIATE 0x03 + +// Socks 5 command replys +#define REPLY_REQUEST_GRANTED 0x00 +#define REPLY_GENERAL_FAIL 0x01 +#define REPLY_RULESET_FAIL 0x02 +#define REPLY_NETWORK_UNREACHABLE 0x03 +#define REPLY_HOST_UNREACHABLE 0x04 +#define REPLY_CONNECTION_REFUSED 0x05 +#define REPLY_TTL_EXPIRED 0x06 +#define REPLY_PROTOCOL_ERROR 0x07 +#define REPLY_TYPE_NOT_SUPPORTED 0x08 + +#define FIELD_RESERVED 0x00 + +// The standard socks5 request packet +// Push current alignment to stack and set alignment to 1 byte boundary +// This enabled us to use structs directly to set up and receive network packets +// into the correct fields, without fear of boundary alignment causing issues +#pragma pack(push,1) + +// Socks5 command packet +struct socks_command_request_t { + unsigned char version; + unsigned char command; + unsigned char flag; + unsigned char atype; + U32 address; + U16 port; +}; + +// Standard socks5 reply packet +struct socks_command_response_t { + unsigned char version; + unsigned char reply; + unsigned char flag; + unsigned char atype; + unsigned char add_bytes[4]; + U16 port; +}; + +#define AUTH_NOT_ACCEPTABLE 0xFF // reply if prefered methods are not avaiable +#define AUTH_SUCCESS 0x00 // reply if authentication successfull + +// socks 5 authentication request, stating which methods the client supports +struct socks_auth_request_t { + unsigned char version; + unsigned char num_methods; + unsigned char methods; // We are only using a single method currently +}; + +// socks 5 authentication response packet, stating server prefered method +struct socks_auth_response_t { + unsigned char version; + unsigned char method; +}; + +// socks 5 password reply packet +struct authmethod_password_reply_t { + unsigned char version; + unsigned char status; +}; + +// socks 5 UDP packet header +struct proxywrap_t { + U16 rsv; + U8 frag; + U8 atype; + U32 addr; + U16 port; +}; + +#pragma pack(pop) /* restore original alignment from stack */ + + +// Currently selected http proxy type +enum LLHttpProxyType +{ + LLPROXY_SOCKS = 0, + LLPROXY_HTTP = 1 +}; + +// Auth types +enum LLSocks5AuthType +{ + METHOD_NOAUTH = 0x00, // Client supports no auth + METHOD_GSSAPI = 0x01, // Client supports GSSAPI (Not currently supported) + METHOD_PASSWORD = 0x02 // Client supports username/password +}; + +class LLSocks: public LLSingleton +{ +public: + LLSocks(); + + // Start a connection to the socks 5 proxy + int startProxy(std::string host,U32 port); + int startProxy(LLHost proxy,U32 messagePort); + + // Disconnect and clean up any connection to the socks 5 proxy + void stopProxy(); + + // Set up to use Password auth when connecting to the socks proxy + void setAuthPassword(std::string username,std::string password); + + // Set up to use No Auth when connecting to the socks proxy; + void setAuthNone(); + + // get the currently selected auth method + LLSocks5AuthType getSelectedAuthMethod() { return mAuthMethodSelected; }; + + // static check for enabled status for UDP packets + static bool isEnabled(){return sUdpProxyEnabled;}; + + // static check for enabled status for http packets + static bool isHttpProxyEnabled(){return sHttpProxyEnabled;}; + + // Proxy http packets via httpHost, which can be a Socks5 or a http proxy + // as specified in type + void EnableHttpProxy(LLHost httpHost,LLHttpProxyType type); + + // Stop proxying http packets + void DisableHttpProxy() {sHttpProxyEnabled = false;}; + + // get the UDP proxy address and port + LLHost getUDPProxy(){return mUDPProxy;}; + + // get the socks 5 TCP control channel address and port + LLHost getTCPProxy(){return mTCPProxy;}; + + //get the http proxy address and port + LLHost getHTTPProxy(){return mHTTPProxy;}; + + // get the currently selected http proxy type + LLHttpProxyType getHttpProxyType(){return mProxyType;}; + + //Get the username password in a curl compatible format + std::string getProxyUserPwd(){ return (mSocksUsername + ":" + mSocksPassword);}; + +private: + + // Open a communication channel to the socks5 proxy proxy, at port messagePort + int proxyHandshake(LLHost proxy,U32 messagePort); + + // socket handle to proxy tcp control channel + S32 hProxyControlChannel; + + // is the UDP proxy enabled + static bool sUdpProxyEnabled; + // is the http proxy enabled + static bool sHttpProxyEnabled; + + // currently selected http proxy type + LLHttpProxyType mProxyType; + + // UDP proxy address and port + LLHost mUDPProxy; + // TCP Proxy control channel address and port + LLHost mTCPProxy; + // HTTP proxy address and port + LLHost mHTTPProxy; + + // socks 5 auth method selected + LLSocks5AuthType mAuthMethodSelected; + + // socks 5 username + std::string mSocksUsername; + // socks 5 password + std::string mSocksPassword; +}; + +#endif diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index 97611c3b51..ab5c1950c6 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -50,6 +50,7 @@ #include "lltimer.h" #include "indra_constants.h" +#include "llsocks5.h" // Globals #if LL_WINDOWS @@ -189,6 +190,90 @@ U32 ip_string_to_u32(const char* ip_string) #if LL_WINDOWS +int tcp_handshake(S32 handle, char * dataout, int outlen, char * datain, int maxinlen) +{ + int result; + result = send(handle, dataout, outlen, 0); + if (result != outlen) + { + S32 err = WSAGetLastError(); + llwarns << "Error sending data to proxy control channel, number of bytes sent were " << result << " error code was " << err << llendl; + return -1; + } + + result = recv(handle, datain, maxinlen, 0); + if (result != maxinlen) + { + S32 err = WSAGetLastError(); + llwarns << "Error receiving data from proxy control channel, number of bytes received were " << result << " error code was " << err << llendl; + return -1; + } + + return 0; +} + +S32 tcp_open_channel(LLHost host) +{ + // Open a TCP channel + // Jump through some hoops to ensure that if the request hosts is down + // or not reachable connect() does not block + + S32 handle; + handle = socket(AF_INET, SOCK_STREAM, 0); + if (!handle) + { + llwarns << "Error opening TCP control socket, socket() returned " << handle << llendl; + return -1; + } + + struct sockaddr_in address; + address.sin_port = htons(host.getPort()); + address.sin_family = AF_INET; + address.sin_addr.s_addr = host.getAddress(); + + // Non blocking + WSAEVENT hEvent=WSACreateEvent(); + WSAEventSelect(handle, hEvent, FD_CONNECT) ; + connect(handle, (struct sockaddr*)&address, sizeof(address)) ; + // Wait fot 5 seconds, if we can't get a TCP channel open in this + // time frame then there is something badly wrong. + WaitForSingleObject(hEvent, 1000*5); // 5 seconds time out + + WSANETWORKEVENTS netevents; + WSAEnumNetworkEvents(handle,hEvent,&netevents); + + // Check the async event status to see if we connected + if ((netevents.lNetworkEvents & FD_CONNECT) == FD_CONNECT) + { + if (netevents.iErrorCode[FD_CONNECT_BIT] != 0) + { + llwarns << "Unable to open TCP channel, WSA returned an error code of " << netevents.iErrorCode[FD_CONNECT_BIT] << llendl; + WSACloseEvent(hEvent); + return -1; + } + + // Now we are connected disable non blocking + // we don't need support an async interface as + // currently our only consumer (socks5) will make one round + // of packets then just hold the connection open + WSAEventSelect(handle, hEvent, NULL) ; + unsigned long NonBlock = 0; + ioctlsocket(handle, FIONBIO, &NonBlock); + + return handle; + } + + llwarns << "Unable to open TCP channel, Timeout is the host up?" << netevents.iErrorCode[FD_CONNECT_BIT] << llendl; + return -1; +} + +void tcp_close_channel(S32 handle) +{ + llinfos << "Closing TCP channel" << llendl; + shutdown(handle, SD_BOTH); + closesocket(handle); +} + S32 start_net(S32& socket_out, int& nPort) { // Create socket, make non-blocking @@ -385,6 +470,77 @@ BOOL send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, i #else + +int tcp_handshake(S32 handle, char * dataout, int outlen, char * datain, int maxinlen) +{ + if (send(handle, dataout, outlen, 0) != outlen) + { + llwarns << "Error sending data to proxy control channel" << llendl; + return -1; + } + + if (recv(handle, datain, maxinlen, 0) != maxinlen) + { + llwarns << "Error receiving data to proxy control channel" << llendl; + return -1; + } + + return 0; +} + +S32 tcp_open_channel(LLHost host) +{ + S32 handle; + handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (!handle) + { + llwarns << "Error opening TCP control socket, socket() returned " << handle << llendl; + return -1; + } + + struct sockaddr_in address; + address.sin_port = htons(host.getPort()); + address.sin_family = AF_INET; + address.sin_addr.s_addr = host.getAddress(); + + // Set the socket to non blocking for the connect() + int flags = fcntl(handle, F_GETFL, 0); + fcntl(handle, F_SETFL, flags | O_NONBLOCK); + + S32 error = connect(handle, (sockaddr*)&address, sizeof(address)); + if (error && (errno != EINPROGRESS)) + { + llwarns << "Unable to open TCP channel, error code: " << errno << llendl; + return -1; + } + + struct timeval timeout; + timeout.tv_sec = 5; // Maximum time to wait for the connect() to complete + timeout.tv_usec = 0; + fd_set fds; + FD_ZERO(&fds); + FD_SET(handle, &fds); + + // See if we have connectde or time out after 5 seconds + U32 rc = select(sizeof(fds)*8, NULL, &fds, NULL, &timeout); + + if (rc != 1) // we require exactly one descriptor to be set + { + llwarns << "Unable to open TCP channel" << llendl; + return -1; + } + + // Return the socket to blocking operations + fcntl(handle, F_SETFL, flags); + + return handle; +} + +void tcp_close_channel(S32 handle) +{ + close(handle); +} + // Create socket, make non-blocking S32 start_net(S32& socket_out, int& nPort) { diff --git a/indra/llmessage/net.h b/indra/llmessage/net.h index 9f4f5c5821..d93ed20c98 100644 --- a/indra/llmessage/net.h +++ b/indra/llmessage/net.h @@ -52,6 +52,11 @@ U32 get_sender_ip(void); LLHost get_receiving_interface(); U32 get_receiving_interface_ip(void); +// Some helpful tcp functions added for the socks 5 proxy support +S32 tcp_open_channel(LLHost host); // Open a tcp channel to a given host +void tcp_close_channel(S32 handle); // Close an open tcp channel +int tcp_handshake(S32 handle, char * dataout, int outlen, char * datain, int maxinlen); // Do a TCP data handshake + const char* u32_to_ip_string(U32 ip); // Returns pointer to internal string buffer, "(bad IP addr)" on failure, cannot nest calls char* u32_to_ip_string(U32 ip, char *ip_string); // NULL on failure, ip_string on success, you must allocate at least MAXADDRSTR chars U32 ip_string_to_u32(const char* ip_string); // Wrapper for inet_addr() diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f0e28d4ae3..2b7b7b8484 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -774,6 +774,83 @@ Value 5 + Socks5ProxyEnabled + + Comment + Use Socks5 Proxy + Persist + 1 + Type + Boolean + Value + 1 + + Socks5HttpProxyType + + Comment + Proxy type to use for HTTP operations + Persist + 1 + Type + String + Value + Socks + + Socks5ProxyHost + + Comment + Socks 5 Proxy Host + Persist + 1 + Type + String + Value + 64.79.219.97 + + Socks5ProxyPort + + Comment + Socks 5 Proxy Port + Persist + 1 + Type + U32 + Value + 1080 + + Socks5Username + + Comment + Socks 5 Username + Persist + 1 + Type + String + Value + + + Socks5Password + + Comment + Socks 5 Password + Persist + 1 + Type + String + Value + + + Socks5AuthType + + Comment + Selected Auth mechanism for Socks5 + Persist + 1 + Type + String + Value + None + BuildAxisDeadZone0 Comment diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 724096b443..a0d3852d30 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -103,6 +103,7 @@ #include "llviewermedia.h" #include "llpluginclassmedia.h" #include "llteleporthistorystorage.h" +#include "llsocks5.h" #include "lllogininstance.h" // to check if logged in yet #include "llsdserialize.h" @@ -325,6 +326,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.getUIColor", boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2)); mCommitCallbackRegistrar.add("Pref.MaturitySettings", boost::bind(&LLFloaterPreference::onChangeMaturity, this)); mCommitCallbackRegistrar.add("Pref.BlockList", boost::bind(&LLFloaterPreference::onClickBlockList, this)); + mCommitCallbackRegistrar.add("Pref.Proxy", boost::bind(&LLFloaterPreference::onClickProxySettings, this)); sSkin = gSavedSettings.getString("SkinCurrent"); @@ -603,6 +605,12 @@ void LLFloaterPreference::cancel() updateDoubleClickControls(); mDoubleClickActionDirty = false; } + LLFloaterPreferenceProxy * advanced_socks_settings = LLFloaterReg::findTypedInstance("prefs_socks5_advanced"); + if(advanced_socks_settings) + { + advanced_socks_settings->cancel(); + } + } void LLFloaterPreference::onOpen(const LLSD& key) @@ -1497,6 +1505,11 @@ void LLFloaterPreference::updateDoubleClickSettings() } } +void LLFloaterPreference::onClickProxySettings() +{ + LLFloaterReg::showInstance("prefs_proxy"); +} + void LLFloaterPreference::updateDoubleClickControls() { // check is one of double-click actions settings enabled @@ -1805,3 +1818,161 @@ void LLPanelPreferenceGraphics::setHardwareDefaults() resetDirtyChilds(); LLPanelPreference::setHardwareDefaults(); } + + +/* ------------------------------------------------------------ */ + +LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key) + : LLFloater(key), + mSocksSettingsDirty(false) +{ + mCommitCallbackRegistrar.add("Proxy.OK", boost::bind(&LLFloaterPreferenceProxy::onBtnOk, this)); + mCommitCallbackRegistrar.add("Proxy.Cancel", boost::bind(&LLFloaterPreferenceProxy::onBtnCancel, this)); + mCommitCallbackRegistrar.add("Proxy.Change", boost::bind(&LLFloaterPreferenceProxy::onChangeSocksSettings, this)); +} + +LLFloaterPreferenceProxy::~LLFloaterPreferenceProxy() +{ +} + +BOOL LLFloaterPreferenceProxy::postBuild() +{ + LLLineEditor* edit = getChild("socks_password_editor"); + if (edit) edit->setDrawAsterixes(TRUE); + + LLRadioGroup* socksAuth = getChild("socks5_auth_type"); + if(socksAuth->getSelectedValue().asString() == "None") + { + getChild("socks5_username")->setEnabled(false); + getChild("socks5_password")->setEnabled(false); + } + + center(); + return TRUE; +} + +void LLFloaterPreferenceProxy::onOpen(const LLSD& key) +{ + saveSettings(); +} + +void LLFloaterPreferenceProxy::onClose(bool app_quitting) +{ + if(mSocksSettingsDirty) + { + + // If the user plays with the Socks proxy settings after login, its only fair we let them know + // it will not be updated untill next restart. + if(LLStartUp::getStartupState()>STATE_LOGIN_WAIT) + { + if(this->mSocksSettingsDirty == true ) + { + LLNotifications::instance().add("ChangeSocks5Settings",LLSD(),LLSD()); + mSocksSettingsDirty = false; // we have notified the user now be quiet again + } + } + } +} + +void LLFloaterPreferenceProxy::saveSettings() +{ + // Save the value of all controls in the hierarchy + mSavedValues.clear(); + std::list view_stack; + view_stack.push_back(this); + while(!view_stack.empty()) + { + // Process view on top of the stack + LLView* curview = view_stack.front(); + view_stack.pop_front(); + + LLUICtrl* ctrl = dynamic_cast(curview); + if (ctrl) + { + LLControlVariable* control = ctrl->getControlVariable(); + if (control) + { + mSavedValues[control] = control->getValue(); + } + } + + // Push children onto the end of the work stack + for (child_list_t::const_iterator iter = curview->getChildList()->begin(); + iter != curview->getChildList()->end(); ++iter) + { + view_stack.push_back(*iter); + } + } + +} + +void LLFloaterPreferenceProxy::onBtnOk() +{ + // commit any outstanding text entry + if (hasFocus()) + { + LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); + if (cur_focus && cur_focus->acceptsTextInput()) + { + cur_focus->onCommit(); + } + } + closeFloater(false); +} + +void LLFloaterPreferenceProxy::onBtnCancel() +{ + if (hasFocus()) + { + LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); + if (cur_focus && cur_focus->acceptsTextInput()) + { + cur_focus->onCommit(); + } + refresh(); + } + + cancel(); + +} +void LLFloaterPreferenceProxy::cancel() +{ + + for (control_values_map_t::iterator iter = mSavedValues.begin(); + iter != mSavedValues.end(); ++iter) + { + LLControlVariable* control = iter->first; + LLSD ctrl_value = iter->second; + control->set(ctrl_value); + } + + closeFloater(); +} + +void LLFloaterPreferenceProxy::onChangeSocksSettings() +{ + mSocksSettingsDirty = true; + + LLRadioGroup* socksAuth = getChild("socks5_auth_type"); + if(socksAuth->getSelectedValue().asString() == "None") + { + getChild("socks5_username")->setEnabled(false); + getChild("socks5_password")->setEnabled(false); + } + else + { + getChild("socks5_username")->setEnabled(true); + getChild("socks5_password")->setEnabled(true); + } + + //Check for invalid states for the other http proxy radio + LLRadioGroup* otherHttpProxy = getChild("other_http_proxy_selection"); + if( (otherHttpProxy->getSelectedValue().asString() == "Socks" && + getChild("socks_proxy_enabled")->get() == FALSE )||( + otherHttpProxy->getSelectedValue().asString() == "Web" && + getChild("web_proxy_enabled")->get() == FALSE ) ) + { + otherHttpProxy->selectFirstItem(); + } + +}; \ No newline at end of file diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 46014804ec..fd5454ebcf 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -154,6 +154,7 @@ public: void applyResolution(); void onChangeMaturity(); void onClickBlockList(); + void onClickProxySettings(); void applyUIColor(LLUICtrl* ctrl, const LLSD& param); void getUIColor(LLUICtrl* ctrl, const LLSD& param); @@ -225,4 +226,33 @@ protected: }; +class LLFloaterPreferenceProxy : public LLFloater +{ +public: + LLFloaterPreferenceProxy(const LLSD& key); + ~LLFloaterPreferenceProxy(); + + /// show off our menu + static void show(); + void cancel(); + +protected: + BOOL postBuild(); + void onOpen(const LLSD& key); + void onClose(bool app_quitting); + void saveSettings(); + void onBtnOk(); + void onBtnCancel(); + + void onChangeSocksSettings(); + +private: + + bool mSocksSettingsDirty; + typedef std::map control_values_map_t; + control_values_map_t mSavedValues; + +}; + + #endif // LL_LLPREFERENCEFLOATER_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 8fccb35886..f054bd11b8 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -191,6 +191,8 @@ #include "llevents.h" #include "llstartuplistener.h" +#include "llsocks5.h" + #if LL_WINDOWS #include "lldxhardware.h" #endif @@ -393,7 +395,7 @@ bool idle_startup() gSavedSettings.setS32("LastGPUClass", LLFeatureManager::getInstance()->getGPUClass()); // load dynamic GPU/feature tables from website (S3) - LLFeatureManager::getInstance()->fetchHTTPTables(); + //LLFeatureManager::getInstance()->fetchHTTPTables(); std::string xml_file = LLUI::locateSkin("xui_version.xml"); LLXMLNodePtr root; @@ -595,6 +597,15 @@ bool idle_startup() LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL; + //------------------------------------------------- + // Init the socks 5 proxy and open the control TCP + // connection if the user is using SOCKS5 + // We need to do this early incase the user is using + // socks for http so we get the login screen via socks + //------------------------------------------------- + + LLStartUp::handleSocksProxy(false); + //------------------------------------------------- // Init audio, which may be needed for prefs dialog // or audio cues in connection UI. @@ -809,6 +820,27 @@ bool idle_startup() if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState()) { + // Post login screen, we should see if any settings have changed that may + // require us to either start/stop or change the socks proxy. As various communications + // past this point may require the proxy to be up. + if ( gSavedSettings.getBOOL("Socks5ProxyEnabled") ) + { + if (!LLStartUp::handleSocksProxy(true)) + { + // Proxy start up failed, we should now bail the state machine + // HandleSocksProxy() will have reported an error to the user + // already, so we just go back to the login screen. The user + // could then change the preferences to fix the issue. + LLStartUp::setStartupState(STATE_LOGIN_SHOW); + return FALSE; + } + } + else + { + LLSocks::getInstance()->stopProxy(); + } + + //reset the values that could have come in from a slurl // DEV-42215: Make sure they're not empty -- gUserCredential // might already have been set from gSavedSettings, and it's too bad @@ -2746,6 +2778,95 @@ void LLStartUp::setStartSLURL(const LLSLURL& slurl) } } +bool LLStartUp::handleSocksProxy(bool reportOK) +{ + std::string httpProxyType = gSavedSettings.getString("Socks5HttpProxyType"); + + // Determine the http proxy type (if any) + if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled")) + { + LLHost httpHost; + httpHost.setHostByName(gSavedSettings.getString("BrowserProxyAddress")); + httpHost.setPort(gSavedSettings.getS32("BrowserProxyPort")); + LLSocks::getInstance()->EnableHttpProxy(httpHost,LLPROXY_HTTP); + } + else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled")) + { + LLHost httpHost; + httpHost.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); + httpHost.setPort(gSavedSettings.getU32("Socks5ProxyPort")); + LLSocks::getInstance()->EnableHttpProxy(httpHost,LLPROXY_SOCKS); + } + else + { + LLSocks::getInstance()->DisableHttpProxy(); + } + + bool use_socks_proxy = gSavedSettings.getBOOL("Socks5ProxyEnabled"); + if (use_socks_proxy) + { + + // Determine and update LLSocks with the saved authentication system + std::string auth_type = gSavedSettings.getString("Socks5AuthType"); + + if (auth_type.compare("None") == 0) + { + LLSocks::getInstance()->setAuthNone(); + } + + if (auth_type.compare("UserPass") == 0) + { + LLSocks::getInstance()->setAuthPassword(gSavedSettings.getString("Socks5Username"),gSavedSettings.getString("Socks5Password")); + } + + // Start the proxy and check for errors + int status = LLSocks::getInstance()->startProxy(gSavedSettings.getString("Socks5ProxyHost"), gSavedSettings.getU32("Socks5ProxyPort")); + LLSD subs; + LLSD payload; + subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost"); + subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort"); + + switch(status) + { + case SOCKS_OK: + return true; + break; + + case SOCKS_CONNECT_ERROR: // TCP Fail + LLNotifications::instance().add("SOCKS_CONNECT_ERROR", subs,payload); + break; + + case SOCKS_NOT_PERMITTED: // Socks5 server rule set refused connection + LLNotifications::instance().add("SOCKS_NOT_PERMITTED", subs,payload); + break; + + case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server + LLNotifications::instance().add("SOCKS_NOT_ACCEPTABLE", subs,payload); + break; + + case SOCKS_AUTH_FAIL: // Authentication failed + LLNotifications::instance().add("SOCKS_AUTH_FAIL", subs,payload); + break; + + case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed + LLNotifications::instance().add("SOCKS_UDP_FWD_NOT_GRANTED", subs,payload); + break; + + case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server + LLNotifications::instance().add("SOCKS_HOST_CONNECT_FAILED", subs,payload); + break; + } + + return false; + } + else + { + LLSocks::getInstance()->stopProxy(); //ensure no UDP proxy is running and its all cleaned up + } + + return true; +} + bool login_alert_done(const LLSD& notification, const LLSD& response) { LLPanelLogin::giveFocus(); diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index b3d9ef1dcc..a512ec7bff 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -113,6 +113,8 @@ public: static void setStartSLURL(const LLSLURL& slurl); static LLSLURL& getStartSLURL() { return sStartSLURL; } + static bool handleSocksProxy(bool reportOK); //handle kicking the socks 5 proxy code at startup time + private: static LLSLURL sStartSLURL; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index dca1e33e60..976dc76b50 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -202,6 +202,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("postcard", "floater_postcard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("perm_prefs", "floater_perm_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 257884d921..b3d899c61a 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -41,6 +41,8 @@ #include "llappviewer.h" #include "lltrans.h" +#include "llsocks5.h" + // Static instance of LLXMLRPCListener declared here so that every time we // bring in this code, we instantiate a listener. If we put the static // instance of LLXMLRPCListener into llxmlrpclistener.cpp, the linker would @@ -307,16 +309,23 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) } mErrorCert = NULL; - if (gSavedSettings.getBOOL("BrowserProxyEnabled")) + if (LLSocks::getInstance()->isHttpProxyEnabled()) { - mProxyAddress = gSavedSettings.getString("BrowserProxyAddress"); - S32 port = gSavedSettings.getS32 ( "BrowserProxyPort" ); - - // tell curl about the settings - mCurlRequest->setoptString(CURLOPT_PROXY, mProxyAddress); + std::string address = LLSocks::getInstance()->getHTTPProxy().getIPString(); + U16 port = LLSocks::getInstance()->getHTTPProxy().getPort(); + mCurlRequest->setoptString(CURLOPT_PROXY, address.c_str()); mCurlRequest->setopt(CURLOPT_PROXYPORT, port); + if (LLSocks::getInstance()->getHttpProxyType() == LLPROXY_SOCKS) + { + mCurlRequest->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + if(LLSocks::getInstance()->getSelectedAuthMethod()==METHOD_PASSWORD) + mCurlRequest->setoptString(CURLOPT_PROXYUSERPWD,LLSocks::getInstance()->getProxyUserPwd()); + } + else + { mCurlRequest->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); } + } // mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // usefull for debugging mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1); diff --git a/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml new file mode 100644 index 0000000000..bb9ade067b --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml @@ -0,0 +1,274 @@ + + + + + + Other Http traffic proxy: + + + + + + + + HTTP Proxy: + + + + + SOCKS 5 Proxy: + + + + + Authentication: + + + + width="120" /> + + width="120" /> + + + Username: + + + + Password: + + + -- cgit v1.3 From 1213e5d3548a111a39b6556c6178fc4bc655d367 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Mon, 4 Apr 2011 14:40:32 -0600 Subject: fix a crash inherited from viewer-development --- indra/llmessage/llavatarnamecache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 767001b633..f6a1aca71b 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -561,7 +561,7 @@ void LLAvatarNameCache::eraseUnrefreshed() const LLAvatarName& av_name = cur->second; if (av_name.mExpires < max_unrefreshed) { - const LLUUID& agent_id = it->first; + const LLUUID& agent_id = cur->first; LL_DEBUGS("AvNameCache") << agent_id << " user '" << av_name.mUsername << "' " << "expired " << now - av_name.mExpires << " secs ago" -- cgit v1.3 From 9bfae21706288802f94d642eb252ac78b4d9e85c Mon Sep 17 00:00:00 2001 From: Dave SIMmONs Date: Mon, 2 May 2011 16:35:55 -0700 Subject: ER-858: Add viewer checkbox to toggle parcel privacy settings. Reviewed by Kelly --- indra/llinventory/llparcel.cpp | 10 +++++++++- indra/llinventory/llparcel.h | 12 +++++++++++- indra/llmessage/message_prehash.cpp | 1 + indra/llmessage/message_prehash.h | 1 + indra/newview/llfloaterland.cpp | 13 +++++++++++++ indra/newview/llfloaterland.h | 1 + .../newview/skins/default/xui/en/floater_about_land.xml | 17 +++++++++++++++-- 7 files changed, 51 insertions(+), 4 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index 0a4cd51ea0..7562bb8320 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -702,7 +702,7 @@ void LLParcel::packMessage(LLSD& msg) msg["user_location"] = ll_sd_from_vector3(mUserLocation); msg["user_look_at"] = ll_sd_from_vector3(mUserLookAt); msg["landing_type"] = (U8)mLandingType; - + msg["privacy"] = (LLSD::Boolean) getPrivacy(); } @@ -721,6 +721,14 @@ void LLParcel::unpackMessage(LLMessageSystem* msg) msg->getStringFast( _PREHASH_ParcelData,_PREHASH_MediaURL, buffer ); setMediaURL(buffer); + BOOL private_parcel = FALSE; + bool have_privacy_data = (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_Privacy) > 0); + if (have_privacy_data) + { + msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_Privacy, private_parcel); + } + setPrivacy((bool) private_parcel); + // non-optimized version msg->getU8 ( "ParcelData", "MediaAutoScale", mMediaAutoScale ); diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index 71b65d99ce..4d2236ec66 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -75,7 +75,7 @@ const U8 PARCEL_AUCTION = 0x05; // unused 0x06 // unused 0x07 // flag, unused 0x08 -// flag, unused 0x10 +const U8 PARCEL_PRIVATE = 0x10; const U8 PARCEL_SOUND_LOCAL = 0x20; const U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge const U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge @@ -130,6 +130,12 @@ class LLSD; class LLAccessEntry { public: + LLAccessEntry() + : mID(), + mTime(0), + mFlags(0) + {} + LLUUID mID; // Agent ID S32 mTime; // Time (unix seconds) when entry expires U32 mFlags; // Not used - currently should always be zero @@ -265,6 +271,7 @@ public: void setUserLocation(const LLVector3& pos) { mUserLocation = pos; } void setUserLookAt(const LLVector3& rot) { mUserLookAt = rot; } void setLandingType(const ELandingType type) { mLandingType = type; } + void setPrivacy(bool privacy) { mPrivacy = privacy; } void setAuctionID(U32 auction_id) { mAuctionID = auction_id;} @@ -367,6 +374,8 @@ public: const LLVector3& getUserLocation() const { return mUserLocation; } const LLVector3& getUserLookAt() const { return mUserLookAt; } ELandingType getLandingType() const { return mLandingType; } + bool getPrivacy() const { return mPrivacy; } + // User-specified snapshot const LLUUID& getSnapshotID() const { return mSnapshotID; } @@ -602,6 +611,7 @@ protected: LLVector3 mUserLocation; LLVector3 mUserLookAt; ELandingType mLandingType; + bool mPrivacy; LLTimer mSaleTimerExpires; LLTimer mMediaResetTimer; diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 5d03615e53..020ece5414 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -1375,3 +1375,4 @@ char const* const _PREHASH_VCoord = LLMessageStringTable::getInstance()->getStri char const* const _PREHASH_FaceIndex = LLMessageStringTable::getInstance()->getString("FaceIndex"); char const* const _PREHASH_StatusData = LLMessageStringTable::getInstance()->getString("StatusData"); char const* const _PREHASH_ProductSKU = LLMessageStringTable::getInstance()->getString("ProductSKU"); +char const* const _PREHASH_Privacy = LLMessageStringTable::getInstance()->getString("Privacy"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 8dc86601e6..32bf882d90 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -1375,4 +1375,5 @@ extern char const* const _PREHASH_VCoord; extern char const* const _PREHASH_FaceIndex; extern char const* const _PREHASH_StatusData; extern char const* const _PREHASH_ProductSKU; +extern char const* const _PREHASH_Privacy; #endif diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 7be4ebc690..1ebcae4e5c 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1817,6 +1817,7 @@ LLPanelLandOptions::LLPanelLandOptions(LLParcelSelectionHandle& parcel) mClearBtn(NULL), mMatureCtrl(NULL), mPushRestrictionCtrl(NULL), + mPrivateParcelCtrl(NULL), mParcel(parcel) { } @@ -1859,6 +1860,9 @@ BOOL LLPanelLandOptions::postBuild() mPushRestrictionCtrl = getChild( "PushRestrictCheck"); childSetCommitCallback("PushRestrictCheck", onCommitAny, this); + mPrivateParcelCtrl = getChild( "PrivateParcelCheck"); + childSetCommitCallback("PrivateParcelCheck", onCommitAny, this); + mCheckShowDirectory = getChild( "ShowDirectoryCheck"); childSetCommitCallback("ShowDirectoryCheck", onCommitAny, this); @@ -1967,6 +1971,9 @@ void LLPanelLandOptions::refresh() mPushRestrictionCtrl->set(FALSE); mPushRestrictionCtrl->setEnabled(FALSE); + mPrivateParcelCtrl->set(FALSE); + mPrivateParcelCtrl->setEnabled(FALSE); + mLandingTypeCombo->setCurrentByIndex(0); mLandingTypeCombo->setEnabled(FALSE); @@ -2026,6 +2033,10 @@ void LLPanelLandOptions::refresh() mPushRestrictionCtrl->setEnabled(can_change_options); } + mPrivateParcelCtrl->set(parcel->getPrivacy()); + mPrivateParcelCtrl->setLabel(getString("private_parcel_text")); + mPrivateParcelCtrl->setEnabled(can_change_options); + BOOL can_change_landing_point = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_SET_LANDING_POINT); mLandingTypeCombo->setCurrentByIndex((S32)parcel->getLandingType()); @@ -2230,6 +2241,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) BOOL allow_publish = FALSE; BOOL mature_publish = self->mMatureCtrl->get(); BOOL push_restriction = self->mPushRestrictionCtrl->get(); + BOOL private_parcel = self->mPrivateParcelCtrl->get(); BOOL show_directory = self->mCheckShowDirectory->get(); // we have to get the index from a lookup, not from the position in the dropdown! S32 category_index = LLParcel::getCategoryFromString(self->mCategoryCombo->getSelectedValue()); @@ -2263,6 +2275,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) parcel->setCategory((LLParcel::ECategory)category_index); parcel->setLandingType((LLParcel::ELandingType)landing_type_index); parcel->setSnapshotID(snapshot_id); + parcel->setPrivacy(private_parcel); // Send current parcel data upstream to server LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index a096fb64cd..ff1fb62041 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -347,6 +347,7 @@ private: LLCheckBoxCtrl *mMatureCtrl; LLCheckBoxCtrl *mPushRestrictionCtrl; + LLCheckBoxCtrl *mPrivateParcelCtrl; LLSafeHandle& mParcel; }; diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index 6e985e0476..d2567e8197 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1204,6 +1204,10 @@ Only large parcels can be listed in search. name="push_restrict_region_text"> No Pushing (Region Override) + + Private Parcel + + width="280" /> + width="280" /> + Date: Thu, 9 Jun 2011 13:46:19 -0700 Subject: ER-910: Parcel Privacy. Rename things in code to reflect feature name change to "hidden avatars" --- indra/llinventory/llparcel.cpp | 18 +++++++------- indra/llinventory/llparcel.h | 14 +++++------ indra/llinventory/llparcelflags.h | 2 +- indra/llmessage/message_prehash.cpp | 2 +- indra/llmessage/message_prehash.h | 2 +- indra/lscript/lscript_compile/indra.l | 2 +- indra/newview/app_settings/keywords.ini | 2 +- indra/newview/llfloaterland.cpp | 10 ++++---- indra/newview/lllocationinputctrl.cpp | 22 ++++++++--------- indra/newview/lllocationinputctrl.h | 4 ++-- indra/newview/llpanelplaceprofile.cpp | 26 ++++++++++----------- indra/newview/llpanelplaceprofile.h | 4 ++-- indra/newview/llpaneltopinfobar.cpp | 14 +++++------ indra/newview/llpaneltopinfobar.h | 2 +- .../textures/icons/Parcel_HiddenAVsOff_Dark.png | Bin 0 -> 730 bytes .../textures/icons/Parcel_HiddenAVsOn_Dark.png | Bin 0 -> 814 bytes .../textures/icons/Parcel_PrivacyOff_Dark.png | Bin 730 -> 0 bytes .../textures/icons/Parcel_PrivacyOn_Dark.png | Bin 814 -> 0 bytes indra/newview/skins/default/textures/textures.xml | 4 ++-- .../skins/default/xui/en/floater_about_land.xml | 4 ++-- .../newview/skins/default/xui/en/notifications.xml | 8 +++---- .../skins/default/xui/en/panel_place_profile.xml | 20 ++++++++-------- .../skins/default/xui/en/panel_topinfo_bar.xml | 4 ++-- indra/newview/skins/default/xui/en/strings.xml | 10 ++++---- .../default/xui/en/widgets/location_input.xml | 6 ++--- .../minimal/xui/en/widgets/location_input.xml | 4 ++-- 26 files changed, 91 insertions(+), 93 deletions(-) create mode 100644 indra/newview/skins/default/textures/icons/Parcel_HiddenAVsOff_Dark.png create mode 100644 indra/newview/skins/default/textures/icons/Parcel_HiddenAVsOn_Dark.png delete mode 100644 indra/newview/skins/default/textures/icons/Parcel_PrivacyOff_Dark.png delete mode 100644 indra/newview/skins/default/textures/icons/Parcel_PrivacyOn_Dark.png (limited to 'indra/llmessage') diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index c79d410ade..b388d34580 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -227,8 +227,8 @@ void LLParcel::init(const LLUUID &owner_id, setPreviousOwnerID(LLUUID::null); setPreviouslyGroupOwned(FALSE); - setPrivacy(false); - setHavePrivacyData(false); + setHiddenAVs(false); + setHaveHiddenAVsData(false); } void LLParcel::overrideOwner(const LLUUID& owner_id, BOOL is_group_owned) @@ -705,7 +705,7 @@ void LLParcel::packMessage(LLSD& msg) msg["user_location"] = ll_sd_from_vector3(mUserLocation); msg["user_look_at"] = ll_sd_from_vector3(mUserLookAt); msg["landing_type"] = (U8)mLandingType; - msg["privacy"] = (LLSD::Boolean) getPrivacy(); + msg["hidden_avs"] = (LLSD::Boolean) getHiddenAVs(); } @@ -724,14 +724,14 @@ void LLParcel::unpackMessage(LLMessageSystem* msg) msg->getStringFast( _PREHASH_ParcelData,_PREHASH_MediaURL, buffer ); setMediaURL(buffer); - BOOL private_parcel = FALSE; - bool have_privacy_data = (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_Privacy) > 0); - if (have_privacy_data) + BOOL hidden_avs = FALSE; + bool have_hidden_av_data = (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_HiddenAVs) > 0); + if (have_hidden_av_data) { - msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_Privacy, private_parcel); + msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_HiddenAVs, hidden_avs); } - setPrivacy((bool) private_parcel); - setHavePrivacyData(have_privacy_data); + setHiddenAVs((bool) hidden_avs); + setHaveHiddenAVsData(have_hidden_av_data); // non-optimized version msg->getU8 ( "ParcelData", "MediaAutoScale", mMediaAutoScale ); diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index edf1e9d4fd..e785dba91b 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -75,7 +75,7 @@ const U8 PARCEL_AUCTION = 0x05; // unused 0x06 // unused 0x07 // flag, unused 0x08 -const U8 PARCEL_PRIVATE = 0x10; +const U8 PARCEL_HIDDENAVS = 0x10; // avatars not visible outside of parcel const U8 PARCEL_SOUND_LOCAL = 0x20; const U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge const U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge @@ -271,8 +271,8 @@ public: void setUserLocation(const LLVector3& pos) { mUserLocation = pos; } void setUserLookAt(const LLVector3& rot) { mUserLookAt = rot; } void setLandingType(const ELandingType type) { mLandingType = type; } - void setPrivacy(bool privacy) { mPrivacy = privacy; } - void setHavePrivacyData(bool have_privacy_data) { mHavePrivacyData = have_privacy_data; } // Remove this once parcel privacy is fully available grid-wide + void setHiddenAVs(bool hidden_avs) { mHiddenAVs = hidden_avs; } + void setHaveHiddenAVsData(bool have_hidden_av_data) { mHaveHiddenAVData = have_hidden_av_data; } // Remove this once hidden AV feature is fully available grid-wide void setAuctionID(U32 auction_id) { mAuctionID = auction_id;} @@ -375,8 +375,8 @@ public: const LLVector3& getUserLocation() const { return mUserLocation; } const LLVector3& getUserLookAt() const { return mUserLookAt; } ELandingType getLandingType() const { return mLandingType; } - bool getPrivacy() const { return mPrivacy; } - bool getHavePrivacyData() const { return mHavePrivacyData; } + bool getHiddenAVs() const { return mHiddenAVs; } + bool getHaveHiddenAVsData() const { return mHaveHiddenAVData; } // User-specified snapshot const LLUUID& getSnapshotID() const { return mSnapshotID; } @@ -616,8 +616,8 @@ protected: LLVector3 mUserLocation; LLVector3 mUserLookAt; ELandingType mLandingType; - bool mPrivacy; - bool mHavePrivacyData; // Remove once parcel privacy is grid-wide + bool mHiddenAVs; // Avatars are hidden on this parcel from outside it + bool mHaveHiddenAVData; // Remove once hidden AV feature is grid-wide LLTimer mSaleTimerExpires; LLTimer mMediaResetTimer; diff --git a/indra/llinventory/llparcelflags.h b/indra/llinventory/llparcelflags.h index a3d131c7a2..a85a6a51b3 100644 --- a/indra/llinventory/llparcelflags.h +++ b/indra/llinventory/llparcelflags.h @@ -127,6 +127,6 @@ const S32 PARCEL_DETAILS_OWNER = 2; const S32 PARCEL_DETAILS_GROUP = 3; const S32 PARCEL_DETAILS_AREA = 4; const S32 PARCEL_DETAILS_ID = 5; -const S32 PARCEL_DETAILS_PRIVACY = 6; +const S32 PARCEL_DETAILS_HIDDEN_AVS = 6; #endif diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 020ece5414..1248436f16 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -1375,4 +1375,4 @@ char const* const _PREHASH_VCoord = LLMessageStringTable::getInstance()->getStri char const* const _PREHASH_FaceIndex = LLMessageStringTable::getInstance()->getString("FaceIndex"); char const* const _PREHASH_StatusData = LLMessageStringTable::getInstance()->getString("StatusData"); char const* const _PREHASH_ProductSKU = LLMessageStringTable::getInstance()->getString("ProductSKU"); -char const* const _PREHASH_Privacy = LLMessageStringTable::getInstance()->getString("Privacy"); +char const* const _PREHASH_HiddenAVs = LLMessageStringTable::getInstance()->getString("HiddenAVs"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 32bf882d90..f871caa3df 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -1375,5 +1375,5 @@ extern char const* const _PREHASH_VCoord; extern char const* const _PREHASH_FaceIndex; extern char const* const _PREHASH_StatusData; extern char const* const _PREHASH_ProductSKU; -extern char const* const _PREHASH_Privacy; +extern char const* const _PREHASH_HiddenAVs; #endif diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l index ee31510efb..78e31ead1a 100644 --- a/indra/lscript/lscript_compile/indra.l +++ b/indra/lscript/lscript_compile/indra.l @@ -604,7 +604,7 @@ extern "C" { int yyerror(const char *fmt, ...); } "PARCEL_DETAILS_GROUP" { count(); yylval.ival = PARCEL_DETAILS_GROUP; return(INTEGER_CONSTANT); } "PARCEL_DETAILS_AREA" { count(); yylval.ival = PARCEL_DETAILS_AREA; return(INTEGER_CONSTANT); } "PARCEL_DETAILS_ID" { count(); yylval.ival = PARCEL_DETAILS_ID; return(INTEGER_CONSTANT); } -"PARCEL_DETAILS_PRIVACY" { count(); yylval.ival = PARCEL_DETAILS_PRIVACY; return(INTEGER_CONSTANT); } +"PARCEL_DETAILS_HIDDEN_AVS" { count(); yylval.ival = PARCEL_DETAILS_HIDDEN_AVS; return(INTEGER_CONSTANT); } "STRING_TRIM_HEAD" { count(); yylval.ival = STRING_TRIM_HEAD; return(INTEGER_CONSTANT); } "STRING_TRIM_TAIL" { count(); yylval.ival = STRING_TRIM_TAIL; return(INTEGER_CONSTANT); } diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index 6426d5c2a8..4e8f90d901 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -498,7 +498,7 @@ PARCEL_DETAILS_OWNER Used with llGetParcelDetails to get the parcel owner id. PARCEL_DETAILS_GROUP Used with llGetParcelDetails to get the parcel group id. PARCEL_DETAILS_AREA Used with llGetParcelDetails to get the parcel area in square meters. PARCEL_DETAILS_ID Used with llGetParcelDetails to get the parcel id. -PARCEL_DETAILS_PRIVACY Used with llGetParcelDetails to get the parcel privacy setting. +PARCEL_DETAILS_HIDDEN_AVS Used with llGetParcelDetails to get the hidden avatars setting. STRING_TRIM_HEAD Used with llStringTrim to trim leading spaces from a string. STRING_TRIM_TAIL Used with llStringTrim to trim trailing spaces from a string. diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 8de93a385f..0300867363 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2034,9 +2034,9 @@ void LLPanelLandOptions::refresh() mPushRestrictionCtrl->setEnabled(can_change_options); } - mPrivateParcelCtrl->set(parcel->getPrivacy()); - mPrivateParcelCtrl->setLabel(getString("private_parcel_text")); - mPrivateParcelCtrl->setEnabled(can_change_options && parcel->getHavePrivacyData()); + mPrivateParcelCtrl->set(parcel->getHiddenAVs()); + mPrivateParcelCtrl->setLabel(getString("hidden_avs_text")); + mPrivateParcelCtrl->setEnabled(can_change_options && parcel->getHaveHiddenAVsData()); BOOL can_change_landing_point = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_SET_LANDING_POINT); @@ -2242,7 +2242,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) BOOL allow_publish = FALSE; BOOL mature_publish = self->mMatureCtrl->get(); BOOL push_restriction = self->mPushRestrictionCtrl->get(); - BOOL private_parcel = self->mPrivateParcelCtrl->get(); + BOOL hidden_avs = self->mPrivateParcelCtrl->get(); BOOL show_directory = self->mCheckShowDirectory->get(); // we have to get the index from a lookup, not from the position in the dropdown! S32 category_index = LLParcel::getCategoryFromString(self->mCategoryCombo->getSelectedValue()); @@ -2276,7 +2276,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) parcel->setCategory((LLParcel::ECategory)category_index); parcel->setLandingType((LLParcel::ELandingType)landing_type_index); parcel->setSnapshotID(snapshot_id); - parcel->setPrivacy(private_parcel); + parcel->setHiddenAVs(hidden_avs); // Send current parcel data upstream to server LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index c68d1bb845..7a988e95b9 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -190,7 +190,7 @@ LLLocationInputCtrl::Params::Params() scripts_icon("scripts_icon"), damage_icon("damage_icon"), damage_text("damage_text"), - privacy_icon("privacy_icon"), + hidden_av_icon("hidden_av_icon"), maturity_help_topic("maturity_help_topic") { } @@ -343,12 +343,12 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p) mDamageText = LLUICtrlFactory::create(damage_text); addChild(mDamageText); - LLIconCtrl::Params privacy_icon = p.privacy_icon; - privacy_icon.tool_tip = LLTrans::getString("LocationCtrlPrivacyTooltip"); - privacy_icon.mouse_opaque = true; - mParcelIcon[PRIVACY_ICON] = LLUICtrlFactory::create(privacy_icon); - mParcelIcon[PRIVACY_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, PRIVACY_ICON)); - addChild(mParcelIcon[PRIVACY_ICON]); + LLIconCtrl::Params hidden_av_icon = p.hidden_av_icon; + hidden_av_icon.tool_tip = LLTrans::getString("LocationCtrlHiddenAVsTooltip"); + hidden_av_icon.mouse_opaque = true; + mParcelIcon[HIDDEN_AV_ICON] = LLUICtrlFactory::create(hidden_av_icon); + mParcelIcon[HIDDEN_AV_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, HIDDEN_AV_ICON)); + addChild(mParcelIcon[HIDDEN_AV_ICON]); // Register callbacks and load the location field context menu (NB: the order matters). LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Navbar.Action", boost::bind(&LLLocationInputCtrl::onLocationContextMenuItemClicked, this, _2)); @@ -818,7 +818,7 @@ void LLLocationInputCtrl::refreshParcelIcons() bool allow_build = vpm->allowAgentBuild(current_parcel); // true when anyone is allowed to build. See EXT-4610. bool allow_scripts = vpm->allowAgentScripts(agent_region, current_parcel); bool allow_damage = vpm->allowAgentDamage(agent_region, current_parcel); - bool privacy = current_parcel->getPrivacy(); + bool hidden_avs = current_parcel->getHiddenAVs(); // Most icons are "block this ability" mParcelIcon[VOICE_ICON]->setVisible( !allow_voice ); @@ -828,7 +828,7 @@ void LLLocationInputCtrl::refreshParcelIcons() mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts ); mParcelIcon[DAMAGE_ICON]->setVisible( allow_damage ); mDamageText->setVisible(allow_damage); - mParcelIcon[PRIVACY_ICON]->setVisible( privacy ); + mParcelIcon[HIDDEN_AV_ICON]->setVisible( hidden_avs ); // Padding goes to left of both landmark star and for sale btn x -= mAddLandmarkHPad; @@ -1185,8 +1185,8 @@ void LLLocationInputCtrl::onParcelIconClick(EParcelIcon icon) case DAMAGE_ICON: LLNotificationsUtil::add("NotSafe"); break; - case PRIVACY_ICON: - LLNotificationsUtil::add("PrivateParcel"); + case HIDDEN_AV_ICON: + LLNotificationsUtil::add("HiddenAVs"); break; case ICON_COUNT: break; diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h index ee4e55e829..ead20efcb6 100644 --- a/indra/newview/lllocationinputctrl.h +++ b/indra/newview/lllocationinputctrl.h @@ -78,7 +78,7 @@ public: build_icon, scripts_icon, damage_icon, - privacy_icon; + hidden_av_icon; Optional damage_text; Params(); }; @@ -115,7 +115,7 @@ private: BUILD_ICON, // 3 SCRIPTS_ICON, // 4 DAMAGE_ICON, // 5 - PRIVACY_ICON, // 6 + HIDDEN_AV_ICON, // 6 ICON_COUNT // 7 total }; diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index da6a9fbbc6..1500ac5429 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -70,8 +70,8 @@ static std::string icon_scripts; static std::string icon_scripts_no; static std::string icon_damage; static std::string icon_damage_no; -static std::string icon_privacy_on; -static std::string icon_privacy_off; +static std::string icon_hidden_avs_on; +static std::string icon_hidden_avs_off; LLPanelPlaceProfile::LLPanelPlaceProfile() : LLPanelPlaceInfo(), @@ -116,8 +116,8 @@ BOOL LLPanelPlaceProfile::postBuild() mScriptsText = getChild("scripts_value"); mDamageIcon = getChild("damage_icon"); mDamageText = getChild("damage_value"); - mPrivacyIcon = getChild("privacy_icon"); - mPrivacyText = getChild("privacy_value"); + mHiddenAVsIcon = getChild("hidden_av_icon"); + mHiddenAVsText = getChild("hidden_av_value"); mRegionNameText = getChild("region_name"); mRegionTypeText = getChild("region_type"); @@ -157,8 +157,8 @@ BOOL LLPanelPlaceProfile::postBuild() icon_scripts_no = getString("icon_ScriptsNo"); icon_damage = getString("icon_Damage"); icon_damage_no = getString("icon_DamageNo"); - icon_privacy_on = getString("icon_PrivacyOn"); - icon_privacy_off = getString("icon_PrivacyOff"); + icon_hidden_avs_on = getString("icon_HiddenAVsOn"); + icon_hidden_avs_off = getString("icon_HiddenAVsOff"); return TRUE; } @@ -188,8 +188,8 @@ void LLPanelPlaceProfile::resetLocation() mScriptsText->setText(loading); mDamageIcon->setValue(loading); mDamageText->setText(loading); - mPrivacyIcon->setValue(loading); - mPrivacyText->setText(loading); + mHiddenAVsIcon->setValue(loading); + mHiddenAVsText->setText(loading); mRegionNameText->setValue(loading); mRegionTypeText->setValue(loading); @@ -422,15 +422,15 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, mDamageText->setText(off); } - if (parcel->getPrivacy()) + if (parcel->getHiddenAVs()) { - mPrivacyIcon->setValue(icon_privacy_on); - mPrivacyText->setText(on); + mHiddenAVsIcon->setValue(icon_hidden_avs_on); + mHiddenAVsText->setText(on); } else { - mPrivacyIcon->setValue(icon_privacy_off); - mPrivacyText->setText(off); + mHiddenAVsIcon->setValue(icon_hidden_avs_off); + mHiddenAVsText->setText(off); } mRegionNameText->setText(region->getName()); diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h index b20107dc4b..6550dae06b 100644 --- a/indra/newview/llpanelplaceprofile.h +++ b/indra/newview/llpanelplaceprofile.h @@ -91,8 +91,8 @@ private: LLTextBox* mScriptsText; LLIconCtrl* mDamageIcon; LLTextBox* mDamageText; - LLIconCtrl* mPrivacyIcon; - LLTextBox* mPrivacyText; + LLIconCtrl* mHiddenAVsIcon; + LLTextBox* mHiddenAVsText; LLTextBox* mRegionNameText; LLTextBox* mRegionTypeText; diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp index c2359b8b23..d1d7c3e4b9 100644 --- a/indra/newview/llpaneltopinfobar.cpp +++ b/indra/newview/llpaneltopinfobar.cpp @@ -102,7 +102,7 @@ void LLPanelTopInfoBar::initParcelIcons() mParcelIcon[BUILD_ICON] = getChild("build_icon"); mParcelIcon[SCRIPTS_ICON] = getChild("scripts_icon"); mParcelIcon[DAMAGE_ICON] = getChild("damage_icon"); - mParcelIcon[PRIVACY_ICON] = getChild("privacy_icon"); + mParcelIcon[HIDDEN_AV_ICON] = getChild("hidden_av_icon"); mParcelIcon[VOICE_ICON]->setToolTip(LLTrans::getString("LocationCtrlVoiceTooltip")); mParcelIcon[FLY_ICON]->setToolTip(LLTrans::getString("LocationCtrlFlyTooltip")); @@ -110,7 +110,7 @@ void LLPanelTopInfoBar::initParcelIcons() mParcelIcon[BUILD_ICON]->setToolTip(LLTrans::getString("LocationCtrlBuildTooltip")); mParcelIcon[SCRIPTS_ICON]->setToolTip(LLTrans::getString("LocationCtrlScriptsTooltip")); mParcelIcon[DAMAGE_ICON]->setToolTip(LLTrans::getString("LocationCtrlDamageTooltip")); - mParcelIcon[PRIVACY_ICON]->setToolTip(LLTrans::getString("LocationCtrlPrivacyTooltip")); + mParcelIcon[HIDDEN_AV_ICON]->setToolTip(LLTrans::getString("LocationCtrlHiddenAVsTooltip")); mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, VOICE_ICON)); mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, FLY_ICON)); @@ -118,7 +118,7 @@ void LLPanelTopInfoBar::initParcelIcons() mParcelIcon[BUILD_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, BUILD_ICON)); mParcelIcon[SCRIPTS_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, SCRIPTS_ICON)); mParcelIcon[DAMAGE_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, DAMAGE_ICON)); - mParcelIcon[PRIVACY_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, PRIVACY_ICON)); + mParcelIcon[HIDDEN_AV_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, HIDDEN_AV_ICON)); mDamageText->setText(LLStringExplicit("100%")); } @@ -298,7 +298,7 @@ void LLPanelTopInfoBar::updateParcelIcons() bool allow_build = vpm->allowAgentBuild(current_parcel); // true when anyone is allowed to build. See EXT-4610. bool allow_scripts = vpm->allowAgentScripts(agent_region, current_parcel); bool allow_damage = vpm->allowAgentDamage(agent_region, current_parcel); - bool privacy = current_parcel->getPrivacy(); + bool hidden_avs = current_parcel->getHiddenAVs(); // Most icons are "block this ability" mParcelIcon[VOICE_ICON]->setVisible( !allow_voice ); @@ -308,7 +308,7 @@ void LLPanelTopInfoBar::updateParcelIcons() mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts ); mParcelIcon[DAMAGE_ICON]->setVisible( allow_damage ); mDamageText->setVisible(allow_damage); - mParcelIcon[PRIVACY_ICON]->setVisible( privacy ); + mParcelIcon[HIDDEN_AV_ICON]->setVisible( hidden_avs ); layoutParcelIcons(); } @@ -414,8 +414,8 @@ void LLPanelTopInfoBar::onParcelIconClick(EParcelIcon icon) case DAMAGE_ICON: LLNotificationsUtil::add("NotSafe"); break; - case PRIVACY_ICON: - LLNotificationsUtil::add("PrivateParcel"); + case HIDDEN_AV_ICON: + LLNotificationsUtil::add("HiddenAVs"); break; case ICON_COUNT: break; diff --git a/indra/newview/llpaneltopinfobar.h b/indra/newview/llpaneltopinfobar.h index f497ce9633..ffbd53fe29 100644 --- a/indra/newview/llpaneltopinfobar.h +++ b/indra/newview/llpaneltopinfobar.h @@ -70,7 +70,7 @@ private: BUILD_ICON, // 3 SCRIPTS_ICON, // 4 DAMAGE_ICON, // 5 - PRIVACY_ICON, // 6 + HIDDEN_AV_ICON, // 6 ICON_COUNT // 7 total }; diff --git a/indra/newview/skins/default/textures/icons/Parcel_HiddenAVsOff_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_HiddenAVsOff_Dark.png new file mode 100644 index 0000000000..8b3376e514 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Parcel_HiddenAVsOff_Dark.png differ diff --git a/indra/newview/skins/default/textures/icons/Parcel_HiddenAVsOn_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_HiddenAVsOn_Dark.png new file mode 100644 index 0000000000..4e474d7f5a Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Parcel_HiddenAVsOn_Dark.png differ diff --git a/indra/newview/skins/default/textures/icons/Parcel_PrivacyOff_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_PrivacyOff_Dark.png deleted file mode 100644 index 8b3376e514..0000000000 Binary files a/indra/newview/skins/default/textures/icons/Parcel_PrivacyOff_Dark.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/icons/Parcel_PrivacyOn_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_PrivacyOn_Dark.png deleted file mode 100644 index 4e474d7f5a..0000000000 Binary files a/indra/newview/skins/default/textures/icons/Parcel_PrivacyOn_Dark.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index cb20cf3740..e8fe3cd82f 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -369,8 +369,8 @@ with the same filename but different name - - + + diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index d2567e8197..4ad42ea5bf 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1205,8 +1205,8 @@ Only large parcels can be listed in search. No Pushing (Region Override) - Private Parcel + name="hidden_avs_text"> + Hidden Avatars -This is a private parcel. You can't see -others outside the parcel, and those -outside are not able to see you. +This parcel hides avatars from view from another parcel. You can't see others outside the parcel, and those outside are not able to see you. + value="Parcel_HiddenAVsOff_Dark" /> + value="Parcel_HiddenAVsOn_Dark" />