From 7b298b471ea010bd9c053e59986421c9e8b3fbf9 Mon Sep 17 00:00:00 2001 From: Nicky Date: Sat, 12 Nov 2011 19:48:45 +0100 Subject: [PATCH] FIRE-3877; Fix mediaplugin for Bigfoot cards (VWR-25909,VWR-25190, likely VWR-25113 too). --- indra/llplugin/llpluginprocessparent.cpp | 27 ++++++++++++++++++++---- indra/llplugin/llpluginprocessparent.h | 5 +++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 110fac0f23..d56bb7aa66 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -34,6 +34,8 @@ #include "llapr.h" +#include "llrand.h" // FIRE-3877; So we can choose a random port number + //virtual LLPluginProcessParentOwner::~LLPluginProcessParentOwner() { @@ -164,8 +166,13 @@ void LLPluginProcessParent::init(const std::string &launcher_filename, const std mPluginFile = plugin_filename; mPluginDir = plugin_dir; mCPUUsage = 0.0f; - mDebug = debug; + mDebug = debug; setState(STATE_INITIALIZED); + + // FIRE-3877; Port 0 = choose one for use as default. This was the standard behaviour of LLPluginProcessParent and the reasonable thing to do. + mPortToBind = 0; + mBindRetries = 0; + // } bool LLPluginProcessParent::accept() @@ -274,7 +281,6 @@ void LLPluginProcessParent::idle(void) case STATE_INITIALIZED: { - apr_status_t status = APR_SUCCESS; apr_sockaddr_t* addr = NULL; mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); @@ -286,7 +292,7 @@ void LLPluginProcessParent::idle(void) &addr, "127.0.0.1", APR_INET, - 0, // port 0 = ephemeral ("find me a port") + mPortToBind, // port 0 = ephemeral ("find me a port") 0, gAPRPoolp); @@ -324,7 +330,20 @@ void LLPluginProcessParent::idle(void) LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL; killSockets(); - errorState(); + + // FIRE-3877; Some drivers, eg bigfoot. Refuse to tell us which port is used when the socket is bound on port 0 (= choose a free port). + // If not out of retry attempts, choose a random port between 5500 - 60000 and try again. + if( mBindRetries > 10 ) //In theory we could have bad luck and randomly draft already used ports each try. In practice we already deal with a buggy driver anyway. So just fail instead hogging resources in a loop. + errorState(); + else + { + ++mBindRetries; + mPortToBind = ll_rand(55000)+5000; // Ports < 4096 are reserved for root (at least on BSD like systems), do never touch them. + setState( STATE_INITIALIZED ); + idle_again = true; // Just try a new loop to bind the socket + } + // + break; } } diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h index 26c6b0c402..8b9c830f79 100644 --- a/indra/llplugin/llpluginprocessparent.h +++ b/indra/llplugin/llpluginprocessparent.h @@ -189,6 +189,11 @@ private: LLMutex mIncomingQueueMutex; std::queue mIncomingQueue; + + // FIRE-3877; Bind to a fixed port. Some network drivers (Bigfoot) refuse to tell us to which port a socket is bound if 0 (= choose one) was used. + U32 mPortToBind; + U32 mBindRetries; + // }; #endif // LL_LLPLUGINPROCESSPARENT_H