aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llstartup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llstartup.cpp')
-rw-r--r--linden/indra/newview/llstartup.cpp3939
1 files changed, 3939 insertions, 0 deletions
diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp
new file mode 100644
index 0000000..5eabad3
--- /dev/null
+++ b/linden/indra/newview/llstartup.cpp
@@ -0,0 +1,3939 @@
1/**
2 * @file llstartup.cpp
3 * @brief startup routines.
4 *
5 * Copyright (c) 2004-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "llstartup.h"
31
32#if LL_WINDOWS
33# include <process.h> // _spawnl()
34#else
35# include <sys/stat.h> // mkdir()
36#endif
37
38#include "audioengine.h"
39
40#if LL_FMOD
41#include "audioengine_fmod.h"
42#endif
43
44#include "audiosettings.h"
45#include "llcachename.h"
46#include "llviewercontrol.h"
47#include "llcrypto.h"
48#include "lldir.h"
49#include "lleconomy.h"
50#include "llfiltersd2xmlrpc.h"
51#include "llfocusmgr.h"
52#include "imageids.h"
53#include "lllandmark.h"
54#include "llloginflags.h"
55#include "llmd5.h"
56#include "llmemorystream.h"
57#include "llregionhandle.h"
58#include "llsd.h"
59#include "llsdserialize.h"
60#include "llsdutil.h"
61#include "llsecondlifeurls.h"
62#include "llstring.h"
63#include "lluserrelations.h"
64#include "llversion.h"
65#include "llvfs.h"
66#include "llwindow.h" // for shell_open
67#include "message.h"
68#include "v3math.h"
69
70#include "llagent.h"
71#include "llagentpilot.h"
72#include "llasynchostbyname.h"
73#include "llfloateravatarpicker.h"
74#include "llcallbacklist.h"
75#include "llcallingcard.h"
76#include "llcolorscheme.h"
77#include "llconsole.h"
78#include "llcontainerview.h"
79#include "lldebugview.h"
80#include "lldrawable.h"
81#include "lleventnotifier.h"
82#include "llface.h"
83#include "llfeaturemanager.h"
84#include "llfloateraccounthistory.h"
85#include "llfloaterchat.h"
86#include "llfloatergesture.h"
87#include "llfloaterland.h"
88#include "llfloatertopobjects.h"
89#include "llfloaterrate.h"
90#include "llfloatertos.h"
91#include "llfloaterworldmap.h"
92#include "llframestats.h"
93#include "llframestatview.h"
94#include "llgesturemgr.h"
95#include "llgroupmgr.h"
96#include "llhudeffecttrail.h"
97#include "llhudmanager.h"
98#include "llhttpclient.h"
99#include "llimagebmp.h"
100#include "llinventorymodel.h"
101#include "llinventoryview.h"
102#include "llkeyboard.h"
103#include "llpanellogin.h"
104#include "llmutelist.h"
105#include "llnotify.h"
106#include "llpanelavatar.h"
107#include "llpaneldirbrowser.h"
108#include "llpaneldirland.h"
109#include "llpanelevent.h"
110#include "llpanelclassified.h"
111#include "llpanelpick.h"
112#include "llpanelplace.h"
113#include "llpanelgrouplandmoney.h"
114#include "llpanelgroupnotices.h"
115#include "llpreview.h"
116#include "llpreviewscript.h"
117#include "llselectmgr.h"
118#include "llsky.h"
119#include "llstatview.h"
120#include "llsurface.h"
121#include "lltoolmgr.h"
122#include "llui.h"
123#include "llurlwhitelist.h"
124#include "lluserauth.h"
125#include "llviewerassetstorage.h"
126#include "llviewercamera.h"
127#include "llviewerdisplay.h"
128#include "llviewergesture.h"
129#include "llviewerimagelist.h"
130#include "llviewermenu.h"
131#include "llviewermessage.h"
132#include "llviewernetwork.h"
133#include "llviewerobjectlist.h"
134#include "llviewerparcelmgr.h"
135#include "llviewerregion.h"
136#include "llviewerstats.h"
137#include "llviewerthrottle.h"
138#include "llviewerwindow.h"
139#include "llvoavatar.h"
140#include "llvoclouds.h"
141#include "llworld.h"
142#include "llworldmap.h"
143#include "llxfermanager.h"
144#include "pipeline.h"
145#include "viewer.h"
146#include "llmediaengine.h"
147#include "llfasttimerview.h"
148#include "llmozlib.h"
149#include "llweb.h"
150#include "llfloaterhtml.h"
151
152#if LL_WINDOWS
153#include "llwindebug.h"
154#include "lldxhardware.h"
155#endif
156
157#if LL_QUICKTIME_ENABLED
158#if LL_DARWIN
159#include <QuickTime/QuickTime.h>
160#else
161// quicktime specific includes
162#include "MacTypes.h"
163#include "QTML.h"
164#include "Movies.h"
165#include "FixMath.h"
166#endif
167#endif
168
169//
170// exported globals
171//
172
173// HACK: Allow server to change sun and moon IDs.
174// I can't figure out how to pass the appropriate
175// information into the LLVOSky constructor. JC
176LLUUID gSunTextureID = IMG_SUN;
177LLUUID gMoonTextureID = IMG_MOON;
178LLUUID gCloudTextureID = IMG_CLOUD_POOF;
179
180const char* SCREEN_HOME_FILENAME = "screen_home.bmp";
181const char* SCREEN_LAST_FILENAME = "screen_last.bmp";
182
183//
184// Imported globals
185//
186extern LLPointer<LLImageGL> gStartImageGL;
187extern S32 gStartImageWidth;
188extern S32 gStartImageHeight;
189extern std::string gSerialNumber;
190
191//
192// local globals
193//
194
195static LLHost gAgentSimHost;
196static BOOL gSkipOptionalUpdate = FALSE;
197
198bool gQuickTimeInitialized = false;
199static bool gGotUseCircuitCodeAck = false;
200LLString gInitialOutfit;
201LLString gInitialOutfitGender; // "male" or "female"
202
203
204//
205// local function declaration
206//
207
208void login_show();
209void login_callback(S32 option, void* userdata);
210LLString load_password_from_disk();
211void save_password_to_disk(const char* hashed_password);
212BOOL is_hex_string(U8* str, S32 len);
213void show_first_run_dialog();
214void first_run_dialog_callback(S32 option, void* userdata);
215void set_startup_status(const F32 frac, const char* string, const char* msg);
216void on_userserver_name_resolved( BOOL success, const LLString& host_name, U32 ip, void* userdata );
217void login_alert_status(S32 option, void* user_data);
218void update_app(BOOL mandatory, const std::string& message);
219void update_dialog_callback(S32 option, void *userdata);
220void login_packet_failed(void**, S32 result);
221void use_circuit_callback(void**, S32 result);
222void register_viewer_callbacks(LLMessageSystem* msg);
223void init_stat_view();
224void asset_callback_nothing(LLVFS*, const LLUUID&, LLAssetType::EType, void*, S32);
225void dialog_choose_gender_first_start();
226void callback_choose_gender(S32 option, void* userdata);
227void init_start_screen(S32 location_id);
228void release_start_screen();
229void process_connect_to_userserver(LLMessageSystem* msg, void**);
230
231
232//
233// exported functionality
234//
235
236//
237// local classes
238//
239class LLGestureInventoryFetchObserver : public LLInventoryFetchObserver
240{
241public:
242 LLGestureInventoryFetchObserver() {}
243 virtual void done()
244 {
245 // we've downloaded all the items, so repaint the dialog
246 LLFloaterGesture::refreshAll();
247
248 gInventory.removeObserver(this);
249 delete this;
250 }
251};
252
253
254
255// Returns FALSE to skip other idle processing. Should only return
256// TRUE when all initialization done.
257BOOL idle_startup()
258{
259 LLMemType mt1(LLMemType::MTYPE_STARTUP);
260
261 const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay");
262 const F32 TIMEOUT_SECONDS = 5.f;
263 const S32 MAX_TIMEOUT_COUNT = 3;
264 static LLTimer timeout;
265 static S32 timeout_count = 0;
266
267 static LLTimer login_time;
268
269 // until this is encapsulated, this little hack for the
270 // auth/transform loop will do.
271 static F32 progress = 0.10f;
272
273 static std::string auth_uri;
274 static std::string auth_method;
275 static std::string auth_desc;
276 static std::string auth_message;
277 static LLString firstname;
278 static LLString lastname;
279 static LLString password;
280 static std::vector<const char*> requested_options;
281
282 static U32 region_size = 256;
283 static F32 region_scale = 1.f;
284 static U64 first_sim_handle = 0;
285 static LLHost first_sim;
286 static std::string first_sim_seed_cap;
287
288 static LLVector3 initial_sun_direction(1.f, 0.f, 0.f);
289 static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server
290 static LLVector3 agent_start_look_at(1.0f, 0.f, 0.f);
291 static std::string agent_start_location = "safe";
292
293 // last location by default
294 static S32 agent_location_id = START_LOCATION_ID_LAST;
295 static S32 location_which = START_LOCATION_ID_LAST;
296
297 static BOOL show_connect_box = TRUE;
298 static BOOL remember_password = TRUE;
299
300 static BOOL stipend_since_login = FALSE;
301
302 static BOOL samename = FALSE;
303
304 static BOOL did_precache = FALSE;
305
306 BOOL do_normal_idle = FALSE;
307
308 // HACK: These are things from the main loop that usually aren't done
309 // until initialization is complete, but need to be done here for things
310 // to work.
311 gIdleCallbacks.callFunctions();
312 gViewerWindow->handlePerFrameHover();
313 LLMortician::updateClass();
314
315 if (gNoRender)
316 {
317 // HACK, skip optional updates if you're running drones
318 gSkipOptionalUpdate = TRUE;
319 }
320 else
321 {
322 // Update images?
323 gImageList.updateImages(0.01f);
324 }
325
326 if (STATE_FIRST == gStartupState)
327 {
328 gViewerWindow->showCursor();
329 gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
330
331 /////////////////////////////////////////////////
332 //
333 // Initialize stuff that doesn't need data from userserver/simulators
334 //
335
336 if (gFeatureManagerp->isSafe())
337 {
338 gViewerWindow->alertXml("DisplaySetToSafe");
339 }
340 else if (gSavedSettings.getS32("LastFeatureVersion") < gFeatureManagerp->getVersion())
341 {
342 if (gSavedSettings.getS32("LastFeatureVersion") != 0)
343 {
344 gViewerWindow->alertXml("DisplaySetToRecommended");
345 }
346 }
347 gSavedSettings.setS32("LastFeatureVersion", gFeatureManagerp->getVersion());
348
349 LLString xml_file = LLUI::locateSkin("xui_version.xml");
350 LLXMLNodePtr root;
351 bool xml_ok = false;
352 if (LLXMLNode::parseFile(xml_file, root, NULL))
353 {
354 if( (root->hasName("xui_version") ) )
355 {
356 LLString value = root->getValue();
357 F32 version = 0.0f;
358 LLString::convertToF32(value, version);
359 if (version >= 1.0f)
360 {
361 xml_ok = true;
362 }
363 }
364 }
365 if (!xml_ok)
366 {
367 // XUI:translate (maybe - very unlikely error message)
368 // Note: alerts.xml may be invalid - if this gets translated it will need to be in the code
369 LLString bad_xui_msg = "An error occured while updating Second Life. Please download the latest version from www.secondlife.com.";
370 app_early_exit(bad_xui_msg);
371 }
372 //
373 // Statistics stuff
374 //
375
376 // Load autopilot and stats stuff
377 gAgentPilot.load(gSavedSettings.getString("StatsPilotFile").c_str());
378 gFrameStats.setFilename(gSavedSettings.getString("StatsFile"));
379 gFrameStats.setSummaryFilename(gSavedSettings.getString("StatsSummaryFile"));
380
381 //gErrorStream.setTime(gSavedSettings.getBOOL("LogTimestamps"));
382
383 // Load the throttle settings
384 gViewerThrottle.load();
385
386 //
387 // Initialize messaging system
388 //
389 llinfos << "Initializing messaging system..." << llendl;
390
391 std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg");
392
393 FILE* found_template = NULL;
394 found_template = LLFile::fopen(message_template_path.c_str(), "r");
395 if (found_template)
396 {
397 fclose(found_template);
398
399 if(!start_messaging_system(
400 message_template_path,
401 gAgent.mViewerPort,
402 LL_VERSION_MAJOR,
403 LL_VERSION_MINOR,
404 LL_VERSION_PATCH,
405 FALSE,
406 std::string()))
407 {
408 std::string msg = llformat("Unable to start networking, error %d", gMessageSystem->getErrorCode());
409 app_early_exit(msg);
410 }
411 }
412 else
413 {
414 app_early_exit("Unable to initialize communications.");
415 }
416
417 if(gMessageSystem && gMessageSystem->isOK())
418 {
419 // Initialize all of the callbacks in case of bad message
420 // system data
421 LLMessageSystem* msg = gMessageSystem;
422 msg->setExceptionFunc(MX_UNREGISTERED_MESSAGE,
423 invalid_message_callback,
424 NULL);
425 msg->setExceptionFunc(MX_PACKET_TOO_SHORT,
426 invalid_message_callback,
427 NULL);
428 msg->setExceptionFunc(MX_RAN_OFF_END_OF_PACKET,
429 invalid_message_callback,
430 NULL);
431 msg->setExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE,
432 invalid_message_callback,
433 NULL);
434
435 gErrorStream.setUTCTimestamp(gLogUTC);
436 if (gSavedSettings.getBOOL("LogMessages") || gLogMessages)
437 {
438 llinfos << "Message logging activated!" << llendl;
439 msg->startLogging();
440 }
441
442 // start the xfer system. by default, choke the downloads
443 // a lot...
444 const S32 VIEWER_MAX_XFER = 3;
445 start_xfer_manager(gVFS);
446 gXferManager->setMaxIncomingXfers(VIEWER_MAX_XFER);
447 F32 xfer_throttle_bps = gSavedSettings.getF32("XferThrottle");
448 if (xfer_throttle_bps > 1.f)
449 {
450 gXferManager->setUseAckThrottling(TRUE);
451 gXferManager->setAckThrottleBPS(xfer_throttle_bps);
452 }
453 gAssetStorage = new LLViewerAssetStorage(msg, gXferManager, gVFS, gUserServer);
454
455 msg->mPacketRing.setDropPercentage(gPacketDropPercentage);
456 if (gInBandwidth != 0.f)
457 {
458 llinfos << "Setting packetring incoming bandwidth to " << gInBandwidth << llendl;
459 msg->mPacketRing.setUseInThrottle(TRUE);
460 msg->mPacketRing.setInBandwidth(gInBandwidth);
461 }
462 if (gOutBandwidth != 0.f)
463 {
464 llinfos << "Setting packetring outgoing bandwidth to " << gOutBandwidth << llendl;
465 msg->mPacketRing.setUseOutThrottle(TRUE);
466 msg->mPacketRing.setOutBandwidth(gOutBandwidth);
467 }
468 }
469
470 // initialize the economy
471 gGlobalEconomy = new LLGlobalEconomy();
472
473 //---------------------------------------------------------------------
474 // LibXUL (Mozilla) initialization
475 //---------------------------------------------------------------------
476 #if LL_LIBXUL_ENABLED
477 set_startup_status(0.48f, "Initializing embedded web browser...", gAgent.mMOTD.c_str());
478 display_startup();
479
480 #if LL_DARWIN
481 // For Mac OS, we store both the shared libraries and the runtime files (chrome/, plugins/, etc) in
482 // Second Life.app/Contents/MacOS/. This matches the way Firefox is distributed on the Mac.
483 std::string profileBaseDir(gDirUtilp->getExecutableDir());
484 #else
485 std::string profileBaseDir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) );
486 profileBaseDir += gDirUtilp->getDirDelimiter();
487 #ifdef LL_DEBUG
488 profileBaseDir += "mozilla_debug";
489 #else
490 profileBaseDir += "mozilla";
491 #endif
492 #endif
493 LLMozLib::getInstance()->init( profileBaseDir, gDirUtilp->getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" ) );
494
495 std::ostringstream codec;
496 codec << "[Second Life " << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH << "." << LL_VERSION_BUILD << "]";
497 LLMozLib::getInstance()->setBrowserAgentId( codec.str() );
498 #endif
499
500 //-------------------------------------------------
501 // Init audio, which may be needed for prefs dialog
502 // or audio cues in connection UI.
503 //-------------------------------------------------
504
505 if (gUseAudio)
506 {
507#if LL_FMOD
508 gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD();
509#else
510 gAudiop = NULL;
511#endif
512
513 if (gAudiop)
514 {
515#if LL_WINDOWS
516 // FMOD on Windows needs the window handle to stop playing audio
517 // when window is minimized. JC
518 void* window_handle = (HWND)gViewerWindow->getPlatformWindow();
519#else
520 void* window_handle = NULL;
521#endif
522 BOOL init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle);
523 if(!init)
524 {
525 llwarns << "Unable to initialize audio engine" << llendl;
526 }
527 gAudiop->setMuted(TRUE);
528 }
529 }
530
531 if (LLTimer::knownBadTimer())
532 {
533 llwarns << "Unreliable timers detected (may be bad PCI chipset)!!" << llendl;
534 }
535
536 // Get ready to show the login dialog
537 if (!gConnectToSomething)
538 {
539 // Don't use a session token, and generate a random user id
540 gAgentID.generate();
541 gAgentSessionID = LLUUID::null;
542
543 gStartupState = STATE_WORLD_INIT;
544 return do_normal_idle;
545 }
546 else if (!gRunLocal)
547 {
548 //
549 // Log on to userserver
550 //
551 if( !gCmdLineFirstName.empty()
552 && !gCmdLineLastName.empty()
553 && !gCmdLinePassword.empty())
554 {
555 firstname = gCmdLineFirstName;
556 lastname = gCmdLineLastName;
557
558 LLMD5 pass((unsigned char*)gCmdLinePassword.c_str());
559 char md5pass[33];
560 pass.hex_digest(md5pass);
561 password = md5pass;
562
563 remember_password = gSavedSettings.getBOOL("RememberPassword");
564 show_connect_box = FALSE;
565 }
566 else if (gAutoLogin || gSavedSettings.getBOOL("AutoLogin"))
567 {
568 firstname = gSavedSettings.getString("FirstName");
569 lastname = gSavedSettings.getString("LastName");
570 password = load_password_from_disk();
571 remember_password = TRUE;
572 show_connect_box = FALSE;
573 }
574 else
575 {
576 // if not automatically logging in, display login dialog
577 // until a valid userserver is selected
578 firstname = gSavedSettings.getString("FirstName");
579 lastname = gSavedSettings.getString("LastName");
580 password = load_password_from_disk();
581 remember_password = gSavedSettings.getBOOL("RememberPassword");
582 show_connect_box = TRUE;
583 }
584
585 // Go to the next startup state
586 gStartupState++;
587 return do_normal_idle;
588 }
589 else
590 {
591 gStartupState++;
592 return do_normal_idle;
593 }
594 }
595
596 if (STATE_LOGIN_SHOW == gStartupState)
597 {
598 gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
599 // Push our window frontmost
600 gViewerWindow->getWindow()->show();
601
602 timeout_count = 0;
603
604 if (gConnectToSomething && !gRunLocal)
605 {
606 if (show_connect_box)
607 {
608 if (gNoRender)
609 {
610 llerrs << "Need to autologin or use command line with norender!" << llendl;
611 }
612 // Make sure the process dialog doesn't hide things
613 gViewerWindow->setShowProgress(FALSE);
614
615 // Show the login dialog
616 login_show();
617
618 // connect dialog is already shown, so fill in the names
619 LLPanelLogin::setFields( firstname, lastname, password, remember_password );
620 LLPanelLogin::giveFocus();
621
622 gSavedSettings.setBOOL("FirstRunThisInstall", FALSE);
623
624 gStartupState++;
625 }
626 else
627 {
628 // skip directly to message template verification
629 gStartupState = STATE_LOGIN_CLEANUP;
630 }
631 }
632 else
633 {
634 gMessageSystem->setCircuitProtection(FALSE);
635 gStartupState = STATE_LOGIN_CLEANUP;
636 }
637
638 timeout.reset();
639 return do_normal_idle;
640 }
641
642 if (STATE_LOGIN_WAIT == gStartupState)
643 {
644 // Don't do anything. Wait for the login view to call the login_callback,
645 // which will push us to the next state.
646
647 // Sleep so we don't spin the CPU
648 ms_sleep(1);
649 return do_normal_idle;
650 }
651
652 if (STATE_LOGIN_CLEANUP == gStartupState)
653 {
654 if (show_connect_box)
655 {
656 // Load all the name information out of the login view
657 LLPanelLogin::getFields(firstname, lastname, password, remember_password);
658
659 // HACK: Try to make not jump on login
660 gKeyboard->resetKeys();
661 }
662
663 if (!firstname.empty() && !lastname.empty())
664 {
665 gSavedSettings.setString("FirstName", firstname);
666 gSavedSettings.setString("LastName", lastname);
667
668 llinfos << "Attempting login as: " << firstname << " " << lastname << llendl;
669 write_debug("Attempting login as: ");
670 write_debug(firstname);
671 write_debug(" ");
672 write_debug(lastname);
673 write_debug("\n");
674 }
675
676 // create necessary directories
677 // *FIX: these mkdir's should error check
678 gDirUtilp->setLindenUserDir(firstname.c_str(), lastname.c_str());
679
680
681 LLFile::mkdir(gDirUtilp->getLindenUserDir().c_str());
682
683 // the mute list is loaded in the llmutelist class.
684
685 gSavedSettings.loadFromFile(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT,"overrides.xml"));
686
687 // handle the per account settings setup
688 strcpy(gPerAccountSettingsFileName, gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, DEFAULT_SETTINGS_FILE).c_str());
689
690 // per account settings. Set defaults here if not found. If we get a bunch of these, eventually move to a function.
691 gSavedPerAccountSettings.loadFromFile(gPerAccountSettingsFileName);
692
693 // Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation
694 // and startup time is close enough if we don't have a real value.
695 if (gSavedPerAccountSettings.getU32("LastLogoff") == 0)
696 {
697 gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
698 }
699
700 //Default the path if one isn't set.
701 if (gSavedPerAccountSettings.getString("InstantMessageLogPath").empty())
702 {
703 gDirUtilp->setChatLogsDir(gDirUtilp->getOSUserAppDir());
704 gSavedPerAccountSettings.setString("InstantMessageLogPath",gDirUtilp->getChatLogsDir());
705 }
706 else
707 {
708 gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath"));
709 }
710
711 gDirUtilp->setPerAccountChatLogsDir(firstname.c_str(), lastname.c_str());
712
713 LLFile::mkdir(gDirUtilp->getChatLogsDir().c_str());
714 LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir().c_str());
715
716
717#if LL_WINDOWS
718 if (gSavedSettings.getBOOL("UseDebugLogin") && show_connect_box)
719#else
720 if (show_connect_box)
721#endif
722 {
723 LLString server_label;
724 S32 domain_name_index;
725 LLPanelLogin::getServer( server_label, domain_name_index );
726 gUserServerChoice = (EUserServerDomain) domain_name_index;
727 gSavedSettings.setS32("ServerChoice", gUserServerChoice);
728 if (gUserServerChoice == USERSERVER_OTHER)
729 {
730 gUserServer.setHostByName( server_label.c_str() );
731 snprintf(gUserServerName, MAX_STRING, "%s", server_label.c_str());
732 }
733 }
734
735 if (show_connect_box)
736 {
737 LLString location;
738 LLPanelLogin::getLocation( location );
739 LLURLSimString::setString( location );
740 LLPanelLogin::close();
741 }
742
743 //For HTML parsing in text boxes.
744 LLTextEditor::setLinkColor( gSavedSettings.getColor4("HTMLLinkColor") );
745 LLTextEditor::setURLCallbacks ( &LLWeb::loadURL, &process_secondlife_url );
746
747 //-------------------------------------------------
748 // Handle startup progress screen
749 //-------------------------------------------------
750
751 // on startup the user can request to go to their home,
752 // their last location, or some URL "-url //sim/x/y[/z]"
753 // All accounts have both a home and a last location, and we don't support
754 // more locations than that. Choose the appropriate one. JC
755 if (LLURLSimString::parse())
756 {
757 // a startup URL was specified
758 agent_location_id = START_LOCATION_ID_TELEHUB;
759
760 // doesn't really matter what location_which is, since
761 // agent_start_look_at will be overwritten when the
762 // UserLoginLocationReply arrives
763 location_which = START_LOCATION_ID_LAST;
764 }
765 else if (gSavedSettings.getBOOL("LoginLastLocation"))
766 {
767 agent_location_id = START_LOCATION_ID_LAST; // last location
768 location_which = START_LOCATION_ID_LAST;
769 }
770 else
771 {
772 agent_location_id = START_LOCATION_ID_HOME; // home
773 location_which = START_LOCATION_ID_HOME;
774 }
775
776 gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
777
778 if (!gNoRender)
779 {
780 init_start_screen(agent_location_id);
781 }
782
783 // Display the startup progress bar.
784 gViewerWindow->setShowProgress(TRUE);
785 gViewerWindow->setProgressCancelButtonVisible(TRUE, "Quit");
786
787 // Poke the VFS, which could potentially block for a while if
788 // Windows XP is acting up
789 set_startup_status(0.05f, "Verifying cache files (can take 60-90 seconds)...", NULL);
790 display_startup();
791
792 gVFS->pokeFiles();
793
794 // color init must be after saved settings loaded
795 init_colors();
796
797 // Request userserver domain name
798 set_startup_status(0.05f, "Finding Server Domain Name...", NULL);
799
800 // We're prematurely switching out of this state because the
801 // userserver name resolver can potentiallly occur before reaching the end of the
802 // switch statement. Also, if it's done at the bottom, sometimes we will
803 // skip the userserver resolved step (in the local cases) - djs 09/24/03
804 gStartupState++;
805 timeout.reset();
806
807 switch( gUserServerChoice )
808 {
809 case USERSERVER_AGNI:
810 gInProductionGrid = TRUE;
811 case USERSERVER_DMZ:
812 case USERSERVER_ADITI:
813 case USERSERVER_SIVA:
814 case USERSERVER_SHAKTI:
815 case USERSERVER_DURGA:
816 case USERSERVER_SOMA:
817 case USERSERVER_GANGA:
818 case USERSERVER_UMA:
819 {
820 const char* host_name = gUserServerDomainName[gUserServerChoice].mName;
821 sprintf(gUserServerName,"%s", host_name);
822 llinfos << "Resolving " <<
823 gUserServerDomainName[gUserServerChoice].mLabel <<
824 " userserver domain name " << host_name << llendl;
825
826 BOOL requested_domain_name = gAsyncHostByName.startRequest( host_name, on_userserver_name_resolved, NULL );
827 if( !requested_domain_name )
828 //BOOL resolved_domain_name = gUserServer.setHostByName( host_name );
829 //if( !resolved_domain_name )
830 {
831 llwarns << "setHostByName failed" << llendl;
832
833 LLStringBase<char>::format_map_t args;
834 args["[HOST_NAME]"] = host_name;
835
836 gViewerWindow->alertXml("UnableToConnect", args, login_alert_done );
837 gStartupState = STATE_LOGIN_SHOW;
838 return FALSE;
839 }
840 break;
841 }
842
843 case USERSERVER_LOCAL:
844 llinfos << "Using local userserver" << llendl;
845 gUserServer.setAddress( LOOPBACK_ADDRESS_STRING );
846 gStartupState = STATE_USERSERVER_RESOLVED;
847 break;
848
849 case USERSERVER_OTHER:
850 llinfos << "Userserver set explicitly" << llendl;
851 gStartupState = STATE_USERSERVER_RESOLVED;
852 break;
853
854 case USERSERVER_NONE:
855 default:
856 llerrs << "No userserver IP address specified" << llendl;
857 break;
858 }
859 return do_normal_idle;
860 }
861
862 if (STATE_RESOLVING_USERSERVER == gStartupState)
863 {
864 // Don't do anything. Wait for LL_WM_HOST_RESOLVED which is handled by LLAsyncHostByName,
865 // which calls on_userserver_name_resolved, which will push us to the next state.
866 if (timeout.getElapsedTimeF32() > TIMEOUT_SECONDS*3.f)
867 {
868 // Cancel the pending asynchostbyname request
869
870 gViewerWindow->alertXml("CanNotFindServer",
871 login_alert_status, NULL);
872
873 // Back up to login screen
874 gStartupState = STATE_LOGIN_SHOW;
875 gViewerStats->incStat(LLViewerStats::ST_LOGIN_TIMEOUT_COUNT);
876 }
877 ms_sleep(1);
878 return do_normal_idle;
879 }
880
881 if (STATE_USERSERVER_RESOLVED == gStartupState)
882 {
883 if (!gUserServer.isOk())
884 {
885 LLStringBase<char>::format_map_t args;
886 args["[IP_ADDRESS]"] = u32_to_ip_string( gUserServer.getAddress() );
887
888 gViewerWindow->alertXml("PleaseSelectServer", args, login_alert_done );
889
890 gStartupState = STATE_LOGIN_SHOW;
891 return FALSE;
892 }
893
894 write_debug("Userserver: ");
895 char tmp_str[256];
896 gUserServer.getIPString(tmp_str, 256);
897 write_debug(tmp_str);
898 write_debug("\n");
899
900 gStartupState++;
901 }
902
903 if (STATE_MESSAGE_TEMPLATE_SEND == gStartupState)
904 {
905 set_startup_status(0.10f, "Verifying protocol version...", NULL);
906
907 LLHost mt_host;
908 if (!gRunLocal)
909 {
910 // open up user server circuit (trusted)
911 gMessageSystem->enableCircuit(gUserServer, TRUE);
912 mt_host = gUserServer;
913 }
914 else
915 {
916 mt_host = gAgentSimHost;
917 }
918
919 llinfos << "Verifying message template..." << llendl;
920
921 // register with the message system so it knows we're
922 // expecting this message
923 LLMessageSystem* msg = gMessageSystem;
924 msg->setHandlerFuncFast(_PREHASH_TemplateChecksumReply, null_message_callback, NULL);
925 msg->newMessageFast(_PREHASH_SecuredTemplateChecksumRequest);
926 msg->nextBlockFast(_PREHASH_TokenBlock);
927 lldebugs << "random token: " << gTemplateToken << llendl;
928 msg->addUUIDFast(_PREHASH_Token, gTemplateToken);
929 msg->sendReliable(mt_host);
930
931 timeout.reset();
932 gStartupState++;
933 return do_normal_idle;
934 }
935
936 if (STATE_MESSAGE_TEMPLATE_WAIT == gStartupState)
937 {
938 U32 remote_template_checksum = 0;
939
940 U8 major_version = 0;
941 U8 minor_version = 0;
942 U8 patch_version = 0;
943 U8 server_version = 0;
944 U32 flags = 0x0;
945
946 LLMessageSystem* msg = gMessageSystem;
947 while (msg->checkMessages(gFrameCount))
948 {
949 if (msg->isMessageFast(_PREHASH_TemplateChecksumReply))
950 {
951 LLUUID token;
952 msg->getUUID("TokenBlock", "Token", token);
953 if(token != gTemplateToken)
954 {
955 llwarns << "Incorrect token in template checksum reply: "
956 << token << llendl;
957 return do_normal_idle;
958 }
959 msg->getU32("DataBlock", "Checksum", remote_template_checksum);
960 msg->getU8 ("DataBlock", "MajorVersion", major_version);
961 msg->getU8 ("DataBlock", "MinorVersion", minor_version);
962 msg->getU8 ("DataBlock", "PatchVersion", patch_version);
963 msg->getU8 ("DataBlock", "ServerVersion", server_version);
964 msg->getU32("DataBlock", "Flags", flags);
965
966 BOOL update_available = FALSE;
967 BOOL mandatory = FALSE;
968
969 if (remote_template_checksum != msg->mMessageFileChecksum)
970 {
971 llinfos << "Message template out of sync" << llendl;
972 // Mandatory update -- message template checksum doesn't match
973 update_available = TRUE;
974 mandatory = TRUE;
975 }
976
977 BOOL quit = FALSE;
978 if (update_available)
979 {
980 if (show_connect_box)
981 {
982 update_app(mandatory, "");
983 gStartupState = STATE_UPDATE_CHECK;
984 return FALSE;
985 }
986 else
987 {
988 quit = TRUE;
989 }
990 }
991 // Bail out and clean up circuit
992 if (quit)
993 {
994 msg->newMessageFast(_PREHASH_CloseCircuit);
995 msg->sendMessage( msg->getSender() );
996 app_force_quit(NULL);
997 return FALSE;
998 }
999
1000 // If we get here, we've got a compatible message template
1001
1002 if (!mandatory)
1003 {
1004 llinfos << "Message template is current!" << llendl;
1005 }
1006 gStartupState = STATE_LOGIN_AUTH_INIT;
1007 timeout.reset();
1008 // unregister with the message system so it knows we're no longer expecting this message
1009 msg->setHandlerFuncFast(_PREHASH_TemplateChecksumReply, NULL, NULL);
1010
1011 msg->newMessageFast(_PREHASH_CloseCircuit);
1012 msg->sendMessage(gUserServer);
1013 msg->disableCircuit(gUserServer);
1014 if (gRunLocal)
1015 {
1016 msg->enableCircuit(gAgentSimHost, TRUE);
1017
1018 // Don't use a session token, and generate a random user id
1019 gAgentID.generate();
1020 gAgentSessionID = LLUUID::null;
1021
1022 // Skip userserver queries.
1023 gStartupState = STATE_WORLD_INIT;
1024 }
1025 }
1026 }
1027 gMessageSystem->processAcks();
1028
1029 if (timeout.getElapsedTimeF32() > TIMEOUT_SECONDS)
1030 {
1031 if (timeout_count > MAX_TIMEOUT_COUNT)
1032 {
1033 gViewerWindow->alertXml("SystemMayBeDown",
1034 login_alert_status,
1035 NULL);
1036
1037 // Back up to login screen
1038 gStartupState = STATE_LOGIN_SHOW;
1039 gViewerStats->incStat(LLViewerStats::ST_LOGIN_TIMEOUT_COUNT);
1040 }
1041 else
1042 {
1043 llinfos << "Resending on timeout" << llendl;
1044 gStartupState--;
1045 timeout_count++;
1046 }
1047 }
1048
1049 return do_normal_idle;
1050 }
1051
1052 if (STATE_UPDATE_CHECK == gStartupState)
1053 {
1054 return do_normal_idle;
1055 }
1056
1057 if(STATE_LOGIN_AUTH_INIT == gStartupState)
1058 {
1059//#define LL_MINIMIAL_REQUESTED_OPTIONS
1060 lldebugs << "STATE_LOGIN_AUTH_INIT" << llendl;
1061 if (!gUserAuthp)
1062 {
1063 gUserAuthp = new LLUserAuth();
1064 }
1065 requested_options.clear();
1066 requested_options.push_back("inventory-root");
1067 requested_options.push_back("inventory-skeleton");
1068 //requested_options.push_back("inventory-meat");
1069 //requested_options.push_back("inventory-skel-targets");
1070#if (!defined LL_MINIMIAL_REQUESTED_OPTIONS)
1071 if(gRequestInventoryLibrary)
1072 {
1073 requested_options.push_back("inventory-lib-root");
1074 requested_options.push_back("inventory-lib-owner");
1075 requested_options.push_back("inventory-skel-lib");
1076 // requested_options.push_back("inventory-meat-lib");
1077 }
1078
1079 requested_options.push_back("initial-outfit");
1080 requested_options.push_back("gestures");
1081 requested_options.push_back("event_categories");
1082 requested_options.push_back("event_notifications");
1083 requested_options.push_back("classified_categories");
1084 //requested_options.push_back("inventory-targets");
1085 requested_options.push_back("buddy-list");
1086 requested_options.push_back("ui-config");
1087#endif
1088 requested_options.push_back("login-flags");
1089 requested_options.push_back("global-textures");
1090 if(gGodConnect)
1091 {
1092 gSavedSettings.setBOOL("UseDebugMenus", TRUE);
1093 requested_options.push_back("god-connect");
1094 }
1095 auth_uri = getLoginURI();
1096 auth_method = "login_to_simulator";
1097 auth_desc = "Logging in. ";
1098 auth_desc += gSecondLife;
1099 auth_desc += " may appear frozen. Please wait.";
1100 ++gStartupState;
1101 }
1102
1103 if (STATE_LOGIN_AUTHENTICATE == gStartupState)
1104 {
1105 lldebugs << "STATE_LOGIN_AUTHENTICATE" << llendl;
1106 set_startup_status(progress, auth_desc.c_str(), auth_message.c_str());
1107 progress += 0.02f;
1108 display_startup();
1109
1110 std::stringstream start;
1111 if (LLURLSimString::parse())
1112 {
1113 // a startup URL was specified
1114 std::stringstream unescaped_start;
1115 unescaped_start << "uri:"
1116 << LLURLSimString::sInstance.mSimName << "&"
1117 << LLURLSimString::sInstance.mX << "&"
1118 << LLURLSimString::sInstance.mY << "&"
1119 << LLURLSimString::sInstance.mZ;
1120 start << xml_escape_string(unescaped_start.str().c_str());
1121 }
1122 else if (gSavedSettings.getBOOL("LoginLastLocation"))
1123 {
1124 start << "last";
1125 }
1126 else
1127 {
1128 start << "home";
1129 }
1130
1131 char hashed_mac_string[MD5HEX_STR_SIZE];
1132 LLMD5 hashed_mac;
1133 hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES );
1134 hashed_mac.finalize();
1135 hashed_mac.hex_digest(hashed_mac_string);
1136
1137 gUserAuthp->authenticate(
1138 auth_uri.c_str(),
1139 auth_method.c_str(),
1140 firstname.c_str(),
1141 lastname.c_str(),
1142 password.c_str(),
1143 start.str().c_str(),
1144 gSkipOptionalUpdate,
1145 gAcceptTOS,
1146 gAcceptCriticalMessage,
1147 gViewerDigest,
1148 gLastExecFroze,
1149 requested_options,
1150 hashed_mac_string,
1151 gSerialNumber);
1152 // reset globals
1153 gAcceptTOS = FALSE;
1154 gAcceptCriticalMessage = FALSE;
1155 ++gStartupState;
1156 return do_normal_idle;
1157 }
1158
1159 if(STATE_LOGIN_NO_DATA_YET == gStartupState)
1160 {
1161 //lldebugs << "STATE_LOGIN_NO_DATA_YET" << llendl;
1162 if (!gUserAuthp)
1163 {
1164 llerrs << "No userauth in STATE_LOGIN_NO_DATA_YET!" << llendl;
1165 }
1166 // Process messages to keep from dropping circuit.
1167 LLMessageSystem* msg = gMessageSystem;
1168 while (msg->checkMessages(gFrameCount))
1169 {
1170 }
1171 msg->processAcks();
1172 LLUserAuth::UserAuthcode error = gUserAuthp->authResponse();
1173 if(LLUserAuth::E_NO_RESPONSE_YET == error)
1174 {
1175 //llinfos << "waiting..." << llendl;
1176 return do_normal_idle;
1177 }
1178 ++gStartupState;
1179 progress += 0.01f;
1180 set_startup_status(progress, auth_desc.c_str(), auth_message.c_str());
1181 return do_normal_idle;
1182 }
1183
1184 if(STATE_LOGIN_DOWNLOADING == gStartupState)
1185 {
1186 lldebugs << "STATE_LOGIN_DOWNLOADING" << llendl;
1187 if (!gUserAuthp)
1188 {
1189 llerrs << "No userauth in STATE_LOGIN_DOWNLOADING!" << llendl;
1190 }
1191 // Process messages to keep from dropping circuit.
1192 LLMessageSystem* msg = gMessageSystem;
1193 while (msg->checkMessages(gFrameCount))
1194 {
1195 }
1196 msg->processAcks();
1197 LLUserAuth::UserAuthcode error = gUserAuthp->authResponse();
1198 if(LLUserAuth::E_DOWNLOADING == error)
1199 {
1200 //llinfos << "downloading..." << llendl;
1201 return do_normal_idle;
1202 }
1203 ++gStartupState;
1204 progress += 0.01f;
1205 set_startup_status(progress, "Processing Response...", auth_message.c_str());
1206 return do_normal_idle;
1207 }
1208
1209 if(STATE_LOGIN_PROCESS_RESPONSE == gStartupState)
1210 {
1211 lldebugs << "STATE_LOGIN_PROCESS_RESPONSE" << llendl;
1212 std::ostringstream emsg;
1213 BOOL quit = FALSE;
1214 const char* login_response = NULL;
1215 const char* reason_response = NULL;
1216 const char* message_response = NULL;
1217 BOOL successful_login = FALSE;
1218 LLUserAuth::UserAuthcode error = gUserAuthp->authResponse();
1219 // reset globals
1220 gAcceptTOS = FALSE;
1221 gAcceptCriticalMessage = FALSE;
1222 switch(error)
1223 {
1224 case LLUserAuth::E_OK:
1225 login_response = gUserAuthp->getResponse("login");
1226 if(login_response && (0 == strcmp(login_response, "true")))
1227 {
1228 // Yay, login!
1229 successful_login = TRUE;
1230 }
1231 else if(login_response && (0 == strcmp(login_response, "indeterminate")))
1232 {
1233 llinfos << "Indeterminate login..." << llendl;
1234 auth_uri = gUserAuthp->getResponse("next_url");
1235 auth_method = gUserAuthp->getResponse("next_method");
1236 auth_message = gUserAuthp->getResponse("message");
1237 if(auth_method.substr(0, 5) == "login")
1238 {
1239 auth_desc.assign("Authenticating...");
1240 }
1241 else
1242 {
1243 auth_desc.assign("Performing account maintenance...");
1244 }
1245 // ignoring the duration & options array for now.
1246 // Go back to authenticate.
1247 gStartupState = STATE_LOGIN_AUTHENTICATE;
1248 return do_normal_idle;
1249 }
1250 else
1251 {
1252 emsg << "Login failed.\n";
1253 reason_response = gUserAuthp->getResponse("reason");
1254 message_response = gUserAuthp->getResponse("message");
1255
1256 if (gHideLinks && reason_response && (0 == strcmp(reason_response, "disabled")))
1257 {
1258 emsg << gDisabledMessage;
1259 }
1260 else if (message_response)
1261 {
1262 emsg << message_response;
1263 }
1264
1265 if(reason_response && (0 == strcmp(reason_response, "tos")))
1266 {
1267 if (show_connect_box)
1268 {
1269 llinfos << "Need tos agreement" << llendl;
1270 gStartupState = STATE_UPDATE_CHECK;
1271 LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS,
1272 message_response);
1273 tos_dialog->startModal();
1274 // LLFloaterTOS deletes itself.
1275 return FALSE;
1276 }
1277 else
1278 {
1279 quit = TRUE;
1280 }
1281 }
1282 if(reason_response && (0 == strcmp(reason_response, "critical")))
1283 {
1284 if (show_connect_box)
1285 {
1286 llinfos << "Need critical message" << llendl;
1287 gStartupState = STATE_UPDATE_CHECK;
1288 LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE,
1289 message_response);
1290 tos_dialog->startModal();
1291 // LLFloaterTOS deletes itself.
1292 return FALSE;
1293 }
1294 else
1295 {
1296 quit = TRUE;
1297 }
1298 }
1299 if(reason_response && (0 == strcmp(reason_response, "key")))
1300 {
1301 // Couldn't login because user/password is wrong
1302 // Clear the password
1303 password = "";
1304 }
1305 if(reason_response && (0 == strcmp(reason_response, "update")))
1306 {
1307 auth_message = gUserAuthp->getResponse("message");
1308 if (show_connect_box)
1309 {
1310 update_app(TRUE, auth_message);
1311 gStartupState = STATE_UPDATE_CHECK;
1312 return FALSE;
1313 }
1314 else
1315 {
1316 quit = TRUE;
1317 }
1318 }
1319 if(reason_response && (0 == strcmp(reason_response, "optional")))
1320 {
1321 llinfos << "Login got optional update" << llendl;
1322 auth_message = gUserAuthp->getResponse("message");
1323 if (show_connect_box)
1324 {
1325 update_app(FALSE, auth_message);
1326 gStartupState = STATE_UPDATE_CHECK;
1327 gSkipOptionalUpdate = TRUE;
1328 return FALSE;
1329 }
1330 }
1331 }
1332 break;
1333 case LLUserAuth::E_COULDNT_RESOLVE_HOST:
1334 case LLUserAuth::E_SSL_PEER_CERTIFICATE:
1335 case LLUserAuth::E_UNHANDLED_ERROR:
1336 default:
1337 emsg << "Unable to connect to " << gSecondLife << ".\n";
1338 emsg << gUserAuthp->errorMessage();
1339 break;
1340 case LLUserAuth::E_SSL_CACERT:
1341 case LLUserAuth::E_SSL_CONNECT_ERROR:
1342 emsg << "Unable to establish a secure connection to the login server.\n";
1343 emsg << gUserAuthp->errorMessage();
1344 break;
1345 }
1346
1347 // Version update and we're not showing the dialog
1348 if(quit)
1349 {
1350 delete gUserAuthp;
1351 gUserAuthp = NULL;
1352 app_force_quit(NULL);
1353 return FALSE;
1354 }
1355
1356 if(successful_login)
1357 {
1358 if (!gUserAuthp)
1359 {
1360 llerrs << "No userauth on successful login!" << llendl;
1361 }
1362
1363 // unpack login data needed by the application
1364 const char* text;
1365 text = gUserAuthp->getResponse("agent_id");
1366 if(text) gAgentID.set(text);
1367 write_debug("AgentID: ");
1368 write_debug(text);
1369 write_debug("\n");
1370
1371 text = gUserAuthp->getResponse("session_id");
1372 if(text) gAgentSessionID.set(text);
1373 write_debug("SessionID: ");
1374 write_debug(text);
1375 write_debug("\n");
1376
1377 text = gUserAuthp->getResponse("secure_session_id");
1378 if(text) gAgent.mSecureSessionID.set(text);
1379
1380 text = gUserAuthp->getResponse("first_name");
1381 if(text)
1382 {
1383 // Remove quotes from string. Login.cgi sends these to force
1384 // names that look like numbers into strings.
1385 firstname.assign(text);
1386 LLString::replaceChar(firstname, '"', ' ');
1387 LLString::trim(firstname);
1388 }
1389 text = gUserAuthp->getResponse("last_name");
1390 if(text) lastname.assign(text);
1391 gSavedSettings.setString("FirstName", firstname);
1392 gSavedSettings.setString("LastName", lastname);
1393 if (remember_password)
1394 {
1395 save_password_to_disk(password.c_str());
1396 }
1397 else
1398 {
1399 save_password_to_disk(NULL);
1400 }
1401 gSavedSettings.setBOOL("RememberPassword", remember_password);
1402 gSavedSettings.setBOOL("LoginLastLocation", gSavedSettings.getBOOL("LoginLastLocation"));
1403 gSavedSettings.setBOOL("LoggedIn", TRUE);
1404
1405 text = gUserAuthp->getResponse("agent_access");
1406 if(text && (text[0] == 'M'))
1407 {
1408 gAgent.mAccess = SIM_ACCESS_MATURE;
1409 }
1410 else
1411 {
1412 gAgent.mAccess = SIM_ACCESS_PG;
1413 }
1414
1415 text = gUserAuthp->getResponse("start_location");
1416 if(text) agent_start_location.assign(text);
1417 text = gUserAuthp->getResponse("circuit_code");
1418 if(text)
1419 {
1420 gMessageSystem->mOurCircuitCode = strtoul(text, NULL, 10);
1421 }
1422 const char* sim_ip_str = gUserAuthp->getResponse("sim_ip");
1423 const char* sim_port_str = gUserAuthp->getResponse("sim_port");
1424 if(sim_ip_str && sim_port_str)
1425 {
1426 U32 sim_port = strtoul(sim_port_str, NULL, 10);
1427 first_sim.set(sim_ip_str, sim_port);
1428 if (first_sim.isOk())
1429 {
1430 gMessageSystem->enableCircuit(first_sim, TRUE);
1431 }
1432 }
1433 const char* region_x_str = gUserAuthp->getResponse("region_x");
1434 const char* region_y_str = gUserAuthp->getResponse("region_y");
1435 if(region_x_str && region_y_str)
1436 {
1437 U32 region_x = strtoul(region_x_str, NULL, 10);
1438 U32 region_y = strtoul(region_y_str, NULL, 10);
1439 first_sim_handle = to_region_handle(region_x, region_y);
1440 }
1441
1442 const char* look_at_str = gUserAuthp->getResponse("look_at");
1443 if (look_at_str)
1444 {
1445 LLMemoryStream mstr((U8*)look_at_str, strlen(look_at_str));
1446 LLSD sd = LLSDNotationParser::parse(mstr);
1447 agent_start_look_at = ll_vector3_from_sd(sd);
1448 }
1449
1450 text = gUserAuthp->getResponse("seed_capability");
1451 if (text) first_sim_seed_cap = text;
1452
1453 text = gUserAuthp->getResponse("seconds_since_epoch");
1454 if(text)
1455 {
1456 U32 server_utc_time = strtoul(text, NULL, 10);
1457 if(server_utc_time)
1458 {
1459 time_t now = time(NULL);
1460 gUTCOffset = (server_utc_time - now);
1461 }
1462 }
1463
1464 const char* home_location = gUserAuthp->getResponse("home");
1465 if(home_location)
1466 {
1467 LLMemoryStream mstr((U8*)home_location, strlen(home_location));
1468 LLSD sd = LLSDNotationParser::parse(mstr);
1469 S32 region_x = sd["region_handle"][0].asInteger();
1470 S32 region_y = sd["region_handle"][1].asInteger();
1471 U64 region_handle = to_region_handle(region_x, region_y);
1472 LLVector3 position = ll_vector3_from_sd(sd["position"]);
1473 gAgent.setHomePosRegion(region_handle, position);
1474 }
1475
1476 gAgent.mMOTD.assign(gUserAuthp->getResponse("message"));
1477 LLUserAuth::options_t options;
1478 if(gUserAuthp->getOptions("inventory-root", options))
1479 {
1480 LLUserAuth::response_t::iterator it;
1481 it = options[0].find("folder_id");
1482 if(it != options[0].end())
1483 {
1484 gAgent.mInventoryRootID.set((*it).second.c_str());
1485 //gInventory.mock(gAgent.getInventoryRootID());
1486 }
1487 }
1488
1489 options.clear();
1490 if(gUserAuthp->getOptions("login-flags", options))
1491 {
1492 LLUserAuth::response_t::iterator it;
1493 LLUserAuth::response_t::iterator no_flag = options[0].end();
1494 it = options[0].find("ever_logged_in");
1495 if(it != no_flag)
1496 {
1497 if((*it).second == "N") gAgent.setFirstLogin(TRUE);
1498 else gAgent.setFirstLogin(FALSE);
1499 }
1500 it = options[0].find("stipend_since_login");
1501 if(it != no_flag)
1502 {
1503 if((*it).second == "Y") stipend_since_login = TRUE;
1504 }
1505 it = options[0].find("gendered");
1506 if(it != no_flag)
1507 {
1508 if((*it).second == "Y") gAgent.setGenderChosen(TRUE);
1509 }
1510 it = options[0].find("daylight_savings");
1511 if(it != no_flag)
1512 {
1513 if((*it).second == "Y") gPacificDaylightTime = TRUE;
1514 else gPacificDaylightTime = FALSE;
1515 }
1516 }
1517 options.clear();
1518 if (gUserAuthp->getOptions("initial-outfit", options)
1519 && !options.empty())
1520 {
1521 LLUserAuth::response_t::iterator it;
1522 LLUserAuth::response_t::iterator it_end = options[0].end();
1523 it = options[0].find("folder_name");
1524 if(it != it_end)
1525 {
1526 gInitialOutfit = (*it).second;
1527 }
1528 it = options[0].find("gender");
1529 if (it != it_end)
1530 {
1531 gInitialOutfitGender = (*it).second;
1532 }
1533 }
1534
1535 options.clear();
1536 if(gUserAuthp->getOptions("global-textures", options))
1537 {
1538 // Extract sun and moon texture IDs. These are used
1539 // in the LLVOSky constructor, but I can't figure out
1540 // how to pass them in. JC
1541 LLUserAuth::response_t::iterator it;
1542 LLUserAuth::response_t::iterator no_texture = options[0].end();
1543 it = options[0].find("sun_texture_id");
1544 if(it != no_texture)
1545 {
1546 gSunTextureID.set((*it).second.c_str());
1547 }
1548 it = options[0].find("moon_texture_id");
1549 if(it != no_texture)
1550 {
1551 gMoonTextureID.set((*it).second.c_str());
1552 }
1553 it = options[0].find("cloud_texture_id");
1554 if(it != no_texture)
1555 {
1556 gCloudTextureID.set((*it).second.c_str());
1557 }
1558 }
1559
1560
1561 // JC: gesture loading done below, when we have an asset system
1562 // in place. Don't delete/clear user_credentials until then.
1563
1564 if(gAgentID.notNull()
1565 && gAgentSessionID.notNull()
1566 && gMessageSystem->mOurCircuitCode
1567 && first_sim.isOk()
1568 && gAgent.mInventoryRootID.notNull())
1569 {
1570 ++gStartupState;
1571 }
1572 else
1573 {
1574 if (gNoRender)
1575 {
1576 llinfos << "Bad login - missing return values" << llendl;
1577 llinfos << emsg << llendl;
1578 exit(0);
1579 }
1580 // Bounce back to the login screen.
1581 LLStringBase<char>::format_map_t args;
1582 args["[ERROR_MESSAGE]"] = emsg.str();
1583 gViewerWindow->alertXml("ErrorMessage", args, login_alert_done);
1584 gStartupState = STATE_LOGIN_SHOW;
1585 }
1586 }
1587 else
1588 {
1589 if (gNoRender)
1590 {
1591 llinfos << "Failed to login!" << llendl;
1592 llinfos << emsg << llendl;
1593 exit(0);
1594 }
1595 // Bounce back to the login screen.
1596 LLStringBase<char>::format_map_t args;
1597 args["[ERROR_MESSAGE]"] = emsg.str();
1598 gViewerWindow->alertXml("ErrorMessage", args, login_alert_done);
1599 gStartupState = STATE_LOGIN_SHOW;
1600 }
1601 return do_normal_idle;
1602 }
1603
1604 //---------------------------------------------------------------------
1605 // World Init
1606 //---------------------------------------------------------------------
1607 if (STATE_WORLD_INIT == gStartupState)
1608 {
1609 set_startup_status(0.40f, "Initializing World...", gAgent.mMOTD.c_str());
1610 display_startup();
1611 // We should have an agent id by this point.
1612 llassert(!(gAgentID == LLUUID::null));
1613
1614 // Finish agent initialization. (Requires gSavedSettings, builds camera)
1615 gAgent.init();
1616
1617 // Since we connected, save off the settings so the user doesn't have to
1618 // type the name/password again if we crash.
1619 gSavedSettings.saveToFile(gSettingsFileName, TRUE);
1620
1621 // Create selection manager
1622 // Must be done before menus created, because many enabled callbacks
1623 // require its existance.
1624 gSelectMgr = new LLSelectMgr();
1625 gParcelMgr = new LLViewerParcelMgr();
1626 gHUDManager = new LLHUDManager();
1627 gMuteListp = new LLMuteList();
1628
1629 //
1630 // Initialize classes w/graphics stuff.
1631 //
1632 LLSurface::initClasses();
1633
1634 LLFace::initClass();
1635
1636 LLDrawable::initClass();
1637
1638 // RN: don't initialize VO classes in drone mode, they are too closely tied to rendering
1639 LLViewerObject::initVOClasses();
1640
1641 display_startup();
1642
1643 // World initialization must be done after above window init
1644 gWorldp = new LLWorld(region_size, region_scale);
1645
1646 // User might have overridden far clip
1647 gWorldp->setLandFarClip( gAgent.mDrawDistance );
1648
1649 if (!gRunLocal)
1650 {
1651 // Before we create the first region, we need to set the agent's mOriginGlobal
1652 // This is necessary because creating objects before this is set will result in a
1653 // bad mPositionAgent cache.
1654
1655 gAgent.initOriginGlobal(from_region_handle(first_sim_handle));
1656
1657 gWorldp->addRegion(first_sim_handle, first_sim);
1658
1659 LLViewerRegion *regionp = gWorldp->getRegionFromHandle(first_sim_handle);
1660 llinfos << "Adding initial simulator " << regionp->getOriginGlobal() << llendl;
1661
1662 regionp->setSeedCapability(first_sim_seed_cap);
1663
1664 // Set agent's initial region to be the one we just created.
1665 gAgent.setRegion(regionp);
1666
1667 // Set agent's initial position, which will be read by LLVOAvatar when the avatar
1668 // object is created. I think this must be done after setting the region. JC
1669 gAgent.setPositionAgent(agent_start_position_region);
1670 }
1671 else
1672 {
1673 // With one simulator, assume region is at 0,0, hence has regionHandle 0
1674 // VEFFECT: Login
1675 gWorldp->addRegion(0, gAgentSimHost);
1676 gAgent.setRegion(gWorldp->getRegionFromHandle(0));
1677 }
1678
1679 display_startup();
1680
1681 // Initialize UI
1682 if (!gNoRender)
1683 {
1684 // Initialize all our tools. Must be done after saved settings loaded.
1685 gToolMgr = new LLToolMgr();
1686 gToolMgr->initTools();
1687 // Quickly get something onscreen to look at.
1688 gViewerWindow->initWorldUI();
1689
1690 // Move the progress view in front of the UI
1691 gViewerWindow->moveProgressViewToFront();
1692
1693 gErrorStream.setFixedBuffer(gDebugView->mDebugConsolep);
1694 // set initial visibility of debug console
1695 gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole"));
1696 gDebugView->mStatViewp->setVisible(gSavedSettings.getBOOL("ShowDebugStats"));
1697 }
1698
1699 //
1700 // Set message handlers
1701 //
1702 llinfos << "Initializing communications..." << llendl;
1703
1704 // register callbacks for messages. . . do this after initial handshake to make sure that we don't catch any unwanted
1705 register_viewer_callbacks(gMessageSystem);
1706
1707 // Debugging info parameters
1708 gMessageSystem->setMaxMessageTime( 0.5f ); // Spam if decoding all msgs takes more than 500 ms
1709
1710 #ifndef LL_RELEASE_FOR_DOWNLOAD
1711 gMessageSystem->setTimeDecodes( TRUE ); // Time the decode of each msg
1712 gMessageSystem->setTimeDecodesSpamThreshold( 0.05f ); // Spam if a single msg takes over 50ms to decode
1713 #endif
1714
1715 gXferManager->registerCallbacks(gMessageSystem);
1716
1717 gCacheName = new LLCacheName(gMessageSystem);
1718 gCacheName->addObserver(callback_cache_name);
1719
1720 // Load stored cache if possible
1721 load_name_cache();
1722
1723 // Data storage for map of world.
1724 gWorldMap = new LLWorldMap();
1725
1726 // register null callbacks for audio until the audio system is initialized
1727 gMessageSystem->setHandlerFuncFast(_PREHASH_SoundTrigger, null_message_callback, NULL);
1728 gMessageSystem->setHandlerFuncFast(_PREHASH_AttachedSound, null_message_callback, NULL);
1729
1730 //reset statistics
1731 gViewerStats->resetStats();
1732
1733 if (!gNoRender)
1734 {
1735 //
1736 // Set up all of our statistics UI stuff.
1737 //
1738 init_stat_view();
1739 }
1740
1741 display_startup();
1742 //
1743 // Set up region and surface defaults
1744 //
1745
1746
1747 // Sets up the parameters for the first simulator
1748
1749 llinfos << "Initializing camera..." << llendl;
1750 gFrameTime = totalTime();
1751 F32 last_time = gFrameTimeSeconds;
1752 gFrameTimeSeconds = (S64)(gFrameTime - gStartTime)/SEC_TO_MICROSEC;
1753
1754 gFrameIntervalSeconds = gFrameTimeSeconds - last_time;
1755 if (gFrameIntervalSeconds < 0.f)
1756 {
1757 gFrameIntervalSeconds = 0.f;
1758 }
1759
1760 // Make sure agent knows correct aspect ratio
1761 gCamera->setViewHeightInPixels(gViewerWindow->getWindowDisplayHeight());
1762 if (gViewerWindow->mWindow->getFullscreen())
1763 {
1764 gCamera->setAspect(gViewerWindow->getDisplayAspectRatio());
1765 }
1766 else
1767 {
1768 gCamera->setAspect( (F32) gViewerWindow->getWindowWidth() / (F32) gViewerWindow->getWindowHeight());
1769 }
1770
1771 // Move agent to starting location. The position handed to us by
1772 // the space server is in global coordinates, but the agent frame
1773 // is in region local coordinates. Therefore, we need to adjust
1774 // the coordinates handed to us to fit in the local region.
1775
1776 gAgent.setPositionAgent(agent_start_position_region);
1777 gAgent.resetAxes(agent_start_look_at);
1778 gAgent.stopCameraAnimation();
1779 gAgent.resetCamera();
1780
1781 // Initialize global class data needed for surfaces (i.e. textures)
1782 if (!gNoRender)
1783 {
1784 llinfos << "Initializing sky..." << llendl;
1785 // Initialize all of the viewer object classes for the first time (doing things like texture fetches.
1786 gSky.init(initial_sun_direction);
1787 }
1788
1789 set_startup_status(0.45f, "Decoding UI images...", gAgent.mMOTD.c_str());
1790 display_startup();
1791 llinfos << "Decoding images..." << llendl;
1792 // For all images pre-loaded into viewer cache, decode them.
1793 // Need to do this AFTER we init the sky
1794 gImageList.decodeAllImages();
1795 gStartupState++;
1796
1797 // JC - Do this as late as possible to increase likelihood Purify
1798 // will run.
1799 if (!gRunLocal)
1800 {
1801 LLMessageSystem* msg = gMessageSystem;
1802 if (!msg->mOurCircuitCode)
1803 {
1804 llwarns << "Attempting to connect to simulator with a zero circuit code!" << llendl;
1805 }
1806 msg->enableCircuit(first_sim, TRUE);
1807 // now, use the circuit info to tell simulator about us!
1808 llinfos << "viewer: UserLoginLocationReply() Enabling " << first_sim << " with code " << msg->mOurCircuitCode << llendl;
1809 msg->newMessageFast(_PREHASH_UseCircuitCode);
1810 msg->nextBlockFast(_PREHASH_CircuitCode);
1811 msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode);
1812 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
1813 msg->addUUIDFast(_PREHASH_ID, gAgent.getID());
1814 msg->sendReliable(
1815 first_sim,
1816 MAX_TIMEOUT_COUNT,
1817 FALSE,
1818 TIMEOUT_SECONDS,
1819 use_circuit_callback,
1820 NULL);
1821 }
1822
1823 timeout.reset();
1824 if (!gConnectToSomething)
1825 {
1826 gStartupState = STATE_MISC;
1827 }
1828
1829 return do_normal_idle;
1830 }
1831
1832 //---------------------------------------------------------------------
1833 // LLMediaEngine Init
1834 //---------------------------------------------------------------------
1835 if (STATE_QUICKTIME_INIT == gStartupState)
1836 {
1837 if (gViewerWindow)
1838 {
1839 if (gSavedSettings.getBOOL("MuteAudio"))
1840 {
1841 LLMediaEngine::updateClass( 0.0f );
1842 }
1843 else
1844 {
1845 LLMediaEngine::updateClass( gSavedSettings.getF32( "MediaAudioVolume" ) );
1846 }
1847 }
1848
1849 #if LL_QUICKTIME_ENABLED // windows only right now but will be ported to mac
1850 if (!gQuickTimeInitialized)
1851 {
1852 // initialize quicktime libraries (fails gracefully if quicktime not installed ($QUICKTIME)
1853 llinfos << "Initializing QuickTime...." << llendl;
1854 set_startup_status(0.47f, "Initializing QuickTime...", gAgent.mMOTD.c_str());
1855 display_startup();
1856 #if LL_WINDOWS
1857 // Only necessary/available on Windows.
1858 if ( InitializeQTML ( 0L ) != noErr )
1859 {
1860 // quicktime init failed - turn off media engine support
1861 LLMediaEngine::getInstance ()->setAvailable ( FALSE );
1862 llinfos << "...not found - unable to initialize." << llendl;
1863 set_startup_status(0.47f, "QuickTime not found - unable to initialize.", gAgent.mMOTD.c_str());
1864 }
1865 else
1866 {
1867 llinfos << ".. initialized successfully." << llendl;
1868 set_startup_status(0.47f, "QuickTime initialized successfully.", gAgent.mMOTD.c_str());
1869 };
1870 #endif
1871 EnterMovies ();
1872 gQuickTimeInitialized = true;
1873 }
1874 #endif
1875
1876 gStartupState++;
1877 return do_normal_idle;
1878 }
1879
1880 //---------------------------------------------------------------------
1881 // Agent Send
1882 //---------------------------------------------------------------------
1883 if(STATE_WORLD_WAIT == gStartupState)
1884 {
1885 //llinfos << "Waiting for simulator ack...." << llendl;
1886 set_startup_status(0.49f, "Waiting for region handshake...", gAgent.mMOTD.c_str());
1887 if(gGotUseCircuitCodeAck)
1888 {
1889 ++gStartupState;
1890 }
1891 LLMessageSystem* msg = gMessageSystem;
1892 while (msg->checkMessages(gFrameCount))
1893 {
1894 }
1895 msg->processAcks();
1896 return do_normal_idle;
1897 }
1898
1899 //---------------------------------------------------------------------
1900 // Agent Send
1901 //---------------------------------------------------------------------
1902 if (STATE_AGENT_SEND == gStartupState)
1903 {
1904 llinfos << "Connecting to region..." << llendl;
1905 set_startup_status(0.50f, "Connecting to region...", gAgent.mMOTD.c_str());
1906 // register with the message system so it knows we're
1907 // expecting this message
1908 LLMessageSystem* msg = gMessageSystem;
1909 msg->setHandlerFuncFast(
1910 _PREHASH_AgentMovementComplete,
1911 process_agent_movement_complete,
1912 NULL);
1913 LLViewerRegion* regionp = gAgent.getRegion();
1914 if(!gRunLocal && regionp)
1915 {
1916 send_complete_agent_movement(regionp->getHost());
1917 gAssetStorage->setUpstream(regionp->getHost());
1918 gCacheName->setUpstream(regionp->getHost());
1919 msg->newMessageFast(_PREHASH_EconomyDataRequest);
1920 gAgent.sendReliableMessage();
1921 }
1922 else
1923 {
1924 gStartupState++;
1925 }
1926
1927 // Create login effect
1928 // But not on first login, because you can't see your avatar then
1929 if (!gAgent.isFirstLogin())
1930 {
1931 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
1932 effectp->setPositionGlobal(gAgent.getPositionGlobal());
1933 effectp->setColor(LLColor4U(gAgent.getEffectColor()));
1934 gHUDManager->sendEffects();
1935 }
1936
1937 gStartupState++;
1938
1939 timeout.reset();
1940 return do_normal_idle;
1941 }
1942
1943 //---------------------------------------------------------------------
1944 // Agent Wait
1945 //---------------------------------------------------------------------
1946 if (STATE_AGENT_WAIT == gStartupState)
1947 {
1948 LLMessageSystem* msg = gMessageSystem;
1949 while (msg->checkMessages(gFrameCount))
1950 {
1951 if (msg->isMessageFast(_PREHASH_AgentMovementComplete))
1952 {
1953 gStartupState++;
1954 // Sometimes we have more than one message in the
1955 // queue. break out of this loop and continue
1956 // processing. If we don't, then this could skip one
1957 // or more login steps.
1958 break;
1959 }
1960 else
1961 {
1962 //llinfos << "Awaiting AvatarInitComplete, got "
1963 //<< msg->getMessageName() << llendl;
1964 }
1965 }
1966 msg->processAcks();
1967 return do_normal_idle;
1968 }
1969
1970 //---------------------------------------------------------------------
1971 // Inventory Send
1972 //---------------------------------------------------------------------
1973 if (STATE_INVENTORY_SEND == gStartupState)
1974 {
1975 if (!gUserAuthp)
1976 {
1977 llerrs << "No userauth in STATE_INVENTORY_SEND!" << llendl;
1978 }
1979
1980 if (gConnectToSomething && !gRunLocal)
1981 {
1982 // unpack thin inventory
1983 LLUserAuth::options_t options;
1984 options.clear();
1985 //bool dump_buffer = false;
1986
1987 if(gUserAuthp->getOptions("inventory-lib-root", options)
1988 && !options.empty())
1989 {
1990 // should only be one
1991 LLUserAuth::response_t::iterator it;
1992 it = options[0].find("folder_id");
1993 if(it != options[0].end())
1994 {
1995 gInventoryLibraryRoot.set((*it).second.c_str());
1996 }
1997 }
1998 options.clear();
1999 if(gUserAuthp->getOptions("inventory-lib-owner", options)
2000 && !options.empty())
2001 {
2002 // should only be one
2003 LLUserAuth::response_t::iterator it;
2004 it = options[0].find("agent_id");
2005 if(it != options[0].end())
2006 {
2007 gInventoryLibraryOwner.set((*it).second.c_str());
2008 }
2009 }
2010 options.clear();
2011 if(gUserAuthp->getOptions("inventory-skel-lib", options)
2012 && gInventoryLibraryOwner.notNull())
2013 {
2014 if(!gInventory.loadSkeleton(options, gInventoryLibraryOwner))
2015 {
2016 llwarns << "Problem loading inventory-skel-lib" << llendl;
2017 }
2018 }
2019 options.clear();
2020 if(gUserAuthp->getOptions("inventory-skeleton", options))
2021 {
2022 if(!gInventory.loadSkeleton(options, gAgent.getID()))
2023 {
2024 llwarns << "Problem loading inventory-skel-targets"
2025 << llendl;
2026 }
2027 }
2028
2029 options.clear();
2030 if(gUserAuthp->getOptions("buddy-list", options))
2031 {
2032 LLUserAuth::options_t::iterator it = options.begin();
2033 LLUserAuth::options_t::iterator end = options.end();
2034 LLAvatarTracker::buddy_map_t list;
2035 LLUUID agent_id;
2036 S32 has_rights = 0, given_rights = 0;
2037 for (; it != end; ++it)
2038 {
2039 LLUserAuth::response_t::const_iterator option_it;
2040 option_it = (*it).find("buddy_id");
2041 if(option_it != (*it).end())
2042 {
2043 agent_id.set((*option_it).second.c_str());
2044 }
2045 option_it = (*it).find("buddy_rights_has");
2046 if(option_it != (*it).end())
2047 {
2048 has_rights = atoi((*option_it).second.c_str());
2049 }
2050 option_it = (*it).find("buddy_rights_given");
2051 if(option_it != (*it).end())
2052 {
2053 given_rights = atoi((*option_it).second.c_str());
2054 }
2055 list[agent_id] = new LLRelationship(given_rights, has_rights, false);
2056 }
2057 LLAvatarTracker::instance().addBuddyList(list);
2058 }
2059
2060 options.clear();
2061 if(gUserAuthp->getOptions("ui-config", options))
2062 {
2063 LLUserAuth::options_t::iterator it = options.begin();
2064 LLUserAuth::options_t::iterator end = options.end();
2065 for (; it != end; ++it)
2066 {
2067 LLUserAuth::response_t::const_iterator option_it;
2068 option_it = (*it).find("allow_first_life");
2069 if(option_it != (*it).end())
2070 {
2071 if (option_it->second == "Y")
2072 {
2073 LLPanelAvatar::sAllowFirstLife = TRUE;
2074 }
2075 }
2076 }
2077 }
2078
2079 options.clear();
2080 if(gUserAuthp->getOptions("event_categories", options))
2081 {
2082 LLEventInfo::loadCategories(options);
2083 }
2084 if(gUserAuthp->getOptions("event_notifications", options))
2085 {
2086 gEventNotifier.load(options);
2087 }
2088 options.clear();
2089 if(gUserAuthp->getOptions("classified_categories", options))
2090 {
2091 LLClassifiedInfo::loadCategories(options);
2092 }
2093 gInventory.buildParentChildMap();
2094 gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
2095 gInventory.notifyObservers();
2096
2097 // set up callbacks
2098 LLMessageSystem* msg = gMessageSystem;
2099 LLInventoryModel::registerCallbacks(msg);
2100 LLAvatarTracker::instance().registerCallbacks(msg);
2101 LLLandmark::registerCallbacks(msg);
2102
2103 // request mute list
2104 gMuteListp->requestFromServer(gAgent.getID());
2105
2106 // Get money and ownership credit information
2107 msg->newMessageFast(_PREHASH_MoneyBalanceRequest);
2108 msg->nextBlockFast(_PREHASH_AgentData);
2109 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
2110 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
2111 msg->nextBlockFast(_PREHASH_MoneyData);
2112 msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null );
2113 gAgent.sendReliableMessage();
2114
2115 // request all group information
2116 // *FIX: This will not do the right thing if the message
2117 // gets there before the requestuserserverconnection
2118 // circuit is completed.
2119 gAgent.sendAgentDataUpdateRequest();
2120
2121
2122 // NOTE: removed as part of user-privacy
2123 // enhancements. this information should be available from
2124 // login. 2006-10-16 Phoenix.
2125 // get the users that have been granted modify powers
2126 //msg->newMessageFast(_PREHASH_RequestGrantedProxies);
2127 //msg->nextBlockFast(_PREHASH_AgentData);
2128 //msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
2129 //msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
2130 //gAgent.sendReliableMessage();
2131
2132 BOOL shown_at_exit = gSavedSettings.getBOOL("ShowInventory");
2133
2134 // Create the inventory views
2135 LLInventoryView::showAgentInventory();
2136
2137 // Hide the inventory if it wasn't shown at exit
2138 if(!shown_at_exit)
2139 {
2140 LLInventoryView::toggleVisibility(NULL);
2141 }
2142 }
2143 gStartupState++;
2144 return do_normal_idle;
2145 }
2146
2147 //---------------------------------------------------------------------
2148 // Assert agent to userserver
2149 //---------------------------------------------------------------------
2150 if (STATE_CONNECT_USERSERVER == gStartupState)
2151 {
2152 LLMessageSystem* msg = gMessageSystem;
2153 msg->enableCircuit(gUserServer, TRUE);
2154 msg->newMessage("ConnectAgentToUserserver");
2155 msg->nextBlockFast(_PREHASH_AgentData);
2156 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
2157 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
2158 msg->sendReliable(gUserServer);
2159 gStartupState++;
2160 return do_normal_idle;
2161 }
2162
2163 //---------------------------------------------------------------------
2164 // Misc
2165 //---------------------------------------------------------------------
2166 if (STATE_MISC == gStartupState)
2167 {
2168 // Create a few objects if we don't actually have a world
2169 if (!gConnectToSomething)
2170 {
2171 // could add them here
2172 }
2173
2174 // We have a region, and just did a big inventory download.
2175 // We can estimate the user's connection speed, and set their
2176 // max bandwidth accordingly. JC
2177 if (gSavedSettings.getBOOL("FirstLoginThisInstall")
2178 && gUserAuthp)
2179 {
2180 // This is actually a pessimistic computation, because TCP may not have enough
2181 // time to ramp up on the (small) default inventory file to truly measure max
2182 // bandwidth. JC
2183 F64 rate_bps = gUserAuthp->getLastTransferRateBPS();
2184 const F32 FAST_RATE_BPS = 600.f * 1024.f;
2185 const F32 FASTER_RATE_BPS = 750.f * 1024.f;
2186 F32 max_bandwidth = gViewerThrottle.getMaxBandwidth();
2187 if (rate_bps > FASTER_RATE_BPS
2188 && rate_bps > max_bandwidth)
2189 {
2190 llinfos << "Fast network connection, increasing max bandwidth to "
2191 << FASTER_RATE_BPS/1024.f
2192 << " Kbps" << llendl;
2193 gViewerThrottle.setMaxBandwidth(FASTER_RATE_BPS / 1024.f);
2194 }
2195 else if (rate_bps > FAST_RATE_BPS
2196 && rate_bps > max_bandwidth)
2197 {
2198 llinfos << "Fast network connection, increasing max bandwidth to "
2199 << FAST_RATE_BPS/1024.f
2200 << " Kbps" << llendl;
2201 gViewerThrottle.setMaxBandwidth(FAST_RATE_BPS / 1024.f);
2202 }
2203 }
2204
2205 // We're successfully logged in.
2206 gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE);
2207
2208
2209 // based on the comments, we've successfully logged in so we can delete the 'forced'
2210 // URL that the updater set in settings.ini (in a mostly paranoid fashion)
2211 LLString nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
2212 if ( nextLoginLocation.length() )
2213 {
2214 // clear it
2215 gSavedSettings.setString( "NextLoginLocation", "" );
2216
2217 // and make sure it's saved
2218 gSavedSettings.saveToFile( gSettingsFileName, TRUE );
2219 };
2220
2221 if (!gNoRender)
2222 {
2223 // JC: Initializing audio requests many sounds for download.
2224 init_audio();
2225
2226 // JC: Initialize "active" gestures. This may also trigger
2227 // many gesture downloads, if this is the user's first
2228 // time on this machine or -purge has been run.
2229 LLUserAuth::options_t gesture_options;
2230 if (gUserAuthp->getOptions("gestures", gesture_options))
2231 {
2232 llinfos << "Gesture Manager loading " << gesture_options.size()
2233 << llendl;
2234 std::vector<LLUUID> item_ids;
2235 LLUserAuth::options_t::iterator resp_it;
2236 for (resp_it = gesture_options.begin();
2237 resp_it != gesture_options.end();
2238 ++resp_it)
2239 {
2240 const LLUserAuth::response_t& response = *resp_it;
2241 LLUUID item_id;
2242 LLUUID asset_id;
2243 LLUserAuth::response_t::const_iterator option_it;
2244
2245 option_it = response.find("item_id");
2246 if (option_it != response.end())
2247 {
2248 const std::string& uuid_string = (*option_it).second;
2249 item_id.set(uuid_string.c_str());
2250 }
2251 option_it = response.find("asset_id");
2252 if (option_it != response.end())
2253 {
2254 const std::string& uuid_string = (*option_it).second;
2255 asset_id.set(uuid_string.c_str());
2256 }
2257
2258 if (item_id.notNull() && asset_id.notNull())
2259 {
2260 // Could schedule and delay these for later.
2261 const BOOL no_inform_server = FALSE;
2262 const BOOL no_deactivate_similar = FALSE;
2263 gGestureManager.activateGestureWithAsset(item_id, asset_id,
2264 no_inform_server,
2265 no_deactivate_similar);
2266 // We need to fetch the inventory items for these gestures
2267 // so we have the names to populate the UI.
2268 item_ids.push_back(item_id);
2269 }
2270 }
2271
2272 LLGestureInventoryFetchObserver* fetch = new LLGestureInventoryFetchObserver();
2273 fetch->fetchItems(item_ids);
2274 // deletes itself when done
2275 gInventory.addObserver(fetch);
2276 }
2277 }
2278 gDisplaySwapBuffers = TRUE;
2279
2280 LLMessageSystem* msg = gMessageSystem;
2281 msg->setHandlerFuncFast(_PREHASH_SoundTrigger, process_sound_trigger);
2282 msg->setHandlerFuncFast(_PREHASH_PreloadSound, process_preload_sound);
2283 msg->setHandlerFuncFast(_PREHASH_AttachedSound, process_attached_sound);
2284 msg->setHandlerFuncFast(_PREHASH_AttachedSoundGainChange, process_attached_sound_gain_change);
2285 //msg->setHandlerFuncFast(_PREHASH_AttachedSoundCutoffRadius, process_attached_sound_cutoff_radius);
2286 msg->setHandlerFunc(
2287 "ConnectToUserserver",
2288 process_connect_to_userserver);
2289
2290 llinfos << "Initialization complete" << llendl;
2291 gInitializationComplete = TRUE;
2292
2293 gRenderStartTime.reset();
2294
2295 // HACK: Inform simulator of window size.
2296 // Do this here so it's less likely to race with RegisterNewAgent.
2297 // TODO: Put this into RegisterNewAgent
2298 // JC - 7/20/2002
2299 gViewerWindow->sendShapeToSim();
2300
2301 // if needed, show the money history window
2302 if (stipend_since_login && !gNoRender)
2303 {
2304 LLFloaterAccountHistory::show(NULL);
2305 }
2306
2307 if (!gAgent.isFirstLogin())
2308 {
2309 bool url_ok = LLURLSimString::sInstance.parse();
2310 if (!((agent_start_location == "url" && url_ok) ||
2311 (!url_ok && ((agent_start_location == "last" && gSavedSettings.getBOOL("LoginLastLocation")) ||
2312 (agent_start_location == "home" && !gSavedSettings.getBOOL("LoginLastLocation"))))))
2313 {
2314 // The reason we show the alert is because we want to
2315 // reduce confusion for when you log in and your provided
2316 // location is not your expected location. So, if this is
2317 // your first login, then you do not have an expectation,
2318 // thus, do not show this alert.
2319 LLString::format_map_t args;
2320 if (url_ok)
2321 {
2322 args["[TYPE]"] = "desired";
2323 args["[HELP]"] = " ";
2324 }
2325 else if (gSavedSettings.getBOOL("LoginLastLocation"))
2326 {
2327 args["[TYPE]"] = "last";
2328 args["[HELP]"] = " \n ";
2329 }
2330 else
2331 {
2332 args["[TYPE]"] = "home";
2333 args["[HELP]"] = " \nYou may want to set a new home location.\n ";
2334 }
2335 gViewerWindow->alertXml("AvatarMoved", args);
2336 }
2337 else
2338 {
2339 if (samename)
2340 {
2341 // restore old camera pos
2342 gAgent.setFocusOnAvatar(FALSE, FALSE);
2343 gAgent.setCameraPosAndFocusGlobal(gSavedSettings.getVector3d("CameraPosOnLogout"), gSavedSettings.getVector3d("FocusPosOnLogout"), LLUUID::null);
2344 BOOL limit_hit = FALSE;
2345 gAgent.calcCameraPositionTargetGlobal(&limit_hit);
2346 if (limit_hit)
2347 {
2348 gAgent.setFocusOnAvatar(TRUE, FALSE);
2349 }
2350 gAgent.stopCameraAnimation();
2351 }
2352 }
2353 }
2354
2355 gStartupState++;
2356 timeout.reset();
2357 return do_normal_idle;
2358 }
2359
2360 if (STATE_PRECACHE == gStartupState)
2361 {
2362 do_normal_idle = TRUE;
2363 if (!did_precache)
2364 {
2365 did_precache = TRUE;
2366 // Don't preload map information! The amount of data for all the
2367 // map items (icons for classifieds, avatar locations, etc.) is
2368 // huge, and not throttled. This overflows the downstream
2369 // pipe during startup, when lots of information is being sent.
2370 // The problem manifests itself as invisible avatars on login. JC
2371 //gWorldMap->setCurrentLayer(0); // pre-load layer 0 of the world map
2372
2373 gImageList.doPreloadImages(); // pre-load some images from static VFS
2374 }
2375
2376 F32 timeout_frac = timeout.getElapsedTimeF32()/PRECACHING_DELAY;
2377 // wait precache-delay and for agent's avatar or a lot longer.
2378 if(((timeout_frac > 1.f) && gAgent.getAvatarObject())
2379 || (timeout_frac > 3.f))
2380 {
2381 gStartupState++;
2382 }
2383 else
2384 {
2385 set_startup_status(0.50f + 0.50f * timeout_frac, "Precaching...",
2386 gAgent.mMOTD.c_str());
2387 }
2388
2389 return do_normal_idle;
2390 }
2391
2392 if (STATE_WEARABLES_WAIT == gStartupState)
2393 {
2394 do_normal_idle = TRUE;
2395
2396 static LLFrameTimer wearables_timer;
2397
2398 const F32 wearables_time = wearables_timer.getElapsedTimeF32();
2399 const F32 MAX_WEARABLES_TIME = 10.f;
2400
2401 if(gAgent.getWearablesLoaded() || !gAgent.isGenderChosen())
2402 {
2403 gStartupState++;
2404 }
2405 else if (wearables_time > MAX_WEARABLES_TIME)
2406 {
2407 gViewerWindow->alertXml("ClothingLoading");
2408 gViewerStats->incStat(LLViewerStats::ST_WEARABLES_TOO_LONG);
2409 gStartupState++;
2410 }
2411 else
2412 {
2413 set_startup_status(0.f + 0.25f * wearables_time / MAX_WEARABLES_TIME,
2414 "Downloading clothing...",
2415 gAgent.mMOTD.c_str());
2416 }
2417 return do_normal_idle;
2418 }
2419
2420 if (STATE_CLEANUP == gStartupState)
2421 {
2422 set_startup_status(1.0, "", NULL);
2423
2424 do_normal_idle = TRUE;
2425
2426 // Let the map know about the inventory.
2427 if(gFloaterWorldMap)
2428 {
2429 gFloaterWorldMap->observeInventory(&gInventory);
2430 gFloaterWorldMap->observeFriends();
2431 }
2432
2433 gViewerWindow->showCursor();
2434 gViewerWindow->getWindow()->resetBusyCount();
2435 gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
2436 //llinfos << "Done releasing bitmap" << llendl;
2437 gViewerWindow->setShowProgress(FALSE);
2438 gViewerWindow->setProgressCancelButtonVisible(FALSE, "");
2439
2440 // We're not away from keyboard, even though login might have taken
2441 // a while. JC
2442 gAgent.clearAFK();
2443
2444 // Have the agent start watching the friends list so we can update proxies
2445 gAgent.observeFriends();
2446 if (gSavedSettings.getBOOL("LoginAsGod"))
2447 {
2448 gAgent.requestEnterGodMode();
2449 }
2450
2451 // On first start, ask user for gender
2452 dialog_choose_gender_first_start();
2453
2454 // Start automatic replay if the flag is set.
2455 if (gSavedSettings.getBOOL("StatsAutoRun"))
2456 {
2457 LLUUID id;
2458 llinfos << "Starting automatic playback" << llendl;
2459 gAgentPilot.startPlayback();
2460 }
2461
2462 // ok, if we've gotten this far and have a startup URL
2463 if (LLURLSimString::sInstance.parse())
2464 {
2465 // kick off request for landmark to startup URL
2466 if(gFloaterWorldMap)
2467 {
2468 LLVector3 pos = gAgent.getPositionAgent();
2469 if( LLURLSimString::sInstance.mSimName != gAgent.getRegion()->getName()
2470 || LLURLSimString::sInstance.mX != llfloor(pos[VX])
2471 || LLURLSimString::sInstance.mY != llfloor(pos[VY]) )
2472 {
2473 LLFloaterWorldMap::show(NULL, TRUE);
2474 gFloaterWorldMap->trackURL(LLURLSimString::sInstance.mSimName,
2475 LLURLSimString::sInstance.mX,
2476 LLURLSimString::sInstance.mY,
2477 LLURLSimString::sInstance.mZ);
2478 }
2479 }
2480 }
2481
2482 // Clean up the userauth stuff.
2483 if (gUserAuthp)
2484 {
2485 delete gUserAuthp;
2486 gUserAuthp = NULL;
2487 }
2488
2489 gStartupState++;
2490 //RN: unmute audio now that we are entering world
2491 //JC: But only if the user wants audio working.
2492 if (gAudiop)
2493 {
2494 BOOL mute = gSavedSettings.getBOOL("MuteAudio");
2495 gAudiop->setMuted(mute);
2496 }
2497
2498 // reset keyboard focus to sane state of pointing at world
2499 gFocusMgr.setKeyboardFocus(NULL, NULL);
2500
2501#if 0 // sjb: enable for auto-enabling timer display
2502 gDebugView->mFastTimerView->setVisible(TRUE);
2503#endif
2504 return do_normal_idle;
2505 }
2506
2507 llwarns << "Reached end of idle_startup for state " << gStartupState << llendl;
2508 return do_normal_idle;
2509}
2510
2511//
2512// local function definition
2513//
2514
2515void unsupported_graphics_callback(S32 option, void* userdata)
2516{
2517 if (0 == option)
2518 {
2519 llinfos << "User cancelled after driver check" << llendl;
2520 std::string help_path;
2521 help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP,
2522 "unsupported_card.html");
2523 app_force_quit( help_path.c_str() );
2524 }
2525
2526 LLPanelLogin::giveFocus();
2527}
2528
2529void check_driver_callback(S32 option, void* userdata)
2530{
2531 if (0 == option)
2532 {
2533 llinfos << "User cancelled after driver check" << llendl;
2534 std::string help_path;
2535 help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP,
2536 "graphics_driver_update.html");
2537 app_force_quit( help_path.c_str() );
2538 }
2539
2540 LLPanelLogin::giveFocus();
2541}
2542
2543void login_show()
2544{
2545 LLPanelLogin::show( gViewerWindow->getVirtualWindowRect(),
2546 gSavedSettings.getBOOL("UseDebugLogin"),
2547 login_callback, NULL );
2548
2549 // Make sure all the UI textures are present and decoded.
2550 gImageList.decodeAllImages();
2551
2552 if( USERSERVER_OTHER == gUserServerChoice )
2553 {
2554 LLPanelLogin::addServer( gUserServerName, USERSERVER_OTHER );
2555 }
2556 else
2557 {
2558 LLPanelLogin::addServer( gUserServerDomainName[gUserServerChoice].mLabel, gUserServerChoice );
2559 }
2560
2561 // Arg! We hate loops!
2562 LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_DMZ].mLabel, USERSERVER_DMZ );
2563 LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_LOCAL].mLabel, USERSERVER_LOCAL );
2564 LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_AGNI].mLabel, USERSERVER_AGNI );
2565 LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_ADITI].mLabel, USERSERVER_ADITI );
2566 LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_SIVA].mLabel, USERSERVER_SIVA );
2567 LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_DURGA].mLabel, USERSERVER_DURGA );
2568 LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_SHAKTI].mLabel, USERSERVER_SHAKTI );
2569 LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_GANGA].mLabel, USERSERVER_GANGA );
2570 LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_UMA].mLabel, USERSERVER_UMA );
2571 LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_SOMA].mLabel, USERSERVER_SOMA );
2572}
2573
2574// Callback for when login screen is closed. Option 0 = connect, option 1 = quit.
2575void login_callback(S32 option, void *userdata)
2576{
2577 const S32 CONNECT_OPTION = 0;
2578 const S32 QUIT_OPTION = 1;
2579
2580 if (CONNECT_OPTION == option)
2581 {
2582 gStartupState++;
2583 return;
2584 }
2585 else if (QUIT_OPTION == option)
2586 {
2587 // Make sure we don't save the password if the user is trying to clear it.
2588 LLString first, last, password;
2589 BOOL remember = TRUE;
2590 LLPanelLogin::getFields(first, last, password, remember);
2591 if (!remember)
2592 {
2593 // turn off the setting and write out to disk
2594 gSavedSettings.setBOOL("RememberPassword", FALSE);
2595 gSavedSettings.saveToFile(gSettingsFileName, TRUE);
2596
2597 // stomp the saved password on disk
2598 save_password_to_disk(NULL);
2599 }
2600
2601 LLPanelLogin::close();
2602
2603 // Next iteration through main loop should shut down the app cleanly.
2604 gQuit = TRUE;
2605
2606 return;
2607 }
2608 else
2609 {
2610 llwarns << "Unknown login button clicked" << llendl;
2611 }
2612}
2613
2614LLString load_password_from_disk()
2615{
2616 LLString hashed_password("");
2617
2618 // Look for legacy "marker" password from settings.ini
2619 hashed_password = gSavedSettings.getString("Marker");
2620 if (!hashed_password.empty())
2621 {
2622 // Stomp the Marker entry.
2623 gSavedSettings.setString("Marker", "");
2624
2625 // Return that password.
2626 return hashed_password;
2627 }
2628
2629 std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
2630 "password.dat");
2631 FILE* fp = LLFile::fopen(filepath.c_str(), "rb");
2632 if (!fp)
2633 {
2634 return hashed_password;
2635 }
2636
2637 // UUID is 16 bytes, written into ASCII is 32 characters
2638 // without trailing \0
2639 const S32 HASHED_LENGTH = 32;
2640 U8 buffer[HASHED_LENGTH+1];
2641
2642 if (1 != fread(buffer, HASHED_LENGTH, 1, fp))
2643 {
2644 return hashed_password;
2645 }
2646
2647 fclose(fp);
2648
2649 // Decipher with MAC address
2650 LLXORCipher cipher(gMACAddress, 6);
2651 cipher.decrypt(buffer, HASHED_LENGTH);
2652
2653 buffer[HASHED_LENGTH] = '\0';
2654
2655 // Check to see if the mac address generated a bad hashed
2656 // password. It should be a hex-string or else the mac adress has
2657 // changed. This is a security feature to make sure that if you
2658 // get someone's password.dat file, you cannot hack their account.
2659 if(is_hex_string(buffer, HASHED_LENGTH))
2660 {
2661 hashed_password.assign((char*)buffer);
2662 }
2663
2664 return hashed_password;
2665}
2666
2667void save_password_to_disk(const char* hashed_password)
2668{
2669 std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
2670 "password.dat");
2671 if (!hashed_password)
2672 {
2673 // No password, remove the file.
2674 LLFile::remove(filepath.c_str());
2675 }
2676 else
2677 {
2678 FILE* fp = LLFile::fopen(filepath.c_str(), "wb");
2679 if (!fp)
2680 {
2681 return;
2682 }
2683
2684 // Encipher with MAC address
2685 const S32 HASHED_LENGTH = 32;
2686 U8 buffer[HASHED_LENGTH+1];
2687
2688 LLString::copy((char*)buffer, hashed_password, HASHED_LENGTH+1);
2689
2690 LLXORCipher cipher(gMACAddress, 6);
2691 cipher.encrypt(buffer, HASHED_LENGTH);
2692
2693 fwrite(buffer, HASHED_LENGTH, 1, fp);
2694
2695 fclose(fp);
2696 }
2697}
2698
2699BOOL is_hex_string(U8* str, S32 len)
2700{
2701 BOOL rv = TRUE;
2702 U8* c = str;
2703 while(rv && len--)
2704 {
2705 switch(*c)
2706 {
2707 case '0':
2708 case '1':
2709 case '2':
2710 case '3':
2711 case '4':
2712 case '5':
2713 case '6':
2714 case '7':
2715 case '8':
2716 case '9':
2717 case 'a':
2718 case 'b':
2719 case 'c':
2720 case 'd':
2721 case 'e':
2722 case 'f':
2723 ++c;
2724 break;
2725 default:
2726 rv = FALSE;
2727 break;
2728 }
2729 }
2730 return rv;
2731}
2732
2733void show_first_run_dialog()
2734{
2735 gViewerWindow->alertXml("FirstRun", first_run_dialog_callback, NULL);
2736}
2737
2738void first_run_dialog_callback(S32 option, void* userdata)
2739{
2740 if (0 == option)
2741 {
2742 llinfos << "First run dialog cancelling" << llendl;
2743 LLWeb::loadURL( CREATE_ACCOUNT_URL );
2744 }
2745
2746 LLPanelLogin::giveFocus();
2747}
2748
2749
2750
2751void set_startup_status(const F32 frac, const char *string, const char* msg)
2752{
2753 gViewerWindow->setProgressPercent(frac*100);
2754 gViewerWindow->setProgressString(string);
2755
2756 gViewerWindow->setProgressMessage(msg);
2757}
2758
2759void on_userserver_name_resolved( BOOL success, const LLString& host_name, U32 ip, void* userdata )
2760{
2761 if( STATE_RESOLVING_USERSERVER != gStartupState )
2762 {
2763 llwarns << "Userserver name callback returned during invalid state!" << llendl;
2764 return;
2765 }
2766
2767 if( success )
2768 {
2769 gUserServer.setAddress( ip );
2770 llinfos << "...Userserver resolved to " << gUserServer << llendl;
2771 gStartupState = STATE_USERSERVER_RESOLVED;
2772 }
2773 else
2774 {
2775 llwarns << "setHostByName failed" << llendl;
2776
2777 LLStringBase<char>::format_map_t args;
2778 args["[HOST_NAME]"] = host_name;
2779 gViewerWindow->alertXml("SetByHostFail", args, login_alert_done );
2780 gStartupState = STATE_LOGIN_SHOW;
2781 }
2782}
2783
2784void login_alert_status(S32 option, void* user_data)
2785{
2786 if (0 == option)
2787 {
2788 // OK button
2789 }
2790 else if (1 == option)
2791 {
2792 // Help button
2793 std::string help_path;
2794 help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP, "unable_to_connect.html");
2795 load_url_local_file(help_path.c_str() );
2796 }
2797
2798 LLPanelLogin::giveFocus();
2799}
2800
2801void update_app(BOOL mandatory, const std::string& auth_msg)
2802{
2803 // store off config state, as we might quit soon
2804 gSavedSettings.saveToFile(gSettingsFileName, TRUE);
2805
2806 std::ostringstream message;
2807
2808 //XUI:translate
2809 std::string msg;
2810 if (!auth_msg.empty())
2811 {
2812 msg = "(" + auth_msg + ") \n";
2813 }
2814 LLStringBase<char>::format_map_t args;
2815 args["[MESSAGE]"] = msg;
2816
2817 BOOL *mandatoryp = new BOOL(mandatory);
2818
2819#if LL_WINDOWS
2820 if (mandatory)
2821 {
2822 gViewerWindow->alertXml("DownloadWindowsMandatory", args,
2823 update_dialog_callback,
2824 (void *)mandatoryp);
2825 }
2826 else
2827 {
2828#if LL_RELEASE_FOR_DOWNLOAD
2829 gViewerWindow->alertXml("DownloadWindowsReleaseForDownload", args,
2830 update_dialog_callback,
2831 (void *)mandatoryp);
2832#else
2833 gViewerWindow->alertXml("DownloadWindows", args,
2834 update_dialog_callback,
2835 (void *)mandatoryp);
2836#endif
2837 }
2838#else
2839 if (mandatory)
2840 {
2841 gViewerWindow->alertXml("DownloadMacMandatory", args,
2842 update_dialog_callback,
2843 (void *)mandatoryp);
2844 }
2845 else
2846 {
2847#if LL_RELEASE_FOR_DOWNLOAD
2848 gViewerWindow->alertXml("DownloadMacReleaseForDownload", args,
2849 update_dialog_callback,
2850 (void *)mandatoryp);
2851#else
2852 gViewerWindow->alertXml("DownloadMac", args,
2853 update_dialog_callback,
2854 (void *)mandatoryp);
2855#endif
2856 }
2857#endif
2858
2859}
2860
2861
2862void update_dialog_callback(S32 option, void *userdata)
2863{
2864 std::string update_exe_path;
2865 BOOL mandatory = *(BOOL *)userdata;
2866
2867#if !LL_RELEASE_FOR_DOWNLOAD
2868 if (option == 2)
2869 {
2870 gStartupState++;
2871 return;
2872 }
2873#endif
2874
2875 if (option == 1)
2876 {
2877 // ...user doesn't want to do it
2878 if (mandatory)
2879 {
2880 app_force_quit();
2881 // Bump them back to the login screen.
2882 //gStartupState = STATE_LOGIN_SHOW;
2883 }
2884 else
2885 {
2886 gStartupState++;
2887 }
2888 return;
2889 }
2890
2891#if LL_WINDOWS
2892 char ip[MAX_STRING];
2893
2894 update_exe_path = gDirUtilp->getTempFilename();
2895 if (update_exe_path.empty())
2896 {
2897 // We're hosed, bail
2898 llwarns << "LLDir::getTempFilename() failed" << llendl;
2899 app_force_quit(NULL);
2900 return;
2901 }
2902
2903 update_exe_path += ".exe";
2904
2905 std::string updater_source = gDirUtilp->getAppRODataDir();
2906 updater_source += gDirUtilp->getDirDelimiter();
2907 updater_source += "updater.exe";
2908
2909 llinfos << "Calling CopyFile source: " << updater_source.c_str()
2910 << " dest: " << update_exe_path
2911 << llendl;
2912
2913
2914 if (!CopyFileA(updater_source.c_str(), update_exe_path.c_str(), FALSE))
2915 {
2916 llinfos << "Unable to copy the updater!" << llendl;
2917 app_force_quit(NULL);
2918 return;
2919 }
2920 u32_to_ip_string(gUserServer.getAddress(), ip);
2921
2922 std::ostringstream params;
2923 params << "-userserver " << gUserServerName;
2924
2925 // if a sim name was passed in via command line parameter (typically through a SLURL)
2926 if ( LLURLSimString::sInstance.mSimString.length() )
2927 {
2928 // record the location to start at next time
2929 gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString );
2930 };
2931
2932 if (gHideLinks)
2933 {
2934 // Figure out the program name.
2935 const char* data_dir = gDirUtilp->getAppRODataDir().c_str();
2936 // Roll back from the end, stopping at the first '\'
2937 const char* program_name = data_dir + strlen(data_dir);
2938 while ( (data_dir != --program_name) &&
2939 *(program_name) != '\\');
2940
2941 if ( *(program_name) == '\\')
2942 {
2943 // We found a '\'.
2944 program_name++;
2945 }
2946 else
2947 {
2948 // Oops.
2949 program_name = "SecondLife";
2950 }
2951
2952 params << " -silent -name \"" << gSecondLife << "\" -program \"" << program_name << "\"";
2953 }
2954
2955 llinfos << "Calling updater: " << update_exe_path << " " << params.str() << llendl;
2956
2957 remove_marker_file(); // In case updater fails
2958
2959 // Use spawn() to run asynchronously
2960 int retval = _spawnl(_P_NOWAIT, update_exe_path.c_str(), update_exe_path.c_str(), params.str().c_str(), NULL);
2961 llinfos << "Spawn returned " << retval << llendl;
2962
2963#elif LL_DARWIN
2964 // if a sim name was passed in via command line parameter (typically through a SLURL)
2965 if ( LLURLSimString::sInstance.mSimString.length() )
2966 {
2967 // record the location to start at next time
2968 gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString );
2969 };
2970
2971 update_exe_path = "'";
2972 update_exe_path += gDirUtilp->getAppRODataDir();
2973 update_exe_path += "/AutoUpdater.app/Contents/MacOS/AutoUpdater' -userserver ";
2974 update_exe_path += gUserServerName;
2975 update_exe_path += " -name \"";
2976 update_exe_path += gSecondLife;
2977 update_exe_path += "\" &";
2978
2979 llinfos << "Calling updater: " << update_exe_path << llendl;
2980
2981 remove_marker_file(); // In case updater fails
2982
2983 // Run the auto-updater.
2984 system(update_exe_path.c_str());
2985
2986#elif LL_LINUX
2987 OSMessageBox("Automatic updating is not yet implemented for Linux.\n"
2988 "Please download the latest version from www.secondlife.com.",
2989 NULL, OSMB_OK);
2990 remove_marker_file();
2991
2992#endif
2993 app_force_quit(NULL);
2994}
2995
2996void use_circuit_callback(void**, S32 result)
2997{
2998 // bail if we're quitting.
2999 if(gQuit) return;
3000 static bool called = false;
3001 if(!called)
3002 {
3003 called = true;
3004 if (result)
3005 {
3006 // Make sure user knows something bad happened. JC
3007 llinfos << "Backing up to login screen!" << llendl;
3008 gViewerWindow->alertXml("LoginPacketNeverReceived",
3009 login_alert_status, NULL);
3010 gStartupState = STATE_LOGIN_SHOW;
3011 }
3012 else
3013 {
3014 gGotUseCircuitCodeAck = true;
3015 }
3016 }
3017}
3018
3019void register_viewer_callbacks(LLMessageSystem* msg)
3020{
3021 msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data );
3022 msg->setHandlerFuncFast(_PREHASH_ImageData, LLViewerImage::receiveImage );
3023 msg->setHandlerFuncFast(_PREHASH_ImagePacket, LLViewerImage::receiveImagePacket );
3024 msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update );
3025 msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update );
3026 msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update );
3027 msg->setHandlerFuncFast(_PREHASH_ImprovedTerseObjectUpdate, process_terse_object_update_improved );
3028 msg->setHandlerFunc("SimStats", process_sim_stats);
3029 msg->setHandlerFuncFast(_PREHASH_HealthMessage, process_health_message );
3030 msg->setHandlerFuncFast(_PREHASH_EconomyData, process_economy_data);
3031 msg->setHandlerFunc("RegionInfo", LLViewerRegion::processRegionInfo);
3032
3033 msg->setHandlerFuncFast(_PREHASH_ChatFromSimulator, process_chat_from_simulator);
3034 msg->setHandlerFuncFast(_PREHASH_KillObject, process_kill_object, NULL);
3035 msg->setHandlerFuncFast(_PREHASH_SimulatorViewerTimeMessage, process_time_synch, NULL);
3036 msg->setHandlerFuncFast(_PREHASH_EnableSimulator, process_enable_simulator);
3037 msg->setHandlerFuncFast(_PREHASH_DisableSimulator, process_disable_simulator);
3038 msg->setHandlerFuncFast(_PREHASH_KickUser, process_kick_user, NULL);
3039
3040 msg->setHandlerFunc("CrossedRegion", process_crossed_region);
3041 msg->setHandlerFuncFast(_PREHASH_TeleportFinish, process_teleport_finish);
3042
3043 msg->setHandlerFuncFast(_PREHASH_AlertMessage, process_alert_message);
3044 msg->setHandlerFunc("AgentAlertMessage", process_agent_alert_message);
3045 msg->setHandlerFuncFast(_PREHASH_MeanCollisionAlert, process_mean_collision_alert_message, NULL);
3046 msg->setHandlerFunc("ViewerFrozenMessage", process_frozen_message);
3047
3048 msg->setHandlerFuncFast(_PREHASH_RequestAvatarInfo, process_avatar_info_request);
3049 msg->setHandlerFuncFast(_PREHASH_NameValuePair, process_name_value);
3050 msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair, process_remove_name_value);
3051 msg->setHandlerFuncFast(_PREHASH_AvatarAnimation, process_avatar_animation);
3052 msg->setHandlerFuncFast(_PREHASH_AvatarAppearance, process_avatar_appearance);
3053 msg->setHandlerFunc("AgentCachedTextureResponse", LLAgent::processAgentCachedTextureResponse);
3054 msg->setHandlerFunc("RebakeAvatarTextures", LLVOAvatar::processRebakeAvatarTextures);
3055 msg->setHandlerFuncFast(_PREHASH_CameraConstraint, process_camera_constraint);
3056 msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse, process_avatar_sit_response);
3057 msg->setHandlerFunc("SetFollowCamProperties", process_set_follow_cam_properties);
3058 msg->setHandlerFunc("ClearFollowCamProperties", process_clear_follow_cam_properties);
3059
3060 msg->setHandlerFuncFast(_PREHASH_ImprovedInstantMessage, process_improved_im);
3061 msg->setHandlerFuncFast(_PREHASH_ScriptQuestion, process_script_question);
3062 msg->setHandlerFuncFast(_PREHASH_ObjectProperties, LLSelectMgr::processObjectProperties, NULL);
3063 msg->setHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, LLSelectMgr::processObjectPropertiesFamily, NULL);
3064 msg->setHandlerFunc("ForceObjectSelect", LLSelectMgr::processForceObjectSelect);
3065
3066 msg->setHandlerFuncFast(_PREHASH_MoneyBalanceReply, process_money_balance_reply, NULL);
3067 msg->setHandlerFuncFast(_PREHASH_CoarseLocationUpdate, LLWorld::processCoarseUpdate, NULL);
3068 msg->setHandlerFuncFast(_PREHASH_ReplyTaskInventory, LLViewerObject::processTaskInv, NULL);
3069 msg->setHandlerFuncFast(_PREHASH_DerezContainer, process_derez_container, NULL);
3070 msg->setHandlerFuncFast(_PREHASH_ScriptRunningReply,
3071 &LLLiveLSLEditor::processScriptRunningReply);
3072
3073 msg->setHandlerFuncFast(_PREHASH_DeRezAck, process_derez_ack);
3074
3075 msg->setHandlerFunc("LogoutReply", process_logout_reply);
3076
3077 //msg->setHandlerFuncFast(_PREHASH_AddModifyAbility,
3078 // &LLAgent::processAddModifyAbility);
3079 //msg->setHandlerFuncFast(_PREHASH_RemoveModifyAbility,
3080 // &LLAgent::processRemoveModifyAbility);
3081 msg->setHandlerFuncFast(_PREHASH_AgentDataUpdate,
3082 &LLAgent::processAgentDataUpdate);
3083 msg->setHandlerFuncFast(_PREHASH_AgentGroupDataUpdate,
3084 &LLAgent::processAgentGroupDataUpdate);
3085 msg->setHandlerFunc("AgentDropGroup",
3086 &LLAgent::processAgentDropGroup);
3087 // land ownership messages
3088 msg->setHandlerFuncFast(_PREHASH_ParcelOverlay,
3089 LLViewerParcelMgr::processParcelOverlay);
3090 msg->setHandlerFuncFast(_PREHASH_ParcelProperties,
3091 LLViewerParcelMgr::processParcelProperties);
3092 msg->setHandlerFunc("ParcelAccessListReply",
3093 LLViewerParcelMgr::processParcelAccessListReply);
3094 msg->setHandlerFunc("ParcelDwellReply",
3095 LLViewerParcelMgr::processParcelDwellReply);
3096
3097 msg->setHandlerFunc("AvatarPropertiesReply",
3098 LLPanelAvatar::processAvatarPropertiesReply);
3099 msg->setHandlerFunc("AvatarInterestsReply",
3100 LLPanelAvatar::processAvatarInterestsReply);
3101 msg->setHandlerFunc("AvatarGroupsReply",
3102 LLPanelAvatar::processAvatarGroupsReply);
3103 msg->setHandlerFuncFast(_PREHASH_AvatarStatisticsReply,
3104 LLPanelAvatar::processAvatarStatisticsReply);
3105 msg->setHandlerFunc("AvatarNotesReply",
3106 LLPanelAvatar::processAvatarNotesReply);
3107 msg->setHandlerFunc("AvatarPicksReply",
3108 LLPanelAvatar::processAvatarPicksReply);
3109 msg->setHandlerFunc("AvatarClassifiedReply",
3110 LLPanelAvatar::processAvatarClassifiedReply);
3111
3112 msg->setHandlerFuncFast(_PREHASH_CreateGroupReply,
3113 LLGroupMgr::processCreateGroupReply);
3114 msg->setHandlerFuncFast(_PREHASH_JoinGroupReply,
3115 LLGroupMgr::processJoinGroupReply);
3116 msg->setHandlerFuncFast(_PREHASH_EjectGroupMemberReply,
3117 LLGroupMgr::processEjectGroupMemberReply);
3118 msg->setHandlerFuncFast(_PREHASH_LeaveGroupReply,
3119 LLGroupMgr::processLeaveGroupReply);
3120 msg->setHandlerFuncFast(_PREHASH_GroupProfileReply,
3121 LLGroupMgr::processGroupPropertiesReply);
3122
3123 msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply,
3124 LLFloaterRate::processReputationIndividualReply);
3125
3126 msg->setHandlerFuncFast(_PREHASH_AgentWearablesUpdate,
3127 LLAgent::processAgentInitialWearablesUpdate );
3128
3129 msg->setHandlerFunc("ScriptControlChange",
3130 LLAgent::processScriptControlChange );
3131
3132 msg->setHandlerFuncFast(_PREHASH_GestureUpdate,
3133 LLViewerGestureList::processGestureUpdate);
3134
3135 msg->setHandlerFuncFast(_PREHASH_ViewerEffect, LLHUDManager::processViewerEffect);
3136
3137 msg->setHandlerFuncFast(_PREHASH_GrantGodlikePowers, process_grant_godlike_powers);
3138
3139 msg->setHandlerFuncFast(_PREHASH_MoneySummaryReply,
3140 LLFloaterAccountHistory::processMoneySummaryReply);
3141 msg->setHandlerFuncFast(_PREHASH_MoneyDetailsReply,
3142 LLFloaterAccountHistory::processMoneyDetailsReply);
3143 msg->setHandlerFuncFast(_PREHASH_MoneyTransactionsReply,
3144 LLFloaterAccountHistory::processMoneyTransactionsReply);
3145
3146 // ASDF
3147 msg->setHandlerFuncFast(_PREHASH_GroupAccountSummaryReply,
3148 LLGroupMoneyPlanningTabEventHandler::processGroupAccountSummaryReply);
3149 msg->setHandlerFuncFast(_PREHASH_GroupAccountDetailsReply,
3150 LLGroupMoneyDetailsTabEventHandler::processGroupAccountDetailsReply);
3151 msg->setHandlerFuncFast(_PREHASH_GroupAccountTransactionsReply,
3152 LLGroupMoneySalesTabEventHandler::processGroupAccountTransactionsReply);
3153
3154 msg->setHandlerFuncFast(_PREHASH_UserInfoReply,
3155 process_user_info_reply);
3156
3157 msg->setHandlerFunc("RegionHandshake", process_region_handshake, NULL);
3158
3159 msg->setHandlerFunc("TeleportStart", process_teleport_start );
3160 msg->setHandlerFunc("TeleportProgress", process_teleport_progress);
3161 msg->setHandlerFunc("TeleportFailed", process_teleport_failed, NULL);
3162 msg->setHandlerFunc("TeleportLocal", process_teleport_local, NULL);
3163
3164 msg->setHandlerFunc("ImageNotInDatabase", LLViewerImageList::processImageNotInDatabase, NULL);
3165
3166 msg->setHandlerFuncFast(_PREHASH_GroupMembersReply,
3167 LLGroupMgr::processGroupMembersReply);
3168 msg->setHandlerFunc("GroupRoleDataReply",
3169 LLGroupMgr::processGroupRoleDataReply);
3170 msg->setHandlerFunc("GroupRoleMembersReply",
3171 LLGroupMgr::processGroupRoleMembersReply);
3172 msg->setHandlerFunc("GroupTitlesReply",
3173 LLGroupMgr::processGroupTitlesReply);
3174 // Special handler as this message is sometimes used for group land.
3175 msg->setHandlerFunc("PlacesReply", process_places_reply);
3176 msg->setHandlerFunc("GroupNoticesListReply", LLPanelGroupNotices::processGroupNoticesListReply);
3177
3178 msg->setHandlerFunc("DirPlacesReply", LLPanelDirBrowser::processDirPlacesReply);
3179 msg->setHandlerFunc("DirPeopleReply", LLPanelDirBrowser::processDirPeopleReply);
3180 msg->setHandlerFunc("DirEventsReply", LLPanelDirBrowser::processDirEventsReply);
3181 msg->setHandlerFunc("DirGroupsReply", LLPanelDirBrowser::processDirGroupsReply);
3182 //msg->setHandlerFunc("DirPicksReply", LLPanelDirBrowser::processDirPicksReply);
3183 msg->setHandlerFunc("DirClassifiedReply", LLPanelDirBrowser::processDirClassifiedReply);
3184 msg->setHandlerFunc("DirLandReply", LLPanelDirBrowser::processDirLandReply);
3185 msg->setHandlerFunc("DirPopularReply",LLPanelDirBrowser::processDirPopularReply);
3186
3187 msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply);
3188
3189 msg->setHandlerFunc("MapLayerReply", LLWorldMap::processMapLayerReply);
3190 msg->setHandlerFunc("MapBlockReply", LLWorldMap::processMapBlockReply);
3191 msg->setHandlerFunc("MapItemReply", LLWorldMap::processMapItemReply);
3192
3193 msg->setHandlerFunc("EventInfoReply", LLPanelEvent::processEventInfoReply);
3194 msg->setHandlerFunc("PickInfoReply", LLPanelPick::processPickInfoReply);
3195 msg->setHandlerFunc("ClassifiedInfoReply", LLPanelClassified::processClassifiedInfoReply);
3196 msg->setHandlerFunc("ParcelInfoReply", LLPanelPlace::processParcelInfoReply);
3197 msg->setHandlerFunc("ScriptDialog", process_script_dialog);
3198 msg->setHandlerFunc("LoadURL", process_load_url);
3199 msg->setHandlerFunc("ScriptTeleportRequest", process_script_teleport_request);
3200 msg->setHandlerFunc("EstateCovenantReply", process_covenant_reply);
3201
3202 // calling cards
3203 msg->setHandlerFunc("OfferCallingCard", process_offer_callingcard);
3204 msg->setHandlerFunc("AcceptCallingCard", process_accept_callingcard);
3205 msg->setHandlerFunc("DeclineCallingCard", process_decline_callingcard);
3206
3207 msg->setHandlerFunc("ParcelObjectOwnersReply", LLPanelLandObjects::processParcelObjectOwnersReply);
3208
3209 // Reponse to the "Refresh" button on land objects floater.
3210 if (gSavedSettings.getBOOL("AudioStreamingVideo"))
3211 {
3212 msg->setHandlerFunc("ParcelMediaCommandMessage", LLMediaEngine::process_parcel_media);
3213 msg->setHandlerFunc ( "ParcelMediaUpdate", LLMediaEngine::process_parcel_media_update );
3214 }
3215 else
3216 {
3217 msg->setHandlerFunc("ParcelMediaCommandMessage", null_message_callback);
3218 gMessageSystem->setHandlerFunc ( "ParcelMediaUpdate", null_message_callback );
3219 }
3220
3221 msg->setHandlerFunc("InitiateDownload", process_initiate_download);
3222 msg->setHandlerFunc("LandStatReply", LLFloaterTopObjects::handle_land_reply);
3223 msg->setHandlerFunc("GenericMessage", process_generic_message);
3224
3225 msg->setHandlerFuncFast(_PREHASH_FeatureDisabled, process_feature_disabled_message);
3226}
3227
3228
3229void init_stat_view()
3230{
3231 LLFrameStatView *frameviewp = gDebugView->mFrameStatView;
3232 frameviewp->setup(gFrameStats);
3233 frameviewp->mShowPercent = FALSE;
3234
3235 LLRect rect;
3236 LLStatBar *stat_barp;
3237 rect = gDebugView->mStatViewp->getRect();
3238
3239 //
3240 // Viewer advanced stats
3241 //
3242 LLStatView *stat_viewp = NULL;
3243
3244 //
3245 // Viewer Basic
3246 //
3247 stat_viewp = new LLStatView("basic stat view", "Basic", "OpenDebugStatBasic", rect);
3248 gDebugView->mStatViewp->addChildAtEnd(stat_viewp);
3249
3250 stat_barp = stat_viewp->addStat("FPS", &(gViewerStats->mFPSStat));
3251 stat_barp->setUnitLabel(" fps");
3252 stat_barp->mMinBar = 0.f;
3253 stat_barp->mMaxBar = 45.f;
3254 stat_barp->mTickSpacing = 7.5f;
3255 stat_barp->mLabelSpacing = 15.f;
3256 stat_barp->mPrecision = 1;
3257 stat_barp->mDisplayBar = TRUE;
3258 stat_barp->mDisplayHistory = TRUE;
3259
3260 stat_barp = stat_viewp->addStat("Bandwidth", &(gViewerStats->mKBitStat));
3261 stat_barp->setUnitLabel(" kbps");
3262 stat_barp->mMinBar = 0.f;
3263 stat_barp->mMaxBar = 900.f;
3264 stat_barp->mTickSpacing = 100.f;
3265 stat_barp->mLabelSpacing = 300.f;
3266 stat_barp->mDisplayBar = TRUE;
3267 stat_barp->mDisplayHistory = FALSE;
3268
3269 stat_barp = stat_viewp->addStat("Packet Loss", &(gViewerStats->mPacketsLostPercentStat));
3270 stat_barp->setUnitLabel(" %%");
3271 stat_barp->mMinBar = 0.f;
3272 stat_barp->mMaxBar = 5.f;
3273 stat_barp->mTickSpacing = 1.f;
3274 stat_barp->mLabelSpacing = 1.f;
3275 stat_barp->mDisplayBar = FALSE;
3276 stat_barp->mPerSec = FALSE;
3277 stat_barp->mDisplayMean = TRUE;
3278 stat_barp->mPrecision = 1;
3279
3280 stat_barp = stat_viewp->addStat("Ping Sim", &(gViewerStats->mSimPingStat));
3281 stat_barp->setUnitLabel(" msec");
3282 stat_barp->mMinBar = 0.f;
3283 stat_barp->mMaxBar = 1000.f;
3284 stat_barp->mTickSpacing = 100.f;
3285 stat_barp->mLabelSpacing = 200.f;
3286 stat_barp->mDisplayBar = FALSE;
3287 stat_barp->mPerSec = FALSE;
3288 stat_barp->mDisplayMean = FALSE;
3289
3290 stat_barp = stat_viewp->addStat("Ping User", &(gViewerStats->mUserserverPingStat));
3291 stat_barp->setUnitLabel(" msec");
3292 stat_barp->mMinBar = 0.f;
3293 stat_barp->mMaxBar = 1000.f;
3294 stat_barp->mTickSpacing = 100.f;
3295 stat_barp->mLabelSpacing = 200.f;
3296 stat_barp->mDisplayBar = FALSE;
3297 stat_barp->mPerSec = FALSE;
3298 stat_barp->mDisplayMean = FALSE;
3299
3300
3301 stat_viewp = new LLStatView("advanced stat view", "Advanced", "OpenDebugStatAdvanced", rect);
3302 gDebugView->mStatViewp->addChildAtEnd(stat_viewp);
3303
3304
3305 LLStatView *render_statviewp;
3306 render_statviewp = new LLStatView("render stat view", "Render", "OpenDebugStatRender", rect);
3307 stat_viewp->addChildAtEnd(render_statviewp);
3308
3309 stat_barp = render_statviewp->addStat("KTris Drawn", &(gPipeline.mTrianglesDrawnStat));
3310 stat_barp->setUnitLabel("/fr");
3311 stat_barp->mMinBar = 0.f;
3312 stat_barp->mMaxBar = 500.f;
3313 stat_barp->mTickSpacing = 100.f;
3314 stat_barp->mLabelSpacing = 500.f;
3315 stat_barp->mPrecision = 1;
3316 stat_barp->mPerSec = FALSE;
3317
3318 stat_barp = render_statviewp->addStat("KTris Drawn", &(gPipeline.mTrianglesDrawnStat));
3319 stat_barp->setUnitLabel("/sec");
3320 stat_barp->mMinBar = 0.f;
3321 stat_barp->mMaxBar = 3000.f;
3322 stat_barp->mTickSpacing = 250.f;
3323 stat_barp->mLabelSpacing = 1000.f;
3324 stat_barp->mPrecision = 1;
3325
3326 stat_barp = render_statviewp->addStat("Total Objs", &(gObjectList.mNumObjectsStat));
3327 stat_barp->mMinBar = 0.f;
3328 stat_barp->mMaxBar = 10000.f;
3329 stat_barp->mTickSpacing = 2500.f;
3330 stat_barp->mLabelSpacing = 5000.f;
3331 stat_barp->mPerSec = FALSE;
3332 stat_barp->mDisplayBar = FALSE;
3333
3334 stat_barp = render_statviewp->addStat("New Objs", &(gObjectList.mNumNewObjectsStat));
3335 stat_barp->setLabel("New Objs");
3336 stat_barp->setUnitLabel("/sec");
3337 stat_barp->mMinBar = 0.f;
3338 stat_barp->mMaxBar = 1000.f;
3339 stat_barp->mTickSpacing = 100.f;
3340 stat_barp->mLabelSpacing = 500.f;
3341 stat_barp->mPerSec = TRUE;
3342 stat_barp->mDisplayBar = FALSE;
3343
3344
3345 // Pipeline statistics
3346 LLStatView *pipeline_statviewp;
3347 pipeline_statviewp = new LLStatView("pipeline stat view", "Pipeline", "", rect);
3348 render_statviewp->addChildAtEnd(pipeline_statviewp);
3349
3350 stat_barp = pipeline_statviewp->addStat("Visible Drawables", &(gPipeline.mNumVisibleDrawablesStat));
3351 stat_barp->setUnitLabel("");
3352 stat_barp->mMinBar = 0.f;
3353 stat_barp->mMaxBar = 10000.f;
3354 stat_barp->mTickSpacing = 1000.f;
3355 stat_barp->mLabelSpacing = 5000.f;
3356 stat_barp->mPerSec = FALSE;
3357
3358 stat_barp = pipeline_statviewp->addStat("Visible Faces", &(gPipeline.mNumVisibleFacesStat));
3359 stat_barp->setUnitLabel("");
3360 stat_barp->mMinBar = 0.f;
3361 stat_barp->mMaxBar = 40000.f;
3362 stat_barp->mTickSpacing = 5000.f;
3363 stat_barp->mLabelSpacing = 10000.f;
3364 stat_barp->mPerSec = FALSE;
3365
3366 stat_barp = pipeline_statviewp->addStat("DirtyGeom", &(gPipeline.mGeometryChangesStat));
3367 stat_barp->setUnitLabel("/fr");
3368 stat_barp->mMinBar = 0.f;
3369 stat_barp->mMaxBar = 1000.f;
3370 stat_barp->mTickSpacing = 100.f;
3371 stat_barp->mLabelSpacing = 500.f;
3372 stat_barp->mPerSec = FALSE;
3373
3374 stat_barp = pipeline_statviewp->addStat("DirtyLight", &(gPipeline.mLightingChangesStat));
3375 stat_barp->setUnitLabel("/fr");
3376 stat_barp->mMinBar = 0.f;
3377 stat_barp->mMaxBar = 1000.f;
3378 stat_barp->mTickSpacing = 100.f;
3379 stat_barp->mLabelSpacing = 500.f;
3380 stat_barp->mPerSec = FALSE;
3381
3382 stat_barp = pipeline_statviewp->addStat("MoveList", &(gPipeline.mMoveChangesStat));
3383 stat_barp->setUnitLabel("dr");
3384 stat_barp->mMinBar = 0.f;
3385 stat_barp->mMaxBar = 1000.f;
3386 stat_barp->mTickSpacing = 100.f;
3387 stat_barp->mLabelSpacing = 500.f;
3388 stat_barp->mPerSec = FALSE;
3389
3390 stat_barp = pipeline_statviewp->addStat("Compiles", &(gPipeline.mCompilesStat));
3391 stat_barp->setUnitLabel("/fr");
3392 stat_barp->mMinBar = 0.f;
3393 stat_barp->mMaxBar = 1000.f;
3394 stat_barp->mTickSpacing = 100.f;
3395 stat_barp->mLabelSpacing = 500.f;
3396 stat_barp->mPerSec = FALSE;
3397
3398 stat_barp = pipeline_statviewp->addStat("Verts Relit", &(gPipeline.mVerticesRelitStat));
3399 stat_barp->setUnitLabel("/fr");
3400 stat_barp->mMinBar = 0.f;
3401 stat_barp->mMaxBar = 40000.f;
3402 stat_barp->mTickSpacing = 10000.f;
3403 stat_barp->mLabelSpacing = 20000.f;
3404 stat_barp->mPerSec = FALSE;
3405
3406 // Texture statistics
3407 LLStatView *texture_statviewp;
3408 texture_statviewp = new LLStatView("texture stat view", "Texture", "", rect);
3409 render_statviewp->addChildAtEnd(texture_statviewp);
3410
3411 stat_barp = texture_statviewp->addStat("Count", &(gImageList.sNumImagesStat));
3412 stat_barp->setUnitLabel("");
3413 stat_barp->mMinBar = 0.f;
3414 stat_barp->mMaxBar = 8000.f;
3415 stat_barp->mTickSpacing = 2000.f;
3416 stat_barp->mLabelSpacing = 4000.f;
3417 stat_barp->mPerSec = FALSE;
3418 stat_barp->mDisplayBar = FALSE;
3419
3420 stat_barp = texture_statviewp->addStat("Raw Count", &(gImageList.sNumRawImagesStat));
3421 stat_barp->setUnitLabel("");
3422 stat_barp->mMinBar = 0.f;
3423 stat_barp->mMaxBar = 8000.f;
3424 stat_barp->mTickSpacing = 2000.f;
3425 stat_barp->mLabelSpacing = 4000.f;
3426 stat_barp->mPerSec = FALSE;
3427 stat_barp->mDisplayBar = FALSE;
3428
3429 stat_barp = texture_statviewp->addStat("GL Mem", &(gImageList.sGLTexMemStat));
3430 stat_barp->setUnitLabel("");
3431 stat_barp->mMinBar = 0.f;
3432 stat_barp->mMaxBar = 400.f;
3433 stat_barp->mTickSpacing = 100.f;
3434 stat_barp->mLabelSpacing = 200.f;
3435 stat_barp->mPrecision = 1;
3436 stat_barp->mPerSec = FALSE;
3437
3438 stat_barp = texture_statviewp->addStat("Formatted Mem", &(gImageList.sFormattedMemStat));
3439 stat_barp->setUnitLabel("");
3440 stat_barp->mMinBar = 0.f;
3441 stat_barp->mMaxBar = 400.f;
3442 stat_barp->mTickSpacing = 100.f;
3443 stat_barp->mLabelSpacing = 200.f;
3444 stat_barp->mPrecision = 1;
3445 stat_barp->mPerSec = FALSE;
3446
3447 stat_barp = texture_statviewp->addStat("Raw Mem", &(gImageList.sRawMemStat));
3448 stat_barp->setUnitLabel("");
3449 stat_barp->mMinBar = 0.f;
3450 stat_barp->mMaxBar = 400.f;
3451 stat_barp->mTickSpacing = 100.f;
3452 stat_barp->mLabelSpacing = 200.f;
3453 stat_barp->mPrecision = 1;
3454 stat_barp->mPerSec = FALSE;
3455
3456 stat_barp = texture_statviewp->addStat("Bound Mem", &(gImageList.sGLBoundMemStat));
3457 stat_barp->setUnitLabel("");
3458 stat_barp->mMinBar = 0.f;
3459 stat_barp->mMaxBar = 400.f;
3460 stat_barp->mTickSpacing = 100.f;
3461 stat_barp->mLabelSpacing = 200.f;
3462 stat_barp->mPrecision = 1;
3463 stat_barp->mPerSec = FALSE;
3464
3465
3466 // Network statistics
3467 LLStatView *net_statviewp;
3468 net_statviewp = new LLStatView("network stat view", "Network", "OpenDebugStatNet", rect);
3469 stat_viewp->addChildAtEnd(net_statviewp);
3470
3471 stat_barp = net_statviewp->addStat("Packets In", &(gViewerStats->mPacketsInStat));
3472 stat_barp->setUnitLabel("/sec");
3473 stat_barp->mDisplayBar = FALSE;
3474
3475 stat_barp = net_statviewp->addStat("Packets Out", &(gViewerStats->mPacketsOutStat));
3476 stat_barp->setUnitLabel("/sec");
3477 stat_barp->mDisplayBar = FALSE;
3478
3479 stat_barp = net_statviewp->addStat("Objects", &(gViewerStats->mObjectKBitStat));
3480 stat_barp->setUnitLabel(" kbps");
3481 stat_barp->mDisplayBar = FALSE;
3482
3483 stat_barp = net_statviewp->addStat("Texture", &(gViewerStats->mTextureKBitStat));
3484 stat_barp->setUnitLabel(" kbps");
3485 stat_barp->mDisplayBar = FALSE;
3486
3487 stat_barp = net_statviewp->addStat("Asset", &(gViewerStats->mAssetKBitStat));
3488 stat_barp->setUnitLabel(" kbps");
3489 stat_barp->mDisplayBar = FALSE;
3490
3491 stat_barp = net_statviewp->addStat("Layers", &(gViewerStats->mLayersKBitStat));
3492 stat_barp->setUnitLabel(" kbps");
3493 stat_barp->mDisplayBar = FALSE;
3494
3495 stat_barp = net_statviewp->addStat("Actual In", &(gViewerStats->mActualInKBitStat));
3496 stat_barp->setUnitLabel(" kbps");
3497 stat_barp->mMinBar = 0.f;
3498 stat_barp->mMaxBar = 1024.f;
3499 stat_barp->mTickSpacing = 128.f;
3500 stat_barp->mLabelSpacing = 256.f;
3501 stat_barp->mDisplayBar = TRUE;
3502 stat_barp->mDisplayHistory = FALSE;
3503
3504 stat_barp = net_statviewp->addStat("Actual Out", &(gViewerStats->mActualOutKBitStat));
3505 stat_barp->setUnitLabel(" kbps");
3506 stat_barp->mMinBar = 0.f;
3507 stat_barp->mMaxBar = 512.f;
3508 stat_barp->mTickSpacing = 128.f;
3509 stat_barp->mLabelSpacing = 256.f;
3510 stat_barp->mDisplayBar = TRUE;
3511 stat_barp->mDisplayHistory = FALSE;
3512
3513 stat_barp = net_statviewp->addStat("VFS Pending Ops", &(gViewerStats->mVFSPendingOperations));
3514 stat_barp->setUnitLabel(" ");
3515 stat_barp->mPerSec = FALSE;
3516 stat_barp->mDisplayBar = FALSE;
3517
3518
3519 // Simulator stats
3520 LLStatView *sim_statviewp = new LLStatView("sim stat view", "Simulator", "OpenDebugStatSim", rect);
3521 gDebugView->mStatViewp->addChildAtEnd(sim_statviewp);
3522
3523 stat_barp = sim_statviewp->addStat("Time Dilation", &(gViewerStats->mSimTimeDilation));
3524 stat_barp->mPrecision = 2;
3525 stat_barp->mMinBar = 0.f;
3526 stat_barp->mMaxBar = 1.f;
3527 stat_barp->mTickSpacing = 0.25f;
3528 stat_barp->mLabelSpacing = 0.5f;
3529 stat_barp->mPerSec = FALSE;
3530 stat_barp->mDisplayBar = FALSE;
3531 stat_barp->mDisplayMean = FALSE;
3532
3533 stat_barp = sim_statviewp->addStat("Sim FPS", &(gViewerStats->mSimFPS));
3534 stat_barp->mMinBar = 0.f;
3535 stat_barp->mMaxBar = 200.f;
3536 stat_barp->mTickSpacing = 20.f;
3537 stat_barp->mLabelSpacing = 100.f;
3538 stat_barp->mPerSec = FALSE;
3539 stat_barp->mDisplayBar = FALSE;
3540 stat_barp->mDisplayMean = FALSE;
3541
3542 stat_barp = sim_statviewp->addStat("Physics FPS", &(gViewerStats->mSimPhysicsFPS));
3543 stat_barp->mPrecision = 1;
3544 stat_barp->mMinBar = 0.f;
3545 stat_barp->mMaxBar = 66.f;
3546 stat_barp->mTickSpacing = 33.f;
3547 stat_barp->mLabelSpacing = 33.f;
3548 stat_barp->mPerSec = FALSE;
3549 stat_barp->mDisplayBar = FALSE;
3550 stat_barp->mDisplayMean = FALSE;
3551
3552 stat_barp = sim_statviewp->addStat("Agent Updates/Sec", &(gViewerStats->mSimAgentUPS));
3553 stat_barp->mPrecision = 1;
3554 stat_barp->mMinBar = 0.f;
3555 stat_barp->mMaxBar = 100.f;
3556 stat_barp->mTickSpacing = 25.f;
3557 stat_barp->mLabelSpacing = 50.f;
3558 stat_barp->mPerSec = FALSE;
3559 stat_barp->mDisplayBar = FALSE;
3560 stat_barp->mDisplayMean = FALSE;
3561
3562 stat_barp = sim_statviewp->addStat("Main Agents", &(gViewerStats->mSimMainAgents));
3563 stat_barp->mPrecision = 0;
3564 stat_barp->mMinBar = 0.f;
3565 stat_barp->mMaxBar = 80.f;
3566 stat_barp->mTickSpacing = 10.f;
3567 stat_barp->mLabelSpacing = 40.f;
3568 stat_barp->mPerSec = FALSE;
3569 stat_barp->mDisplayBar = FALSE;
3570 stat_barp->mDisplayMean = FALSE;
3571
3572 stat_barp = sim_statviewp->addStat("Child Agents", &(gViewerStats->mSimChildAgents));
3573 stat_barp->mPrecision = 0;
3574 stat_barp->mMinBar = 0.f;
3575 stat_barp->mMaxBar = 40.f;
3576 stat_barp->mTickSpacing = 5.f;
3577 stat_barp->mLabelSpacing = 10.f;
3578 stat_barp->mPerSec = FALSE;
3579 stat_barp->mDisplayBar = FALSE;
3580 stat_barp->mDisplayMean = FALSE;
3581
3582 stat_barp = sim_statviewp->addStat("Objects", &(gViewerStats->mSimObjects));
3583 stat_barp->mPrecision = 0;
3584 stat_barp->mMinBar = 0.f;
3585 stat_barp->mMaxBar = 30000.f;
3586 stat_barp->mTickSpacing = 5000.f;
3587 stat_barp->mLabelSpacing = 10000.f;
3588 stat_barp->mPerSec = FALSE;
3589 stat_barp->mDisplayBar = FALSE;
3590 stat_barp->mDisplayMean = FALSE;
3591
3592 stat_barp = sim_statviewp->addStat("Active Objects", &(gViewerStats->mSimActiveObjects));
3593 stat_barp->mPrecision = 0;
3594 stat_barp->mMinBar = 0.f;
3595 stat_barp->mMaxBar = 800.f;
3596 stat_barp->mTickSpacing = 100.f;
3597 stat_barp->mLabelSpacing = 200.f;
3598 stat_barp->mPerSec = FALSE;
3599 stat_barp->mDisplayBar = FALSE;
3600 stat_barp->mDisplayMean = FALSE;
3601
3602 stat_barp = sim_statviewp->addStat("Active Scripts", &(gViewerStats->mSimActiveScripts));
3603 stat_barp->mPrecision = 0;
3604 stat_barp->mMinBar = 0.f;
3605 stat_barp->mMaxBar = 800.f;
3606 stat_barp->mTickSpacing = 100.f;
3607 stat_barp->mLabelSpacing = 200.f;
3608 stat_barp->mPerSec = FALSE;
3609 stat_barp->mDisplayBar = FALSE;
3610 stat_barp->mDisplayMean = FALSE;
3611
3612 stat_barp = sim_statviewp->addStat("Script Perf", &(gViewerStats->mSimLSLIPS));
3613 stat_barp->setUnitLabel(" ips");
3614 stat_barp->mPrecision = 0;
3615 stat_barp->mMinBar = 0.f;
3616 stat_barp->mMaxBar = 100000.f;
3617 stat_barp->mTickSpacing = 25000.f;
3618 stat_barp->mLabelSpacing = 50000.f;
3619 stat_barp->mPerSec = FALSE;
3620 stat_barp->mDisplayBar = FALSE;
3621 stat_barp->mDisplayMean = FALSE;
3622
3623 stat_barp = sim_statviewp->addStat("Packets In", &(gViewerStats->mSimInPPS));
3624 stat_barp->setUnitLabel(" pps");
3625 stat_barp->mPrecision = 0;
3626 stat_barp->mMinBar = 0.f;
3627 stat_barp->mMaxBar = 2000.f;
3628 stat_barp->mTickSpacing = 250.f;
3629 stat_barp->mLabelSpacing = 1000.f;
3630 stat_barp->mPerSec = FALSE;
3631 stat_barp->mDisplayBar = FALSE;
3632 stat_barp->mDisplayMean = FALSE;
3633
3634 stat_barp = sim_statviewp->addStat("Packets Out", &(gViewerStats->mSimOutPPS));
3635 stat_barp->setUnitLabel(" pps");
3636 stat_barp->mPrecision = 0;
3637 stat_barp->mMinBar = 0.f;
3638 stat_barp->mMaxBar = 2000.f;
3639 stat_barp->mTickSpacing = 250.f;
3640 stat_barp->mLabelSpacing = 1000.f;
3641 stat_barp->mPerSec = FALSE;
3642 stat_barp->mDisplayBar = FALSE;
3643 stat_barp->mDisplayMean = FALSE;
3644
3645 stat_barp = sim_statviewp->addStat("Pending Downloads", &(gViewerStats->mSimPendingDownloads));
3646 stat_barp->mPrecision = 0;
3647 stat_barp->mMinBar = 0.f;
3648 stat_barp->mMaxBar = 800.f;
3649 stat_barp->mTickSpacing = 100.f;
3650 stat_barp->mLabelSpacing = 200.f;
3651 stat_barp->mPerSec = FALSE;
3652 stat_barp->mDisplayBar = FALSE;
3653 stat_barp->mDisplayMean = FALSE;
3654
3655 stat_barp = sim_statviewp->addStat("Pending Uploads", &(gViewerStats->mSimPendingUploads));
3656 stat_barp->mPrecision = 0;
3657 stat_barp->mMinBar = 0.f;
3658 stat_barp->mMaxBar = 100.f;
3659 stat_barp->mTickSpacing = 25.f;
3660 stat_barp->mLabelSpacing = 50.f;
3661 stat_barp->mPerSec = FALSE;
3662 stat_barp->mDisplayBar = FALSE;
3663 stat_barp->mDisplayMean = FALSE;
3664
3665 stat_barp = sim_statviewp->addStat("Total Unacked Bytes", &(gViewerStats->mSimTotalUnackedBytes));
3666 stat_barp->setUnitLabel(" kb");
3667 stat_barp->mPrecision = 0;
3668 stat_barp->mMinBar = 0.f;
3669 stat_barp->mMaxBar = 100000.f;
3670 stat_barp->mTickSpacing = 25000.f;
3671 stat_barp->mLabelSpacing = 50000.f;
3672 stat_barp->mPerSec = FALSE;
3673 stat_barp->mDisplayBar = FALSE;
3674 stat_barp->mDisplayMean = FALSE;
3675
3676 LLStatView *sim_time_viewp;
3677 sim_time_viewp = new LLStatView("sim perf view", "Time (ms)", "", rect);
3678 sim_statviewp->addChildAtEnd(sim_time_viewp);
3679
3680 stat_barp = sim_time_viewp->addStat("Total Frame Time", &(gViewerStats->mSimFrameMsec));
3681 stat_barp->setUnitLabel("ms");
3682 stat_barp->mPrecision = 1;
3683 stat_barp->mMinBar = 0.f;
3684 stat_barp->mMaxBar = 40.f;
3685 stat_barp->mTickSpacing = 10.f;
3686 stat_barp->mLabelSpacing = 20.f;
3687 stat_barp->mPerSec = FALSE;
3688 stat_barp->mDisplayBar = FALSE;
3689 stat_barp->mDisplayMean = FALSE;
3690
3691 stat_barp = sim_time_viewp->addStat("Net Time", &(gViewerStats->mSimNetMsec));
3692 stat_barp->setUnitLabel("ms");
3693 stat_barp->mPrecision = 1;
3694 stat_barp->mMinBar = 0.f;
3695 stat_barp->mMaxBar = 40.f;
3696 stat_barp->mTickSpacing = 10.f;
3697 stat_barp->mLabelSpacing = 20.f;
3698 stat_barp->mPerSec = FALSE;
3699 stat_barp->mDisplayBar = FALSE;
3700 stat_barp->mDisplayMean = FALSE;
3701
3702 stat_barp = sim_time_viewp->addStat("Sim Time (Physics)", &(gViewerStats->mSimSimPhysicsMsec));
3703 stat_barp->setUnitLabel("ms");
3704 stat_barp->mPrecision = 1;
3705 stat_barp->mMinBar = 0.f;
3706 stat_barp->mMaxBar = 40.f;
3707 stat_barp->mTickSpacing = 10.f;
3708 stat_barp->mLabelSpacing = 20.f;
3709 stat_barp->mPerSec = FALSE;
3710 stat_barp->mDisplayBar = FALSE;
3711 stat_barp->mDisplayMean = FALSE;
3712
3713 stat_barp = sim_time_viewp->addStat("Sim Time (Other)", &(gViewerStats->mSimSimOtherMsec));
3714 stat_barp->setUnitLabel("ms");
3715 stat_barp->mPrecision = 1;
3716 stat_barp->mMinBar = 0.f;
3717 stat_barp->mMaxBar = 40.f;
3718 stat_barp->mTickSpacing = 10.f;
3719 stat_barp->mLabelSpacing = 20.f;
3720 stat_barp->mPerSec = FALSE;
3721 stat_barp->mDisplayBar = FALSE;
3722 stat_barp->mDisplayMean = FALSE;
3723
3724 stat_barp = sim_time_viewp->addStat("Agent Time", &(gViewerStats->mSimAgentMsec));
3725 stat_barp->setUnitLabel("ms");
3726 stat_barp->mPrecision = 1;
3727 stat_barp->mMinBar = 0.f;
3728 stat_barp->mMaxBar = 40.f;
3729 stat_barp->mTickSpacing = 10.f;
3730 stat_barp->mLabelSpacing = 20.f;
3731 stat_barp->mPerSec = FALSE;
3732 stat_barp->mDisplayBar = FALSE;
3733 stat_barp->mDisplayMean = FALSE;
3734
3735 stat_barp = sim_time_viewp->addStat("Images Time", &(gViewerStats->mSimImagesMsec));
3736 stat_barp->setUnitLabel("ms");
3737 stat_barp->mPrecision = 1;
3738 stat_barp->mMinBar = 0.f;
3739 stat_barp->mMaxBar = 40.f;
3740 stat_barp->mTickSpacing = 10.f;
3741 stat_barp->mLabelSpacing = 20.f;
3742 stat_barp->mPerSec = FALSE;
3743 stat_barp->mDisplayBar = FALSE;
3744 stat_barp->mDisplayMean = FALSE;
3745
3746 stat_barp = sim_time_viewp->addStat("Script Time", &(gViewerStats->mSimScriptMsec));
3747 stat_barp->setUnitLabel("ms");
3748 stat_barp->mPrecision = 1;
3749 stat_barp->mMinBar = 0.f;
3750 stat_barp->mMaxBar = 40.f;
3751 stat_barp->mTickSpacing = 10.f;
3752 stat_barp->mLabelSpacing = 20.f;
3753 stat_barp->mPerSec = FALSE;
3754 stat_barp->mDisplayBar = FALSE;
3755 stat_barp->mDisplayMean = FALSE;
3756
3757 LLRect r = gDebugView->mStatViewp->getRect();
3758
3759 // Reshape based on the parameters we set.
3760 gDebugView->mStatViewp->reshape(r.getWidth(), r.getHeight());
3761}
3762
3763void asset_callback_nothing(LLVFS*, const LLUUID&, LLAssetType::EType, void*, S32)
3764{
3765 // nothing
3766}
3767
3768// *HACK: Must match name in Library or agent inventory
3769const char* COMMON_GESTURES_FOLDER = "Common Gestures";
3770const char* MALE_GESTURES_FOLDER = "Male Gestures";
3771const char* FEMALE_GESTURES_FOLDER = "Female Gestures";
3772const char* MALE_OUTFIT_FOLDER = "Male Shape & Outfit";
3773const char* FEMALE_OUTFIT_FOLDER = "Female Shape & Outfit";
3774const S32 OPT_USE_INITIAL_OUTFIT = -2;
3775const S32 OPT_CLOSED_WINDOW = -1;
3776const S32 OPT_MALE = 0;
3777const S32 OPT_FEMALE = 1;
3778
3779void callback_choose_gender(S32 option, void* userdata)
3780{
3781 S32 gender = OPT_FEMALE;
3782 const char* outfit = FEMALE_OUTFIT_FOLDER;
3783 const char* gestures = FEMALE_GESTURES_FOLDER;
3784 const char* common_gestures = COMMON_GESTURES_FOLDER;
3785 if (!gInitialOutfit.empty())
3786 {
3787 outfit = gInitialOutfit.c_str();
3788 if (gInitialOutfitGender == "male")
3789 {
3790 gender = OPT_MALE;
3791 gestures = MALE_GESTURES_FOLDER;
3792 }
3793 else
3794 {
3795 gender = OPT_FEMALE;
3796 gestures = FEMALE_GESTURES_FOLDER;
3797 }
3798 }
3799 else
3800 {
3801 switch(option)
3802 {
3803 case OPT_MALE:
3804 gender = OPT_MALE;
3805 outfit = MALE_OUTFIT_FOLDER;
3806 gestures = MALE_GESTURES_FOLDER;
3807 break;
3808
3809 case OPT_FEMALE:
3810 case OPT_CLOSED_WINDOW:
3811 default:
3812 gender = OPT_FEMALE;
3813 outfit = FEMALE_OUTFIT_FOLDER;
3814 gestures = FEMALE_GESTURES_FOLDER;
3815 break;
3816 }
3817 }
3818
3819 // try to find the outfit - if not there, create some default
3820 // wearables.
3821 LLInventoryModel::cat_array_t cat_array;
3822 LLInventoryModel::item_array_t item_array;
3823 LLNameCategoryCollector has_name(outfit);
3824 gInventory.collectDescendentsIf(LLUUID::null,
3825 cat_array,
3826 item_array,
3827 LLInventoryModel::EXCLUDE_TRASH,
3828 has_name);
3829 if (0 == cat_array.count())
3830 {
3831 gAgent.createStandardWearables(gender);
3832 }
3833 else
3834 {
3835 wear_outfit_by_name(outfit);
3836 }
3837 wear_outfit_by_name(gestures);
3838 wear_outfit_by_name(common_gestures);
3839
3840 typedef std::map<LLUUID, LLMultiGesture*> item_map_t;
3841 item_map_t::iterator gestureIterator;
3842
3843 // Must be here so they aren't invisible if they close the window.
3844 gAgent.setGenderChosen(TRUE);
3845}
3846
3847// XUI:translate
3848void dialog_choose_gender_first_start()
3849{
3850 if (!gNoRender
3851 && (!gAgent.isGenderChosen()))
3852 {
3853 if (!gInitialOutfit.empty())
3854 {
3855 gViewerWindow->alertXml("WelcomeNoClothes",
3856 callback_choose_gender, NULL);
3857 }
3858 else
3859 {
3860 gViewerWindow->alertXml("WelcomeChooseSex",
3861 callback_choose_gender, NULL);
3862
3863 }
3864 }
3865}
3866
3867// Loads a bitmap to display during load
3868// location_id = 0 => last position
3869// location_id = 1 => home position
3870void init_start_screen(S32 location_id)
3871{
3872 if (gStartImageGL)
3873 {
3874 gStartImageGL = NULL;
3875 llinfos << "re-initializing start screen" << llendl;
3876 }
3877
3878 llinfos << "Loading startup bitmap..." << llendl;
3879
3880 LLString temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter();
3881
3882 if ((S32)START_LOCATION_ID_LAST == location_id)
3883 {
3884 temp_str += SCREEN_LAST_FILENAME;
3885 }
3886 else
3887 {
3888 temp_str += SCREEN_HOME_FILENAME;
3889 }
3890
3891 LLPointer<LLImageBMP> start_image_bmp = new LLImageBMP;
3892 if( !start_image_bmp->load(temp_str) )
3893 {
3894 llinfos << "Bitmap load failed" << llendl;
3895 return;
3896 }
3897
3898 gStartImageGL = new LLImageGL(FALSE);
3899 gStartImageWidth = start_image_bmp->getWidth();
3900 gStartImageHeight = start_image_bmp->getHeight();
3901 LLPointer<LLImageRaw> raw = new LLImageRaw;
3902 if (!start_image_bmp->decode(raw))
3903 {
3904 llinfos << "Bitmap decode failed" << llendl;
3905 gStartImageGL = NULL;
3906 return;
3907 }
3908
3909 raw->expandToPowerOfTwo();
3910 gStartImageGL->createGLTexture(0, raw);
3911}
3912
3913
3914// frees the bitmap
3915void release_start_screen()
3916{
3917 //llinfos << "Releasing bitmap..." << llendl;
3918 gStartImageGL = NULL;
3919}
3920
3921void process_connect_to_userserver(LLMessageSystem* msg, void**)
3922{
3923 // Sent unreliably since if we've become disconnected, the
3924 // userserver will get back to us eventually. By sending reliable,
3925 // we also may accidently induce two separate validations under
3926 // conditions where the userserver is already lagged.
3927 msg->newMessage("ConnectAgentToUserserver");
3928 msg->nextBlockFast(_PREHASH_AgentData);
3929 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
3930 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
3931 msg->sendMessage(gUserServer);
3932}
3933
3934bool LLStartUp::canGoFullscreen()
3935{
3936 return gStartupState >= STATE_WORLD_INIT;
3937}
3938
3939