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/llmessage/message_prehash.cpp | 1 + indra/llmessage/message_prehash.h | 1 + 2 files changed, 2 insertions(+) (limited to 'indra/llmessage') 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 -- cgit v1.2.3 From ce554304fbc21e8a52b236a56eea70287f002fdd Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 18 May 2011 11:46:55 -0600 Subject: fix for SH-1591: crash at LLVOCacheEntry::~LLVOCacheEntry() line 138 --- indra/llmessage/lldatapacker.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra/llmessage') diff --git a/indra/llmessage/lldatapacker.h b/indra/llmessage/lldatapacker.h index dd9c4eaa38..b0a638c16e 100644 --- a/indra/llmessage/lldatapacker.h +++ b/indra/llmessage/lldatapacker.h @@ -168,10 +168,15 @@ public: S32 getCurrentSize() const { return (S32)(mCurBufferp - mBufferp); } S32 getBufferSize() const { return mBufferSize; } + const U8* getBuffer() const { return mBufferp; } void reset() { mCurBufferp = mBufferp; mWriteEnabled = (mCurBufferp != NULL); } void freeBuffer() { delete [] mBufferp; mBufferp = mCurBufferp = NULL; mBufferSize = 0; mWriteEnabled = FALSE; } void assignBuffer(U8 *bufferp, S32 size) { + if(mBufferp && mBufferp != bufferp) + { + freeBuffer() ; + } mBufferp = bufferp; mCurBufferp = bufferp; mBufferSize = size; -- cgit v1.2.3 From 7e322d837f7958eba62844583e2db55f6c69268f Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 23 May 2011 22:16:38 -0400 Subject: CHOP-661: Add information to try to zero in on remaining failures. Make testrunner.py module interpret $INTEGRATION_TEST_VERBOSE environment variable, setting module global VERBOSE. Enable/disable debug() output based on that variable, defaulting to VERBOSE True. Add debug() output to freeport(), including reporting exceptions. Add debug() output to test_llsdmessage_peer.py, including normal BaseHTTPRequestHandler output: when VERBOSE is set, don't suppress log_request() or log_error() output. Add C++ verbose() function to query $INTEGRATION_TEST_VERBOSE, broken out as two functions so we only have to interpret the value once. Default to 'true'. Move C++ commtest_data::getport(variable) function to global namespace, broken out as two functions to cache the value. Report value received when verbose() returns true. --- indra/llmessage/tests/commtest.h | 64 +++++++++++++-- indra/llmessage/tests/test_llsdmessage_peer.py | 32 +++++--- indra/llmessage/tests/testrunner.py | 103 ++++++++++++++----------- 3 files changed, 136 insertions(+), 63 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h index 0fef596df2..0d149b5258 100644 --- a/indra/llmessage/tests/commtest.h +++ b/indra/llmessage/tests/commtest.h @@ -34,6 +34,7 @@ #include "llsd.h" #include "llhost.h" #include "stringize.h" +#include #include #include #include @@ -43,6 +44,58 @@ struct CommtestError: public std::runtime_error CommtestError(const std::string& what): std::runtime_error(what) {} }; +static bool query_verbose() +{ + const char* cbose = getenv("INTEGRATION_TEST_VERBOSE"); + if (! cbose) + { + cbose = "1"; + } + std::string strbose(cbose); + return (! (strbose == "0" || strbose == "off" || + strbose == "false" || strbose == "quiet")); +} + +bool verbose() +{ + // This should only be initialized once. + static bool vflag = query_verbose(); + return vflag; +} + +static int query_port(const std::string& var) +{ + const char* cport = getenv(var.c_str()); + if (! cport) + { + throw CommtestError(STRINGIZE("missing environment variable" << var)); + } + // This will throw, too, if the value of PORT isn't numeric. + int port(boost::lexical_cast(cport)); + if (verbose()) + { + std::cout << "getport('" << var << "') = " << port << std::endl; + } + return port; +} + +static int getport(const std::string& var) +{ + typedef std::map portsmap; + static portsmap ports; + // We can do this with a single map lookup with map::insert(). Either it + // returns an existing entry and 'false' (not newly inserted), or it + // inserts the specified value and 'true'. + std::pair inserted(ports.insert(portsmap::value_type(var, 0))); + if (inserted.second) + { + // We haven't yet seen this var. Remember its value. + inserted.first->second = query_port(var); + } + // Return the (existing or new) iterator's value. + return inserted.first->second; +} + /** * This struct is shared by a couple of standalone comm tests (ADD_COMM_BUILD_TEST). */ @@ -71,13 +124,10 @@ struct commtest_data static int getport(const std::string& var) { - const char* port = getenv(var.c_str()); - if (! port) - { - throw CommtestError("missing $PORT environment variable"); - } - // This will throw, too, if the value of PORT isn't numeric. - return boost::lexical_cast(port); + // We have a couple consumers of commtest_data::getport(). But we've + // since moved it out to the global namespace. So this is just a + // facade. + return ::getport(var); } bool outcome(const LLSD& _result, bool _success) diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py index cea5032111..9886d49ccc 100644 --- a/indra/llmessage/tests/test_llsdmessage_peer.py +++ b/indra/llmessage/tests/test_llsdmessage_peer.py @@ -38,7 +38,7 @@ mydir = os.path.dirname(__file__) # expected to be .../indra/llmessage/tes sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) from indra.util.fastest_elementtree import parse as xml_parse from indra.base import llsd -from testrunner import freeport, run, debug +from testrunner import freeport, run, debug, VERBOSE class TestHTTPRequestHandler(BaseHTTPRequestHandler): """This subclass of BaseHTTPRequestHandler is to receive and echo @@ -72,10 +72,10 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler): ## # assuming that the underlying XML parser reads its input file ## # incrementally. Unfortunately I haven't been able to make it work. ## tree = xml_parse(self.rfile) -## debug("Finished raw parse\n") -## debug("parsed XML tree %s\n" % tree) -## debug("parsed root node %s\n" % tree.getroot()) -## debug("root node tag %s\n" % tree.getroot().tag) +## debug("Finished raw parse") +## debug("parsed XML tree %s", tree) +## debug("parsed root node %s", tree.getroot()) +## debug("root node tag %s", tree.getroot().tag) ## return llsd.to_python(tree.getroot()) def do_GET(self): @@ -88,8 +88,10 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler): self.answer(self.read_xml()) def answer(self, data): + debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path) if "fail" not in self.path: response = llsd.format_xml(data.get("reply", llsd.LLSD("success"))) + debug("success: %s", response) self.send_response(200) self.send_header("Content-type", "application/llsd+xml") self.send_header("Content-Length", str(len(response))) @@ -106,16 +108,21 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler): ("fail requested", "Your request specified failure status %s " "without providing a reason" % status))[1]) + debug("fail requested: %s: %r", status, reason) self.send_error(status, reason) - def log_request(self, code, size=None): - # For present purposes, we don't want the request splattered onto - # stderr, as it would upset devs watching the test run - pass + if not VERBOSE: + # When VERBOSE is set, skip both these overrides because they exist to + # suppress output. - def log_error(self, format, *args): - # Suppress error output as well - pass + def log_request(self, code, size=None): + # For present purposes, we don't want the request splattered onto + # stderr, as it would upset devs watching the test run + pass + + def log_error(self, format, *args): + # Suppress error output as well + pass if __name__ == "__main__": # Instantiate an HTTPServer(TestHTTPRequestHandler) on the first free port @@ -130,4 +137,5 @@ if __name__ == "__main__": # command-line parsing -- and anyway, for C++ integration tests, that's # performed in TUT code rather than our own. os.environ["PORT"] = str(port) + debug("$PORT = %s", port) sys.exit(run(server=Thread(name="httpd", target=httpd.serve_forever), *sys.argv[1:])) diff --git a/indra/llmessage/tests/testrunner.py b/indra/llmessage/tests/testrunner.py index 8ff13e0426..f329ec2a0e 100644 --- a/indra/llmessage/tests/testrunner.py +++ b/indra/llmessage/tests/testrunner.py @@ -29,14 +29,21 @@ $/LicenseInfo$ import os import sys +import re import errno import socket -def debug(*args): - sys.stdout.writelines(args) - sys.stdout.flush() -# comment out the line below to enable debug output -debug = lambda *args: None +VERBOSE = os.environ.get("INTEGRATION_TEST_VERBOSE", "1") # default to verbose +# Support usage such as INTEGRATION_TEST_VERBOSE=off -- distressing to user if +# that construct actually turns on verbosity... +VERBOSE = not re.match(r"(0|off|false|quiet)$", VERBOSE, re.IGNORECASE) + +if VERBOSE: + def debug(fmt, *args): + print fmt % args + sys.stdout.flush() +else: + debug = lambda *args: None def freeport(portlist, expr): """ @@ -78,44 +85,53 @@ def freeport(portlist, expr): # pass 'port' to client code # call server.serve_forever() """ - # If portlist is completely empty, let StopIteration propagate: that's an - # error because we can't return meaningful values. We have no 'port', - # therefore no 'expr(port)'. - portiter = iter(portlist) - port = portiter.next() - - while True: - try: - # If this value of port works, return as promised. - return expr(port), port - - except socket.error, err: - # Anything other than 'Address already in use', propagate - if err.args[0] != errno.EADDRINUSE: - raise - - # Here we want the next port from portiter. But on StopIteration, - # we want to raise the original exception rather than - # StopIteration. So save the original exc_info(). - type, value, tb = sys.exc_info() + try: + # If portlist is completely empty, let StopIteration propagate: that's an + # error because we can't return meaningful values. We have no 'port', + # therefore no 'expr(port)'. + portiter = iter(portlist) + port = portiter.next() + + while True: try: + # If this value of port works, return as promised. + value = expr(port) + + except socket.error, err: + # Anything other than 'Address already in use', propagate + if err.args[0] != errno.EADDRINUSE: + raise + + # Here we want the next port from portiter. But on StopIteration, + # we want to raise the original exception rather than + # StopIteration. So save the original exc_info(). + type, value, tb = sys.exc_info() try: - port = portiter.next() - except StopIteration: - raise type, value, tb - finally: - # Clean up local traceback, see docs for sys.exc_info() - del tb - - # Recap of the control flow above: - # If expr(port) doesn't raise, return as promised. - # If expr(port) raises anything but EADDRINUSE, propagate that - # exception. - # If portiter.next() raises StopIteration -- that is, if the port - # value we just passed to expr(port) was the last available -- reraise - # the EADDRINUSE exception. - # If we've actually arrived at this point, portiter.next() delivered a - # new port value. Loop back to pass that to expr(port). + try: + port = portiter.next() + except StopIteration: + raise type, value, tb + finally: + # Clean up local traceback, see docs for sys.exc_info() + del tb + + else: + debug("freeport() returning %s on port %s", value, port) + return value, port + + # Recap of the control flow above: + # If expr(port) doesn't raise, return as promised. + # If expr(port) raises anything but EADDRINUSE, propagate that + # exception. + # If portiter.next() raises StopIteration -- that is, if the port + # value we just passed to expr(port) was the last available -- reraise + # the EADDRINUSE exception. + # If we've actually arrived at this point, portiter.next() delivered a + # new port value. Loop back to pass that to expr(port). + + except Exception, err: + debug("*** freeport() raising %s: %s", err.__class__.__name__, err) + raise def run(*args, **kwds): """All positional arguments collectively form a command line, executed as @@ -144,8 +160,7 @@ def run(*args, **kwds): # - [no p] don't use the PATH because we specifically want to invoke the # executable passed as our first arg, # - [no e] child should inherit this process's environment. - debug("Running %s...\n" % (" ".join(args))) - sys.stdout.flush() + debug("Running %s...", " ".join(args)) rc = os.spawnv(os.P_WAIT, args[0], args) - debug("%s returned %s\n" % (args[0], rc)) + debug("%s returned %s", args[0], rc) return rc -- cgit v1.2.3 From 31e850d04885bed2ac779c66bb6b7923a0a51d96 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Fri, 27 May 2011 11:50:39 -0700 Subject: transplant fix for SH-1467 viewer now uses simulatorfeatures to check whether to show UI elements for mesh or not --- indra/llmessage/message_prehash.cpp | 1 + indra/llmessage/message_prehash.h | 1 + 2 files changed, 2 insertions(+) (limited to 'indra/llmessage') diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 5d03615e53..6133f50637 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -742,6 +742,7 @@ char const* const _PREHASH_MoneyData = LLMessageStringTable::getInstance()->getS char const* const _PREHASH_ObjectDeselect = LLMessageStringTable::getInstance()->getString("ObjectDeselect"); char const* const _PREHASH_NewAssetID = LLMessageStringTable::getInstance()->getString("NewAssetID"); char const* const _PREHASH_ObjectAdd = LLMessageStringTable::getInstance()->getString("ObjectAdd"); +char const* const _PREHASH_SimulatorFeatures = LLMessageStringTable::getInstance()->getString("SimulatorFeatures"); char const* const _PREHASH_RayEndIsIntersection = LLMessageStringTable::getInstance()->getString("RayEndIsIntersection"); char const* const _PREHASH_CompleteAuction = LLMessageStringTable::getInstance()->getString("CompleteAuction"); char const* const _PREHASH_CircuitCode = LLMessageStringTable::getInstance()->getString("CircuitCode"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 8dc86601e6..f94ee1ed22 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -742,6 +742,7 @@ extern char const* const _PREHASH_MoneyData; extern char const* const _PREHASH_ObjectDeselect; extern char const* const _PREHASH_NewAssetID; extern char const* const _PREHASH_ObjectAdd; +extern char const* const _PREHASH_SimulatorFeatures; extern char const* const _PREHASH_RayEndIsIntersection; extern char const* const _PREHASH_CompleteAuction; extern char const* const _PREHASH_CircuitCode; -- cgit v1.2.3 From 50393788693578a2fe3a934faa04b382d75f1657 Mon Sep 17 00:00:00 2001 From: Dave SIMmONs 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/llmessage/message_prehash.cpp | 2 +- indra/llmessage/message_prehash.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llmessage') 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 -- cgit v1.2.3 From c0c0a2b9a5f41fc06619330a81c34955a39ddfe2 Mon Sep 17 00:00:00 2001 From: "simon@lindenlab.com" Date: Mon, 20 Jun 2011 09:28:10 -0700 Subject: ER-944: Add feature to control user sounds on a parcel. Added new checkboxes to the About Land / Sound tab. Reviewed by Kelly. --- indra/llmessage/message_prehash.cpp | 2 ++ indra/llmessage/message_prehash.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'indra/llmessage') diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 1248436f16..f7615b5ccb 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -1376,3 +1376,5 @@ char const* const _PREHASH_FaceIndex = LLMessageStringTable::getInstance()->getS char const* const _PREHASH_StatusData = LLMessageStringTable::getInstance()->getString("StatusData"); char const* const _PREHASH_ProductSKU = LLMessageStringTable::getInstance()->getString("ProductSKU"); char const* const _PREHASH_HiddenAVs = LLMessageStringTable::getInstance()->getString("HiddenAVs"); +char const* const _PREHASH_AnyAVSounds = LLMessageStringTable::getInstance()->getString("AnyAVSounds"); +char const* const _PREHASH_GroupAVSounds = LLMessageStringTable::getInstance()->getString("GroupAVSounds"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index f871caa3df..44c7440436 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -1376,4 +1376,6 @@ extern char const* const _PREHASH_FaceIndex; extern char const* const _PREHASH_StatusData; extern char const* const _PREHASH_ProductSKU; extern char const* const _PREHASH_HiddenAVs; +extern char const* const _PREHASH_AnyAVSounds; +extern char const* const _PREHASH_GroupAVSounds; #endif -- cgit v1.2.3 From aba4f7ddc89c9d28bdd4b02735134101f40634ed Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Mon, 20 Jun 2011 14:01:32 -0600 Subject: fix for SH-1870: can not upload book_collection_1.dae when include textures --- indra/llmessage/llcurl.cpp | 14 +++++++------- indra/llmessage/llcurl.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 7c8b7e3584..44330cf8ff 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -244,7 +244,7 @@ public: U32 report(CURLcode); void getTransferInfo(LLCurl::TransferInfo* info); - void prepRequest(const std::string& url, const std::vector& headers, ResponderPtr, bool post = false); + void prepRequest(const std::string& url, const std::vector& headers, ResponderPtr, S32 time_out = 0, bool post = false); const char* getErrorBuffer(); @@ -525,7 +525,7 @@ size_t curlHeaderCallback(void* data, size_t size, size_t nmemb, void* user_data void LLCurl::Easy::prepRequest(const std::string& url, const std::vector& headers, - ResponderPtr responder, bool post) + ResponderPtr responder, S32 time_out, bool post) { resetState(); @@ -558,7 +558,7 @@ void LLCurl::Easy::prepRequest(const std::string& url, //don't verify host name so urls with scrubbed host names will work (improves DNS performance) setopt(CURLOPT_SSL_VERIFYHOST, 0); - setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT); + setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT)); setoptString(CURLOPT_URL, url); @@ -855,14 +855,14 @@ bool LLCurlRequest::getByteRange(const std::string& url, bool LLCurlRequest::post(const std::string& url, const headers_t& headers, const LLSD& data, - LLCurl::ResponderPtr responder) + LLCurl::ResponderPtr responder, S32 time_out) { LLCurl::Easy* easy = allocEasy(); if (!easy) { return false; } - easy->prepRequest(url, headers, responder); + easy->prepRequest(url, headers, responder, time_out); LLSDSerialize::toXML(data, easy->getInput()); S32 bytes = easy->getInput().str().length(); @@ -882,14 +882,14 @@ bool LLCurlRequest::post(const std::string& url, bool LLCurlRequest::post(const std::string& url, const headers_t& headers, const std::string& data, - LLCurl::ResponderPtr responder) + LLCurl::ResponderPtr responder, S32 time_out) { LLCurl::Easy* easy = allocEasy(); if (!easy) { return false; } - easy->prepRequest(url, headers, responder); + easy->prepRequest(url, headers, responder, time_out); easy->getInput().write(data.data(), data.size()); S32 bytes = easy->getInput().str().length(); diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 4ce3fa1078..5833a27b84 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -201,8 +201,8 @@ public: void get(const std::string& url, LLCurl::ResponderPtr responder); bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder); - bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder); - bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder); + bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder, S32 time_out = 0); + bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder, S32 time_out = 0); S32 process(); S32 getQueued(); -- cgit v1.2.3 From c91d6962337e3394038d72b173431dceffb44317 Mon Sep 17 00:00:00 2001 From: Aaron Stone Date: Mon, 27 Jun 2011 12:49:45 -0700 Subject: STORM-1446 Portability fix when setting non-blocking socket options. --- indra/llmessage/lliosocket.cpp | 26 +++++++++++++++++++++----- indra/llmessage/lliosocket.h | 11 +++++++++-- 2 files changed, 30 insertions(+), 7 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index ca84fa8bb8..8c752fbe30 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -191,7 +191,7 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port) port = PORT_EPHEMERAL; } rv->mPort = port; - rv->setOptions(); + rv->setNonBlocking(); return rv; } @@ -206,7 +206,7 @@ LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool) } rv = ptr_t(new LLSocket(socket, pool)); rv->mPort = PORT_EPHEMERAL; - rv->setOptions(); + rv->setNonBlocking(); return rv; } @@ -227,10 +227,10 @@ bool LLSocket::blockingConnect(const LLHost& host) { return false; } - apr_socket_timeout_set(mSocket, 1000); + setBlocking(1000); ll_debug_socket("Blocking connect", mSocket); if(ll_apr_warn_status(apr_socket_connect(mSocket, sa))) return false; - setOptions(); + setNonBlocking(); return true; } @@ -258,11 +258,27 @@ LLSocket::~LLSocket() } } -void LLSocket::setOptions() +// See http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-13.html#ss13.4 +// for an explanation of how to get non-blocking sockets and timeouts with +// consistent behavior across platforms. + +void LLSocket::setBlocking(S32 timeout) +{ + LLMemType m1(LLMemType::MTYPE_IO_TCP); + // set up the socket options + ll_apr_warn_status(apr_socket_timeout_set(mSocket, timeout)); + ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_NONBLOCK, 0)); + ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE)); + ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE)); + +} + +void LLSocket::setNonBlocking() { LLMemType m1(LLMemType::MTYPE_IO_TCP); // set up the socket options ll_apr_warn_status(apr_socket_timeout_set(mSocket, 0)); + ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_NONBLOCK, 1)); ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE)); ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE)); diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h index 6806e5084a..e0f6c1e34d 100644 --- a/indra/llmessage/lliosocket.h +++ b/indra/llmessage/lliosocket.h @@ -153,9 +153,16 @@ protected: LLSocket(apr_socket_t* socket, apr_pool_t* pool); /** - * @brief Set default socket options. + * @brief Set default socket options, with SO_NONBLOCK = 0 and a timeout in us. + * @param timeout Number of microseconds to wait on this socket. Any + * negative number means block-forever. TIMEOUT OF 0 IS NON-PORTABLE. */ - void setOptions(); + void setBlocking(S32 timeout); + + /** + * @brief Set default socket options, with SO_NONBLOCK = 1 and timeout = 0. + */ + void setNonBlocking(); public: /** -- cgit v1.2.3 From 918238dd18f74ee2783d55dfb961e8f44b2f4b1b Mon Sep 17 00:00:00 2001 From: "simon@lindenlab.com" Date: Fri, 1 Jul 2011 14:06:08 -0700 Subject: ER-1016 - "Remove ability for anyone to edit terrain" and ER-910 "Parcel Privacy" changes. Many naming changes for the featureto be "See avatars" instead of "hidden avatars". Also removed the "anyone can edit terrain" checkbox and slammed the value to FALSE. --- indra/llmessage/message_prehash.cpp | 2 +- indra/llmessage/message_prehash.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index e33da51aee..e71fb96540 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -1376,6 +1376,6 @@ 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_HiddenAVs = LLMessageStringTable::getInstance()->getString("HiddenAVs"); +char const* const _PREHASH_SeeAVs = LLMessageStringTable::getInstance()->getString("SeeAVs"); char const* const _PREHASH_AnyAVSounds = LLMessageStringTable::getInstance()->getString("AnyAVSounds"); char const* const _PREHASH_GroupAVSounds = LLMessageStringTable::getInstance()->getString("GroupAVSounds"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index b706ef8866..dd2c2dbd64 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -1376,7 +1376,7 @@ 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_HiddenAVs; +extern char const* const _PREHASH_SeeAVs; extern char const* const _PREHASH_AnyAVSounds; extern char const* const _PREHASH_GroupAVSounds; #endif -- cgit v1.2.3 From 43616131dc5e27bb49b849ed597a98772c5bbb95 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 7 Jul 2011 22:21:59 -0400 Subject: CHOP-661: Fix HTTPServer usage to turn off allow_reuse_address. Turns out that BaseHTTPServer.HTTPServer turns on that flag by default, which causes freeport() to fail (on Windows only?), happily instantiating multiple servers on the same port. Change known instances, fix freeport() docstring to highlight the issue. Add freeport() unit tests to verify expected behavior. --- indra/llmessage/tests/test_llsdmessage_peer.py | 9 ++- indra/llmessage/tests/testrunner.py | 100 ++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 4 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py index 9886d49ccc..22edd9dad8 100644 --- a/indra/llmessage/tests/test_llsdmessage_peer.py +++ b/indra/llmessage/tests/test_llsdmessage_peer.py @@ -124,14 +124,19 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler): # Suppress error output as well pass +class Server(HTTPServer): + # This pernicious flag is on by default in HTTPServer. But proper + # operation of freeport() absolutely depends on it being off. + allow_reuse_address = False + if __name__ == "__main__": - # Instantiate an HTTPServer(TestHTTPRequestHandler) on the first free port + # Instantiate a Server(TestHTTPRequestHandler) on the first free port # in the specified port range. Doing this inline is better than in a # daemon thread: if it blows up here, we'll get a traceback. If it blew up # in some other thread, the traceback would get eaten and we'd run the # subject test program anyway. httpd, port = freeport(xrange(8000, 8020), - lambda port: HTTPServer(('127.0.0.1', port), TestHTTPRequestHandler)) + lambda port: Server(('127.0.0.1', port), TestHTTPRequestHandler)) # Pass the selected port number to the subject test program via the # environment. We don't want to impose requirements on the test program's # command-line parsing -- and anyway, for C++ integration tests, that's diff --git a/indra/llmessage/tests/testrunner.py b/indra/llmessage/tests/testrunner.py index f329ec2a0e..f2c841532a 100644 --- a/indra/llmessage/tests/testrunner.py +++ b/indra/llmessage/tests/testrunner.py @@ -27,6 +27,8 @@ Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA $/LicenseInfo$ """ +from __future__ import with_statement + import os import sys import re @@ -79,9 +81,14 @@ def freeport(portlist, expr): Example: + class Server(HTTPServer): + # If you use BaseHTTPServer.HTTPServer, turning off this flag is + # essential for proper operation of freeport()! + allow_reuse_address = False + # ... server, port = freeport(xrange(8000, 8010), - lambda port: HTTPServer(("localhost", port), - MyRequestHandler)) + lambda port: Server(("localhost", port), + MyRequestHandler)) # pass 'port' to client code # call server.serve_forever() """ @@ -164,3 +171,92 @@ def run(*args, **kwds): rc = os.spawnv(os.P_WAIT, args[0], args) debug("%s returned %s", args[0], rc) return rc + +# **************************************************************************** +# test code -- manual at this point, see SWAT-564 +# **************************************************************************** +def test_freeport(): + # ------------------------------- Helpers -------------------------------- + from contextlib import contextmanager + # helper Context Manager for expecting an exception + # with exc(SomeError): + # raise SomeError() + # raises AssertionError otherwise. + @contextmanager + def exc(exception_class, *args): + try: + yield + except exception_class, err: + for i, expected_arg in enumerate(args): + assert expected_arg == err.args[i], \ + "Raised %s, but args[%s] is %r instead of %r" % \ + (err.__class__.__name__, i, err.args[i], expected_arg) + print "Caught expected exception %s(%s)" % \ + (err.__class__.__name__, ', '.join(repr(arg) for arg in err.args)) + else: + assert False, "Failed to raise " + exception_class.__class__.__name__ + + # helper to raise specified exception + def raiser(exception): + raise exception + + # the usual + def assert_equals(a, b): + assert a == b, "%r != %r" % (a, b) + + # ------------------------ Sanity check the above ------------------------ + class SomeError(Exception): pass + # Without extra args, accept any err.args value + with exc(SomeError): + raiser(SomeError("abc")) + # With extra args, accept only the specified value + with exc(SomeError, "abc"): + raiser(SomeError("abc")) + with exc(AssertionError): + with exc(SomeError, "abc"): + raiser(SomeError("def")) + with exc(AssertionError): + with exc(socket.error, errno.EADDRINUSE): + raiser(socket.error(errno.ECONNREFUSED, 'Connection refused')) + + # ----------- freeport() without engaging socket functionality ----------- + # If portlist is empty, freeport() raises StopIteration. + with exc(StopIteration): + freeport([], None) + + assert_equals(freeport([17], str), ("17", 17)) + + # This is the magic exception that should prompt us to retry + inuse = socket.error(errno.EADDRINUSE, 'Address already in use') + # Get the iterator to our ports list so we can check later if we've used all + ports = iter(xrange(5)) + with exc(socket.error, errno.EADDRINUSE): + freeport(ports, lambda port: raiser(inuse)) + # did we entirely exhaust 'ports'? + with exc(StopIteration): + ports.next() + + ports = iter(xrange(2)) + # Any exception but EADDRINUSE should quit immediately + with exc(SomeError): + freeport(ports, lambda port: raiser(SomeError())) + assert_equals(ports.next(), 1) + + # ----------- freeport() with platform-dependent socket stuff ------------ + # This is what we should've had unit tests to begin with (see CHOP-661). + def newbind(port): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.bind(('127.0.0.1', port)) + return sock + + bound0, port0 = freeport(xrange(7777, 7780), newbind) + assert_equals(port0, 7777) + bound1, port1 = freeport(xrange(7777, 7780), newbind) + assert_equals(port1, 7778) + bound2, port2 = freeport(xrange(7777, 7780), newbind) + assert_equals(port2, 7779) + with exc(socket.error, errno.EADDRINUSE): + bound3, port3 = freeport(xrange(7777, 7780), newbind) + +if __name__ == "__main__": + test_freeport() -- cgit v1.2.3