aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llfloatermessagelog.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llfloatermessagelog.cpp962
1 files changed, 962 insertions, 0 deletions
diff --git a/linden/indra/newview/llfloatermessagelog.cpp b/linden/indra/newview/llfloatermessagelog.cpp
new file mode 100644
index 0000000..161779b
--- /dev/null
+++ b/linden/indra/newview/llfloatermessagelog.cpp
@@ -0,0 +1,962 @@
1// <edit>
2#include "llviewerprecompiledheaders.h"
3#include "llfloatermessagelog.h"
4#include "lluictrlfactory.h"
5#include "llworld.h"
6#include "llviewerregion.h"
7#include "llscrolllistctrl.h"
8#include "lltexteditor.h"
9#include "llviewerwindow.h" // alertXml
10#include "llmessagetemplate.h"
11#include <boost/tokenizer.hpp>
12#include "llmenugl.h"
13#include "llfloatermessagebuilder.h"
14#include "llagent.h"
15////////////////////////////////
16// LLFloaterMessageLogItem
17////////////////////////////////
18#define MAX_PACKET_LEN (0x2000)
19LLTemplateMessageReader* LLFloaterMessageLogItem::sTemplateMessageReader = NULL;
20LLFloaterMessageLogItem::LLFloaterMessageLogItem(LLMessageLogEntry entry)
21: LLMessageLogEntry(entry.mType, entry.mFromHost, entry.mToHost, entry.mData, entry.mDataSize)
22{
23 if(!sTemplateMessageReader)
24 {
25 sTemplateMessageReader = new LLTemplateMessageReader(gMessageSystem->mMessageNumbers);
26 }
27 mID.generate();
28 mSequenceID = 0;
29 if(mType == TEMPLATE)
30 {
31 BOOL decode_invalid = FALSE;
32 S32 decode_len = mDataSize;
33 std::vector<U8> DecodeBuffer(MAX_PACKET_LEN,0);
34 memcpy(&(DecodeBuffer[0]),&(mData[0]),decode_len);
35 U8* decodep = &(DecodeBuffer[0]);
36 mFlags = DecodeBuffer[0];
37 gMessageSystem->zeroCodeExpand(&decodep, &decode_len);
38 if(decode_len < 7)
39 decode_invalid = TRUE;
40 else
41 {
42 mSequenceID = ntohl(*((U32*)(&decodep[1])));
43 sTemplateMessageReader->clearMessage();
44 if(!sTemplateMessageReader->validateMessage(decodep, decode_len, mFromHost, TRUE))
45 decode_invalid = TRUE;
46 else
47 {
48 if(!sTemplateMessageReader->decodeData(decodep, mFromHost, TRUE))
49 decode_invalid = TRUE;
50 else
51 {
52 LLMessageTemplate* temp = sTemplateMessageReader->getTemplate();
53 mName = temp->mName;
54 mSummary = "";
55
56 if(mFlags)
57 {
58 mSummary.append(" [ ");
59 if(mFlags & LL_ZERO_CODE_FLAG)
60 mSummary.append(" Zer ");
61 if(mFlags & LL_RELIABLE_FLAG)
62 mSummary.append(" Rel ");
63 if(mFlags & LL_RESENT_FLAG)
64 mSummary.append(" Rsd ");
65 if(mFlags & LL_ACK_FLAG)
66 mSummary.append(" Ack ");
67 mSummary.append(" ] ");
68 }
69
70 LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end();
71 for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin();
72 blocks_iter != blocks_end; ++blocks_iter)
73 {
74 LLMessageBlock* block = (*blocks_iter);
75 const char* block_name = block->mName;
76 S32 num_blocks = sTemplateMessageReader->getNumberOfBlocks(block_name);
77 if(!num_blocks)
78 mSummary.append(" { } ");
79 else if(num_blocks > 1)
80 mSummary.append(llformat(" %s [ %d ] { ... } ", block_name, num_blocks));
81 else for(S32 i = 0; i < 1; i++)
82 {
83 mSummary.append(" { ");
84 LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end();
85 for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin();
86 var_iter != var_end; ++var_iter)
87 {
88 LLMessageVariable* variable = (*var_iter);
89 const char* var_name = variable->getName();
90 BOOL returned_hex;
91 std::string value = getString(sTemplateMessageReader, block_name, i, var_name, variable->getType(), returned_hex, TRUE);
92 mSummary.append(llformat(" %s=%s ", var_name, value.c_str()));
93 }
94 mSummary.append(" } ");
95 if(mSummary.length() > 255) break;
96 }
97 if(mSummary.length() > 255)
98 {
99 mSummary.append(" ... ");
100 break;
101 }
102 } // blocks_iter
103 } // decode_valid
104 }
105 }
106 if(decode_invalid)
107 {
108 mName = "Invalid";
109 mSummary = "";
110 for(S32 i = 0; i < mDataSize; i++)
111 mSummary.append(llformat("%02X ", mData[i]));
112 }
113 }
114 else // not template
115 {
116 mName = "SOMETHING ELSE";
117 mSummary = "TODO: SOMETHING ELSE";
118 }
119}
120LLFloaterMessageLogItem::~LLFloaterMessageLogItem()
121{
122}
123BOOL LLFloaterMessageLogItem::isOutgoing()
124{
125 return mFromHost == LLHost(16777343, gMessageSystem->getListenPort());
126}
127std::string LLFloaterMessageLogItem::getFull(BOOL show_header)
128{
129 std::string full("");
130 if(mType == TEMPLATE)
131 {
132 BOOL decode_invalid = FALSE;
133 S32 decode_len = mDataSize;
134 std::vector<U8> DecodeBuffer(MAX_PACKET_LEN,0);
135 memcpy(&(DecodeBuffer[0]),&(mData[0]),decode_len);
136 U8* decodep = &(DecodeBuffer[0]);
137 gMessageSystem->zeroCodeExpand(&decodep, &decode_len);
138 if(decode_len < 7)
139 decode_invalid = TRUE;
140 else
141 {
142 sTemplateMessageReader->clearMessage();
143 if(!sTemplateMessageReader->validateMessage(decodep, decode_len, mFromHost, TRUE))
144 decode_invalid = TRUE;
145 else
146 {
147 if(!sTemplateMessageReader->decodeData(decodep, mFromHost, TRUE))
148 decode_invalid = TRUE;
149 else
150 {
151 LLMessageTemplate* temp = sTemplateMessageReader->getTemplate();
152 full.append(isOutgoing() ? "out " : "in ");
153 full.append(llformat("%s\n", temp->mName));
154 if(show_header)
155 {
156 full.append("[Header]\n");
157 full.append(llformat("SequenceID = %u\n", mSequenceID));
158 full.append(llformat("LL_ZERO_CODE_FLAG = %s\n", (mFlags & LL_ZERO_CODE_FLAG) ? "True" : "False"));
159 full.append(llformat("LL_RELIABLE_FLAG = %s\n", (mFlags & LL_RELIABLE_FLAG) ? "True" : "False"));
160 full.append(llformat("LL_RESENT_FLAG = %s\n", (mFlags & LL_RESENT_FLAG) ? "True" : "False"));
161 full.append(llformat("LL_ACK_FLAG = %s\n", (mFlags & LL_ACK_FLAG) ? "True" : "False"));
162 }
163 LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end();
164 for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin();
165 blocks_iter != blocks_end; ++blocks_iter)
166 {
167 LLMessageBlock* block = (*blocks_iter);
168 const char* block_name = block->mName;
169 S32 num_blocks = sTemplateMessageReader->getNumberOfBlocks(block_name);
170 for(S32 i = 0; i < num_blocks; i++)
171 {
172 full.append(llformat("[%s]\n", block->mName));
173 LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end();
174 for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin();
175 var_iter != var_end; ++var_iter)
176 {
177 LLMessageVariable* variable = (*var_iter);
178 const char* var_name = variable->getName();
179 BOOL returned_hex;
180 std::string value = getString(sTemplateMessageReader, block_name, i, var_name, variable->getType(), returned_hex);
181 if(returned_hex)
182 full.append(llformat("%s =| ", var_name));
183 else
184 full.append(llformat("%s = ", var_name));
185 // llformat has a 1024 char limit!?
186 full.append(value);
187 full.append("\n");
188 }
189 }
190 } // blocks_iter
191 } // decode_valid
192 }
193 }
194 if(decode_invalid)
195 {
196 full = isOutgoing() ? "out" : "in";
197 full.append("\n");
198 for(S32 i = 0; i < mDataSize; i++)
199 full.append(llformat("%02X ", mData[i]));
200 }
201 }
202 else // not template
203 {
204 full = "FIXME";
205 }
206 return full;
207}
208// static
209std::string LLFloaterMessageLogItem::getString(LLTemplateMessageReader* readerp, const char* block_name, S32 block_num, const char* var_name, e_message_variable_type var_type, BOOL &returned_hex, BOOL summary_mode)
210{
211 returned_hex = FALSE;
212 std::stringstream stream;
213 char* value;
214 U32 valueU32;
215 U16 valueU16;
216 LLVector3 valueVector3;
217 LLVector3d valueVector3d;
218 LLVector4 valueVector4;
219 LLQuaternion valueQuaternion;
220 LLUUID valueLLUUID;
221 switch(var_type)
222 {
223 case MVT_U8:
224 U8 valueU8;
225 readerp->getU8(block_name, var_name, valueU8, block_num);
226 stream << U32(valueU8);
227 break;
228 case MVT_U16:
229 readerp->getU16(block_name, var_name, valueU16, block_num);
230 stream << valueU16;
231 break;
232 case MVT_U32:
233 readerp->getU32(block_name, var_name, valueU32, block_num);
234 stream << valueU32;
235 break;
236 case MVT_U64:
237 U64 valueU64;
238 readerp->getU64(block_name, var_name, valueU64, block_num);
239 stream << valueU64;
240 break;
241 case MVT_S8:
242 S8 valueS8;
243 readerp->getS8(block_name, var_name, valueS8, block_num);
244 stream << S32(valueS8);
245 break;
246 case MVT_S16:
247 S16 valueS16;
248 readerp->getS16(block_name, var_name, valueS16, block_num);
249 stream << valueS16;
250 break;
251 case MVT_S32:
252 S32 valueS32;
253 readerp->getS32(block_name, var_name, valueS32, block_num);
254 stream << valueS32;
255 break;
256 /*case MVT_S64:
257 S64 valueS64;
258 readerp->getS64(block_name, var_name, valueS64, block_num);
259 stream << valueS64;
260 break;*/
261 case MVT_F32:
262 F32 valueF32;
263 readerp->getF32(block_name, var_name, valueF32, block_num);
264 stream << valueF32;
265 break;
266 case MVT_F64:
267 F64 valueF64;
268 readerp->getF64(block_name, var_name, valueF64, block_num);
269 stream << valueF64;
270 break;
271 case MVT_LLVector3:
272 readerp->getVector3(block_name, var_name, valueVector3, block_num);
273 //stream << valueVector3;
274 stream << "<" << valueVector3.mV[0] << ", " << valueVector3.mV[1] << ", " << valueVector3.mV[2] << ">";
275 break;
276 case MVT_LLVector3d:
277 readerp->getVector3d(block_name, var_name, valueVector3d, block_num);
278 //stream << valueVector3d;
279 stream << "<" << valueVector3d.mdV[0] << ", " << valueVector3d.mdV[1] << ", " << valueVector3d.mdV[2] << ">";
280 break;
281 case MVT_LLVector4:
282 readerp->getVector4(block_name, var_name, valueVector4, block_num);
283 //stream << valueVector4;
284 stream << "<" << valueVector4.mV[0] << ", " << valueVector4.mV[1] << ", " << valueVector4.mV[2] << ", " << valueVector4.mV[3] << ">";
285 break;
286 case MVT_LLQuaternion:
287 readerp->getQuat(block_name, var_name, valueQuaternion, block_num);
288 //stream << valueQuaternion;
289 stream << "<" << valueQuaternion.mQ[0] << ", " << valueQuaternion.mQ[1] << ", " << valueQuaternion.mQ[2] << ", " << valueQuaternion.mQ[3] << ">";
290 break;
291 case MVT_LLUUID:
292 readerp->getUUID(block_name, var_name, valueLLUUID, block_num);
293 stream << valueLLUUID;
294 break;
295 case MVT_BOOL:
296 BOOL valueBOOL;
297 readerp->getBOOL(block_name, var_name, valueBOOL, block_num);
298 stream << valueBOOL;
299 break;
300 case MVT_IP_ADDR:
301 readerp->getIPAddr(block_name, var_name, valueU32, block_num);
302 stream << LLHost(valueU32, 0).getIPString();
303 break;
304 case MVT_IP_PORT:
305 readerp->getIPPort(block_name, var_name, valueU16, block_num);
306 stream << valueU16;
307 case MVT_VARIABLE:
308 case MVT_FIXED:
309 default:
310 S32 size = readerp->getSize(block_name, block_num, var_name);
311 if(size)
312 {
313 value = new char[size + 1];
314 readerp->getBinaryData(block_name, var_name, value, size, block_num);
315 value[size] = '\0';
316 S32 readable = 0;
317 S32 unreadable = 0;
318 S32 end = (summary_mode && (size > 64)) ? 64 : size;
319 for(S32 i = 0; i < end; i++)
320 {
321 if(!value[i])
322 {
323 if(i != (end - 1))
324 { // don't want null terminator hiding data
325 unreadable = S32_MAX;
326 break;
327 }
328 }
329 else if(value[i] < 0x20 || value[i] >= 0x7F)
330 {
331 if(summary_mode)
332 unreadable++;
333 else
334 { // never want any wrong characters outside of summary mode
335 unreadable = S32_MAX;
336 break;
337 }
338 }
339 else readable++;
340 }
341 if(readable >= unreadable)
342 {
343 if(summary_mode && (size > 64))
344 {
345 for(S32 i = 60; i < 63; i++)
346 value[i] = '.';
347 value[63] = '\0';
348 }
349 stream << value;
350
351 delete[] value;
352 }
353 else
354 {
355 returned_hex = TRUE;
356 S32 end = (summary_mode && (size > 8)) ? 8 : size;
357 for(S32 i = 0; i < end; i++)
358 //stream << std::uppercase << std::hex << U32(value[i]) << " ";
359 stream << llformat("%02X ", (U8)value[i]);
360 if(summary_mode && (size > 8))
361 stream << " ... ";
362 }
363 }
364 break;
365 }
366
367 return stream.str();
368}
369LLMessageLogFilter::LLMessageLogFilter()
370{
371}
372LLMessageLogFilter::~LLMessageLogFilter()
373{
374}
375BOOL LLMessageLogFilter::set(std::string filter)
376{
377 mPositiveNames.clear();
378 mNegativeNames.clear();
379 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
380 boost::char_separator<char> sep(" ","",boost::keep_empty_tokens);
381 boost::tokenizer<boost::char_separator<char> > tokens(filter, sep);
382 boost::tokenizer<boost::char_separator<char> >::iterator end = tokens.end();
383 for(boost::tokenizer<boost::char_separator<char> >::iterator iter = tokens.begin(); iter != end; ++iter)
384 {
385 std::string token = (*iter);
386 LLStringUtil::trim(token);
387 LLStringUtil::toLower(token);
388 BOOL negative = token.find("!") == 0;
389 if(negative)
390 {
391 token = token.substr(1);
392 mNegativeNames.push_back(token);
393 }
394 else
395 mPositiveNames.push_back(token);
396 }
397 return TRUE;
398}
399////////////////////////////////
400// LLMessageLogFilterApply
401////////////////////////////////
402LLMessageLogFilterApply::LLMessageLogFilterApply()
403: LLEventTimer(0.1f),
404 mFinished(FALSE),
405 mProgress(0)
406{
407 mIter = LLFloaterMessageLog::sMessageLogEntries.begin();
408}
409void LLMessageLogFilterApply::cancel()
410{
411 mFinished = TRUE;
412}
413BOOL LLMessageLogFilterApply::tick()
414{
415 std::deque<LLMessageLogEntry>::iterator end = LLFloaterMessageLog::sMessageLogEntries.end();
416 if(mIter == end || !LLFloaterMessageLog::sInstance)
417 {
418 mFinished = TRUE;
419 if(LLFloaterMessageLog::sInstance)
420 {
421 if(LLFloaterMessageLog::sInstance->mMessageLogFilterApply == this)
422 {
423 LLFloaterMessageLog::sInstance->stopApplyingFilter();
424 }
425 }
426 return TRUE;
427 }
428 for(S32 i = 0; i < 256; i++)
429 {
430 if(mIter == end)
431 {
432 mFinished = TRUE;
433 if(LLFloaterMessageLog::sInstance)
434 {
435 if(LLFloaterMessageLog::sInstance->mMessageLogFilterApply == this)
436 {
437 LLFloaterMessageLog::sInstance->stopApplyingFilter();
438
439 //we're done messing with the deque, push all queued items to the main deque
440 std::deque<LLMessageLogEntry>::iterator queueIter = mQueuedMessages.begin();
441 std::deque<LLMessageLogEntry>::iterator queueEnd = mQueuedMessages.end();
442
443 while(queueIter != queueEnd)
444 {
445 LLFloaterMessageLog::sInstance->conditionalLog(LLFloaterMessageLogItem((*queueIter)));
446 ++queueIter;
447 }
448
449 mQueuedMessages.clear();
450 }
451 }
452
453 return TRUE;
454 }
455
456 LLFloaterMessageLog::sInstance->conditionalLog(LLFloaterMessageLogItem((*mIter)));
457
458 mIter++;
459 mProgress++;
460 }
461 LLFloaterMessageLog::sInstance->updateFilterStatus();
462 return FALSE;
463}
464////////////////////////////////
465// LLFloaterMessageLog
466////////////////////////////////
467LLFloaterMessageLog* LLFloaterMessageLog::sInstance;
468std::list<LLNetListItem*> LLFloaterMessageLog::sNetListItems;
469std::deque<LLMessageLogEntry> LLFloaterMessageLog::sMessageLogEntries;
470std::vector<LLFloaterMessageLogItem> LLFloaterMessageLog::sFloaterMessageLogItems;
471LLMessageLogFilter LLFloaterMessageLog::sMessageLogFilter = LLMessageLogFilter();
472std::string LLFloaterMessageLog::sMessageLogFilterString("!StartPingCheck !CompletePingCheck !PacketAck !SimulatorViewerTimeMessage !SimStats !AgentUpdate !AgentAnimation !AvatarAnimation !ViewerEffect !CoarseLocationUpdate !LayerData !CameraConstraint !ObjectUpdateCached !RequestMultipleObjects !ObjectUpdate !ObjectUpdateCompressed !ImprovedTerseObjectUpdate !KillObject !ImagePacket !SendXferPacket !ConfirmXferPacket !TransferPacket !SoundTrigger !AttachedSound !PreloadSound");
473BOOL LLFloaterMessageLog::sBusyApplyingFilter = FALSE;
474LLFloaterMessageLog::LLFloaterMessageLog()
475: LLFloater(),
476 LLEventTimer(1.0f),
477 mNetInfoMode(NI_NET),
478 mMessageLogFilterApply(NULL)
479{
480 sInstance = this;
481 LLMessageLog::setCallback(onLog);
482 sMessageLogEntries = LLMessageLog::getDeque();
483 LLUICtrlFactory::getInstance()->buildFloater(this, "floater_message_log.xml");
484}
485LLFloaterMessageLog::~LLFloaterMessageLog()
486{
487 LLMessageLog::setCallback(NULL);
488 stopApplyingFilter();
489 sInstance = NULL;
490 sNetListItems.clear();
491 sMessageLogEntries.clear();
492 sFloaterMessageLogItems.clear();
493}
494// static
495void LLFloaterMessageLog::show()
496{
497 if(!sInstance) sInstance = new LLFloaterMessageLog();
498 sInstance->open();
499}
500BOOL LLFloaterMessageLog::postBuild()
501{
502 childSetCommitCallback("net_list", onCommitNetList, this);
503 childSetCommitCallback("message_log", onCommitMessageLog, this);
504 childSetAction("filter_choice_btn", onClickFilterChoice, this);
505 childSetAction("filter_apply_btn", onClickFilterApply, this);
506 childSetCommitCallback("filter_edit", onCommitFilter, this);
507 childSetAction("clear_log_btn", onClickClearLog, this);
508 childSetAction("send_to_message_builder_btn", onClickSendToMessageBuilder, this);
509 childSetText("filter_edit", sMessageLogFilterString);
510 refreshNetList();
511 refreshNetInfo(TRUE);
512 startApplyingFilter(sMessageLogFilterString, TRUE);
513 return TRUE;
514}
515BOOL LLFloaterMessageLog::tick()
516{
517 refreshNetList();
518 refreshNetInfo(FALSE);
519 return FALSE;
520}
521LLNetListItem* LLFloaterMessageLog::findNetListItem(LLHost host)
522{
523 std::list<LLNetListItem*>::iterator end = sNetListItems.end();
524 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter)
525 if((*iter)->mCircuitData && (*iter)->mCircuitData->getHost() == host)
526 return (*iter);
527 return NULL;
528}
529LLNetListItem* LLFloaterMessageLog::findNetListItem(LLUUID id)
530{
531 std::list<LLNetListItem*>::iterator end = sNetListItems.end();
532 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter)
533 if((*iter)->mID == id)
534 return (*iter);
535 return NULL;
536}
537void LLFloaterMessageLog::refreshNetList()
538{
539 LLScrollListCtrl* scrollp = getChild<LLScrollListCtrl>("net_list");
540 // Update circuit data of net list items
541 std::vector<LLCircuitData*> circuits = gMessageSystem->getCircuit()->getCircuitDataList();
542 std::vector<LLCircuitData*>::iterator circuits_end = circuits.end();
543 for(std::vector<LLCircuitData*>::iterator iter = circuits.begin(); iter != circuits_end; ++iter)
544 {
545 LLNetListItem* itemp = findNetListItem((*iter)->getHost());
546 if(!itemp)
547 {
548 LLUUID id; id.generate();
549 itemp = new LLNetListItem(id);
550 sNetListItems.push_back(itemp);
551 }
552 itemp->mCircuitData = (*iter);
553 }
554 // Clear circuit data of items whose circuits are gone
555 std::list<LLNetListItem*>::iterator items_end = sNetListItems.end();
556 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter)
557 {
558 if(std::find(circuits.begin(), circuits.end(), (*iter)->mCircuitData) == circuits.end())
559 (*iter)->mCircuitData = NULL;
560 }
561 // Remove net list items that are totally useless now
562 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != sNetListItems.end();)
563 {
564 if((*iter)->mCircuitData == NULL)
565 iter = sNetListItems.erase(iter);
566 else ++iter;
567 }
568 // Update names of net list items
569 items_end = sNetListItems.end();
570 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter)
571 {
572 LLNetListItem* itemp = (*iter);
573 if(itemp->mAutoName)
574 {
575 if(itemp->mCircuitData)
576 {
577 LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(itemp->mCircuitData->getHost());
578 if(regionp)
579 {
580 std::string name = regionp->getName();
581 if(name == "") name = llformat("%s (awaiting region name)", itemp->mCircuitData->getHost().getString().c_str());
582 itemp->mName = name;
583 itemp->mPreviousRegionName = name;
584 }
585 else
586 {
587 itemp->mName = itemp->mCircuitData->getHost().getString();
588 if(itemp->mPreviousRegionName != "")
589 itemp->mName.append(llformat(" (was %s)", itemp->mPreviousRegionName.c_str()));
590 }
591 }
592 else
593 {
594 // an item just for an event queue, not handled yet
595 itemp->mName = "Something else";
596 }
597 }
598 }
599 // Rebuild scroll list from scratch
600 LLUUID selected_id = scrollp->getFirstSelected() ? scrollp->getFirstSelected()->getUUID() : LLUUID::null;
601 S32 scroll_pos = scrollp->getScrollPos();
602 scrollp->clearRows();
603 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter)
604 {
605 LLNetListItem* itemp = (*iter);
606 LLSD element;
607 element["id"] = itemp->mID;
608 LLSD& text_column = element["columns"][0];
609 text_column["column"] = "text";
610 text_column["value"] = itemp->mName + (itemp->mCircuitData->getHost() == gAgent.getRegionHost() ? " (main)" : "");
611 for(int i = 0; i < 2; i++)
612 {
613 LLSD& icon_column = element["columns"][i + 1];
614 icon_column["column"] = llformat("icon%d", i);
615 icon_column["type"] = "icon";
616 icon_column["value"] = "";
617 }
618 LLScrollListItem* scroll_itemp = scrollp->addElement(element);
619 BOOL has_live_circuit = itemp->mCircuitData && itemp->mCircuitData->isAlive();
620 if(has_live_circuit)
621 {
622 LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(1);
623 icon->setValue("icon_net_close_circuit.tga");
624 icon->setClickCallback(onClickCloseCircuit, itemp);
625 }
626 else
627 {
628 LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(1);
629 icon->setValue("icon_net_close_circuit_gray.tga");
630 icon->setClickCallback(NULL, NULL);
631 }
632 // Event queue isn't even supported yet... FIXME
633 LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(2);
634 icon->setValue("icon_net_close_eventpoll_gray.tga");
635 icon->setClickCallback(NULL, NULL);
636 }
637 if(selected_id.notNull()) scrollp->selectByID(selected_id);
638 if(scroll_pos < scrollp->getItemCount()) scrollp->setScrollPos(scroll_pos);
639}
640void LLFloaterMessageLog::refreshNetInfo(BOOL force)
641{
642 if(mNetInfoMode != NI_NET) return;
643 LLScrollListCtrl* scrollp = getChild<LLScrollListCtrl>("net_list");
644 LLScrollListItem* selected_itemp = scrollp->getFirstSelected();
645 if(selected_itemp)
646 {
647 if(!force) if(getChild<LLTextEditor>("net_info")->hasSelection()) return;
648 LLNetListItem* itemp = findNetListItem(selected_itemp->getUUID());
649 if(itemp)
650 {
651 std::string info(llformat("%s\n--------------------------------\n\n", itemp->mName.c_str()));
652 if(itemp->mCircuitData)
653 {
654 LLCircuitData* cdp = itemp->mCircuitData;
655 info.append("Circuit\n--------------------------------\n");
656 info.append(llformat(" * Host: %s\n", cdp->getHost().getString().c_str()));
657 S32 seconds = (S32)cdp->getAgeInSeconds();
658 S32 minutes = seconds / 60;
659 seconds = seconds % 60;
660 S32 hours = minutes / 60;
661 minutes = minutes % 60;
662 info.append(llformat(" * Age: %dh %dm %ds\n", hours, minutes, seconds));
663 info.append(llformat(" * Alive: %s\n", cdp->isAlive() ? "yes" : "no"));
664 info.append(llformat(" * Blocked: %s\n", cdp->isBlocked() ? "yes" : "no"));
665 info.append(llformat(" * Allow timeout: %s\n", cdp->getAllowTimeout() ? "yes" : "no"));
666 info.append(llformat(" * Trusted: %s\n", cdp->getTrusted() ? "yes" : "no"));
667 info.append(llformat(" * Ping delay: %d\n", cdp->getPingDelay()));
668 info.append(llformat(" * Packets out: %d\n", cdp->getPacketsOut()));
669 info.append(llformat(" * Bytes out: %d\n", cdp->getBytesOut()));
670 info.append(llformat(" * Packets in: %d\n", cdp->getPacketsIn()));
671 info.append(llformat(" * Bytes in: %d\n", cdp->getBytesIn()));
672 info.append(llformat(" * Endpoint ID: %s\n", cdp->getLocalEndPointID().asString().c_str()));
673 info.append(llformat(" * Remote ID: %s\n", cdp->getRemoteID().asString().c_str()));
674 info.append(llformat(" * Remote session ID: %s\n", cdp->getRemoteSessionID().asString().c_str()));
675 }
676 childSetText("net_info", info);
677 }
678 else childSetText("net_info", std::string(""));
679 }
680 else childSetText("net_info", std::string(""));
681}
682void LLFloaterMessageLog::setNetInfoMode(ENetInfoMode mode)
683{
684 mNetInfoMode = mode;
685 if(mNetInfoMode == NI_NET)
686 refreshNetInfo(TRUE);
687 childSetEnabled("send_to_message_builder_btn", mNetInfoMode == NI_LOG);
688}
689// static
690void LLFloaterMessageLog::onLog(LLMessageLogEntry entry)
691{
692 //don't mess with the queue while a filter's being applied, or face invalid iterators
693 if(!sBusyApplyingFilter)
694 {
695 sMessageLogEntries.push_back(entry);
696 conditionalLog(LLFloaterMessageLogItem(entry));
697 }
698}
699// static
700void LLFloaterMessageLog::conditionalLog(LLFloaterMessageLogItem item)
701{
702 if(!sBusyApplyingFilter)
703 sInstance->childSetText("log_status_text", llformat("Showing %d messages from %d", sFloaterMessageLogItems.size(), sMessageLogEntries.size()));
704 std::string find_name = item.mName;
705 LLStringUtil::toLower(find_name);
706 if(sMessageLogFilter.mPositiveNames.size())
707 if(std::find(sMessageLogFilter.mPositiveNames.begin(), sMessageLogFilter.mPositiveNames.end(), find_name) == sMessageLogFilter.mPositiveNames.end())
708 return;
709 if(std::find(sMessageLogFilter.mNegativeNames.begin(), sMessageLogFilter.mNegativeNames.end(), find_name) != sMessageLogFilter.mNegativeNames.end())
710 return;
711 sFloaterMessageLogItems.push_back(item); // moved from beginning...
712 BOOL outgoing = item.isOutgoing();
713 std::string net_name("\?\?\?");
714 if(item.mType == LLFloaterMessageLogItem::TEMPLATE)
715 {
716 LLHost find_host = outgoing ? item.mToHost : item.mFromHost;
717 net_name = find_host.getIPandPort();
718 std::list<LLNetListItem*>::iterator end = sNetListItems.end();
719 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter)
720 {
721 if((*iter)->mCircuitData->getHost() == find_host)
722 {
723 net_name = (*iter)->mName;
724 break;
725 }
726 }
727 }
728 LLSD element;
729 element["id"] = item.mID;
730 LLSD& sequence_column = element["columns"][0];
731 sequence_column["column"] = "sequence";
732 sequence_column["value"] = llformat("%u", item.mSequenceID);
733 LLSD& type_column = element["columns"][1];
734 type_column["column"] = "type";
735 type_column["value"] = item.mType == LLFloaterMessageLogItem::TEMPLATE ? "UDP" : "\?\?\?";
736 LLSD& direction_column = element["columns"][2];
737 direction_column["column"] = "direction";
738 direction_column["value"] = outgoing ? "to" : "from";
739 LLSD& net_column = element["columns"][3];
740 net_column["column"] = "net";
741 net_column["value"] = net_name;
742 LLSD& name_column = element["columns"][4];
743 name_column["column"] = "name";
744 name_column["value"] = item.mName;
745 /*
746 LLSD& zer_column = element["columns"][5];
747 zer_column["column"] = "flag_zer";
748 zer_column["type"] = "icon";
749 zer_column["value"] = (item.mFlags & LL_ZERO_CODE_FLAG) ? "flag_zer.tga" : "";
750 LLSD& rel_column = element["columns"][6];
751 rel_column["column"] = "flag_rel";
752 rel_column["type"] = "icon";
753 rel_column["value"] = (item.mFlags & LL_RELIABLE_FLAG) ? "flag_rel.tga" : "";
754 LLSD& rsd_column = element["columns"][7];
755 rsd_column["column"] = "flag_rsd";
756 rsd_column["type"] = "icon";
757 rsd_column["value"] = (item.mFlags & LL_RESENT_FLAG) ? "flag_rsd.tga" : "";
758 LLSD& ack_column = element["columns"][8];
759 ack_column["column"] = "flag_ack";
760 ack_column["type"] = "icon";
761 ack_column["value"] = (item.mFlags & LL_ACK_FLAG) ? "flag_ack.tga" : "";
762 */
763 LLSD& summary_column = element["columns"][5];
764 summary_column["column"] = "summary";
765 summary_column["value"] = item.mSummary;
766 LLScrollListCtrl* scrollp = sInstance->getChild<LLScrollListCtrl>("message_log");
767 S32 scroll_pos = scrollp->getScrollPos();
768 scrollp->addElement(element);
769 if(scroll_pos > scrollp->getItemCount() - scrollp->getPageLines() - 4)
770 scrollp->setScrollPos(scrollp->getItemCount());
771}
772// static
773void LLFloaterMessageLog::onCommitNetList(LLUICtrl* ctrl, void* user_data)
774{
775 LLFloaterMessageLog* floaterp = (LLFloaterMessageLog*)user_data;
776 floaterp->setNetInfoMode(NI_NET);
777 floaterp->refreshNetInfo(TRUE);
778}
779// static
780void LLFloaterMessageLog::onCommitMessageLog(LLUICtrl* ctrl, void* user_data)
781{
782 LLFloaterMessageLog* floaterp = (LLFloaterMessageLog*)user_data;
783 LLScrollListCtrl* scrollp = floaterp->getChild<LLScrollListCtrl>("message_log");
784 LLScrollListItem* selected_itemp = scrollp->getFirstSelected();
785 if(!selected_itemp) return;
786 LLUUID id = selected_itemp->getUUID();
787 std::vector<LLFloaterMessageLogItem>::iterator end = sFloaterMessageLogItems.end();
788 for(std::vector<LLFloaterMessageLogItem>::iterator iter = sFloaterMessageLogItems.begin(); iter != end; ++iter)
789 {
790 if(iter->mID == id)
791 {
792 floaterp->setNetInfoMode(NI_LOG);
793 floaterp->childSetText("net_info", iter->getFull(FALSE));
794 break;
795 }
796 }
797}
798// static
799BOOL LLFloaterMessageLog::onClickCloseCircuit(void* user_data)
800{
801 LLNetListItem* itemp = (LLNetListItem*)user_data;
802 LLCircuitData* cdp = (LLCircuitData*)itemp->mCircuitData;
803 if(!cdp) return FALSE;
804 LLHost myhost = cdp->getHost();
805 LLSD args;
806 args["MESSAGE"] = "This will delete local circuit data.\nDo you want to tell the remote host to close the circuit too?";
807 LLSD payload;
808 payload["circuittoclose"] = myhost.getString();
809 LLNotifications::instance().add("GenericAlertYesCancel", args, payload, onConfirmCloseCircuit);
810 return TRUE;
811}
812// static
813bool LLFloaterMessageLog::onConfirmCloseCircuit(const LLSD& notification, const LLSD& response )
814{
815 S32 option = LLNotification::getSelectedOption(notification, response);
816 LLCircuitData* cdp = gMessageSystem->mCircuitInfo.findCircuit(LLHost(notification["payload"]["circuittoclose"].asString()));
817 if(!cdp) return false;
818 LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(cdp->getHost());
819 switch(option)
820 {
821 case 0: // yes
822 gMessageSystem->newMessageFast(_PREHASH_CloseCircuit);
823 gMessageSystem->sendReliable(cdp->getHost());
824 break;
825 case 2: // cancel
826 return false;
827 break;
828 case 1: // no
829 default:
830 break;
831 }
832 if(gMessageSystem->findCircuitCode(cdp->getHost()))
833 gMessageSystem->disableCircuit(cdp->getHost());
834 else
835 gMessageSystem->getCircuit()->removeCircuitData(cdp->getHost());
836 if(regionp)
837 {
838 LLHost myhost = regionp->getHost();
839 LLSD args;
840 args["MESSAGE"] = "That host had a region associated with it.\nDo you want to clean that up?";
841 LLSD payload;
842 payload["regionhost"] = myhost.getString();
843 LLNotifications::instance().add("GenericAlertYesCancel", args, payload, onConfirmRemoveRegion);
844 }
845 return false;
846}
847// static
848bool LLFloaterMessageLog::onConfirmRemoveRegion(const LLSD& notification, const LLSD& response )
849{
850 S32 option = LLNotification::getSelectedOption(notification, response);
851 if(option == 0) // yes
852 LLWorld::getInstance()->removeRegion(LLHost(notification["payload"]["regionhost"].asString()));
853 return false;
854}
855// static
856void LLFloaterMessageLog::onClickFilterApply(void* user_data)
857{
858 LLFloaterMessageLog* floaterp = (LLFloaterMessageLog*)user_data;
859 floaterp->startApplyingFilter(floaterp->childGetValue("filter_edit"), FALSE);
860}
861void LLFloaterMessageLog::startApplyingFilter(std::string filter, BOOL force)
862{
863 LLMessageLogFilter new_filter = LLMessageLogFilter();
864 sMessageLogFilterString = filter;
865 new_filter.set(sMessageLogFilterString);
866 if(!filter.length() || filter.at(filter.length()-1) != ' ')
867 childSetText("filter_edit", filter + " ");
868 if(force
869 || (new_filter.mNegativeNames != sMessageLogFilter.mNegativeNames)
870 || (new_filter.mPositiveNames != sMessageLogFilter.mPositiveNames))
871 {
872 stopApplyingFilter();
873 sMessageLogFilter = new_filter;
874 sFloaterMessageLogItems.clear();
875 getChild<LLScrollListCtrl>("message_log")->clearRows();
876 sBusyApplyingFilter = TRUE;
877 childSetVisible("message_log", false);
878 //childSetVisible("log_status_text", true);
879 mMessageLogFilterApply = new LLMessageLogFilterApply();
880 }
881}
882void LLFloaterMessageLog::stopApplyingFilter()
883{
884 if(mMessageLogFilterApply)
885 {
886 if(!(mMessageLogFilterApply->mFinished))
887 mMessageLogFilterApply->cancel();
888 //delete mMessageLogFilterApply;
889 sBusyApplyingFilter = FALSE;
890 //childSetVisible("log_status_text", false);
891 childSetVisible("message_log", true);
892 childSetText("log_status_text", llformat("Showing %d messages from %d", sFloaterMessageLogItems.size(), sMessageLogEntries.size()));
893 }
894}
895void LLFloaterMessageLog::updateFilterStatus()
896{
897 if(!mMessageLogFilterApply || !sBusyApplyingFilter) return;
898 S32 progress = mMessageLogFilterApply->mProgress;
899 S32 packets = sMessageLogEntries.size();
900 S32 matches = sFloaterMessageLogItems.size();
901 std::string text = llformat("Applying filter ( %d / %d ), %d matches ...", progress, packets, matches);
902 childSetText("log_status_text", text);
903}
904// static
905void LLFloaterMessageLog::onCommitFilter(LLUICtrl* ctrl, void* user_data)
906{
907 LLFloaterMessageLog* floaterp = (LLFloaterMessageLog*)user_data;
908 floaterp->startApplyingFilter(floaterp->childGetValue("filter_edit"), FALSE);
909}
910// static
911void LLFloaterMessageLog::onClickClearLog(void* user_data)
912{
913 LLFloaterMessageLog* floaterp = (LLFloaterMessageLog*)user_data;
914 floaterp->stopApplyingFilter();
915 floaterp->getChild<LLScrollListCtrl>("message_log")->clearRows();
916 floaterp->setNetInfoMode(NI_NET);
917 sMessageLogEntries.clear();
918 sFloaterMessageLogItems.clear();
919}
920// static
921void LLFloaterMessageLog::onClickFilterChoice(void* user_data)
922{
923 LLMenuGL* menu = new LLMenuGL(LLStringUtil::null);
924 menu->append(new LLMenuItemCallGL("No filter", onClickFilterMenu, NULL, (void*)""));
925 menu->append(new LLMenuItemCallGL("Fewer spammy messages", onClickFilterMenu, NULL, (void*)"!StartPingCheck !CompletePingCheck !PacketAck !SimulatorViewerTimeMessage !SimStats !AgentUpdate !AgentAnimation !AvatarAnimation !ViewerEffect !CoarseLocationUpdate !LayerData !CameraConstraint !ObjectUpdateCached !RequestMultipleObjects !ObjectUpdate !ObjectUpdateCompressed !ImprovedTerseObjectUpdate !KillObject !ImagePacket !SendXferPacket !ConfirmXferPacket !TransferPacket"));
926 menu->append(new LLMenuItemCallGL("Fewer spammy messages (minus sound crap)", onClickFilterMenu, NULL, (void*)"!StartPingCheck !CompletePingCheck !PacketAck !SimulatorViewerTimeMessage !SimStats !AgentUpdate !AgentAnimation !AvatarAnimation !ViewerEffect !CoarseLocationUpdate !LayerData !CameraConstraint !ObjectUpdateCached !RequestMultipleObjects !ObjectUpdate !ObjectUpdateCompressed !ImprovedTerseObjectUpdate !KillObject !ImagePacket !SendXferPacket !ConfirmXferPacket !TransferPacket !SoundTrigger !AttachedSound !PreloadSound"));
927 menu->append(new LLMenuItemCallGL("Object updates", onClickFilterMenu, NULL, (void*)"ObjectUpdateCached ObjectUpdate ObjectUpdateCompressed ImprovedTerseObjectUpdate KillObject RequestMultipleObjects"));
928 menu->append(new LLMenuItemCallGL("Abnormal", onClickFilterMenu, NULL, (void*)"Invalid TestMessage AddCircuitCode NeighborList AvatarTextureUpdate SimulatorMapUpdate SimulatorSetMap SubscribeLoad UnsubscribeLoad SimulatorReady SimulatorPresentAtLocation SimulatorLoad SimulatorShutdownRequest RegionPresenceRequestByRegionID RegionPresenceRequestByHandle RegionPresenceResponse UpdateSimulator LogDwellTime FeatureDisabled LogFailedMoneyTransaction UserReportInternal SetSimStatusInDatabase SetSimPresenceInDatabase OpenCircuit CloseCircuit DirFindQueryBackend DirPlacesQueryBackend DirClassifiedQueryBackend DirLandQueryBackend DirPopularQueryBackend GroupNoticeAdd DataHomeLocationRequest DataHomeLocationReply DerezContainer ObjectCategory ObjectExportSelected StateSave ReportAutosaveCrash AgentAlertMessage NearestLandingRegionRequest NearestLandingRegionReply NearestLandingRegionUpdated TeleportLandingStatusChanged ConfirmEnableSimulator KickUserAck SystemKickUser AvatarPropertiesRequestBackend UpdateParcel RemoveParcel MergeParcel LogParcelChanges CheckParcelSales ParcelSales StartAuction ConfirmAuctionStart CompleteAuction CancelAuction CheckParcelAuctions ParcelAuctions ChatPass EdgeDataPacket SimStatus ChildAgentUpdate ChildAgentAlive ChildAgentPositionUpdate ChildAgentDying ChildAgentUnknown AtomicPassObject KillChildAgents ScriptSensorRequest ScriptSensorReply DataServerLogout RequestInventoryAsset InventoryAssetResponse TransferInventory TransferInventoryAck EventLocationRequest EventLocationReply MoneyTransferBackend RoutedMoneyBalanceReply SetStartLocation NetTest SetCPURatio SimCrashed NameValuePair RemoveNameValuePair UpdateAttachment RemoveAttachment EmailMessageRequest EmailMessageReply InternalScriptMail ScriptDataRequest ScriptDataReply InviteGroupResponse TallyVotes LiveHelpGroupRequest LiveHelpGroupReply GroupDataUpdate LogTextMessage CreateTrustedCircuit ParcelRename SystemMessage RpcChannelRequest RpcChannelReply RpcScriptRequestInbound RpcScriptRequestInboundForward RpcScriptReplyInbound ScriptMailRegistration Error"));
929 menu->updateParent(LLMenuGL::sMenuContainer);
930 menu->setCanTearOff(FALSE);
931 LLView* buttonp = sInstance->getChild<LLView>("filter_choice_btn");
932 S32 x = buttonp->getRect().mLeft;
933 S32 y = buttonp->getRect().mBottom;
934 LLMenuGL::showPopup(sInstance, menu, x, y);
935}
936// static
937void LLFloaterMessageLog::onClickFilterMenu(void* user_data)
938{
939 std::string filter = std::string((char*)user_data);
940 sInstance->childSetText("filter_edit", filter);
941 sInstance->startApplyingFilter(filter, FALSE);
942}
943// static
944void LLFloaterMessageLog::onClickSendToMessageBuilder(void* user_data)
945{
946 LLFloaterMessageLog* floaterp = (LLFloaterMessageLog*)user_data;
947 LLScrollListCtrl* scrollp = floaterp->getChild<LLScrollListCtrl>("message_log");
948 LLScrollListItem* selected_itemp = scrollp->getFirstSelected();
949 if(!selected_itemp) return;
950 LLUUID id = selected_itemp->getUUID();
951 std::vector<LLFloaterMessageLogItem>::iterator end = sFloaterMessageLogItems.end();
952 for(std::vector<LLFloaterMessageLogItem>::iterator iter = sFloaterMessageLogItems.begin(); iter != end; ++iter)
953 {
954 if(iter->mID == id)
955 {
956 std::string message_text = iter->getFull(FALSE);
957 LLFloaterMessageBuilder::show(message_text);
958 break;
959 }
960 }
961}
962// </edit>