diff options
Diffstat (limited to 'linden/indra/newview/viewer.cpp')
-rw-r--r-- | linden/indra/newview/viewer.cpp | 488 |
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 | ||
326 | LLString gSecondLife; | 325 | LLString gSecondLife; |
327 | LLString gWindowTitle; | 326 | LLString gWindowTitle; |
328 | LLString gWindowName("Second Life"); | 327 | static char sWindowClass[] = "Second Life"; |
329 | LLString gDisabledMessage; | 328 | LLString gDisabledMessage; |
330 | BOOL gHideLinks = FALSE; | 329 | BOOL gHideLinks = FALSE; |
331 | 330 | ||
@@ -447,11 +446,13 @@ U64 gFrameTime = 0; | |||
447 | F32 gFrameTimeSeconds = 0.f; | 446 | F32 gFrameTimeSeconds = 0.f; |
448 | F32 gFrameIntervalSeconds = 0.f; | 447 | F32 gFrameIntervalSeconds = 0.f; |
449 | U32 gFrameCount = 0; | 448 | U32 gFrameCount = 0; |
449 | U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground | ||
450 | U64 gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds | 450 | U64 gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds |
451 | U64 gSpaceTime = 0; // gSpaceTime is the time, according to the spaceserver. | 451 | U64 gSpaceTime = 0; // gSpaceTime is the time, according to the spaceserver. |
452 | 452 | ||
453 | // Timing Globals | 453 | // Timing Globals |
454 | LLTimer gRenderStartTime; | 454 | LLTimer gRenderStartTime; |
455 | LLFrameTimer gForegroundTime; | ||
455 | F32 gQuitAfterSeconds = 0.f; | 456 | F32 gQuitAfterSeconds = 0.f; |
456 | BOOL gRotateRight = FALSE; | 457 | BOOL gRotateRight = FALSE; |
457 | 458 | ||
@@ -482,8 +483,6 @@ LLVector3 gRelativeWindVec(0.0, 0.0, 0.0); | |||
482 | BOOL gVelocityInterpolate = TRUE; // (These are written once/frame with the data from gSavedSettings) | 483 | BOOL gVelocityInterpolate = TRUE; // (These are written once/frame with the data from gSavedSettings) |
483 | BOOL gPingInterpolate = TRUE; | 484 | BOOL gPingInterpolate = TRUE; |
484 | 485 | ||
485 | //static | ||
486 | LLURLSimString LLURLSimString::sInstance; | ||
487 | 486 | ||
488 | // | 487 | // |
489 | // System info | 488 | // System info |
@@ -618,6 +617,7 @@ void bad_network_handler(); | |||
618 | void disable_win_error_reporting(); | 617 | void disable_win_error_reporting(); |
619 | #endif | 618 | #endif |
620 | std::string get_serial_number(); | 619 | std::string get_serial_number(); |
620 | bool send_url_to_other_instance(const std::string& url); | ||
621 | BOOL another_instance_running(); | 621 | BOOL another_instance_running(); |
622 | void main_loop(); | 622 | void 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 | ||
1776 | bool 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 | |||
1757 | BOOL another_instance_running() | 1802 | BOOL 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 | ||
5190 | class ViewerStatsResponder : public LLHTTPClient::Responder | ||
5191 | { | ||
5192 | public: | ||
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 | */ | ||
5156 | void send_stats() | 5216 | void 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(<ime); | 5242 | time(<ime); |
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 | ||
5684 | LLString LLURLSimString::sLocationStringHome("My Home"); | ||
5685 | LLString LLURLSimString::sLocationStringLast("My Last Location"); | ||
5686 | |||
5687 | // "secondlife://simname/x/y/z" -> "simname/x/y/z" | ||
5688 | // (actually .*//foo -> foo) | ||
5689 | // static | ||
5690 | void 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 | ||
5715 | S32 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 | ||
5732 | bool 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 | ||
5772 | bool 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 | ||
5796 | bool 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 | |||
5834 | void load_name_cache() | 5755 | void 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. | ||
5971 | void finish_disconnect(S32 option, void* userdata) | 5893 | void 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 | ||
5902 | void finish_forced_disconnect(S32 /* option */, void* /* userdata */) | ||
5903 | { | ||
5904 | app_force_quit(NULL); | ||
5905 | } | ||
5906 | |||
5979 | void send_logout_request() | 5907 | void 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 | ||
6020 | const LLUUID& agent_get_id() | 5958 | const LLUUID& agent_get_id() |