aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/viewer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/viewer.cpp')
-rw-r--r--linden/indra/newview/viewer.cpp488
1 files changed, 213 insertions, 275 deletions
diff --git a/linden/indra/newview/viewer.cpp b/linden/indra/newview/viewer.cpp
index 8f37bc3..db57f3e 100644
--- a/linden/indra/newview/viewer.cpp
+++ b/linden/indra/newview/viewer.cpp
@@ -2,6 +2,8 @@
2 * @file viewer.cpp 2 * @file viewer.cpp
3 * @brief A window into the virtual world. 3 * @brief A window into the virtual world.
4 * 4 *
5 * $LicenseInfo:firstyear=2000&license=viewergpl$
6 *
5 * Copyright (c) 2000-2007, Linden Research, Inc. 7 * Copyright (c) 2000-2007, Linden Research, Inc.
6 * 8 *
7 * Second Life Viewer Source Code 9 * Second Life Viewer Source Code
@@ -24,6 +26,7 @@
24 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO 26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
25 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, 27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
26 * COMPLETENESS OR PERFORMANCE. 28 * COMPLETENESS OR PERFORMANCE.
29 * $/LicenseInfo$
27 */ 30 */
28 31
29#include "llviewerprecompiledheaders.h" 32#include "llviewerprecompiledheaders.h"
@@ -35,22 +38,16 @@
35#include "llviewerjoystick.h" 38#include "llviewerjoystick.h"
36 39
37// System library headers 40// System library headers
38#include <stdlib.h>
39#include <errno.h> 41#include <errno.h>
40#include <stdio.h>
41#include <stdexcept> 42#include <stdexcept>
42#include <math.h>
43#if LL_WINDOWS 43#if LL_WINDOWS
44# include <share.h> 44# include <share.h>
45#else 45#else
46# include <sys/file.h> 46# include <sys/file.h>
47# include <signal.h> 47# include <signal.h>
48#endif 48#endif
49#include <time.h>
50#include <sys/stat.h> 49#include <sys/stat.h>
51#include <memory.h> 50#include <memory>
52#include <string.h>
53#include <fstream>
54#include <boost/tokenizer.hpp> 51#include <boost/tokenizer.hpp>
55#include "curl/curl.h" 52#include "curl/curl.h"
56 53
@@ -121,6 +118,7 @@
121#include "audioengine.h" 118#include "audioengine.h"
122#include "llcommon.h" 119#include "llcommon.h"
123#include "llapr.h" 120#include "llapr.h"
121#include "llares.h"
124#include "llcachename.h" 122#include "llcachename.h"
125#include "llcurl.h" 123#include "llcurl.h"
126#include "llcriticaldamp.h" 124#include "llcriticaldamp.h"
@@ -153,7 +151,6 @@
153// Viewer headers 151// Viewer headers
154// 152//
155 153
156#include "llasynchostbyname.h"
157#include "llagent.h" 154#include "llagent.h"
158#include "llagentpilot.h" 155#include "llagentpilot.h"
159#include "llbutton.h" // For constants 156#include "llbutton.h" // For constants
@@ -208,6 +205,8 @@
208#include "lltoolbar.h" 205#include "lltoolbar.h"
209#include "lltoolmgr.h" 206#include "lltoolmgr.h"
210#include "lltracker.h" 207#include "lltracker.h"
208#include "llurldispatcher.h"
209#include "llurlsimstring.h"
211#include "llurlwhitelist.h" 210#include "llurlwhitelist.h"
212#include "llv4math.h" // LL_VECTORIZE 211#include "llv4math.h" // LL_VECTORIZE
213#include "llviewerbuild.h" 212#include "llviewerbuild.h"
@@ -325,7 +324,7 @@ F32 gSimFrames;
325 324
326LLString gSecondLife; 325LLString gSecondLife;
327LLString gWindowTitle; 326LLString gWindowTitle;
328LLString gWindowName("Second Life"); 327static char sWindowClass[] = "Second Life";
329LLString gDisabledMessage; 328LLString gDisabledMessage;
330BOOL gHideLinks = FALSE; 329BOOL gHideLinks = FALSE;
331 330
@@ -447,11 +446,13 @@ U64 gFrameTime = 0;
447F32 gFrameTimeSeconds = 0.f; 446F32 gFrameTimeSeconds = 0.f;
448F32 gFrameIntervalSeconds = 0.f; 447F32 gFrameIntervalSeconds = 0.f;
449U32 gFrameCount = 0; 448U32 gFrameCount = 0;
449U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground
450U64 gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds 450U64 gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds
451U64 gSpaceTime = 0; // gSpaceTime is the time, according to the spaceserver. 451U64 gSpaceTime = 0; // gSpaceTime is the time, according to the spaceserver.
452 452
453// Timing Globals 453// Timing Globals
454LLTimer gRenderStartTime; 454LLTimer gRenderStartTime;
455LLFrameTimer gForegroundTime;
455F32 gQuitAfterSeconds = 0.f; 456F32 gQuitAfterSeconds = 0.f;
456BOOL gRotateRight = FALSE; 457BOOL gRotateRight = FALSE;
457 458
@@ -482,8 +483,6 @@ LLVector3 gRelativeWindVec(0.0, 0.0, 0.0);
482BOOL gVelocityInterpolate = TRUE; // (These are written once/frame with the data from gSavedSettings) 483BOOL gVelocityInterpolate = TRUE; // (These are written once/frame with the data from gSavedSettings)
483BOOL gPingInterpolate = TRUE; 484BOOL gPingInterpolate = TRUE;
484 485
485//static
486LLURLSimString LLURLSimString::sInstance;
487 486
488// 487//
489// System info 488// System info
@@ -618,6 +617,7 @@ void bad_network_handler();
618void disable_win_error_reporting(); 617void disable_win_error_reporting();
619#endif 618#endif
620std::string get_serial_number(); 619std::string get_serial_number();
620bool send_url_to_other_instance(const std::string& url);
621BOOL another_instance_running(); 621BOOL another_instance_running();
622void main_loop(); 622void main_loop();
623 623
@@ -948,11 +948,6 @@ int main( int argc, char **argv )
948 } 948 }
949 } 949 }
950 950
951 if (!strcmp(gUserServerName, gUserServerDomainName[USERSERVER_AGNI].mName))
952 {
953 gInProductionGrid = TRUE;
954 }
955
956 // 951 //
957 // Start of the application 952 // Start of the application
958 // 953 //
@@ -1000,8 +995,8 @@ int main( int argc, char **argv )
1000#if LL_DARWIN 995#if LL_DARWIN
1001 { 996 {
1002 // On the Mac, read in arguments.txt (if it exists) and process it for additional arguments. 997 // On the Mac, read in arguments.txt (if it exists) and process it for additional arguments.
1003 LLString args; 998 std::string args;
1004 if(LLString::read(args, "arguments.txt")) /* Flawfinder: ignore*/ 999 if(_read_file_into_string(args, "arguments.txt"))
1005 { 1000 {
1006 // The arguments file exists. 1001 // The arguments file exists.
1007 // It should consist of command line arguments separated by newlines. 1002 // It should consist of command line arguments separated by newlines.
@@ -1045,8 +1040,8 @@ int main( int argc, char **argv )
1045 char path[MAX_PATH]; 1040 char path[MAX_PATH];
1046 if(CFURLGetFileSystemRepresentation(url, false, (UInt8 *)path, sizeof(path))) 1041 if(CFURLGetFileSystemRepresentation(url, false, (UInt8 *)path, sizeof(path)))
1047 { 1042 {
1048 LLString lang; 1043 std::string lang;
1049 if(LLString::read(lang, path)) /* Flawfinder: ignore*/ 1044 if(_read_file_into_string(lang, path))
1050 { 1045 {
1051 gCommandLineForcedSettings["SystemLanguage"] = lang; 1046 gCommandLineForcedSettings["SystemLanguage"] = lang;
1052 } 1047 }
@@ -1065,7 +1060,12 @@ int main( int argc, char **argv )
1065 return args_result; 1060 return args_result;
1066 } 1061 }
1067 1062
1068 // XUI:translate 1063 if (!strcmp(gUserServerName, gUserServerDomainName[USERSERVER_AGNI].mName))
1064 {
1065 gInProductionGrid = TRUE;
1066 }
1067
1068 // *TODO:translate
1069 gSecondLife = "Second Life"; 1069 gSecondLife = "Second Life";
1070 1070
1071 // Read skin/branding settings if specified. 1071 // Read skin/branding settings if specified.
@@ -1122,6 +1122,7 @@ int main( int argc, char **argv )
1122 // Display splash screen. Must be after above check for previous 1122 // Display splash screen. Must be after above check for previous
1123 // crash as this dialog is always frontmost. 1123 // crash as this dialog is always frontmost.
1124 std::ostringstream splash_msg; 1124 std::ostringstream splash_msg;
1125 // *TODO:translate
1125 splash_msg << "Loading " << gSecondLife << "..."; 1126 splash_msg << "Loading " << gSecondLife << "...";
1126 LLSplashScreen::show(); 1127 LLSplashScreen::show();
1127 LLSplashScreen::update(splash_msg.str().c_str()); 1128 LLSplashScreen::update(splash_msg.str().c_str());
@@ -1170,10 +1171,22 @@ int main( int argc, char **argv )
1170 // don't call another_instance_running() when doing URL handoff, as 1171 // don't call another_instance_running() when doing URL handoff, as
1171 // it relies on checking a marker file which will not work when running 1172 // it relies on checking a marker file which will not work when running
1172 // out of different directories 1173 // out of different directories
1173 if (LLURLSimString::parse() && LLURLSimString::send_to_other_instance()) 1174 std::string slurl;
1175 if (!LLStartUp::sSLURLCommand.empty())
1174 { 1176 {
1175 // successfully handed off URL to existing instance, exit 1177 slurl = LLStartUp::sSLURLCommand;
1176 return 1; 1178 }
1179 else if (LLURLSimString::parse())
1180 {
1181 slurl = LLURLSimString::getURL();
1182 }
1183 if (!slurl.empty())
1184 {
1185 if (send_url_to_other_instance(slurl))
1186 {
1187 // successfully handed off URL to existing instance, exit
1188 return 1;
1189 }
1177 } 1190 }
1178 1191
1179 gSecondInstance = another_instance_running(); 1192 gSecondInstance = another_instance_running();
@@ -1254,6 +1267,7 @@ int main( int argc, char **argv )
1254 (char*)"-name", 1267 (char*)"-name",
1255 (char*)gSecondLife.c_str(), 1268 (char*)gSecondLife.c_str(),
1256 NULL}; 1269 NULL};
1270 fflush(NULL);
1257 pid_t pid = fork(); 1271 pid_t pid = fork();
1258 if (pid == 0) 1272 if (pid == 0)
1259 { // child 1273 { // child
@@ -1318,6 +1332,11 @@ int main( int argc, char **argv )
1318 gCurrentVersion = llformat("%d.%d.%d", LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH ); 1332 gCurrentVersion = llformat("%d.%d.%d", LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH );
1319 1333
1320 // 1334 //
1335 // Various introspection concerning the libs we're using
1336 //
1337 llinfos << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << llendl;
1338
1339 //
1321 // Load the feature tables 1340 // Load the feature tables
1322 // 1341 //
1323 llinfos << "Loading feature tables." << llendl; 1342 llinfos << "Loading feature tables." << llendl;
@@ -1637,7 +1656,7 @@ int main( int argc, char **argv )
1637 window_title_str[sizeof(window_title_str) - 1] = '\0'; 1656 window_title_str[sizeof(window_title_str) - 1] = '\0';
1638 1657
1639 // always start windowed 1658 // always start windowed
1640 gViewerWindow = new LLViewerWindow(window_title_str, "Second Life", 1659 gViewerWindow = new LLViewerWindow(window_title_str, sWindowClass,
1641 gSavedSettings.getS32("WindowX"), gSavedSettings.getS32("WindowY"), 1660 gSavedSettings.getS32("WindowX"), gSavedSettings.getS32("WindowY"),
1642 gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"), 1661 gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"),
1643 FALSE, gIgnorePixelDepth); 1662 FALSE, gIgnorePixelDepth);
@@ -1754,6 +1773,32 @@ int main( int argc, char **argv )
1754 return 0; 1773 return 0;
1755} 1774}
1756 1775
1776bool send_url_to_other_instance(const std::string& url)
1777{
1778#if LL_WINDOWS
1779 wchar_t window_class[256]; /* Flawfinder: ignore */ // Assume max length < 255 chars.
1780 mbstowcs(window_class, sWindowClass, 255);
1781 window_class[255] = 0;
1782 // Use the class instead of the window name.
1783 HWND other_window = FindWindow(window_class, NULL);
1784 if (other_window != NULL)
1785 {
1786 lldebugs << "Found other window with the name '" << gWindowTitle << "'" << llendl;
1787 COPYDATASTRUCT cds;
1788 const S32 SLURL_MESSAGE_TYPE = 0;
1789 cds.dwData = SLURL_MESSAGE_TYPE;
1790 cds.cbData = url.length() + 1;
1791 cds.lpData = (void*)url.c_str();
1792
1793 LRESULT msg_result = SendMessage(other_window, WM_COPYDATA, NULL, (LPARAM)&cds);
1794 lldebugs << "SendMessage(WM_COPYDATA) to other window '"
1795 << gWindowTitle << "' returned " << msg_result << llendl;
1796 return true;
1797 }
1798#endif
1799 return false;
1800}
1801
1757BOOL another_instance_running() 1802BOOL another_instance_running()
1758{ 1803{
1759 // We create a marker file when the program starts and remove the file when it finishes. 1804 // We create a marker file when the program starts and remove the file when it finishes.
@@ -1867,6 +1912,7 @@ void main_loop()
1867 LLFastTimer t3(LLFastTimer::FTM_IDLE); 1912 LLFastTimer t3(LLFastTimer::FTM_IDLE);
1868 idle(); 1913 idle();
1869 LLCurl::process(); 1914 LLCurl::process();
1915 gAres->process();
1870 // this pump is necessary to make the login screen show up 1916 // this pump is necessary to make the login screen show up
1871 gServicePump->pump(); 1917 gServicePump->pump();
1872 gServicePump->callback(); 1918 gServicePump->callback();
@@ -2669,6 +2715,7 @@ void viewer_crash_callback()
2669 (char*)"-name", 2715 (char*)"-name",
2670 (char*)gSecondLife.c_str(), 2716 (char*)gSecondLife.c_str(),
2671 NULL}; 2717 NULL};
2718 fflush(NULL);
2672 pid_t pid = fork(); 2719 pid_t pid = fork();
2673 if (pid == 0) 2720 if (pid == 0)
2674 { // child 2721 { // child
@@ -2947,24 +2994,8 @@ OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
2947 2994
2948 if(result == noErr) 2995 if(result == noErr)
2949 { 2996 {
2950 // Got the URL out of the event. 2997 std::string url = buffer;
2951 // secondlife:// 2998 LLURLDispatcher::dispatch(url);
2952
2953 // Parse it and stash in globals.
2954 LLURLSimString::setString(buffer);
2955
2956 if(gFloaterWorldMap != NULL)
2957 {
2958 // If the viewer's already logged in, pass it along directly.
2959 if (LLURLSimString::parse())
2960 {
2961 gFloaterWorldMap->trackURL(LLURLSimString::sInstance.mSimName,
2962 LLURLSimString::sInstance.mX,
2963 LLURLSimString::sInstance.mY,
2964 LLURLSimString::sInstance.mZ);
2965 LLFloaterWorldMap::show(NULL, TRUE);
2966 }
2967 }
2968 } 2999 }
2969 3000
2970 return(result); 3001 return(result);
@@ -3034,9 +3065,8 @@ OSStatus DisplayReleaseNotes(void)
3034 id.signature = 'text'; 3065 id.signature = 'text';
3035 id.id = 0; 3066 id.id = 0;
3036 3067
3037 LLString releaseNotesText; 3068 std::string releaseNotesText;
3038 3069 _read_file_into_string(releaseNotesText, "releasenotes.txt");
3039 LLString::read(releaseNotesText, "releasenotes.txt"); /* Flawfinder: ignore*/
3040 3070
3041 err = HIViewFindByID(HIViewGetRoot(window), id, &textView); 3071 err = HIViewFindByID(HIViewGetRoot(window), id, &textView);
3042 3072
@@ -3422,7 +3452,10 @@ void update_statistics(U32 frame_count)
3422 gViewerStats->mSimPingStat.addValue(10000); 3452 gViewerStats->mSimPingStat.addValue(10000);
3423 } 3453 }
3424 3454
3425 gViewerStats->mFPSStat.addValue(1); 3455 if (gFocusMgr.getAppHasFocus())
3456 {
3457 gViewerStats->mFPSStat.addValue(1);
3458 }
3426 F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits()); 3459 F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits());
3427 gViewerStats->mLayersKBitStat.addValue(layer_bits/1024.f); 3460 gViewerStats->mLayersKBitStat.addValue(layer_bits/1024.f);
3428 gViewerStats->mObjectKBitStat.addValue(gObjectBits/1024.f); 3461 gViewerStats->mObjectKBitStat.addValue(gObjectBits/1024.f);
@@ -3724,6 +3757,7 @@ void idle()
3724 3757
3725 // Update session stats every large chunk of time 3758 // Update session stats every large chunk of time
3726 // *FIX: (???) SAMANTHA 3759 // *FIX: (???) SAMANTHA
3760
3727 if (viewer_stats_timer.getElapsedTimeF32() >= 300.f && !gDisconnected) 3761 if (viewer_stats_timer.getElapsedTimeF32() >= 300.f && !gDisconnected)
3728 { 3762 {
3729 llinfos << "Transmitting sessions stats" << llendl; 3763 llinfos << "Transmitting sessions stats" << llendl;
@@ -3817,7 +3851,7 @@ void idle()
3817 // After agent and camera moved, figure out if we need to 3851 // After agent and camera moved, figure out if we need to
3818 // deselect objects. 3852 // deselect objects.
3819 gSelectMgr->deselectAllIfTooFar(); 3853 gSelectMgr->deselectAllIfTooFar();
3820 3854 gSelectMgr->update(); // once per frame updat
3821 } 3855 }
3822 3856
3823 { 3857 {
@@ -5153,6 +5187,32 @@ void output_statistics(void*)
5153 */ 5187 */
5154} 5188}
5155 5189
5190class ViewerStatsResponder : public LLHTTPClient::Responder
5191{
5192public:
5193 ViewerStatsResponder() { }
5194
5195 void error(U32 statusNum, const std::string& reason)
5196 {
5197 llinfos << "ViewerStatsResponder::error " << statusNum << " "
5198 << reason << llendl;
5199 }
5200
5201 void result(const LLSD& content)
5202 {
5203 llinfos << "ViewerStatsResponder::result" << llendl;
5204 }
5205};
5206
5207/*
5208 * The sim-side LLSD is in newsim/llagentinfo.cpp:forwardViewerStats.
5209 *
5210 * There's also a compatibility shim for the old fixed-format sim
5211 * stats in newsim/llagentinfo.cpp:processViewerStats.
5212 *
5213 * If you move stats around here, make the corresponding changes in
5214 * those locations, too.
5215 */
5156void send_stats() 5216void send_stats()
5157{ 5217{
5158 // IW 9/23/02 I elected not to move this into LLViewerStats 5218 // IW 9/23/02 I elected not to move this into LLViewerStats
@@ -5166,81 +5226,93 @@ void send_stats()
5166 return; 5226 return;
5167 } 5227 }
5168 5228
5169 gMessageSystem->newMessageFast(_PREHASH_ViewerStats); 5229 LLSD body;
5230 std::string url = gAgent.getRegion()->getCapability("ViewerStats");
5231
5232 if (url.empty()) {
5233 llwarns << "Could not get ViewerStats capability" << llendl;
5234 return;
5235 }
5170 5236
5171 gMessageSystem->nextBlockFast(_PREHASH_AgentData); 5237 body["session_id"] = gAgentSessionID;
5172 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
5173 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
5174 5238
5175 // IP will get filled in by the receiver 5239 LLSD &agent = body["agent"];
5176 gMessageSystem->addIPAddrFast(_PREHASH_IP, 0); 5240
5177 5241 time_t ltime;
5178 time_t ltime;
5179 time(&ltime); 5242 time(&ltime);
5180 F32 run_time = F32(LLFrameTimer::getElapsedSeconds()); 5243 F32 run_time = F32(LLFrameTimer::getElapsedSeconds());
5181 5244
5182 gMessageSystem->addU32Fast(_PREHASH_StartTime, ((U32)ltime - (U32)run_time)); 5245 agent["start_time"] = ltime - run_time;
5183 gMessageSystem->addF32Fast(_PREHASH_RunTime, run_time); 5246 agent["run_time"] = run_time;
5184 gMessageSystem->addF32Fast(_PREHASH_FPS, ((F32)gFrameCount / gRenderStartTime.getElapsedTimeF32())); 5247 // send fps only for time app spends in foreground
5248 agent["fps"] = (F32)gForegroundFrameCount / gForegroundTime.getElapsedTimeF32();
5249 agent["version"] = gCurrentVersion;
5250 agent["language"] = gLanguage;
5185 5251
5186 gMessageSystem->addF32Fast(_PREHASH_SimFPS, ((F32)gFrameCount - gSimFrames) / (F32)(gRenderStartTime.getElapsedTimeF32() - gSimLastTime) ); 5252 agent["sim_fps"] = ((F32) gFrameCount - gSimFrames) /
5253 (F32) (gRenderStartTime.getElapsedTimeF32() - gSimLastTime);
5254
5187 gSimLastTime = gRenderStartTime.getElapsedTimeF32(); 5255 gSimLastTime = gRenderStartTime.getElapsedTimeF32();
5188 gSimFrames = (F32)gFrameCount; 5256 gSimFrames = (F32) gFrameCount;
5189 5257
5190 gMessageSystem->addU8Fast (_PREHASH_AgentsInView, (U8)LLVOAvatar::sNumVisibleAvatars ); 5258 agent["agents_in_view"] = LLVOAvatar::sNumVisibleAvatars;
5191 gMessageSystem->addF32Fast(_PREHASH_Ping, gAvgSimPing); 5259 agent["ping"] = gAvgSimPing;
5192 gMessageSystem->addF64Fast(_PREHASH_MetersTraveled, gAgent.getDistanceTraveled()); 5260 agent["meters_traveled"] = gAgent.getDistanceTraveled();
5193 gMessageSystem->addS32Fast(_PREHASH_RegionsVisited, gAgent.getRegionsVisited()); 5261 agent["regions_visited"] = gAgent.getRegionsVisited();
5194 gMessageSystem->addU32Fast(_PREHASH_SysRAM, gSysMemory.getPhysicalMemoryClamped()); 5262 agent["mem_use"] = getCurrentRSS() / 1024.0;
5195 gMessageSystem->addStringFast(_PREHASH_SysOS, gSysOS.getOSString());
5196 gMessageSystem->addStringFast(_PREHASH_SysCPU, gSysCPU.getCPUString());
5197 5263
5264 LLSD &system = body["system"];
5198 5265
5199 std::string gpu_desc = llformat("%-6s Class %d ", 5266 system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB();
5200 gGLManager.mGLVendorShort.substr(0,6).c_str(), 5267 system["os"] = gSysOS.getOSString();
5201 gFeatureManagerp->getGPUClass()) 5268 system["cpu"] = gSysCPU.getCPUString();
5269
5270 std::string gpu_desc = llformat(
5271 "%-6s Class %d ",
5272 gGLManager.mGLVendorShort.substr(0,6).c_str(),
5273 gFeatureManagerp->getGPUClass())
5202 + gFeatureManagerp->getGPUString(); 5274 + gFeatureManagerp->getGPUString();
5203 5275
5204 gMessageSystem->addStringFast(_PREHASH_SysGPU, gpu_desc); 5276 system["gpu"] = gpu_desc;
5277 system["gpu_class"] = gFeatureManagerp->getGPUClass();
5278 system["gpu_vendor"] = gGLManager.mGLVendorShort;
5279 system["gpu_version"] = gGLManager.mDriverVersionVendorString;
5280
5281 LLSD &download = body["downloads"];
5282
5283 download["world_kbytes"] = gTotalWorldBytes / 1024.0;
5284 download["object_kbytes"] = gTotalObjectBytes / 1024.0;
5285 download["texture_kbytes"] = gTotalTextureBytes / 1024.0;
5205 5286
5206 gMessageSystem->nextBlockFast(_PREHASH_DownloadTotals); 5287 LLSD &in = body["stats"]["net"]["in"];
5207 gMessageSystem->addU32Fast(_PREHASH_World, gTotalWorldBytes);
5208 gMessageSystem->addU32Fast(_PREHASH_Objects, gTotalObjectBytes);
5209 gMessageSystem->addU32Fast(_PREHASH_Textures, gTotalTextureBytes);
5210 5288
5211 gMessageSystem->nextBlockFast(_PREHASH_NetStats); 5289 in["kbytes"] = gMessageSystem->mTotalBytesIn / 1024.0;
5212 gMessageSystem->addU32Fast(_PREHASH_Bytes, (U32)gMessageSystem->mTotalBytesIn); 5290 in["packets"] = (S32) gMessageSystem->mPacketsIn;
5213 gMessageSystem->addU32Fast(_PREHASH_Packets, (U32)gMessageSystem->mPacketsIn); 5291 in["compressed_packets"] = (S32) gMessageSystem->mCompressedPacketsIn;
5214 gMessageSystem->addU32Fast(_PREHASH_Compressed, (U32)gMessageSystem->mCompressedPacketsIn); 5292 in["savings"] = (gMessageSystem->mUncompressedBytesIn -
5215 gMessageSystem->addU32Fast(_PREHASH_Savings, (U32)(gMessageSystem->mUncompressedBytesIn - gMessageSystem->mCompressedBytesIn)); 5293 gMessageSystem->mCompressedBytesIn) / 1024.0;
5216 5294
5217 gMessageSystem->nextBlockFast(_PREHASH_NetStats); 5295 LLSD &out = body["stats"]["net"]["out"];
5218 gMessageSystem->addU32Fast(_PREHASH_Bytes, (U32)gMessageSystem->mTotalBytesOut);
5219 gMessageSystem->addU32Fast(_PREHASH_Packets, (U32)gMessageSystem->mPacketsOut);
5220 gMessageSystem->addU32Fast(_PREHASH_Compressed, (U32)gMessageSystem->mCompressedPacketsOut);
5221 gMessageSystem->addU32Fast(_PREHASH_Savings, (U32)(gMessageSystem->mUncompressedBytesOut - gMessageSystem->mCompressedBytesOut));
5222
5223 gMessageSystem->nextBlockFast(_PREHASH_FailStats);
5224 gMessageSystem->addU32Fast(_PREHASH_SendPacket, (U32)gMessageSystem->mSendPacketFailureCount);
5225 gMessageSystem->addU32Fast(_PREHASH_Dropped, (U32)gMessageSystem->mDroppedPackets);
5226 gMessageSystem->addU32Fast(_PREHASH_Resent, (U32)gMessageSystem->mResentPackets);
5227 gMessageSystem->addU32Fast(_PREHASH_FailedResends, (U32)gMessageSystem->mFailedResendPackets);
5228 gMessageSystem->addU32Fast(_PREHASH_OffCircuit, (U32)gMessageSystem->mOffCircuitPackets);
5229 gMessageSystem->addU32Fast(_PREHASH_Invalid, (U32)gMessageSystem->mInvalidOnCircuitPackets);
5230
5231 // 1.00.00.000000
5232 F64 version =
5233 LL_VERSION_MAJOR * 10000000000.0 +
5234 LL_VERSION_MINOR * 100000000.0 +
5235 LL_VERSION_PATCH * 1000000.0 +
5236 LL_VERSION_BUILD;
5237 gViewerStats->setStat(LLViewerStats::ST_VERSION, version);
5238 5296
5239 gViewerStats->addToMessage(); 5297 out["kbytes"] = gMessageSystem->mTotalBytesOut / 1024.0;
5298 out["packets"] = (S32) gMessageSystem->mPacketsOut;
5299 out["compressed_packets"] = (S32) gMessageSystem->mCompressedPacketsOut;
5300 out["savings"] = (gMessageSystem->mUncompressedBytesOut -
5301 gMessageSystem->mCompressedBytesOut) / 1024.0;
5240 5302
5241 gAgent.sendReliableMessage(); 5303 LLSD &fail = body["stats"]["failures"];
5242}
5243 5304
5305 fail["send_packet"] = (S32) gMessageSystem->mSendPacketFailureCount;
5306 fail["dropped"] = (S32) gMessageSystem->mDroppedPackets;
5307 fail["resent"] = (S32) gMessageSystem->mResentPackets;
5308 fail["failed_resends"] = (S32) gMessageSystem->mFailedResendPackets;
5309 fail["off_circuit"] = (S32) gMessageSystem->mOffCircuitPackets;
5310 fail["invalid"] = (S32) gMessageSystem->mInvalidOnCircuitPackets;
5311
5312 gViewerStats->addToMessage(body);
5313
5314 LLHTTPClient::post(url, body, new ViewerStatsResponder());
5315}
5244 5316
5245#if !LL_WINDOWS 5317#if !LL_WINDOWS
5246// catch the first signal and send logout messages logout 5318// catch the first signal and send logout messages logout
@@ -5602,23 +5674,22 @@ int parse_args(int argc, char **argv)
5602 } 5674 }
5603 // some programs don't respect the command line options in protocol handlers (I'm looking at you, Opera) 5675 // some programs don't respect the command line options in protocol handlers (I'm looking at you, Opera)
5604 // so this allows us to parse the URL straight off the command line without a "-url" paramater 5676 // so this allows us to parse the URL straight off the command line without a "-url" paramater
5605 else if (!argument.compare(0, std::string( "secondlife://" ).length(), std::string("secondlife://"))) 5677 else if (LLURLDispatcher::isSLURL(argv[j])
5606 { 5678 || !strcmp(argv[j], "-url") && (++j < argc))
5607 // *NOTE: After setting the url, bail. What can happen is
5608 // that someone can use IE (or potentially other browsers)
5609 // and do the rough equivalent of command injection and
5610 // steal passwords. Phoenix. SL-55321
5611 LLURLSimString::setString(argv[j]);
5612 gArgs += argv[j];
5613 return 0;
5614 }
5615 else if (!strcmp(argv[j], "-url") && (++j < argc))
5616 { 5679 {
5680 std::string slurl = argv[j];
5681 if (LLURLDispatcher::isSLURLCommand(slurl))
5682 {
5683 LLStartUp::sSLURLCommand = slurl;
5684 }
5685 else
5686 {
5687 LLURLSimString::setString(slurl);
5688 }
5617 // *NOTE: After setting the url, bail. What can happen is 5689 // *NOTE: After setting the url, bail. What can happen is
5618 // that someone can use IE (or potentially other browsers) 5690 // that someone can use IE (or potentially other browsers)
5619 // and do the rough equivalent of command injection and 5691 // and do the rough equivalent of command injection and
5620 // steal passwords. Phoenix. SL-55321 5692 // steal passwords. Phoenix. SL-55321
5621 LLURLSimString::setString(argv[j]);
5622 gArgs += argv[j]; 5693 gArgs += argv[j];
5623 return 0; 5694 return 0;
5624 } 5695 }
@@ -5681,156 +5752,6 @@ int parse_args(int argc, char **argv)
5681 5752
5682//============================================================================ 5753//============================================================================
5683 5754
5684LLString LLURLSimString::sLocationStringHome("My Home");
5685LLString LLURLSimString::sLocationStringLast("My Last Location");
5686
5687// "secondlife://simname/x/y/z" -> "simname/x/y/z"
5688// (actually .*//foo -> foo)
5689// static
5690void LLURLSimString::setString(const LLString& url)
5691{
5692 sInstance.mSimString.clear();
5693 sInstance.mSimName.clear();
5694 sInstance.mParseState = NOT_PARSED;
5695 if (url == sLocationStringHome)
5696 {
5697 gSavedSettings.setBOOL("LoginLastLocation", FALSE);
5698 }
5699 else if (url == sLocationStringLast)
5700 {
5701 gSavedSettings.setBOOL("LoginLastLocation", TRUE);
5702 }
5703 else
5704 {
5705 LLString tstring(url);
5706 std::string::size_type idx = tstring.find("//");
5707 idx = (idx == LLString::npos) ? 0 : idx+2;
5708 sInstance.mSimString = tstring.substr(idx);
5709 }
5710 LLPanelLogin::refreshLocation( false ); // in case LLPanelLogin is visible
5711}
5712
5713// "/100" -> 100
5714// static
5715S32 LLURLSimString::parseGridIdx(const LLString& in_string, S32 idx0, S32* res, S32 max)
5716{
5717 if (idx0 == INT_MAX || in_string[idx0] != '/')
5718 {
5719 return INT_MAX; // parse error
5720 }
5721 idx0++;
5722 std::string::size_type idx1 = in_string.find_first_of('/', idx0);
5723 std::string::size_type len = (idx1 == LLString::npos) ? LLString::npos : idx1-idx0;
5724 LLString tstring = in_string.substr(idx0,len);
5725 S32 val = atoi(tstring.c_str());
5726 *res = llclamp(val,0,max);
5727 return idx1;
5728}
5729
5730// "simname/x/y/z" -> mSimName = simname, mX = x, mY = y, mZ = z
5731// static
5732bool LLURLSimString::parse()
5733{
5734 if (sInstance.mParseState == NOT_SET)
5735 {
5736 return false;
5737 }
5738 if (sInstance.mParseState == NOT_PARSED)
5739 {
5740 std::string::size_type idx0=0,idx1=LLString::npos;
5741 sInstance.mSimName.clear();
5742 if (!sInstance.mSimString.empty())
5743 {
5744 idx0 = sInstance.mSimString.find_first_not_of('/'); // strip any bogus initial '/'
5745 if (idx0 == LLString::npos) idx0 = 0;
5746 idx1 = sInstance.mSimString.find_first_of('/', idx0);
5747 std::string::size_type len = (idx1 == LLString::npos) ? LLString::npos : idx1-idx0;
5748 LLString tstring = sInstance.mSimString.substr(idx0,len);
5749 char* curlstr = curl_unescape(tstring.c_str(), tstring.size());
5750 sInstance.mSimName = LLString(curlstr);
5751 curl_free(curlstr);
5752 }
5753 if (!sInstance.mSimName.empty())
5754 {
5755 if (idx1 != LLString::npos)
5756 {
5757 idx1 = parseGridIdx(sInstance.mSimString, idx1, &sInstance.mX, 255);
5758 idx1 = parseGridIdx(sInstance.mSimString, idx1, &sInstance.mY, 255);
5759 idx1 = parseGridIdx(sInstance.mSimString, idx1, &sInstance.mZ, 1000);
5760 }
5761 sInstance.mParseState = PARSE_OK;
5762 }
5763 else
5764 {
5765 sInstance.mParseState = PARSE_FAIL;
5766 }
5767 }
5768 return (sInstance.mParseState == PARSE_OK);
5769}
5770
5771//static
5772bool LLURLSimString::unpack_data(void* data)
5773{
5774 llurl_data* url_data = (llurl_data*)data;
5775
5776 sInstance.mSimName = url_data->mSimName;
5777 if (!sInstance.mSimName.empty())
5778 {
5779 sInstance.mX = llclamp(url_data->mSimX, 0, 255);
5780 sInstance.mY = llclamp(url_data->mSimY, 0, 255);
5781 sInstance.mZ = llclamp(url_data->mSimZ, 0, 1000);
5782 sInstance.mSimString = llformat("%s/%d/%d/%d",
5783 sInstance.mSimName.c_str(),
5784 sInstance.mX,sInstance.mY,sInstance.mZ);
5785 sInstance.mParseState = PARSE_OK;
5786 }
5787 else
5788 {
5789 sInstance.mSimString.clear();
5790 sInstance.mParseState = PARSE_FAIL;
5791 }
5792 return true;
5793}
5794
5795//static
5796bool LLURLSimString::send_to_other_instance()
5797{
5798 if (!parse())
5799 {
5800 return false;
5801 }
5802#if LL_WINDOWS
5803 wchar_t window_class[256]; /* Flawfinder: ignore */ // Assume max length < 255 chars.
5804 mbstowcs(window_class, gWindowName.c_str(), 255);
5805 window_class[255] = 0;
5806 // Use the class instead of the window name.
5807 HWND other_window = FindWindow(window_class, NULL);
5808 if (other_window != NULL)
5809 {
5810 lldebugs << "Found other window with the name '" << gWindowTitle << "'" << llendl;
5811 llurl_data url_data;
5812 strncpy(url_data.mSimName, sInstance.mSimName.c_str(), DB_SIM_NAME_BUF_SIZE); /* Flawfinder: ignore*/
5813 url_data.mSimName[DB_SIM_NAME_BUF_SIZE - 1] = '\0';
5814 url_data.mSimX = sInstance.mX;
5815 url_data.mSimY = sInstance.mY;
5816 url_data.mSimZ = sInstance.mZ;
5817 COPYDATASTRUCT url_CDS;
5818 url_CDS.dwData = 0;
5819 url_CDS.cbData = sizeof(llurl_data);
5820 url_CDS.lpData = &url_data;
5821
5822 LRESULT msg_result = SendMessage(other_window, WM_COPYDATA, NULL, (LPARAM)&url_CDS);
5823 lldebugs << "SendMessage(WM_COPYDATA) to other window '"
5824 << gWindowTitle << "' returned " << msg_result << llendl;
5825 return true;
5826 }
5827#endif
5828 return false;
5829}
5830
5831
5832//============================================================================
5833
5834void load_name_cache() 5755void load_name_cache()
5835{ 5756{
5836 if (!gCacheName) return; 5757 if (!gCacheName) return;
@@ -5968,6 +5889,7 @@ void app_force_exit(S32 arg)
5968 exit(arg); 5889 exit(arg);
5969} 5890}
5970 5891
5892// Callback from a dialog indicating user was logged out.
5971void finish_disconnect(S32 option, void* userdata) 5893void finish_disconnect(S32 option, void* userdata)
5972{ 5894{
5973 if (1 == option) 5895 if (1 == option)
@@ -5976,6 +5898,12 @@ void finish_disconnect(S32 option, void* userdata)
5976 } 5898 }
5977} 5899}
5978 5900
5901// Callback from an early disconnect dialog, force an exit
5902void finish_forced_disconnect(S32 /* option */, void* /* userdata */)
5903{
5904 app_force_quit(NULL);
5905}
5906
5979void send_logout_request() 5907void send_logout_request()
5980{ 5908{
5981 if(!gLogoutRequestSent) 5909 if(!gLogoutRequestSent)
@@ -6003,18 +5931,28 @@ void do_disconnect(const LLString& mesg)
6003 // do this again. 5931 // do this again.
6004 return; 5932 return;
6005 } 5933 }
6006 5934
6007 //RN: just quit if we haven't logged in 5935 // Translate the message if possible
6008 if (LLStartUp::getStartupState() < STATE_STARTED) 5936 LLString big_reason = LLAgent::sTeleportErrorMessages[mesg];
5937 if ( big_reason.size() == 0 )
6009 { 5938 {
6010 finish_disconnect(1, NULL); 5939 big_reason = mesg;
6011 return;
6012 } 5940 }
6013 5941
6014 gDoDisconnect = TRUE;
6015 LLStringBase<char>::format_map_t args; 5942 LLStringBase<char>::format_map_t args;
6016 args["[MESSAGE]"] = mesg; 5943 gDoDisconnect = TRUE;
6017 gViewerWindow->alertXml("YouHaveBeenLoggedOut", args, finish_disconnect); 5944
5945 if (LLStartUp::getStartupState() < STATE_STARTED)
5946 {
5947 // Tell users what happened
5948 args["[ERROR_MESSAGE]"] = big_reason;
5949 gViewerWindow->alertXml("ErrorMessage", args, finish_forced_disconnect);
5950 }
5951 else
5952 {
5953 args["[MESSAGE]"] = big_reason;
5954 gViewerWindow->alertXml("YouHaveBeenLoggedOut", args, finish_disconnect );
5955 }
6018} 5956}
6019 5957
6020const LLUUID& agent_get_id() 5958const LLUUID& agent_get_id()