Merge remote-tracking branch 'll/d476' into fs-vs2017-d476
commit
c7804dbf7e
|
|
@ -838,13 +838,37 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>350866eec6be17ffc265904b91dcfe6b</string>
|
||||
<string>e145f8ea99a21712434e0e868d1885dc</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60900/572290/dullahan-1.7.0.202005311125_81.3.10_gb223419_chromium-81.0.4044.138-darwin64-543086.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/62333/588183/dullahan-1.7.0.202006240858_81.3.10_gb223419_chromium-81.0.4044.138-darwin64-544091.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
</map>
|
||||
<key>windows</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>fdbbbfc377e28cba664f2b1c54ea6086</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/62331/588162/dullahan-1.7.0.202006241556_81.3.10_gb223419_chromium-81.0.4044.138-windows-544091.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
</map>
|
||||
<key>windows64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>d85a32d905b199534e8feafa34b28e39</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/62332/588168/dullahan-1.7.0.202006241556_81.3.10_gb223419_chromium-81.0.4044.138-windows64-544091.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
<key>linux64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
|
|
@ -857,33 +881,9 @@
|
|||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
</map>
|
||||
<key>windows</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>579253178199688a84e9c4f11d6dc3a5</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/dullahan-1.7.0.202007182328_81.3.10_gb223419_chromium-81.0.4044.138-windows-202002136.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
</map>
|
||||
<key>windows64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>8a00268cfd5fce2477420fe2ff2a56e5</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/dullahan-1.7.0.202007182328_81.3.10_gb223419_chromium-81.0.4044.138-windows64-202002125.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.7.0.202005311828_81.3.10_gb223419_chromium-81.0.4044.138</string>
|
||||
<string>1.7.0.202006240858_81.3.10_gb223419_chromium-81.0.4044.138</string>
|
||||
</map>
|
||||
<key>elfio</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -67,7 +67,10 @@ if (WINDOWS)
|
|||
# http://www.cmake.org/pipermail/cmake/2009-September/032143.html
|
||||
string(REPLACE "/Zm1000" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
# Without PreferredToolArchitecture=x64, as of 2020-06-26 the 32-bit
|
||||
# compiler on our TeamCity build hosts has started running out of virtual
|
||||
# memory for the precompiled header file.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /p:PreferredToolArchitecture=x64")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||
"${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Zo"
|
||||
|
|
|
|||
|
|
@ -232,6 +232,11 @@ public:
|
|||
};
|
||||
|
||||
/// thrown by checkStop()
|
||||
// It may sound ironic that Stop is derived from LLContinueError, but the
|
||||
// point is that LLContinueError is the category of exception that should
|
||||
// not immediately crash the viewer. Stop and its subclasses are to notify
|
||||
// coroutines that the viewer intends to shut down. The expected response
|
||||
// is to terminate the coroutine, rather than abort the viewer.
|
||||
struct Stop: public LLContinueError
|
||||
{
|
||||
Stop(const std::string& what): LLContinueError(what) {}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@
|
|||
# include <syslog.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/stat.h>
|
||||
#else
|
||||
# include <io.h>
|
||||
#endif // !LL_WINDOWS
|
||||
#include <vector>
|
||||
#include "string.h"
|
||||
|
|
@ -241,14 +243,11 @@ namespace {
|
|||
|
||||
static bool checkANSI(void)
|
||||
{
|
||||
#if LL_LINUX || LL_DARWIN
|
||||
// Check whether it's okay to use ANSI; if stderr is
|
||||
// a tty then we assume yes. Can be turned off with
|
||||
// the LL_NO_ANSI_COLOR env var.
|
||||
return (0 != isatty(2)) &&
|
||||
(NULL == getenv("LL_NO_ANSI_COLOR"));
|
||||
#endif // LL_LINUX
|
||||
return FALSE; // works in a cygwin shell... ;)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -116,12 +116,25 @@ void llcoro::suspend()
|
|||
void llcoro::suspendUntilTimeout(float seconds)
|
||||
{
|
||||
LLCoros::checkStop();
|
||||
// The fact that we accept non-integer seconds means we should probably
|
||||
// use granularity finer than one second. However, given the overhead of
|
||||
// the rest of our processing, it seems silly to use granularity finer
|
||||
// than a millisecond.
|
||||
LLCoros::TempStatus st(STRINGIZE("waiting for " << seconds << "s"));
|
||||
boost::this_fiber::sleep_for(std::chrono::milliseconds(long(seconds * 1000)));
|
||||
// We used to call boost::this_fiber::sleep_for(). But some coroutines
|
||||
// (e.g. LLExperienceCache::idleCoro()) sit in a suspendUntilTimeout()
|
||||
// loop, in which case a sleep_for() call risks sleeping through shutdown.
|
||||
// So instead, listen for "LLApp" state-changing events -- which
|
||||
// fortunately is handled for us by suspendUntilEventOnWithTimeout().
|
||||
// Wait for an event on a bogus LLEventPump on which nobody ever posts
|
||||
// events. Don't make it static because that would force instantiation of
|
||||
// the LLEventPumps LLSingleton registry at static initialization time.
|
||||
// DO allow tweaking the name for uniqueness, this definitely gets
|
||||
// re-entered on multiple coroutines!
|
||||
// We could use an LLUUID if it were important to actively prohibit anyone
|
||||
// from ever posting on this LLEventPump.
|
||||
LLEventStream bogus("xyzzy", true);
|
||||
// Timeout is the NORMAL case for this call!
|
||||
static LLSD timedout;
|
||||
// Deliver, but ignore, timedout when (as usual) we did not receive any
|
||||
// "LLApp" event. The point is that suspendUntilEventOnWithTimeout() will
|
||||
// itself throw Stopping when "LLApp" starts broadcasting shutdown events.
|
||||
suspendUntilEventOnWithTimeout(bogus, seconds, timedout);
|
||||
}
|
||||
|
||||
namespace
|
||||
|
|
@ -276,6 +289,10 @@ LLSD llcoro::postAndSuspendWithTimeout(const LLSD& event,
|
|||
{
|
||||
LLCoros::TempStatus st(STRINGIZE("waiting for " << replyPump.getPump().getName()
|
||||
<< " for " << timeout << "s"));
|
||||
// The fact that we accept non-integer seconds means we should probably
|
||||
// use granularity finer than one second. However, given the overhead of
|
||||
// the rest of our processing, it seems silly to use granularity finer
|
||||
// than a millisecond.
|
||||
status = future.wait_for(std::chrono::milliseconds(long(timeout * 1000)));
|
||||
}
|
||||
// if the future is NOT yet ready, return timeoutResult instead
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@
|
|||
//=========================================================================
|
||||
namespace
|
||||
{
|
||||
LLTrace::BlockTimerStatHandle FTM_BLEND_WATERVALUES("Blending Water Environment");
|
||||
LLTrace::BlockTimerStatHandle FTM_UPDATE_WATERVALUES("Update Water Environment");
|
||||
LLTrace::BlockTimerStatHandle FTM_BLEND_WATERVALUES("Blending Water Environment Day");
|
||||
LLTrace::BlockTimerStatHandle FTM_UPDATE_WATERVALUES("Update Water Environment Day");
|
||||
|
||||
template<typename T>
|
||||
inline T get_wrapping_distance(T begin, T end)
|
||||
|
|
|
|||
|
|
@ -622,68 +622,76 @@ void LLAppViewerWin32::disableWinErrorReporting()
|
|||
}
|
||||
|
||||
const S32 MAX_CONSOLE_LINES = 500;
|
||||
// Only defined in newer SDKs than we currently use
|
||||
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 4
|
||||
#endif
|
||||
|
||||
static bool create_console()
|
||||
namespace {
|
||||
|
||||
void set_stream(const char* desc, FILE* fp, DWORD handle_id, const char* name, const char* mode="w");
|
||||
|
||||
bool create_console()
|
||||
{
|
||||
int h_con_handle;
|
||||
intptr_t l_std_handle;
|
||||
// allocate a console for this app
|
||||
const bool isConsoleAllocated = AllocConsole();
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO coninfo;
|
||||
FILE *fp;
|
||||
if (isConsoleAllocated)
|
||||
{
|
||||
// set the screen buffer to be big enough to let us scroll text
|
||||
CONSOLE_SCREEN_BUFFER_INFO coninfo;
|
||||
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
|
||||
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
|
||||
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
|
||||
|
||||
// allocate a console for this app
|
||||
const bool isConsoleAllocated = AllocConsole();
|
||||
|
||||
// set the screen buffer to be big enough to let us scroll text
|
||||
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
|
||||
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
|
||||
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
|
||||
|
||||
// redirect unbuffered STDOUT to the console
|
||||
l_std_handle = reinterpret_cast<decltype(l_std_handle)>(GetStdHandle(STD_OUTPUT_HANDLE));
|
||||
h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
|
||||
if (h_con_handle == -1)
|
||||
{
|
||||
LL_WARNS() << "create_console() failed to open stdout handle" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
fp = _fdopen( h_con_handle, "w" );
|
||||
*stdout = *fp;
|
||||
setvbuf( stdout, NULL, _IONBF, 0 );
|
||||
}
|
||||
|
||||
// redirect unbuffered STDIN to the console
|
||||
l_std_handle = reinterpret_cast<decltype(l_std_handle)>(GetStdHandle(STD_INPUT_HANDLE));
|
||||
h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
|
||||
if (h_con_handle == -1)
|
||||
{
|
||||
LL_WARNS() << "create_console() failed to open stdin handle" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
fp = _fdopen( h_con_handle, "r" );
|
||||
*stdin = *fp;
|
||||
setvbuf( stdin, NULL, _IONBF, 0 );
|
||||
}
|
||||
|
||||
// redirect unbuffered STDERR to the console
|
||||
l_std_handle = reinterpret_cast<decltype(l_std_handle)>(GetStdHandle(STD_ERROR_HANDLE));
|
||||
h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
|
||||
if (h_con_handle == -1)
|
||||
{
|
||||
LL_WARNS() << "create_console() failed to open stderr handle" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
fp = _fdopen( h_con_handle, "w" );
|
||||
*stderr = *fp;
|
||||
setvbuf( stderr, NULL, _IONBF, 0 );
|
||||
}
|
||||
// redirect unbuffered STDOUT to the console
|
||||
set_stream("stdout", stdout, STD_OUTPUT_HANDLE, "CONOUT$");
|
||||
// redirect unbuffered STDERR to the console
|
||||
set_stream("stderr", stderr, STD_ERROR_HANDLE, "CONOUT$");
|
||||
// redirect unbuffered STDIN to the console
|
||||
// Don't bother: our console is solely for log output. We never read stdin.
|
||||
// set_stream("stdin", stdin, STD_INPUT_HANDLE, "CONIN$", "r");
|
||||
}
|
||||
|
||||
return isConsoleAllocated;
|
||||
}
|
||||
|
||||
void set_stream(const char* desc, FILE* fp, DWORD handle_id, const char* name, const char* mode)
|
||||
{
|
||||
// SL-13528: This code used to be based on
|
||||
// http://dslweb.nwnexus.com/~ast/dload/guicon.htm
|
||||
// (referenced in https://stackoverflow.com/a/191880).
|
||||
// But one of the comments on that StackOverflow answer points out that
|
||||
// assigning to *stdout or *stderr "probably doesn't even work with the
|
||||
// Universal CRT that was introduced in 2015," suggesting freopen_s()
|
||||
// instead. Code below is based on https://stackoverflow.com/a/55875595.
|
||||
auto std_handle = GetStdHandle(handle_id);
|
||||
if (std_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
LL_WARNS() << "create_console() failed to get " << desc << " handle" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mode == std::string("w"))
|
||||
{
|
||||
// Enable color processing on Windows 10 console windows.
|
||||
DWORD dwMode = 0;
|
||||
GetConsoleMode(std_handle, &dwMode);
|
||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
SetConsoleMode(std_handle, dwMode);
|
||||
}
|
||||
// Redirect the passed fp to the console.
|
||||
FILE* ignore;
|
||||
if (freopen_s(&ignore, name, mode, fp) == 0)
|
||||
{
|
||||
// use unbuffered I/O
|
||||
setvbuf( fp, NULL, _IONBF, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
LLAppViewerWin32::LLAppViewerWin32(const char* cmd_line) :
|
||||
mCmdLine(cmd_line),
|
||||
mIsConsoleAllocated(false)
|
||||
|
|
|
|||
|
|
@ -148,170 +148,173 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
|
|||
}
|
||||
try
|
||||
{
|
||||
LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::getName()
|
||||
<< " with uri '" << uri << "', parameters " << printable_params << LL_ENDL;
|
||||
LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::getName()
|
||||
<< " with uri '" << uri << "', parameters " << printable_params << LL_ENDL;
|
||||
|
||||
LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));
|
||||
// EXT-4193: use a DIFFERENT reply pump than for the SRV request. We used
|
||||
// to share them -- but the EXT-3934 fix made it possible for an abandoned
|
||||
// SRV response to arrive just as we were expecting the XMLRPC response.
|
||||
LLEventStream loginReplyPump("loginreply", true);
|
||||
LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));
|
||||
// EXT-4193: use a DIFFERENT reply pump than for the SRV request. We used
|
||||
// to share them -- but the EXT-3934 fix made it possible for an abandoned
|
||||
// SRV response to arrive just as we were expecting the XMLRPC response.
|
||||
LLEventStream loginReplyPump("loginreply", true);
|
||||
|
||||
LLSD::Integer attempts = 0;
|
||||
LLSD::Integer attempts = 0;
|
||||
|
||||
LLSD request(login_params);
|
||||
request["reply"] = loginReplyPump.getName();
|
||||
request["uri"] = uri;
|
||||
std::string status;
|
||||
LLSD request(login_params);
|
||||
request["reply"] = loginReplyPump.getName();
|
||||
request["uri"] = uri;
|
||||
std::string status;
|
||||
|
||||
// Loop back to here if login attempt redirects to a different
|
||||
// request["uri"]
|
||||
for (;;)
|
||||
{
|
||||
++attempts;
|
||||
LLSD progress_data;
|
||||
progress_data["attempt"] = attempts;
|
||||
progress_data["request"] = request;
|
||||
if (progress_data["request"].has("params")
|
||||
&& progress_data["request"]["params"].has("passwd"))
|
||||
// Loop back to here if login attempt redirects to a different
|
||||
// request["uri"]
|
||||
for (;;)
|
||||
{
|
||||
progress_data["request"]["params"]["passwd"] = "*******";
|
||||
}
|
||||
sendProgressEvent("offline", "authenticating", progress_data);
|
||||
++attempts;
|
||||
LLSD progress_data;
|
||||
progress_data["attempt"] = attempts;
|
||||
progress_data["request"] = request;
|
||||
if (progress_data["request"].has("params")
|
||||
&& progress_data["request"]["params"].has("passwd"))
|
||||
{
|
||||
progress_data["request"]["params"]["passwd"] = "*******";
|
||||
}
|
||||
sendProgressEvent("offline", "authenticating", progress_data);
|
||||
|
||||
// We expect zero or more "Downloading" status events, followed by
|
||||
// exactly one event with some other status. Use postAndSuspend() the
|
||||
// first time, because -- at least in unit-test land -- it's
|
||||
// possible for the reply to arrive before the post() call
|
||||
// returns. Subsequent responses, of course, must be awaited
|
||||
// without posting again.
|
||||
for (mAuthResponse = validateResponse(loginReplyPump.getName(),
|
||||
llcoro::postAndSuspend(request, xmlrpcPump, loginReplyPump, "reply"));
|
||||
mAuthResponse["status"].asString() == "Downloading";
|
||||
mAuthResponse = validateResponse(loginReplyPump.getName(),
|
||||
llcoro::suspendUntilEventOn(loginReplyPump)))
|
||||
// We expect zero or more "Downloading" status events, followed by
|
||||
// exactly one event with some other status. Use postAndSuspend() the
|
||||
// first time, because -- at least in unit-test land -- it's
|
||||
// possible for the reply to arrive before the post() call
|
||||
// returns. Subsequent responses, of course, must be awaited
|
||||
// without posting again.
|
||||
for (mAuthResponse = validateResponse(loginReplyPump.getName(),
|
||||
llcoro::postAndSuspend(request, xmlrpcPump, loginReplyPump, "reply"));
|
||||
mAuthResponse["status"].asString() == "Downloading";
|
||||
mAuthResponse = validateResponse(loginReplyPump.getName(),
|
||||
llcoro::suspendUntilEventOn(loginReplyPump)))
|
||||
{
|
||||
// Still Downloading -- send progress update.
|
||||
sendProgressEvent("offline", "downloading");
|
||||
}
|
||||
|
||||
LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;
|
||||
status = mAuthResponse["status"].asString();
|
||||
|
||||
// Okay, we've received our final status event for this
|
||||
// request. Unless we got a redirect response, break the retry
|
||||
// loop for the current rewrittenURIs entry.
|
||||
if (!(status == "Complete" &&
|
||||
mAuthResponse["responses"]["login"].asString() == "indeterminate"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
|
||||
|
||||
// Here the login service at the current URI is redirecting us
|
||||
// to some other URI ("indeterminate" -- why not "redirect"?).
|
||||
// The response should contain another uri to try, with its
|
||||
// own auth method.
|
||||
request["uri"] = mAuthResponse["responses"]["next_url"].asString();
|
||||
request["method"] = mAuthResponse["responses"]["next_method"].asString();
|
||||
} // loop back to try the redirected URI
|
||||
|
||||
// Here we're done with redirects.
|
||||
if (status == "Complete")
|
||||
{
|
||||
// Still Downloading -- send progress update.
|
||||
sendProgressEvent("offline", "downloading");
|
||||
// StatusComplete does not imply auth success. Check the
|
||||
// actual outcome of the request. We've already handled the
|
||||
// "indeterminate" case in the loop above.
|
||||
if (mAuthResponse["responses"]["login"].asString() == "true")
|
||||
{
|
||||
sendProgressEvent("online", "connect", mAuthResponse["responses"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Synchronize here with the updater. We synchronize here rather
|
||||
// than in the fail.login handler, which actually examines the
|
||||
// response from login.cgi, because here we are definitely in a
|
||||
// coroutine and can definitely use suspendUntilBlah(). Whoever's
|
||||
// listening for fail.login might not be.
|
||||
|
||||
// If the reason for login failure is that we must install a
|
||||
// required update, we definitely want to pass control to the
|
||||
// updater to manage that for us. We'll handle any other login
|
||||
// failure ourselves, as usual. We figure that no matter where you
|
||||
// are in the world, or what kind of network you're on, we can
|
||||
// reasonably expect the Viewer Version Manager to respond more or
|
||||
// less as quickly as login.cgi. This synchronization is only
|
||||
// intended to smooth out minor races between the two services.
|
||||
// But what if the updater crashes? Use a timeout so that
|
||||
// eventually we'll tire of waiting for it and carry on as usual.
|
||||
// Given the above, it can be a fairly short timeout, at least
|
||||
// from a human point of view.
|
||||
|
||||
// Since sSyncPoint is an LLEventMailDrop, we DEFINITELY want to
|
||||
// consume the posted event.
|
||||
// <FS:ND> Disable updater (n.b. this might not beed needed anymore)
|
||||
// LLCoros::OverrideConsuming oc(true);
|
||||
// // Timeout should produce the isUndefined() object passed here.
|
||||
// LL_DEBUGS("LLLogin") << "Login failure, waiting for sync from updater" << LL_ENDL;
|
||||
// LLSD updater = llcoro::suspendUntilEventOnWithTimeout(sSyncPoint, 10, LLSD());
|
||||
// if (updater.isUndefined())
|
||||
// {
|
||||
// LL_WARNS("LLLogin") << "Failed to hear from updater, proceeding with fail.login"
|
||||
// << LL_ENDL;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// LL_DEBUGS("LLLogin") << "Got responses from updater and login.cgi" << LL_ENDL;
|
||||
// }
|
||||
// // Let the fail.login handler deal with empty updater response.
|
||||
// LLSD responses(mAuthResponse["responses"]);
|
||||
// responses["updater"] = updater;
|
||||
// sendProgressEvent("offline", "fail.login", responses);
|
||||
sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
|
||||
// </FS:ND>
|
||||
}
|
||||
return; // Done!
|
||||
}
|
||||
|
||||
LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;
|
||||
status = mAuthResponse["status"].asString();
|
||||
|
||||
// Okay, we've received our final status event for this
|
||||
// request. Unless we got a redirect response, break the retry
|
||||
// loop for the current rewrittenURIs entry.
|
||||
if (!(status == "Complete" &&
|
||||
mAuthResponse["responses"]["login"].asString() == "indeterminate"))
|
||||
/*==========================================================================*|
|
||||
// Sometimes we end with "Started" here. Slightly slow server? Seems
|
||||
// to be ok to just skip it. Otherwise we'd error out and crash in the
|
||||
// if below.
|
||||
if( status == "Started")
|
||||
{
|
||||
break;
|
||||
LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
|*==========================================================================*/
|
||||
|
||||
// If we don't recognize status at all, trouble
|
||||
if (! (status == "CURLError"
|
||||
|| status == "XMLRPCError"
|
||||
|| status == "OtherError"))
|
||||
{
|
||||
LL_ERRS("LLLogin") << "Unexpected status from " << xmlrpcPump.getName() << " pump: "
|
||||
<< mAuthResponse << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
|
||||
// Here status IS one of the errors tested above.
|
||||
// Tell caller this didn't work out so well.
|
||||
|
||||
// Here the login service at the current URI is redirecting us
|
||||
// to some other URI ("indeterminate" -- why not "redirect"?).
|
||||
// The response should contain another uri to try, with its
|
||||
// own auth method.
|
||||
request["uri"] = mAuthResponse["responses"]["next_url"].asString();
|
||||
request["method"] = mAuthResponse["responses"]["next_method"].asString();
|
||||
} // loop back to try the redirected URI
|
||||
|
||||
// Here we're done with redirects.
|
||||
if (status == "Complete")
|
||||
{
|
||||
// StatusComplete does not imply auth success. Check the
|
||||
// actual outcome of the request. We've already handled the
|
||||
// "indeterminate" case in the loop above.
|
||||
if (mAuthResponse["responses"]["login"].asString() == "true")
|
||||
// *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
|
||||
// llsd with no "responses" node. To make the output from an incomplete login symmetrical
|
||||
// to success, add a data/message and data/reason fields.
|
||||
LLSD error_response(LLSDMap
|
||||
("reason", mAuthResponse["status"])
|
||||
("errorcode", mAuthResponse["errorcode"])
|
||||
("message", mAuthResponse["error"]));
|
||||
if(mAuthResponse.has("certificate"))
|
||||
{
|
||||
sendProgressEvent("online", "connect", mAuthResponse["responses"]);
|
||||
error_response["certificate"] = mAuthResponse["certificate"];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Synchronize here with the updater. We synchronize here rather
|
||||
// than in the fail.login handler, which actually examines the
|
||||
// response from login.cgi, because here we are definitely in a
|
||||
// coroutine and can definitely use suspendUntilBlah(). Whoever's
|
||||
// listening for fail.login might not be.
|
||||
|
||||
// If the reason for login failure is that we must install a
|
||||
// required update, we definitely want to pass control to the
|
||||
// updater to manage that for us. We'll handle any other login
|
||||
// failure ourselves, as usual. We figure that no matter where you
|
||||
// are in the world, or what kind of network you're on, we can
|
||||
// reasonably expect the Viewer Version Manager to respond more or
|
||||
// less as quickly as login.cgi. This synchronization is only
|
||||
// intended to smooth out minor races between the two services.
|
||||
// But what if the updater crashes? Use a timeout so that
|
||||
// eventually we'll tire of waiting for it and carry on as usual.
|
||||
// Given the above, it can be a fairly short timeout, at least
|
||||
// from a human point of view.
|
||||
|
||||
// Since sSyncPoint is an LLEventMailDrop, we DEFINITELY want to
|
||||
// consume the posted event.
|
||||
// <FS:Ansariel> Disable updater
|
||||
//LLCoros::OverrideConsuming oc(true);
|
||||
//// Timeout should produce the isUndefined() object passed here.
|
||||
//LL_DEBUGS("LLLogin") << "Login failure, waiting for sync from updater" << LL_ENDL;
|
||||
//LLSD updater = llcoro::suspendUntilEventOnWithTimeout(sSyncPoint, 10, LLSD());
|
||||
//if (updater.isUndefined())
|
||||
//{
|
||||
// LL_WARNS("LLLogin") << "Failed to hear from updater, proceeding with fail.login"
|
||||
// << LL_ENDL;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// LL_DEBUGS("LLLogin") << "Got responses from updater and login.cgi" << LL_ENDL;
|
||||
//}
|
||||
//// Let the fail.login handler deal with empty updater response.
|
||||
//LLSD responses(mAuthResponse["responses"]);
|
||||
//responses["updater"] = updater;
|
||||
//sendProgressEvent("offline", "fail.login", responses);
|
||||
sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
return; // Done!
|
||||
}
|
||||
|
||||
// /* Sometimes we end with "Started" here. Slightly slow server?
|
||||
// * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below.
|
||||
// */
|
||||
// if( status == "Started")
|
||||
// {
|
||||
// LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// If we don't recognize status at all, trouble
|
||||
if (! (status == "CURLError"
|
||||
|| status == "XMLRPCError"
|
||||
|| status == "OtherError"))
|
||||
{
|
||||
LL_ERRS("LLLogin") << "Unexpected status from " << xmlrpcPump.getName() << " pump: "
|
||||
<< mAuthResponse << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Here status IS one of the errors tested above.
|
||||
// Tell caller this didn't work out so well.
|
||||
|
||||
// *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
|
||||
// llsd with no "responses" node. To make the output from an incomplete login symmetrical
|
||||
// to success, add a data/message and data/reason fields.
|
||||
LLSD error_response(LLSDMap
|
||||
("reason", mAuthResponse["status"])
|
||||
("errorcode", mAuthResponse["errorcode"])
|
||||
("message", mAuthResponse["error"]));
|
||||
if(mAuthResponse.has("certificate"))
|
||||
{
|
||||
error_response["certificate"] = mAuthResponse["certificate"];
|
||||
}
|
||||
sendProgressEvent("offline", "fail.login", error_response);
|
||||
sendProgressEvent("offline", "fail.login", error_response);
|
||||
}
|
||||
catch (...) {
|
||||
CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::getName()
|
||||
<< "('" << uri << "', " << printable_params << ")"));
|
||||
LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::getName()
|
||||
<< "('" << uri << "', " << printable_params << ")"));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue