corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 using GridProxyGUI;
2 using System;
3 using System.Collections.Generic;
4 using System.Collections.Concurrent;
5 using Gtk;
6 using OpenMetaverse.Packets;
7 using Logger = OpenMetaverse.Logger;
8 using System.Timers;
9 using System.Text.RegularExpressions;
10  
11 public partial class MainWindow : Gtk.Window
12 {
13 ProxyManager proxy = null;
14 MessageScroller messages;
15 PluginsScroller plugins;
16  
17 // stats tracking
18 int PacketCounter;
19 int CapsInCounter;
20 int CapsInBytes;
21 int CapsOutCounter;
22 int CapsOutBytes;
23 int PacketsInCounter;
24 int PacketsInBytes;
25 int PacketsOutCounter;
26 int PacketsOutBytes;
27  
28 Timer StatsTimer;
29  
30 public MainWindow()
31 : base(Gtk.WindowType.Toplevel)
32 {
33 Build();
34 LoadSavedSettings();
35  
36 ProxyLogger.Init();
37 ProxyLogger.OnLogLine += new ProxyLogger.Log(Logger_OnLogLine);
38  
39 tabsMain.Page = 0;
40  
41 string font;
42 if (PlatformDetection.IsMac)
43 {
44 txtSummary.ModifyFont(Pango.FontDescription.FromString("monospace bold"));
45 font = "monospace";
46 IgeMacIntegration.IgeMacMenu.GlobalKeyHandlerEnabled = true;
47 IgeMacIntegration.IgeMacMenu.MenuBar = menuMain;
48 MenuItem quit = new MenuItem("Quit");
49 quit.Activated += (object sender, EventArgs e) => OnExitActionActivated(sender, e);
50 IgeMacIntegration.IgeMacMenu.QuitMenuItem = quit;
51 menuMain.Hide();
52 menuSeparator.Hide();
53 }
54 else
55 {
56 txtSummary.ModifyFont(Pango.FontDescription.FromString("monospace bold 9"));
57 font = "monospace 9";
58 }
59  
60 btnLoadPlugin.Sensitive = false;
61 txtPort.TextInserted += (object o, TextInsertedArgs args) =>
62 {
63 if (args.Length != 1) return;
64 if (!char.IsDigit(args.Text[0]))
65 {
66 txtPort.DeleteText(args.Position - 1, args.Position);
67 }
68 };
69  
70 InitProxyFilters();
71  
72 txtRequest.ModifyFont(Pango.FontDescription.FromString(font));
73 CreateTags(txtRequest.Buffer);
74 txtRequestRaw.ModifyFont(Pango.FontDescription.FromString(font));
75 txtRequestNotation.ModifyFont(Pango.FontDescription.FromString(font));
76  
77 txtResponse.ModifyFont(Pango.FontDescription.FromString(font));
78 CreateTags(txtResponse.Buffer);
79 txtResponseRaw.ModifyFont(Pango.FontDescription.FromString(font));
80 txtResponseNotation.ModifyFont(Pango.FontDescription.FromString(font));
81  
82  
83 sessionLogScroller.Add(messages = new MessageScroller(this));
84 scrolledwindowPlugin.Add(plugins = new PluginsScroller());
85 messages.CursorChanged += messages_CursorChanged;
86 StatsTimer = new Timer(1000.0);
87 StatsTimer.Elapsed += StatsTimer_Elapsed;
88 StatsTimer.Enabled = true;
89  
90 ProxyManager.OnLoginResponse += ProxyManager_OnLoginResponse;
91 ProxyManager.OnPacketLog += ProxyManager_OnPacketLog;
92 ProxyManager.OnCapabilityAdded += new ProxyManager.CapsAddedHandler(ProxyManager_OnCapabilityAdded);
93 ProxyManager.OnEventMessageLog += new ProxyManager.EventQueueMessageHandler(ProxyManager_OnEventMessageLog);
94 ProxyManager.OnMessageLog += new ProxyManager.MessageLogHandler(ProxyManager_OnMessageLog);
95 }
96  
97 void StatsTimer_Elapsed(object sender, ElapsedEventArgs e)
98 {
99 Application.Invoke((xsender, xe) =>
100 {
101 lblUDPIn.Text = string.Format("Packets In {0} ({1} bytes)", PacketsInCounter, PacketsInBytes);
102 lblUDPOut.Text = string.Format("Packets Out {0} ({1} bytes)", PacketsOutCounter, PacketsOutBytes);
103 lblUDPTotal.Text = string.Format("Packets Total {0} ({1} bytes)", PacketsInCounter + PacketsOutCounter, PacketsInBytes + PacketsOutBytes);
104  
105 lblCapIn.Text = string.Format("Caps In {0} ({1} bytes)", CapsInCounter, CapsInBytes);
106 lblCapOut.Text = string.Format("Caps Out {0} ({1} bytes)", CapsOutCounter, CapsOutBytes);
107 lblCapTotal.Text = string.Format("Caps Total {0} ({1} bytes)", CapsInCounter + CapsOutCounter, CapsInBytes + CapsOutBytes);
108  
109 });
110 }
111  
112 void ProxyManager_OnLoginResponse(object request, GridProxy.Direction direction)
113 {
114 Application.Invoke((xsender, xe) =>
115 {
116 string loginType;
117  
118 if (request is Nwc.XmlRpc.XmlRpcRequest)
119 {
120 loginType = "Login Request";
121 }
122 else
123 {
124 loginType = "Login Response";
125 }
126  
127 if (UDPFilterItems.ContainsKey(loginType) && UDPFilterItems[loginType].Enabled)
128 {
129 PacketCounter++;
130  
131 SessionLogin sessionLogin = new SessionLogin(request, direction, cbLoginURL.ActiveText, request.GetType().Name + " " + loginType);
132  
133 sessionLogin.Columns = new string[] { PacketCounter.ToString(), sessionLogin.TimeStamp.ToString("HH:mm:ss.fff"),
134 sessionLogin.Protocol, sessionLogin.Name, sessionLogin.Length.ToString(), sessionLogin.Host, sessionLogin.ContentType };
135  
136 messages.AddSession(sessionLogin);
137 }
138  
139 });
140 }
141  
142 void ProxyManager_OnPacketLog(Packet packet, GridProxy.Direction direction, System.Net.IPEndPoint endpoint)
143 {
144 Application.Invoke((xsender, xe) =>
145 {
146 PacketCounter++;
147  
148 if (direction == GridProxy.Direction.Incoming)
149 {
150 PacketsInCounter++;
151 PacketsInBytes += packet.Length;
152 }
153 else
154 {
155 PacketsOutCounter++;
156 PacketsOutBytes += packet.Length;
157 }
158  
159 SessionPacket sessionPacket = new SessionPacket(packet, direction, endpoint,
160 PacketDecoder.InterpretOptions(packet.Header) + " Seq: " + packet.Header.Sequence.ToString() + " Freq:" + packet.Header.Frequency.ToString());
161  
162 sessionPacket.Columns = new string[] { PacketCounter.ToString(), sessionPacket.TimeStamp.ToString("HH:mm:ss.fff"), sessionPacket.Protocol, sessionPacket.Name, sessionPacket.Length.ToString(), sessionPacket.Host, sessionPacket.ContentType };
163 messages.AddSession(sessionPacket);
164 });
165 }
166  
167 void ProxyManager_OnCapabilityAdded(GridProxy.CapInfo cap)
168 {
169 Application.Invoke((sender, e) =>
170 {
171 if (!CapFilterItems.ContainsKey(cap.CapType))
172 {
173 FilterItem item = new FilterItem() { Name = cap.CapType, Type = ItemType.Cap };
174 item.FilterItemChanged += item_FilterItemChanged;
175 item.Enabled = true;
176 CapFilterItems[item.Name] = item;
177 capStore.AppendValues(item);
178 }
179 });
180 }
181  
182 void ProxyManager_OnEventMessageLog(GridProxy.CapsRequest req, GridProxy.CapsStage stage)
183 {
184 Application.Invoke((sender, e) =>
185 {
186 if (!CapFilterItems.ContainsKey(req.Info.CapType))
187 {
188 FilterItem item = new FilterItem() { Enabled = true, Name = req.Info.CapType, Type = ItemType.EQ };
189 item.FilterItemChanged += item_FilterItemChanged;
190 CapFilterItems[item.Name] = item;
191 capStore.AppendValues(item);
192 }
193  
194 ProxyManager_OnMessageLog(req, GridProxy.CapsStage.Response);
195 });
196 }
197  
198 void ProxyManager_OnMessageLog(GridProxy.CapsRequest req, GridProxy.CapsStage stage)
199 {
200 Application.Invoke((sender, e) =>
201 {
202 if (CapFilterItems.ContainsKey(req.Info.CapType))
203 {
204 var filter = CapFilterItems[req.Info.CapType];
205 if (!filter.Enabled) return;
206  
207 PacketCounter++;
208  
209 int size = 0;
210 if (req.RawRequest != null)
211 {
212 size += req.RawRequest.Length;
213 }
214  
215 if (req.RawResponse != null)
216 {
217 size += req.RawResponse.Length;
218 }
219  
220 GridProxy.Direction direction;
221 if (stage == GridProxy.CapsStage.Request)
222 {
223 CapsOutCounter++;
224 CapsOutBytes += req.Request.ToString().Length;
225 direction = GridProxy.Direction.Outgoing;
226 }
227 else
228 {
229 CapsInCounter++;
230 CapsInBytes += req.Response.ToString().Length;
231 direction = GridProxy.Direction.Incoming;
232 }
233  
234 string proto = filter.Type.ToString();
235  
236 Session capsSession = null;
237 if (filter.Type == ItemType.Cap)
238 {
239 capsSession = new SessionCaps(req.RawRequest, req.RawResponse, req.RequestHeaders,
240 req.ResponseHeaders, direction, req.Info.URI, req.Info.CapType, proto, req.FullUri);
241 }
242 else
243 {
244 capsSession = new SessionEvent(req.RawResponse, req.ResponseHeaders, req.Info.URI, req.Info.CapType, proto);
245 }
246  
247 capsSession.Columns = new string[] { PacketCounter.ToString(), capsSession.TimeStamp.ToString("HH:mm:ss.fff"), capsSession.Protocol, capsSession.Name, capsSession.Length.ToString(), capsSession.Host, capsSession.ContentType };
248 messages.AddSession(capsSession);
249  
250 }
251 });
252 }
253  
254 void Logger_OnLogLine(object sender, LogEventArgs e)
255 {
256 Gtk.Application.Invoke((sx, ex) =>
257 {
258 AppendLog(e.Message);
259 });
260 }
261  
262 void AppendLog(string msg)
263 {
264 var end = txtSummary.Buffer.EndIter;
265 txtSummary.Buffer.Insert(ref end, msg);
266 }
267  
268 protected void StartPoxy()
269 {
270 AppendLog("Starting proxy..." + Environment.NewLine);
271 try
272 {
273 proxy = new ProxyManager(txtPort.Text, cbListen.ActiveText, cbLoginURL.ActiveText);
274 proxy.Start();
275 btnLoadPlugin.Sensitive = true;
276 ApplyProxyFilters();
277 }
278 catch (Exception ex)
279 {
280 Logger.Log("Failed to start proxy: " + ex.Message, OpenMetaverse.Helpers.LogLevel.Error);
281 try
282 {
283 proxy.Stop();
284 }
285 catch { }
286 btnStart.Label = "Start Proxy";
287 proxy = null;
288 }
289 }
290  
291 protected void StopProxy()
292 {
293 AppendLog("Proxy stopped" + Environment.NewLine);
294 if (proxy != null) proxy.Stop();
295 proxy = null;
296 plugins.Store.Clear();
297 btnLoadPlugin.Sensitive = false;
298 }
299  
300 protected void OnDeleteEvent(object sender, DeleteEventArgs a)
301 {
302 StopProxy();
303 SaveSettings();
304 a.RetVal = true;
305 }
306  
307 protected void OnExitActionActivated(object sender, EventArgs e)
308 {
309 StopProxy();
310 SaveSettings();
311 }
312  
313 protected void OnBtnStartClicked(object sender, EventArgs e)
314 {
315 if (btnStart.Label.StartsWith("Start"))
316 {
317 btnStart.Label = "Stop Proxy";
318 StartPoxy();
319 }
320 else if (btnStart.Label.StartsWith("Stop"))
321 {
322 btnStart.Label = "Start Proxy";
323 StopProxy();
324 }
325 }
326  
327 void SetAllToggles(bool on, ListStore store)
328 {
329 if (null == store) return;
330  
331 store.Foreach((model, path, iter) =>
332 {
333 var item = model.GetValue(iter, 0) as FilterItem;
334 if (null != item)
335 {
336 item.Enabled = on;
337 model.SetValue(iter, 0, item);
338 }
339  
340 return false;
341 });
342 }
343  
344 protected void OnCbSelectAllUDPToggled(object sender, EventArgs e)
345 {
346 SetAllToggles(cbSelectAllUDP.Active, udpStore);
347 }
348  
349 protected void OnCbSelectAllCapToggled(object sender, EventArgs e)
350 {
351 SetAllToggles(cbSelectAllCap.Active, capStore);
352 }
353  
354 protected void OnCbAutoScrollToggled(object sender, EventArgs e)
355 {
356 messages.AutoScroll = cbAutoScroll.Active;
357 }
358  
359 void messages_CursorChanged(object sender, EventArgs e)
360 {
361 var tv = (TreeView)sender;
362 var paths = tv.Selection.GetSelectedRows();
363 TreeIter iter;
364  
365 if (paths.Length == 1 && tv.Model.GetIter(out iter, paths[0]))
366 {
367 var item = tv.Model.GetValue(iter, 0) as Session;
368 if (item != null)
369 {
370 ColorizePacket(txtRequest.Buffer, item.ToPrettyString(GridProxy.Direction.Outgoing));
371 txtRequestRaw.Buffer.Text = item.ToRawString(GridProxy.Direction.Outgoing);
372 txtRequestNotation.Buffer.Text = item.ToStringNotation(GridProxy.Direction.Outgoing);
373  
374 ColorizePacket(txtResponse.Buffer, item.ToPrettyString(GridProxy.Direction.Incoming));
375 txtResponseRaw.Buffer.Text = item.ToRawString(GridProxy.Direction.Incoming);
376 txtResponseNotation.Buffer.Text = item.ToStringNotation(GridProxy.Direction.Incoming);
377  
378 SetVisibility();
379 }
380 }
381 }
382  
383 void SetVisibility()
384 {
385 tabsMain.Page = 2;
386  
387 var w1 = vboxInspector.Children.GetValue(0) as Widget;
388 var w2 = vboxInspector.Children.GetValue(1) as Widget;
389  
390 if (w1 == null || w2 == null) return;
391  
392 // check if request is empry
393 if (txtRequest.Buffer.Text.Trim().Length < 3 && txtRequestRaw.Buffer.Text.Trim().Length < 3)
394 {
395 w1.Hide();
396 }
397 else
398 {
399 w1.Show();
400 }
401  
402 // check if request is empry
403 if (txtResponse.Buffer.Text.Trim().Length < 3 && txtResponseRaw.Buffer.Text.Trim().Length < 3)
404 {
405 w2.Hide();
406 }
407 else
408 {
409 w2.Show();
410 }
411  
412 }
413  
414 void CreateTags(TextBuffer buffer)
415 {
416 TextTag tag = buffer.TagTable.Lookup("bold");
417 if (tag == null)
418 {
419 tag = new TextTag("bold");
420 tag.Weight = Pango.Weight.Bold;
421 buffer.TagTable.Add(tag);
422 }
423  
424 tag = buffer.TagTable.Lookup("type");
425 if (tag == null)
426 {
427 tag = new TextTag("type");
428 tag.ForegroundGdk = new Gdk.Color(43, 145, 175);
429 buffer.TagTable.Add(tag);
430 }
431  
432 tag = buffer.TagTable.Lookup("header");
433 if (tag == null)
434 {
435 tag = new TextTag("header");
436 tag.ForegroundGdk = new Gdk.Color(0, 96, 0);
437 tag.BackgroundGdk = new Gdk.Color(206, 226, 252);
438 buffer.TagTable.Add(tag);
439 }
440  
441 tag = buffer.TagTable.Lookup("block");
442 if (tag == null)
443 {
444 tag = new TextTag("block");
445 tag.ForegroundGdk = new Gdk.Color(255, 215, 0);
446 buffer.TagTable.Add(tag);
447 }
448  
449 tag = buffer.TagTable.Lookup("tag");
450 if (tag == null)
451 {
452 tag = new TextTag("tag");
453 tag.ForegroundGdk = new Gdk.Color(255, 255, 255);
454 tag.BackgroundGdk = new Gdk.Color(40, 40, 40);
455 buffer.TagTable.Add(tag);
456 }
457  
458 tag = buffer.TagTable.Lookup("counter");
459 if (tag == null)
460 {
461 tag = new TextTag("counter");
462 tag.ForegroundGdk = new Gdk.Color(0, 64, 0);
463 buffer.TagTable.Add(tag);
464 }
465  
466 tag = buffer.TagTable.Lookup("UUID");
467 if (tag == null)
468 {
469 tag = new TextTag("UUID");
470 tag.ForegroundGdk = new Gdk.Color(148, 0, 211);
471 buffer.TagTable.Add(tag);
472 }
473 }
474  
475 void ColorizePacket(TextBuffer buffer, string text)
476 {
477 if (!text.StartsWith("Message Type:") && !text.StartsWith("Packet Type:"))
478 {
479 buffer.Text = text;
480 return;
481 }
482  
483 buffer.Text = string.Empty;
484 text = text.Replace("\r", "");
485 TextIter iter = buffer.StartIter;
486  
487 Regex typesRegex = new Regex(@"\[(?<Type>\w+|\w+\[\])\]|\((?<Enum>.*)\)|\s-- (?<Header>\w+|\w+ \[\]) --\s|(?<BlockSep>\s\*\*\*\s)|(?<Tag>\s<\w+>\s|\s<\/\w+>\s)|(?<BlockCounter>\s\w+\[\d+\]\s)|(?<UUID>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})", RegexOptions.ExplicitCapture);
488  
489 MatchCollection matches = typesRegex.Matches(text);
490 int pos = 0;
491  
492 if (matches.Count == 0)
493 {
494 buffer.Text = text;
495 }
496  
497 foreach (Match match in matches)
498 {
499 string tag = "bold";
500  
501 buffer.Insert(ref iter, text.Substring(pos, match.Index - pos));
502 pos += match.Index - pos;
503  
504 if (!String.IsNullOrEmpty(match.Groups["Type"].Value))
505 {
506 tag = "type";
507 }
508 else if (!String.IsNullOrEmpty(match.Groups["Enum"].Value))
509 {
510 tag = "type";
511 }
512 else if (!String.IsNullOrEmpty(match.Groups["Header"].Value))
513 {
514 tag = "header";
515 }
516 else if (!String.IsNullOrEmpty(match.Groups["BlockSep"].Value))
517 {
518 tag = "block";
519 }
520 else if (!String.IsNullOrEmpty(match.Groups["Tag"].Value))
521 {
522 tag = "tag";
523 }
524 else if (!String.IsNullOrEmpty(match.Groups["BlockCounter"].Value))
525 {
526 tag = "counter";
527 }
528 else if (!String.IsNullOrEmpty(match.Groups["UUID"].Value))
529 {
530 tag = "UUID";
531 }
532  
533 buffer.InsertWithTagsByName(ref iter, text.Substring(pos, match.Length), tag);
534 pos += match.Length;
535 }
536 }
537  
538 List<FileFilter> GetFileFilters()
539 {
540 List<FileFilter> filters = new List<FileFilter>();
541  
542 FileFilter filter = new FileFilter();
543 filter.Name = "Grid Proxy Compressed (*.gpz)";
544 filter.AddPattern("*.gpz");
545 filters.Add(filter);
546  
547 filter = new FileFilter();
548 filter.Name = "All Files (*.*)";
549 filter.AddPattern("*.*");
550 filters.Add(filter);
551  
552  
553 return filters;
554 }
555  
556 public void RedrawFilters()
557 {
558 containerFilterCap.QueueDraw();
559 containerFilterUDP.QueueDraw();
560 }
561  
562 protected void OnOpenActionActivated(object sender, EventArgs e)
563 {
564 var od = new Gtk.FileChooserDialog(null, "Open Session", this, FileChooserAction.Open, "Cancel", ResponseType.Cancel, "Open", ResponseType.Accept);
565 foreach (var filter in GetFileFilters()) od.AddFilter(filter);
566  
567 if (od.Run() == (int)ResponseType.Accept)
568 {
569 OpenSession(od.Filename);
570 }
571 od.Destroy();
572 }
573  
574 protected void OnSaveAsActionActivated(object sender, EventArgs e)
575 {
576 var od = new Gtk.FileChooserDialog(null, "Save Session", this, FileChooserAction.Save, "Cancel", ResponseType.Cancel, "Save", ResponseType.Accept);
577 foreach (var filter in GetFileFilters()) od.AddFilter(filter);
578  
579 if (od.Run() == (int)ResponseType.Accept)
580 {
581 SessionFileName = od.Filename;
582 if (string.IsNullOrEmpty(System.IO.Path.GetExtension(SessionFileName)))
583 {
584 SessionFileName += ".gpz";
585 }
586 SaveSession();
587 }
588 od.Destroy();
589 }
590  
591 protected void OnSaveActionActivated(object sender, EventArgs e)
592 {
593 if (string.IsNullOrEmpty(SessionFileName))
594 {
595 OnSaveAsActionActivated(sender, e);
596 }
597 else
598 {
599 SaveSession();
600 }
601 }
602  
603 protected void OnAboutActionActivated(object sender, EventArgs e)
604 {
605 var about = new GridProxyGUI.About();
606 about.SkipTaskbarHint = about.SkipPagerHint = true;
607 about.Run();
608 about.Destroy();
609 }
610  
611 protected void OnBtnLoadPluginClicked(object sender, EventArgs e)
612 {
613 if (proxy == null) return;
614  
615 plugins.LoadPlugin(proxy.Proxy);
616 }
617  
618 }