Subversion Repositories general

Rev

Rev 1199 | Rev 1201 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1092 dev 1
using System;
2
using System.Drawing;
3
using System.Collections;
4
using System.Windows.Forms;
5
using System.IO;
6
using System.Net;
7
using System.Text;
8
using System.Text.RegularExpressions;
9
using System.Xml;
10
 
11
// FIXME:
12
//   - add soap validation
13
//   - icons for all items in the tree
14
//   - use pool of threads?
15
//   - do not store intermediate info, just row packets and the parsed fragments to display
16
//   - make the text fragment store switchable
1199 dev 17
//   - set locks and check exceptions during log writing (?)
1092 dev 18
namespace TCPproxy
19
{
1200 dev 20
	public class MainForm : Form
1092 dev 21
	{
1194 dev 22
		#region constants and settings
1197 dev 23
 
1199 dev 24
		private const int    RECENT_LENGTH          = 20;
25
		public  const string REGISTRY_KEY           = @"Software\Anatoli Klassen\TCPproxy";
26
		public  const string REGISTRY_RECENT_SUBKEY = "Recent Listenings";
1194 dev 27
 
1199 dev 28
		public  const byte   LOG_TYPE_BIN           = 1;
29
		public  const string LOG_BIN_HEADER         = "TCPproxy 1.0\n";
30
 
1194 dev 31
		#endregion constants and settings
32
 
1125 dev 33
		#region private fields
34
 
1194 dev 35
		private ListenForm   listenForm     = new ListenForm();
1125 dev 36
		private TcpListener  tcpListener    = null;
37
		private LogMessages  logMessages    = null;
38
		private Hashtable    treeNodes      = new Hashtable();
1194 dev 39
		private ArrayList    recentItems    = new ArrayList();
1125 dev 40
 
1194 dev 41
        private int          listenPort;
42
        private string       resendHost;
43
        private int          resendPort;
1125 dev 44
		private TcpShowMode  tcpShowMode    = TcpShowMode.ByDirection;
45
		private bool         autoExpand     = true;
46
 
1194 dev 47
		private string       defaultCaption;
48
 
1125 dev 49
		#endregion private fields
50
 
51
		#region web forms fields
1194 dev 52
        private System.ComponentModel.IContainer components;
1200 dev 53
		private SaveFileDialog saveLogDialog;
54
        private StatusBarPanel connectionStatusBar;
55
        private MenuItem selectAllmenuItem;
56
        private MenuItem copyMenuItem;
57
        private ContextMenu viewContextMenu;
58
        private MenuItem closeConnectionMenuItem;
59
		private ImageList saveButtonImageList;
60
        private StatusBar statusBar;
61
        private ContextMenu messagesContextMenu;
62
		private ImageList treeImageList;
63
		private MenuItem wordWrapMenuItem;
1197 dev 64
        private MainMenu mainMenu;
65
        private MenuItem fileMenu;
66
        private MenuItem loadBinLogMenuItem;
67
        private MenuItem saveBinLogMenuItem;
68
        private MenuItem menuSeparator1;
69
        private MenuItem exitMenuItem;
70
        private MenuItem viewMenu;
71
        private MenuItem clearMainMenuItem;
72
        private MenuItem messagesMenu;
73
        private MenuItem saveFullLogMenuItem;
74
        private MenuItem saveTcoLogMenuItem;
75
        private MenuItem saveHttpLogMenuItem;
76
        private MenuItem saveXmlLogMenuItem;
77
        private MenuItem menuSeparator2;
78
        private MenuItem allMessagesMenuItem;
79
        private MenuItem importantMessagesMenuItem;
80
        private MenuItem infoMessagesMenuItem;
81
        private MenuItem menuSeparator3;
82
        private MenuItem tcpShowByDirectionMenuItem;
83
        private MenuItem tcpShowByTimeMenuItem;
84
        private MenuItem menuSeparator4;
85
        private MenuItem autoExpandMenuItem;
86
        private MenuItem wordWrapMainMenuItem;
87
        private MenuItem helpMenu;
1194 dev 88
        private Panel panel1;
89
        private Panel panel3;
90
        private Panel panel4;
91
        private ViewControl messagesBox;
92
        private Splitter splitter2;
93
        private ListBox logBox;
94
        private Splitter splitter1;
95
        private TreeView messageView;
1197 dev 96
        private MenuItem startMenuItem;
97
        private MenuItem stopMenuItem;
98
        private MenuItem menuSeparator5;
99
		private MenuItem recentListeningMenu;
100
		private MenuItem recentListeningNoItem;
1199 dev 101
		private SaveFileDialog saveBinLogDialog;
102
		private OpenFileDialog loadBinLogDialog;
1197 dev 103
        private MenuItem aboutMenuItem;
1092 dev 104
		#endregion web forms fields
105
 
106
		#region Windows Form Designer generated code
107
		/// <summary>
108
		/// Required method for Designer support - do not modify
109
		/// the contents of this method with the code editor.
110
		/// </summary>
111
		private void InitializeComponent() {
112
			this.components = new System.ComponentModel.Container();
1194 dev 113
			System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
1200 dev 114
			this.wordWrapMenuItem = new MenuItem();
115
			this.treeImageList = new ImageList(this.components);
116
			this.messagesContextMenu = new ContextMenu();
117
			this.selectAllmenuItem = new MenuItem();
118
			this.copyMenuItem = new MenuItem();
119
			this.statusBar = new StatusBar();
120
			this.connectionStatusBar = new StatusBarPanel();
121
			this.saveButtonImageList = new ImageList(this.components);
122
			this.closeConnectionMenuItem = new MenuItem();
123
			this.viewContextMenu = new ContextMenu();
124
			this.saveLogDialog = new SaveFileDialog();
125
			this.mainMenu = new MainMenu(this.components);
126
			this.fileMenu = new MenuItem();
127
			this.startMenuItem = new MenuItem();
128
			this.stopMenuItem = new MenuItem();
129
			this.recentListeningMenu = new MenuItem();
130
			this.recentListeningNoItem = new MenuItem();
131
			this.menuSeparator5 = new MenuItem();
132
			this.loadBinLogMenuItem = new MenuItem();
133
			this.saveBinLogMenuItem = new MenuItem();
134
			this.menuSeparator1 = new MenuItem();
135
			this.saveFullLogMenuItem = new MenuItem();
136
			this.saveTcoLogMenuItem = new MenuItem();
137
			this.saveHttpLogMenuItem = new MenuItem();
138
			this.saveXmlLogMenuItem = new MenuItem();
139
			this.menuSeparator2 = new MenuItem();
140
			this.exitMenuItem = new MenuItem();
141
			this.viewMenu = new MenuItem();
142
			this.clearMainMenuItem = new MenuItem();
143
			this.messagesMenu = new MenuItem();
144
			this.allMessagesMenuItem = new MenuItem();
145
			this.infoMessagesMenuItem = new MenuItem();
146
			this.importantMessagesMenuItem = new MenuItem();
147
			this.menuSeparator3 = new MenuItem();
148
			this.tcpShowByDirectionMenuItem = new MenuItem();
149
			this.tcpShowByTimeMenuItem = new MenuItem();
150
			this.menuSeparator4 = new MenuItem();
151
			this.autoExpandMenuItem = new MenuItem();
152
			this.wordWrapMainMenuItem = new MenuItem();
153
			this.helpMenu = new MenuItem();
154
			this.aboutMenuItem = new MenuItem();
155
			this.panel1 = new Panel();
156
			this.panel3 = new Panel();
157
			this.panel4 = new Panel();
1092 dev 158
			this.messagesBox = new TCPproxy.ViewControl();
1200 dev 159
			this.splitter2 = new Splitter();
160
			this.logBox = new ListBox();
161
			this.splitter1 = new Splitter();
162
			this.messageView = new TreeView();
163
			this.saveBinLogDialog = new SaveFileDialog();
164
			this.loadBinLogDialog = new OpenFileDialog();
1194 dev 165
			((System.ComponentModel.ISupportInitialize)(this.connectionStatusBar)).BeginInit();
1092 dev 166
			this.panel1.SuspendLayout();
167
			this.panel3.SuspendLayout();
1194 dev 168
			this.panel4.SuspendLayout();
1092 dev 169
			this.SuspendLayout();
1199 dev 170
			// 
1092 dev 171
			// wordWrapMenuItem
1199 dev 172
			// 
1194 dev 173
			this.wordWrapMenuItem.Index = 2;
1092 dev 174
			this.wordWrapMenuItem.Text = "Word &Wrap";
175
			this.wordWrapMenuItem.Click += new System.EventHandler(this.wordWrapMenuItem_Click);
1199 dev 176
			// 
1092 dev 177
			// treeImageList
1199 dev 178
			// 
1200 dev 179
			this.treeImageList.ImageStream = ((ImageListStreamer)(resources.GetObject("treeImageList.ImageStream")));
1194 dev 180
			this.treeImageList.TransparentColor = System.Drawing.Color.Magenta;
1199 dev 181
			this.treeImageList.Images.SetKeyName(0, "");
182
			this.treeImageList.Images.SetKeyName(1, "");
183
			this.treeImageList.Images.SetKeyName(2, "");
184
			// 
1092 dev 185
			// messagesContextMenu
1199 dev 186
			// 
1200 dev 187
			this.messagesContextMenu.MenuItems.AddRange(new MenuItem[] {
1194 dev 188
            this.selectAllmenuItem,
189
            this.copyMenuItem,
190
            this.wordWrapMenuItem});
1199 dev 191
			// 
1194 dev 192
			// selectAllmenuItem
1199 dev 193
			// 
1194 dev 194
			this.selectAllmenuItem.Index = 0;
1200 dev 195
			this.selectAllmenuItem.Shortcut = Shortcut.CtrlA;
1194 dev 196
			this.selectAllmenuItem.Text = "Select &All";
197
			this.selectAllmenuItem.Click += new System.EventHandler(this.selectAllMenuItem_Click);
1199 dev 198
			// 
1194 dev 199
			// copyMenuItem
1199 dev 200
			// 
1194 dev 201
			this.copyMenuItem.Index = 1;
1200 dev 202
			this.copyMenuItem.Shortcut = Shortcut.CtrlC;
1194 dev 203
			this.copyMenuItem.Text = "&Copy";
204
			this.copyMenuItem.Click += new System.EventHandler(this.copyMenuItem_Click);
1199 dev 205
			// 
1092 dev 206
			// statusBar
1199 dev 207
			// 
208
			this.statusBar.Location = new System.Drawing.Point(0, 359);
1092 dev 209
			this.statusBar.Name = "statusBar";
1200 dev 210
			this.statusBar.Panels.AddRange(new StatusBarPanel[] {
1194 dev 211
            this.connectionStatusBar});
1092 dev 212
			this.statusBar.ShowPanels = true;
213
			this.statusBar.Size = new System.Drawing.Size(780, 22);
214
			this.statusBar.TabIndex = 0;
1199 dev 215
			// 
1194 dev 216
			// connectionStatusBar
1199 dev 217
			// 
1200 dev 218
			this.connectionStatusBar.AutoSize = StatusBarPanelAutoSize.Spring;
1199 dev 219
			this.connectionStatusBar.Name = "connectionStatusBar";
1194 dev 220
			this.connectionStatusBar.Width = 764;
1199 dev 221
			// 
1092 dev 222
			// saveButtonImageList
1199 dev 223
			// 
1200 dev 224
			this.saveButtonImageList.ImageStream = ((ImageListStreamer)(resources.GetObject("saveButtonImageList.ImageStream")));
1194 dev 225
			this.saveButtonImageList.TransparentColor = System.Drawing.Color.Magenta;
1199 dev 226
			this.saveButtonImageList.Images.SetKeyName(0, "");
227
			// 
1092 dev 228
			// closeConnectionMenuItem
1199 dev 229
			// 
1092 dev 230
			this.closeConnectionMenuItem.Index = 0;
231
			this.closeConnectionMenuItem.Text = "&Close connection";
232
			this.closeConnectionMenuItem.Click += new System.EventHandler(this.closeConnectionMenuItem_Click);
1199 dev 233
			// 
1194 dev 234
			// viewContextMenu
1199 dev 235
			// 
1200 dev 236
			this.viewContextMenu.MenuItems.AddRange(new MenuItem[] {
1194 dev 237
            this.closeConnectionMenuItem});
1199 dev 238
			// 
1194 dev 239
			// saveLogDialog
1199 dev 240
			// 
1194 dev 241
			this.saveLogDialog.DefaultExt = "txt";
1199 dev 242
			this.saveLogDialog.Filter = "Text Files (*.txt)|*.txt|All Files|*.*";
1194 dev 243
			this.saveLogDialog.Title = "Save Log";
1199 dev 244
			// 
1194 dev 245
			// mainMenu
1199 dev 246
			// 
1200 dev 247
			this.mainMenu.MenuItems.AddRange(new MenuItem[] {
1199 dev 248
            this.fileMenu,
249
            this.viewMenu,
250
            this.helpMenu});
251
			// 
1194 dev 252
			// fileMenu
1199 dev 253
			// 
254
			this.fileMenu.Index = 0;
1200 dev 255
			this.fileMenu.MenuItems.AddRange(new MenuItem[] {
1199 dev 256
            this.startMenuItem,
257
            this.stopMenuItem,
258
            this.recentListeningMenu,
259
            this.menuSeparator5,
260
            this.loadBinLogMenuItem,
261
            this.saveBinLogMenuItem,
262
            this.menuSeparator1,
263
            this.saveFullLogMenuItem,
264
            this.saveTcoLogMenuItem,
265
            this.saveHttpLogMenuItem,
266
            this.saveXmlLogMenuItem,
267
            this.menuSeparator2,
268
            this.exitMenuItem});
269
			this.fileMenu.Text = "&File";
270
			// 
1194 dev 271
			// startMenuItem
1199 dev 272
			// 
273
			this.startMenuItem.Index = 0;
274
			this.startMenuItem.Text = "&Start...";
1194 dev 275
			this.startMenuItem.Click += new System.EventHandler(this.startMenuItem_Click);
1199 dev 276
			// 
1194 dev 277
			// stopMenuItem
1199 dev 278
			// 
1194 dev 279
			this.stopMenuItem.Enabled = false;
1199 dev 280
			this.stopMenuItem.Index = 1;
281
			this.stopMenuItem.Text = "S&top";
1194 dev 282
			this.stopMenuItem.Click += new System.EventHandler(this.stopMenuItem_Click);
1199 dev 283
			// 
284
			// recentListeningMenu
285
			// 
286
			this.recentListeningMenu.Index = 2;
1200 dev 287
			this.recentListeningMenu.MenuItems.AddRange(new MenuItem[] {
1199 dev 288
            this.recentListeningNoItem});
289
			this.recentListeningMenu.Text = "&Recent Listenings";
290
			// 
291
			// recentListeningNoItem
292
			// 
293
			this.recentListeningNoItem.Enabled = false;
294
			this.recentListeningNoItem.Index = 0;
295
			this.recentListeningNoItem.Text = "(no items)";
296
			// 
1194 dev 297
			// menuSeparator5
1199 dev 298
			// 
299
			this.menuSeparator5.Index = 3;
1197 dev 300
			this.menuSeparator5.Text = "-";
1199 dev 301
			// 
1194 dev 302
			// loadBinLogMenuItem
1199 dev 303
			// 
304
			this.loadBinLogMenuItem.Index = 4;
305
			this.loadBinLogMenuItem.Text = "&Load Bin Log...";
306
			this.loadBinLogMenuItem.Click += new System.EventHandler(this.loadBinLogMenuItem_Click);
307
			// 
1194 dev 308
			// saveBinLogMenuItem
1199 dev 309
			// 
310
			this.saveBinLogMenuItem.Index = 5;
311
			this.saveBinLogMenuItem.Text = "&Save Bin Log...";
1194 dev 312
			this.saveBinLogMenuItem.Click += new System.EventHandler(this.saveBinLogMenuItem_Click);
1199 dev 313
			// 
1194 dev 314
			// menuSeparator1
1199 dev 315
			// 
316
			this.menuSeparator1.Index = 6;
1197 dev 317
			this.menuSeparator1.Text = "-";
1199 dev 318
			// 
1194 dev 319
			// saveFullLogMenuItem
1199 dev 320
			// 
321
			this.saveFullLogMenuItem.Index = 7;
322
			this.saveFullLogMenuItem.Text = "Save F&ull Text Log...";
1194 dev 323
			this.saveFullLogMenuItem.Click += new System.EventHandler(this.saveLogMenuItem_Click);
1199 dev 324
			// 
1194 dev 325
			// saveTcoLogMenuItem
1199 dev 326
			// 
327
			this.saveTcoLogMenuItem.Index = 8;
328
			this.saveTcoLogMenuItem.Text = "Save T&CP Log...";
1194 dev 329
			this.saveTcoLogMenuItem.Click += new System.EventHandler(this.saveTcpMenuItem_Click);
1199 dev 330
			// 
1194 dev 331
			// saveHttpLogMenuItem
1199 dev 332
			// 
333
			this.saveHttpLogMenuItem.Index = 9;
334
			this.saveHttpLogMenuItem.Text = "Save Htt&p Log...";
1194 dev 335
			this.saveHttpLogMenuItem.Click += new System.EventHandler(this.saveHttpMenuItem_Click);
1199 dev 336
			// 
1194 dev 337
			// saveXmlLogMenuItem
1199 dev 338
			// 
339
			this.saveXmlLogMenuItem.Index = 10;
340
			this.saveXmlLogMenuItem.Text = "Save X&ML Log...";
1194 dev 341
			this.saveXmlLogMenuItem.Click += new System.EventHandler(this.saveXmlMenuItem_Click);
1199 dev 342
			// 
1194 dev 343
			// menuSeparator2
1199 dev 344
			// 
345
			this.menuSeparator2.Index = 11;
1197 dev 346
			this.menuSeparator2.Text = "-";
1199 dev 347
			// 
1194 dev 348
			// exitMenuItem
1199 dev 349
			// 
350
			this.exitMenuItem.Index = 12;
351
			this.exitMenuItem.Text = "E&xit";
352
			// 
1194 dev 353
			// viewMenu
1199 dev 354
			// 
355
			this.viewMenu.Index = 1;
1200 dev 356
			this.viewMenu.MenuItems.AddRange(new MenuItem[] {
1199 dev 357
            this.clearMainMenuItem,
358
            this.messagesMenu,
359
            this.menuSeparator3,
360
            this.tcpShowByDirectionMenuItem,
361
            this.tcpShowByTimeMenuItem,
362
            this.menuSeparator4,
363
            this.autoExpandMenuItem,
364
            this.wordWrapMainMenuItem});
365
			this.viewMenu.Text = "&View";
366
			// 
1194 dev 367
			// clearMainMenuItem
1199 dev 368
			// 
369
			this.clearMainMenuItem.Index = 0;
370
			this.clearMainMenuItem.Text = "&Clear";
1194 dev 371
			this.clearMainMenuItem.Click += new System.EventHandler(this.clearMenuItem_Click);
1199 dev 372
			// 
1194 dev 373
			// messagesMenu
1199 dev 374
			// 
375
			this.messagesMenu.Index = 1;
1200 dev 376
			this.messagesMenu.MenuItems.AddRange(new MenuItem[] {
1199 dev 377
            this.allMessagesMenuItem,
378
            this.infoMessagesMenuItem,
379
            this.importantMessagesMenuItem});
380
			this.messagesMenu.Text = "&Messages";
381
			// 
1194 dev 382
			// allMessagesMenuItem
1199 dev 383
			// 
1194 dev 384
			this.allMessagesMenuItem.Checked = true;
1199 dev 385
			this.allMessagesMenuItem.Index = 0;
386
			this.allMessagesMenuItem.Text = "&All";
1194 dev 387
			this.allMessagesMenuItem.Click += new System.EventHandler(this.messagesMenuItem_Click);
1199 dev 388
			// 
1194 dev 389
			// infoMessagesMenuItem
1199 dev 390
			// 
391
			this.infoMessagesMenuItem.Index = 1;
392
			this.infoMessagesMenuItem.Text = "&Info";
1194 dev 393
			this.infoMessagesMenuItem.Click += new System.EventHandler(this.messagesMenuItem_Click);
1199 dev 394
			// 
1194 dev 395
			// importantMessagesMenuItem
1199 dev 396
			// 
397
			this.importantMessagesMenuItem.Index = 2;
398
			this.importantMessagesMenuItem.Text = "I&mportant";
1194 dev 399
			this.importantMessagesMenuItem.Click += new System.EventHandler(this.messagesMenuItem_Click);
1199 dev 400
			// 
1194 dev 401
			// menuSeparator3
1199 dev 402
			// 
403
			this.menuSeparator3.Index = 2;
1197 dev 404
			this.menuSeparator3.Text = "-";
1199 dev 405
			// 
1194 dev 406
			// tcpShowByDirectionMenuItem
1199 dev 407
			// 
1194 dev 408
			this.tcpShowByDirectionMenuItem.Checked = true;
1199 dev 409
			this.tcpShowByDirectionMenuItem.Index = 3;
410
			this.tcpShowByDirectionMenuItem.Text = "TCP Show by &Direction";
1194 dev 411
			this.tcpShowByDirectionMenuItem.Click += new System.EventHandler(this.tcpShowByDirectionMenuItem_Click);
1199 dev 412
			// 
1194 dev 413
			// tcpShowByTimeMenuItem
1199 dev 414
			// 
415
			this.tcpShowByTimeMenuItem.Index = 4;
416
			this.tcpShowByTimeMenuItem.Text = "TCP Show by &Time";
1194 dev 417
			this.tcpShowByTimeMenuItem.Click += new System.EventHandler(this.tcpShowByTimeMenuItem_Click);
1199 dev 418
			// 
1194 dev 419
			// menuSeparator4
1199 dev 420
			// 
421
			this.menuSeparator4.Index = 5;
1197 dev 422
			this.menuSeparator4.Text = "-";
1199 dev 423
			// 
1194 dev 424
			// autoExpandMenuItem
1199 dev 425
			// 
426
			this.autoExpandMenuItem.Index = 6;
427
			this.autoExpandMenuItem.Text = "Auto E&xpand";
1194 dev 428
			this.autoExpandMenuItem.Click += new System.EventHandler(this.autoExpandMenuItem_Click);
1199 dev 429
			// 
1194 dev 430
			// wordWrapMainMenuItem
1199 dev 431
			// 
432
			this.wordWrapMainMenuItem.Index = 7;
433
			this.wordWrapMainMenuItem.Text = "Word &Wrap";
1194 dev 434
			this.wordWrapMainMenuItem.Click += new System.EventHandler(this.wordWrapMenuItem_Click);
1199 dev 435
			// 
1194 dev 436
			// helpMenu
1199 dev 437
			// 
438
			this.helpMenu.Index = 2;
1200 dev 439
			this.helpMenu.MenuItems.AddRange(new MenuItem[] {
1199 dev 440
            this.aboutMenuItem});
441
			this.helpMenu.Text = "&Help";
442
			// 
1194 dev 443
			// aboutMenuItem
1199 dev 444
			// 
445
			this.aboutMenuItem.Index = 0;
446
			this.aboutMenuItem.Text = "&About...";
1194 dev 447
			this.aboutMenuItem.Click += new System.EventHandler(this.aboutMenuItem_Click);
1199 dev 448
			// 
1092 dev 449
			// panel1
1199 dev 450
			// 
1092 dev 451
			this.panel1.Controls.Add(this.panel3);
1200 dev 452
			this.panel1.Dock = DockStyle.Fill;
1199 dev 453
			this.panel1.Location = new System.Drawing.Point(0, 0);
1092 dev 454
			this.panel1.Name = "panel1";
1199 dev 455
			this.panel1.Size = new System.Drawing.Size(780, 359);
1194 dev 456
			this.panel1.TabIndex = 11;
1199 dev 457
			// 
1092 dev 458
			// panel3
1199 dev 459
			// 
1092 dev 460
			this.panel3.Controls.Add(this.panel4);
461
			this.panel3.Controls.Add(this.splitter1);
462
			this.panel3.Controls.Add(this.messageView);
1200 dev 463
			this.panel3.Dock = DockStyle.Fill;
1092 dev 464
			this.panel3.Location = new System.Drawing.Point(0, 0);
465
			this.panel3.Name = "panel3";
1199 dev 466
			this.panel3.Size = new System.Drawing.Size(780, 359);
1092 dev 467
			this.panel3.TabIndex = 5;
1199 dev 468
			// 
1194 dev 469
			// panel4
1199 dev 470
			// 
1194 dev 471
			this.panel4.Controls.Add(this.messagesBox);
472
			this.panel4.Controls.Add(this.splitter2);
473
			this.panel4.Controls.Add(this.logBox);
1200 dev 474
			this.panel4.Dock = DockStyle.Fill;
1194 dev 475
			this.panel4.Location = new System.Drawing.Point(163, 0);
476
			this.panel4.Name = "panel4";
1199 dev 477
			this.panel4.Size = new System.Drawing.Size(617, 359);
1194 dev 478
			this.panel4.TabIndex = 13;
1199 dev 479
			// 
1092 dev 480
			// messagesBox
1199 dev 481
			// 
1092 dev 482
			this.messagesBox.ContextMenu = this.messagesContextMenu;
1200 dev 483
			this.messagesBox.Dock = DockStyle.Fill;
1194 dev 484
			this.messagesBox.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
1092 dev 485
			this.messagesBox.Location = new System.Drawing.Point(0, 0);
486
			this.messagesBox.Name = "messagesBox";
1199 dev 487
			this.messagesBox.Size = new System.Drawing.Size(617, 288);
1092 dev 488
			this.messagesBox.TabIndex = 7;
489
			this.messagesBox.WordWrap = true;
1199 dev 490
			// 
1194 dev 491
			// splitter2
1199 dev 492
			// 
1200 dev 493
			this.splitter2.Dock = DockStyle.Bottom;
1199 dev 494
			this.splitter2.Location = new System.Drawing.Point(0, 288);
1194 dev 495
			this.splitter2.Name = "splitter2";
496
			this.splitter2.Size = new System.Drawing.Size(617, 3);
497
			this.splitter2.TabIndex = 9;
498
			this.splitter2.TabStop = false;
1199 dev 499
			// 
1092 dev 500
			// logBox
1199 dev 501
			// 
1200 dev 502
			this.logBox.Dock = DockStyle.Bottom;
1194 dev 503
			this.logBox.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
1092 dev 504
			this.logBox.HorizontalScrollbar = true;
505
			this.logBox.ItemHeight = 16;
1199 dev 506
			this.logBox.Location = new System.Drawing.Point(0, 291);
1092 dev 507
			this.logBox.Name = "logBox";
508
			this.logBox.ScrollAlwaysVisible = true;
509
			this.logBox.Size = new System.Drawing.Size(617, 68);
510
			this.logBox.TabIndex = 8;
1199 dev 511
			// 
1194 dev 512
			// splitter1
1199 dev 513
			// 
1194 dev 514
			this.splitter1.Location = new System.Drawing.Point(160, 0);
515
			this.splitter1.Name = "splitter1";
1199 dev 516
			this.splitter1.Size = new System.Drawing.Size(3, 359);
1194 dev 517
			this.splitter1.TabIndex = 12;
518
			this.splitter1.TabStop = false;
1199 dev 519
			// 
1194 dev 520
			// messageView
1199 dev 521
			// 
1194 dev 522
			this.messageView.ContextMenu = this.viewContextMenu;
1200 dev 523
			this.messageView.Dock = DockStyle.Left;
1194 dev 524
			this.messageView.HideSelection = false;
525
			this.messageView.ImageIndex = 0;
526
			this.messageView.ImageList = this.treeImageList;
527
			this.messageView.Location = new System.Drawing.Point(0, 0);
528
			this.messageView.Name = "messageView";
529
			this.messageView.SelectedImageIndex = 0;
1199 dev 530
			this.messageView.Size = new System.Drawing.Size(160, 359);
1194 dev 531
			this.messageView.TabIndex = 11;
1200 dev 532
			this.messageView.AfterSelect += new TreeViewEventHandler(this.messageView_AfterSelect);
533
			this.messageView.BeforeSelect += new TreeViewCancelEventHandler(this.messageView_BeforeSelect);
1199 dev 534
			// 
535
			// saveBinLogDialog
536
			// 
537
			this.saveBinLogDialog.DefaultExt = "tcp";
538
			this.saveBinLogDialog.Filter = "TCP Logs (*.bin)|*.bin|All Files|*.*";
539
			this.saveBinLogDialog.Title = "Save Binary Log";
540
			// 
541
			// loadBinLogDialog
542
			// 
543
			this.loadBinLogDialog.FileName = "openFileDialog1";
544
			this.loadBinLogDialog.Filter = "TCP Logs (*.bin)|*.bin|All Files|*.*";
545
			this.loadBinLogDialog.Title = "Load Binary Log";
546
			// 
1092 dev 547
			// MainForm
1199 dev 548
			// 
1092 dev 549
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
1199 dev 550
			this.ClientSize = new System.Drawing.Size(780, 381);
1092 dev 551
			this.Controls.Add(this.panel1);
552
			this.Controls.Add(this.statusBar);
1197 dev 553
			this.Menu = this.mainMenu;
1092 dev 554
			this.MinimumSize = new System.Drawing.Size(400, 200);
555
			this.Name = "MainForm";
1200 dev 556
			this.StartPosition = FormStartPosition.Manual;
1092 dev 557
			this.Text = "TCPproxy";
1194 dev 558
			((System.ComponentModel.ISupportInitialize)(this.connectionStatusBar)).EndInit();
1092 dev 559
			this.panel1.ResumeLayout(false);
560
			this.panel3.ResumeLayout(false);
1194 dev 561
			this.panel4.ResumeLayout(false);
1092 dev 562
			this.ResumeLayout(false);
1194 dev 563
 
1092 dev 564
		}
565
		#endregion
566
 
567
		#region windows forms methods
568
		public MainForm()
569
		{
570
			InitializeComponent();
571
			logMessages = new LogMessages(logBox);
1194 dev 572
			try {
573
				LoadFromRegistry();
574
				LoadRecentItemsFromRegistry();
575
			}
576
			catch(Exception) {}
577
 
578
			// update visual elements
579
			UpdateMessagesMenuItems();
580
 
581
			if(tcpShowMode == TcpShowMode.ByDirection) {
582
				tcpShowByDirectionMenuItem.Checked = true;
583
				tcpShowByTimeMenuItem.Checked      = false;
584
			}
585
			else {
586
				tcpShowByDirectionMenuItem.Checked = false;
587
				tcpShowByTimeMenuItem.Checked      = true;
588
			}
589
 
590
			autoExpandMenuItem.Checked   = autoExpand;
591
			wordWrapMainMenuItem.Checked = messagesBox.WordWrap;
592
 
593
			// save default values
594
			defaultCaption = this.Text;
1092 dev 595
		}
596
 
1194 dev 597
		protected override void Dispose(bool disposing)
1092 dev 598
		{
1194 dev 599
			if(tcpListener != null) {
1092 dev 600
				tcpListener.StopListening();    // stop listening
601
				tcpListener.CancelAll();        // cancel all open connections
602
			}
603
 
1194 dev 604
			// save settings
1197 dev 605
			SaveToRegistry();
1194 dev 606
			SaveRecentItemsToRegistry();
1092 dev 607
 
608
			if( disposing )
609
			{
610
				if (components != null)
611
				{
612
					components.Dispose();
613
				}
614
			}
615
			base.Dispose( disposing );
616
		}
617
 
618
		[STAThread]
619
		static void Main()
620
		{
621
			Application.Run(new MainForm());
622
		}
623
 
1194 dev 624
		private void startMenuItem_Click(object sender, System.EventArgs e)
625
		{
626
			IPAddress resendIp;
627
 
1197 dev 628
			if(!listenForm.Execute(this,
1194 dev 629
				ref listenPort, ref resendHost, out resendIp, ref resendPort)) return;
630
 
631
			StartListening(listenPort, resendIp, resendPort);
632
		}
633
 
634
		private void stopMenuItem_Click(object sender, System.EventArgs e)
1092 dev 635
		{
1199 dev 636
			StopListening();
1092 dev 637
		}
638
 
1194 dev 639
		private void clearMenuItem_Click(object sender, System.EventArgs e)
1092 dev 640
		{
1199 dev 641
			ClearAll();
1092 dev 642
		}
643
 
644
		private void selectAllMenuItem_Click(object sender, System.EventArgs e)
645
		{
646
			messagesBox.SelectAll();
647
		}
648
 
649
		private void copyMenuItem_Click(object sender, System.EventArgs e)
650
		{
651
			string sel = messagesBox.SelectedText;
652
			if(sel != null) Clipboard.SetDataObject(sel);
653
		}
654
 
655
		private void wordWrapMenuItem_Click(object sender, System.EventArgs e)
656
		{
1194 dev 657
			messagesBox.WordWrap         = !messagesBox.WordWrap;
658
			wordWrapMenuItem.Checked     = messagesBox.WordWrap;
659
			wordWrapMainMenuItem.Checked = messagesBox.WordWrap;
1092 dev 660
		}
661
 
662
		private void autoExpandMenuItem_Click(object sender, System.EventArgs e)
663
		{
1194 dev 664
			autoExpand                 = !autoExpand;
665
			autoExpandMenuItem.Checked = autoExpand;
1092 dev 666
		}
667
 
1194 dev 668
		private void aboutMenuItem_Click(object sender, EventArgs e)
669
		{
670
			(new AboutForm()).ShowDialog(this);
671
		}
672
 
1200 dev 673
		private void messageView_BeforeSelect(object sender, TreeViewCancelEventArgs e)
1092 dev 674
		{
675
			if(messageView.SelectedNode == null) return;
676
 
677
			object tag = messageView.SelectedNode.Tag;
678
			if(tag is TreeNodeData)
679
			{
680
				TreeNodeData data = (TreeNodeData)tag;
681
				data.SaveViewState();
682
			}
683
		}
684
 
1200 dev 685
		private void messageView_AfterSelect(object sender, TreeViewEventArgs e)
1092 dev 686
		{
687
			if(messageView.SelectedNode == null) return;
688
 
689
			object tag = messageView.SelectedNode.Tag;
690
			if(tag is TreeNodeData)
691
			{
692
				TreeNodeData data = (TreeNodeData)tag;
693
				data.Show();
694
			}
695
		}
696
 
697
		private void closeConnectionMenuItem_Click(object sender, System.EventArgs e)
698
		{
699
			if(messageView.SelectedNode == null) return;
700
 
701
			object tag = messageView.SelectedNode.Tag;
702
			if(tag is TcpNodeData)
703
				CloseTcpConnection(((TcpNodeData)tag).Tcp);
704
			else if(tag is TcpNodeData)
705
				CloseTcpConnection(((TcpNodeData)messageView.SelectedNode.Parent.Tag).Tcp);
706
			else if(tag is XmlNodeData)
707
				CloseTcpConnection(((TcpNodeData)messageView.SelectedNode.Parent.Parent.Tag).Tcp);
708
		}
709
 
710
		private void tcpShowByDirectionMenuItem_Click(object sender, System.EventArgs e)
711
		{
712
			tcpShowMode = TcpShowMode.ByDirection;
1194 dev 713
			tcpShowByDirectionMenuItem.Checked = true;
714
			tcpShowByTimeMenuItem.Checked      = false;
1092 dev 715
 
716
			if(messageView.SelectedNode == null) return;
717
 
718
			object tag = messageView.SelectedNode.Tag;
719
			if(tag is TcpNodeData)
720
				UpdateTcpNodeInternal(((TcpNodeData)tag).Tcp);
721
		}
722
 
723
		private void tcpShowByTimeMenuItem_Click(object sender, System.EventArgs e)
724
		{
725
			tcpShowMode = TcpShowMode.ByTime;
1194 dev 726
			tcpShowByDirectionMenuItem.Checked = false;
727
			tcpShowByTimeMenuItem.Checked      = true;
1092 dev 728
 
729
			if(messageView.SelectedNode == null) return;
730
 
731
			object tag = messageView.SelectedNode.Tag;
732
			if(tag is TcpNodeData)
733
				UpdateTcpNodeInternal(((TcpNodeData)tag).Tcp);
734
		}
735
 
736
		private void saveLogMenuItem_Click(object sender, System.EventArgs e)
737
		{
738
			if(saveLogDialog.ShowDialog() == DialogResult.OK)
739
			{
740
				SaveLog(saveLogDialog.FileName);
741
			}
742
		}
743
 
744
		private void saveTcpMenuItem_Click(object sender, System.EventArgs e)
745
		{
746
			if(saveLogDialog.ShowDialog() == DialogResult.OK)
747
			{
748
				SaveTcp(saveLogDialog.FileName);
749
			}
750
		}
751
 
752
		private void saveHttpMenuItem_Click(object sender, System.EventArgs e)
753
		{
754
			if(saveLogDialog.ShowDialog() == DialogResult.OK)
755
			{
756
				SaveHttp(saveLogDialog.FileName);
757
			}
758
		}
759
 
760
		private void saveXmlMenuItem_Click(object sender, System.EventArgs e)
761
		{
762
			if(saveLogDialog.ShowDialog() == DialogResult.OK)
763
			{
764
				SaveXml(saveLogDialog.FileName);
765
			}
766
		}
767
 
1199 dev 768
		private void saveBinLogMenuItem_Click(object sender, EventArgs e)
769
		{
770
			if(saveBinLogDialog.ShowDialog() == DialogResult.OK)
771
				SaveBinLog(saveBinLogDialog.FileName);
772
		}
773
 
774
		private void loadBinLogMenuItem_Click(object sender, EventArgs e)
775
		{
776
			if(loadBinLogDialog.ShowDialog() == DialogResult.OK)
777
				LoadBinLog(loadBinLogDialog.FileName);
778
		}
779
 
1194 dev 780
		private void messagesMenuItem_Click(object sender, EventArgs e)
1092 dev 781
		{
1194 dev 782
			if(sender == importantMessagesMenuItem)
783
				logMessages.Level = LogLevel.Important;
784
			else if(sender == infoMessagesMenuItem)
785
				logMessages.Level = LogLevel.Info;
786
			else
787
				logMessages.Level = LogLevel.Debug;
1092 dev 788
 
1194 dev 789
			UpdateMessagesMenuItems();
790
		}
1092 dev 791
 
1194 dev 792
		private void recentMenuItem_Click(object sender, EventArgs e)
793
		{
1198 dev 794
			int n = recentItems.Count-1;
1197 dev 795
			foreach(MenuItem menuItem in recentListeningMenu.MenuItems) {
796
				if(sender == menuItem) break;
1198 dev 797
				n--;
1197 dev 798
			}
1198 dev 799
			if(n < 0)
1197 dev 800
				throw new Exception("Unknown sender");
801
 
802
			RecentItem recentItem = (RecentItem)recentItems[n];
1194 dev 803
			IPAddress  resendIp;
804
 
805
			this.listenPort = recentItem.ListenPort;
806
			this.resendHost = recentItem.ResendHost;
807
			this.resendPort = recentItem.ResendPort;
1197 dev 808
 
1194 dev 809
			try
810
			{
811
				resendIp = HostUtils.ResendHostToIp(resendHost);
812
			}
813
			catch(Exception ex)
814
			{
815
				MessageBox.Show(ex.Message);
816
				return;
817
			}
818
 
819
			StartListening(listenPort, resendIp, resendPort);
820
		}
821
 
1199 dev 822
		#endregion windows forms methods
823
 
824
		#region core methods
825
 
826
		private LogLevel ParseLogLevel(string str)
827
		{
828
			if(str == "Important")
829
				return LogLevel.Important;
830
			else if(str == "Info")
831
				return LogLevel.Info;
832
			else
833
				return LogLevel.Debug;
834
		}
835
 
836
		private void LoadFromRegistry()
837
		{
838
			Microsoft.Win32.RegistryKey subkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(
839
				REGISTRY_KEY);
840
 
841
			if(subkey == null) return;
842
 
843
			listenPort           = (int)subkey.GetValue("Listen Port", 0);
844
			resendHost           = (string)subkey.GetValue("Resend Host", "");
845
			resendPort           = (int)subkey.GetValue("Resend Port", 0);
846
			logMessages.Level    = ParseLogLevel((string)subkey.GetValue("Messages Level", ""));
847
			autoExpand           = (int)subkey.GetValue("Auto Expand", 1) == 1;
848
			messagesBox.WordWrap = (int)subkey.GetValue("Word Wrap", 1) == 1;
849
 
850
			object tcpShowModeStr  = (object)subkey.GetValue("Tcp Show Mode", TcpShowMode.ByDirection);
851
			tcpShowMode            = (tcpShowModeStr as string) == "ByDirection"
852
				? TcpShowMode.ByDirection : TcpShowMode.ByTime;
853
 
854
			int winTop  = (int)subkey.GetValue("Window.Top",  -1);
855
			int winLeft = (int)subkey.GetValue("Window.Left", -1);
856
 
857
			if(winTop == -1 || winLeft == -1) {
858
				this.StartPosition = FormStartPosition.WindowsDefaultBounds;
859
			}
860
			else {
861
				this.Top  = winTop;
862
				this.Left = winLeft;
863
				this.ClientSize = new Size(
864
					(int)subkey.GetValue("Window.Width", this.ClientSize.Width),
865
					(int)subkey.GetValue("Window.Hight", this.ClientSize.Height));
866
				this.messageView.Width 
867
					= (int)subkey.GetValue("Splitter.Left",   this.messageView.Width);
868
				this.logBox.Height     
869
					= (int)subkey.GetValue("Splitter.Bottom", this.logBox.Height);
870
			}
871
		}
872
 
873
		private void LoadRecentItemsFromRegistry()
874
		{
875
			Microsoft.Win32.RegistryKey subkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(
876
				REGISTRY_KEY + @"\" + REGISTRY_RECENT_SUBKEY);
877
 
878
			if(subkey == null) return;
879
 
880
			foreach(string name in subkey.GetValueNames()) {
881
				if(name == "") continue;
882
				AddRecentItem(RecentItem.LoadFromRegistry((string)subkey.GetValue(name, "")));
883
			}
884
		}
885
 
886
		private void SaveToRegistry()
887
		{
888
			Microsoft.Win32.RegistryKey subkey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(
889
				REGISTRY_KEY);
890
 
891
			subkey.SetValue("Listen Port",    listenPort);
892
			subkey.SetValue("Resend Host",    resendHost == null ? "" : resendHost);
893
			subkey.SetValue("Resend Port",    resendPort);
894
			subkey.SetValue("Messages Level", logMessages.Level);
895
			subkey.SetValue("Tcp Show Mode",  tcpShowMode);
896
			subkey.SetValue("Auto Expand",    autoExpand ? 1 : 0);
897
			subkey.SetValue("Word Wrap",      messagesBox.WordWrap ? 1 : 0);
898
 
899
			subkey.SetValue("Window.Top",      this.Top);
900
			subkey.SetValue("Window.Left",     this.Left);
901
			subkey.SetValue("Window.Hight",    this.ClientSize.Height);
902
			subkey.SetValue("Window.Width",    this.ClientSize.Width);
903
			subkey.SetValue("Splitter.Left",   this.messageView.Width);
904
			subkey.SetValue("Splitter.Bottom", this.logBox.Height);
905
		}
906
 
907
		private void SaveRecentItemsToRegistry()
908
		{
909
			Microsoft.Win32.RegistryKey subkey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(
910
				REGISTRY_KEY + @"\" + REGISTRY_RECENT_SUBKEY);
911
 
912
			// load existing from registry
913
			ArrayList old = new ArrayList();
914
			foreach(string name in subkey.GetValueNames()) {
915
				if(name == "") continue;
916
				old.Add(RecentItem.LoadFromRegistry((string)subkey.GetValue(name, "")));
917
			}
918
 
919
			// merge - for the case another program instance has changed the list
920
			foreach(RecentItem item in old) {
921
				int existingIdx = recentItems.IndexOf(item);
922
				if(existingIdx >= 0)
923
					((RecentItem)recentItems[existingIdx]).UpdateTimestamp(item);
924
				else
925
					recentItems.Add(item);
926
			}
927
 
928
			recentItems.Sort();
929
			if(recentItems.Count > 0) // take tail
930
				recentItems = recentItems.GetRange(Math.Max(0, recentItems.Count - RECENT_LENGTH),
931
					Math.Min(recentItems.Count, RECENT_LENGTH));
932
 
933
			int count = 0;
934
			foreach(RecentItem item in recentItems) {
935
				subkey.SetValue(string.Format("{0:0000}", count++), item.SaveToRegistry());
936
			}
937
		}
938
 
1194 dev 939
		private void UpdateMessagesMenuItems()
940
		{
941
			switch(logMessages.Level) {
942
				case LogLevel.Critical:
943
				case LogLevel.Error:
944
				case LogLevel.Warning:
945
				case LogLevel.Important:
946
					importantMessagesMenuItem.Checked = true;
947
					infoMessagesMenuItem.Checked      = false;
948
					allMessagesMenuItem.Checked       = false;
949
					break;
950
 
951
				case LogLevel.Info:
952
					importantMessagesMenuItem.Checked = false;
953
					infoMessagesMenuItem.Checked      = true;
954
					allMessagesMenuItem.Checked       = false;
955
					break;
956
 
957
				case LogLevel.Debug:
958
					importantMessagesMenuItem.Checked = false;
959
					infoMessagesMenuItem.Checked      = false;
960
					allMessagesMenuItem.Checked       = true;
961
					break;
962
			}
963
		}
964
 
965
		private void AddRecentItem(int listenPort, string resendHost, int resendPort)
966
		{
967
			RecentItem recentItem = new RecentItem(listenPort, resendHost, resendPort);
968
			recentItem.UpdateTimestamp();
969
			AddRecentItem(recentItem);
970
		}
971
 
972
		private void AddRecentItem(RecentItem recentItem)
973
		{
974
			int existingIdx = recentItems.IndexOf(recentItem);
975
			if(existingIdx >= 0) {
1198 dev 976
				recentItems.RemoveAt(existingIdx);
977
				this.recentListeningMenu.MenuItems.RemoveAt(recentItems.Count - existingIdx);
1194 dev 978
			}
979
 
1198 dev 980
			if(recentItems.Count == 0 && this.recentListeningMenu.MenuItems.Count == 1)
1197 dev 981
				this.recentListeningMenu.MenuItems.RemoveAt(0);
982
 
1194 dev 983
			recentItems.Add(recentItem);
984
 
1197 dev 985
			MenuItem menuItem = new MenuItem();
986
			this.recentListeningMenu.MenuItems.Add(0, menuItem);
1199 dev 987
			menuItem.Text   = string.Format("&1 {0} to {1}:{2}",
1194 dev 988
				recentItem.ListenPort, recentItem.ResendHost, recentItem.ResendPort);
989
			menuItem.Click += new System.EventHandler(recentMenuItem_Click);
1198 dev 990
 
991
			// check overflow
992
			if(recentItems.Count > RECENT_LENGTH) {
993
				recentItems.RemoveAt(0);
994
				this.recentListeningMenu.MenuItems.RemoveAt(RECENT_LENGTH-1);
995
			}
1199 dev 996
 
997
			// update hot keys of old items
998
			int count = 0;
999
			foreach(MenuItem item in this.recentListeningMenu.MenuItems) {
1000
				if(count == 0) {
1001
				}
1002
				else if(count < 10)
1003
					item.Text = string.Format("&{3} {0} to {1}:{2}", recentItem.ListenPort, 
1004
						recentItem.ResendHost, recentItem.ResendPort, count + 1);
1005
				else
1006
					item.Text = string.Format("{0} to {1}:{2}", recentItem.ListenPort, 
1007
						recentItem.ResendHost, recentItem.ResendPort);
1008
				count++;
1009
			}
1194 dev 1010
		}
1011
 
1199 dev 1012
		private void ClearAll()
1013
		{
1014
			// close all connetions
1015
			foreach(object tcp in treeNodes.Keys)
1016
				if(tcp is TcpConnection)
1017
					((TcpConnection)tcp).Cancel();
1092 dev 1018
 
1199 dev 1019
			// FIXME wait for all log messages from network part
1020
 
1021
			treeNodes.Clear();
1022
			messageView.Nodes.Clear();
1023
			messagesBox.Clear();
1024
			logMessages.Clear();
1025
		}
1026
 
1092 dev 1027
		private void Start(int listenPort, IPAddress resendHost, int resendPort)
1028
		{
1029
			if(tcpListener != null) tcpListener.StopListening();
1030
 
1031
			tcpListener = new TcpListener(listenPort, resendHost, resendPort);
1032
			tcpListener.Log    += new TcpLogEventHandler(TcpConnectionLog);
1033
			tcpListener.NewTcp += new TcpConnectionEventHandler(AddTcpConnetion);
1034
			tcpListener.StartListening();
1035
		}
1036
 
1199 dev 1037
		private void StartListening(int listenPort, IPAddress resendIp, int resendPort)
1038
		{
1039
			// listen to the port
1040
			try
1041
			{
1042
				Start(listenPort, resendIp, resendPort);
1043
			}
1044
			catch(Exception ex)
1045
			{
1046
				MessageBox.Show("Cannot start listening: " + ex.Message, "TCPproxy",
1047
					MessageBoxButtons.OK, MessageBoxIcon.Error);
1048
				Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1049
				return;
1050
			}
1051
 
1052
			AddRecentItem(listenPort, resendHost, resendPort);
1053
 
1054
			startMenuItem.Enabled = false;
1055
			stopMenuItem.Enabled  = true;
1056
 
1057
			foreach(MenuItem subitem in recentListeningMenu.MenuItems) {
1058
				subitem.Enabled = false;
1059
			}
1060
 
1061
			this.Text = string.Format("{0}: {1} to {2}:{3}",
1062
				defaultCaption, listenPort, resendHost, resendPort);
1063
		}
1064
 
1065
		private void StopListening()
1066
		{
1067
			if(tcpListener != null) tcpListener.StopListening();
1068
 
1069
			startMenuItem.Enabled = true;
1070
			stopMenuItem.Enabled  = false;
1071
 
1072
			if(recentItems.Count > 0) {
1073
				foreach(MenuItem subitem in recentListeningMenu.MenuItems) {
1074
					subitem.Enabled = true;
1075
				}
1076
			}
1077
 
1078
			this.Text = defaultCaption;
1079
		}
1080
 
1092 dev 1081
		private void CloseTcpConnection(TcpConnection tcp)
1082
		{
1083
			if(tcp == null) return;
1084
 
1085
			tcp.Cancel();
1086
		}
1087
 
1088
		private void SaveLog(string fileName)
1089
		{
1090
			StreamWriter writer = new StreamWriter(fileName);
1091
 
1092
			foreach(LogMessage message in logMessages.Messages)
1093
			{
1094
				writer.WriteLine(message);
1095
			}
1096
 
1097
			writer.Close();
1098
		}
1099
 
1100
		private void SaveTcp(string fileName)
1101
		{
1102
			StreamWriter writer = new StreamWriter(fileName);
1103
 
1104
			foreach(TreeNode tcpNode in messageView.Nodes)
1105
			{
1106
				TcpNodeData data = (TcpNodeData)tcpNode.Tag;
1107
				data.WriteLog(writer);
1108
			}
1109
 
1110
			writer.Close();
1111
		}
1112
 
1113
		private void SaveHttp(string fileName)
1114
		{
1115
			StreamWriter writer = new StreamWriter(fileName);
1116
 
1117
			foreach(TreeNode tcpNode in messageView.Nodes)
1118
			{
1119
				foreach(TreeNode httpNode in tcpNode.Nodes)
1120
				{
1121
					HttpNodeData data = (HttpNodeData)httpNode.Tag;
1122
					data.WriteLog(writer);
1123
				}
1124
			}
1125
 
1126
			writer.Close();
1127
		}
1128
 
1129
		private void SaveXml(string fileName)
1130
		{
1131
			StreamWriter writer = new StreamWriter(fileName);
1132
 
1133
			foreach(TreeNode tcpNode in messageView.Nodes)
1134
			{
1135
				foreach(TreeNode httpNode in tcpNode.Nodes)
1136
				{
1137
					foreach(TreeNode xmlNode in httpNode.Nodes)
1138
					{
1139
						XmlNodeData data = (XmlNodeData)xmlNode.Tag;
1140
						data.WriteLog(writer);
1141
					}
1142
				}
1143
			}
1144
 
1145
			writer.Close();
1146
		}
1147
 
1199 dev 1148
		private void SaveBinLog(string fileName)
1149
		{
1150
			FileStream   file   = new FileStream(fileName, FileMode.Create);
1151
			BinaryWriter writer = new BinaryWriter(file);
1152
 
1153
			// header
1154
			writer.Write(Encoding.ASCII.GetBytes(LOG_BIN_HEADER));
1155
			writer.Write(LOG_TYPE_BIN);
1156
 
1157
			// for each tcp connection
1158
			foreach(TreeNode tcpNode in messageView.Nodes)
1159
				((TcpNodeData)tcpNode.Tag).Tcp.WriteBinLog(writer);
1160
 
1161
			// end of stream
1162
			writer.Write((byte)BinLogTypes.None);
1163
 
1164
			writer.Close();
1165
			file.Close();
1166
		}
1167
 
1168
		private void LoadBinLog(string fileName)
1169
		{
1170
			StopListening();
1171
			ClearAll();
1172
 
1173
			FileStream   file   = new FileStream(fileName, FileMode.Open);
1174
			BinaryReader reader = new BinaryReader(file);
1175
 
1176
			// header
1177
			byte[] bufExpect = Encoding.ASCII.GetBytes(LOG_BIN_HEADER);
1178
			if(file.Length < bufExpect.Length + sizeof(byte))
1179
				throw new Exception("The file is too short");
1180
 
1181
			byte[] bufRead = reader.ReadBytes(bufExpect.Length);
1182
			for(int i = 0; i < bufRead.Length; i++)
1183
				if(bufRead[i] != bufExpect[i])
1184
					throw new Exception("Wrong header of the file");
1185
 
1186
			if(reader.ReadByte() != LOG_TYPE_BIN)
1187
				throw new Exception("Unknown log type");
1188
 
1189
			tcpListener = new TcpListener(0, null, 0);
1190
			tcpListener.Log    += new TcpLogEventHandler(TcpConnectionLog);
1191
			tcpListener.NewTcp += new TcpConnectionEventHandler(AddTcpConnetion);
1192
			tcpListener.ReadBinLog(reader); // it will send us usual event
1193
 
1194
			reader.Close();
1195
			file.Close();
1196
		}
1197
 
1092 dev 1198
		#endregion core methods
1199
 
1200
		#region network events handlers
1201
		private void TcpConnectionLog(object sender, TcpLogEventArgs e)
1202
		{
1125 dev 1203
			lock(this)
1204
			{
1205
				TcpConnection tcp = sender as TcpConnection;
1206
				LogMessage message = new LogMessage(tcp, e.Level, e.Message, e.Exception);
1092 dev 1207
 
1125 dev 1208
				try
1209
				{
1210
					this.BeginInvoke(new AddLogMessageHandler(AddLogMessageInternal), new object[] { message } );
1211
				}
1212
				catch(InvalidOperationException ex)
1213
				{
1214
					if(!this.Disposing && !this.IsDisposed)
1215
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1216
				}
1092 dev 1217
			}
1218
		}
1219
 
1220
		private void AddTcpConnetion(object sender, TcpConnectionEventArgs e)
1221
		{
1125 dev 1222
			lock(this)
1223
			{
1224
				e.Tcp.Log     += new TcpLogEventHandler(TcpConnectionLog);
1225
				e.Tcp.Update  += new TcpEventHandler(UpdateTcpNode);
1226
				e.Tcp.Close   += new TcpEventHandler(UpdateTcpNode);
1227
				e.Tcp.NewHttp += new TcpHttpEventHandler(AddHttpMessageNode);
1092 dev 1228
 
1125 dev 1229
				try
1230
				{
1231
					this.BeginInvoke(new AddTcpNodeHandler(AddTcpNodeInternal), new object[] { e.Tcp } );
1232
				}
1233
				catch(InvalidOperationException ex)
1234
				{
1235
					if(!this.Disposing && !this.IsDisposed)
1236
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1237
				}
1092 dev 1238
			}
1239
		}
1240
 
1241
		private void UpdateTcpNode(object sender, TcpEventArgs e)
1242
		{
1125 dev 1243
			lock(this)
1092 dev 1244
			{
1125 dev 1245
				try
1246
				{
1247
					this.BeginInvoke(new UpdateTcpNodeHandler(UpdateTcpNodeInternal), new object[] { (TcpConnection)sender } );
1248
				}
1249
				catch(InvalidOperationException ex)
1250
				{
1251
					if(!this.Disposing && !this.IsDisposed)
1252
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1253
				}
1092 dev 1254
			}
1255
		}
1256
 
1257
		private void AddHttpMessageNode(object sender, TcpHttpEventArgs e)
1258
		{
1125 dev 1259
			lock(this)
1260
			{
1261
				e.Http.Update += new TcpEventHandler(UpdateHttpNode);
1092 dev 1262
 
1125 dev 1263
				try
1264
				{
1265
					this.BeginInvoke(new AddHttpNodeHandler(AddHttpNodeInternal),
1266
						new object[] { (TcpConnection)sender, e.Http } );
1267
				}
1268
				catch(InvalidOperationException ex)
1269
				{
1270
					if(!this.Disposing && !this.IsDisposed)
1271
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1272
				}
1092 dev 1273
			}
1274
		}
1275
 
1276
		private void UpdateHttpNode(object sender, TcpEventArgs e)
1277
		{
1125 dev 1278
			lock(this)
1092 dev 1279
			{
1125 dev 1280
				try
1281
				{
1282
					this.BeginInvoke(new UpdateHttpNodeHandler(UpdateHttpNodeInternal), new object[] { (HttpMessage)sender } );
1283
				}
1284
				catch(InvalidOperationException ex)
1285
				{
1286
					if(!this.Disposing && !this.IsDisposed)
1287
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1288
				}
1092 dev 1289
			}
1290
		}
1291
 
1292
		#endregion network events handlers
1293
 
1294
		#region handlers for async GUI events
1295
		private delegate void AddLogMessageHandler(LogMessage message);
1296
		private delegate void AddTcpNodeHandler(TcpConnection tcp);
1297
		private delegate void UpdateTcpNodeHandler(TcpConnection tcp);
1298
		private delegate void AddHttpNodeHandler(TcpConnection tcp, HttpMessage http);
1299
		private delegate void UpdateHttpNodeHandler(HttpMessage http);
1300
 
1301
		private void AddLogMessageInternal(LogMessage message)
1302
		{
1303
			logMessages.Add(message);
1304
 
1305
			if(message.Exception != null)
1306
			{
1307
				Console.WriteLine(message.Exception.Message + " (" + message.Exception.GetType().Name
1308
					+ ")\n" + message.Exception.StackTrace);
1309
			}
1310
		}
1311
 
1312
		private void AddTcpNodeInternal(TcpConnection tcp)
1313
		{
1314
			TreeNode    treeNode = new TreeNode(tcp.ToString());
1315
			TcpNodeData data     = new TcpNodeData(this, treeNode);
1316
 
1317
			data.Tcp = tcp;
1318
			treeNode.Tag                = data;
1199 dev 1319
			treeNode.ImageIndex         = (tcp.LocalState == SocketState.Closed 
1320
				&& tcp.RemoteState == SocketState.Closed) ? 2 : 1;
1321
			treeNode.SelectedImageIndex = treeNode.ImageIndex;
1092 dev 1322
			treeNodes[tcp] = data;
1323
 
1324
			messageView.Nodes.Add(treeNode);
1325
			treeNode.EnsureVisible();
1326
		}
1327
 
1328
		private void UpdateTcpNodeInternal(TcpConnection tcp)
1329
		{
1330
			TcpNodeData data = treeNodes[tcp] as TcpNodeData;
1125 dev 1331
			if(data == null) return; // might be call by Cancel
1092 dev 1332
 
1333
			string title = tcp.ToString();
1334
			if(title != data.Node.Text) data.Node.Text = title;
1335
			if(tcp.LocalState == SocketState.Closed && tcp.RemoteState == SocketState.Closed)
1336
			{
1337
				data.Node.ImageIndex         = 2;
1199 dev 1338
				data.Node.SelectedImageIndex = data.Node.ImageIndex;
1092 dev 1339
			}
1340
 
1341
			if(messageView.SelectedNode == null || data != messageView.SelectedNode.Tag)
1342
				data.ViewExpired = true;  // got update for invisible TCP node, update it later
1343
			else
1344
				data.Show();
1345
		}
1346
 
1347
		private void AddHttpNodeInternal(TcpConnection tcp, HttpMessage http)
1348
		{
1349
			TreeNode     treeNode = new TreeNode(http.ToString());
1350
			HttpNodeData data     = new HttpNodeData(this, treeNode);
1351
 
1352
			data.Http = http;
1353
			treeNode.Tag = data;
1354
			treeNodes[http] = data;
1355
 
1356
			TcpNodeData tcpData = treeNodes[tcp] as TcpNodeData;
1357
			if(tcpData == null) throw new ArgumentException("No node found for TCP message");
1358
 
1359
			tcpData.Node.Nodes.Add(treeNode);
1360
			if(autoExpand) tcpData.Node.Expand();
1361
			tcpData.Node.EnsureVisible();
1362
		}
1363
 
1364
		private void UpdateHttpNodeInternal(HttpMessage http)
1365
		{
1366
			HttpNodeData httpData = treeNodes[http] as HttpNodeData;
1125 dev 1367
			if(httpData == null) return; // might be call by Cancel
1092 dev 1368
 
1369
			string title = http.ToString();
1370
			if(httpData.Node.Text != title) httpData.Node.Text = title;
1371
 
1372
			if(!httpData.RequestXmlShown && http.RequestXml != null)
1373
			{
1374
				httpData.RequestXmlShown = true;
1375
				AddXmlNode(httpData.Node, "Request XML", http.RequestXml);
1376
				if(autoExpand) httpData.Node.Expand();
1377
			}
1378
 
1379
			if(!httpData.ResponseXmlShown && http.ResponseXml != null)
1380
			{
1381
				httpData.ResponseXmlShown = true;
1382
				AddXmlNode(httpData.Node, "Response XML", http.ResponseXml);
1383
				if(autoExpand) httpData.Node.Expand();
1384
			}
1385
 
1386
			// update text view
1387
			if(messageView.SelectedNode == null || httpData != messageView.SelectedNode.Tag)
1388
				httpData.ViewExpired = true;
1389
			else
1390
				httpData.Show();
1391
		}
1392
 
1393
		private void AddXmlNode(TreeNode parent, string title, XmlMessage xml)
1394
		{
1395
			TreeNode    treeNode = new TreeNode(title);
1396
			XmlNodeData data = new XmlNodeData(this, treeNode);
1397
 
1398
			data.Xml       = xml;
1399
			treeNode.Tag   = data;
1400
			treeNodes[xml] = data;
1401
 
1402
			parent.Nodes.Add(treeNode);
1403
		}
1404
 
1405
		#endregion handlers for async GUI events
1406
 
1407
		#region node display classes
1408
		private abstract class TreeNodeData
1409
		{
1410
			protected TreeNode node;
1411
			protected object   viewState;
1412
			protected bool     viewExpired;
1413
			protected MainForm owner;
1414
			protected bool     shown = false;
1415
 
1416
			public TreeNode Node
1417
			{
1418
				get { return node; }
1419
			}
1420
 
1421
			public TreeNodeData(MainForm owner, TreeNode node)
1422
			{
1423
				this.owner = owner;
1424
				this.node  = node;
1425
			}
1426
 
1427
			public bool ViewExpired
1428
			{
1429
				get { return viewExpired; }
1430
				set { viewExpired = value; }
1431
			}
1432
 
1433
			public void SaveViewState()
1434
			{
1435
				viewState = owner.messagesBox.SaveState(false);
1436
			}
1437
 
1438
			protected virtual bool ForceInitView()
1439
			{
1440
				return false;
1441
			}
1442
 
1443
			protected abstract void InitView();
1444
			protected abstract void UpdateView();
1445
 
1446
			public void Show()
1447
			{
1448
				if(!shown || viewState == null || ForceInitView())
1449
				{
1450
					InitView();
1451
					shown = true;
1452
					if(viewState == null) viewState = owner.messagesBox.SaveState(false);
1453
				}
1454
				else
1455
				{
1456
					owner.messagesBox.RestoreState(viewState, true);
1457
					if(viewExpired) UpdateView();
1458
				}
1459
			}
1460
 
1461
			public abstract void WriteLog(StreamWriter writer);
1462
		}
1463
 
1464
		private class TcpNodeData : TreeNodeData
1465
		{
1466
			private TcpConnection tcp;
1467
 
1468
			private TcpShowMode lastShowMode;
1469
			private object      localStateMarker  = null;
1470
			private object      remoteStateMarker = null;
1471
			private object      startMarker       = null;
1472
			private object      localEndMarker    = null;
1473
			private object      remoteEndMarker   = null;
1474
			private object      clientMarker      = null;
1475
			private object      serverMarker      = null;
1476
			private object      sentMarker        = null;
1477
			private object      receivedMarker    = null;
1478
			private object      textMarker1       = null;
1479
			private object      textMarker2       = null;
1480
			private IEnumerator messagesEnum      = null;
1481
 
1482
			public TcpConnection Tcp
1483
			{
1484
				get { return tcp; }
1485
				set { tcp = value; }
1486
			}
1487
 
1488
			public TcpNodeData(MainForm owner, TreeNode node)	: base(owner, node)
1489
			{
1490
			}
1491
 
1492
 
1493
			protected override bool ForceInitView()
1494
			{
1495
				return (lastShowMode != owner.tcpShowMode);
1496
			}
1497
 
1498
			protected override void InitView()
1499
			{
1500
				lastShowMode = owner.tcpShowMode;
1501
 
1502
				try
1503
				{
1504
					owner.messagesBox.BeginUpdate();
1505
 
1506
					lock(tcp)
1507
					{
1508
						owner.messagesBox.Clear();
1509
 
1510
						owner.messagesBox.AppendNewLine();
1511
						owner.messagesBox.AppendText("ID:         ",
1512
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1513
						owner.messagesBox.AppendText(tcp.Id,
1514
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1515
						owner.messagesBox.AppendNewLine();
1516
 
1517
						owner.messagesBox.AppendText("State:      ",
1518
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1519
						localStateMarker = owner.messagesBox.BeginMark();
1520
						owner.messagesBox.AppendText(tcp.LocalState.ToString(),
1521
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1522
						owner.messagesBox.EndMark(localStateMarker);
1523
						owner.messagesBox.AppendText(null,
1524
							Color.DarkRed, Color.Transparent, false, false, 1, 12);
1525
						remoteStateMarker = owner.messagesBox.BeginMark();
1526
						owner.messagesBox.AppendText(tcp.RemoteState.ToString(),
1527
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1528
						owner.messagesBox.EndMark(remoteStateMarker);
1529
						owner.messagesBox.AppendNewLine();
1530
 
1531
						owner.messagesBox.AppendText("Start:      ",
1532
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1533
						startMarker = owner.messagesBox.BeginMark();
1534
						owner.messagesBox.AppendText(tcp.StartTimestamp.ToString("HH:mm:ss.ffff"),
1535
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1536
						owner.messagesBox.EndMark(startMarker);
1537
						owner.messagesBox.AppendNewLine();
1538
						owner.messagesBox.AppendText("Local End:  ",
1539
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1540
						localEndMarker = owner.messagesBox.BeginMark();
1541
						owner.messagesBox.AppendText(tcp.LocalEndTimestamp.ToString("HH:mm:ss.ffff"),
1542
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1543
						owner.messagesBox.EndMark(localEndMarker);
1544
						owner.messagesBox.AppendNewLine();
1545
						owner.messagesBox.AppendText("Remote End: ",
1546
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1547
						remoteEndMarker = owner.messagesBox.BeginMark();
1548
						owner.messagesBox.AppendText(tcp.RemoteEndTimestamp.ToString("HH:mm:ss.ffff"),
1549
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1550
						owner.messagesBox.EndMark(remoteEndMarker);
1551
						owner.messagesBox.AppendNewLine();
1552
 
1553
						owner.messagesBox.AppendText("Client:     ",
1554
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1555
						clientMarker = owner.messagesBox.BeginMark();
1556
						owner.messagesBox.AppendText((tcp.LocalPoint == null) ? "" : tcp.LocalPoint.ToString(),
1557
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1558
						owner.messagesBox.EndMark(clientMarker);
1559
						owner.messagesBox.AppendNewLine();
1560
						owner.messagesBox.AppendText("Server:     ",
1561
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1562
						serverMarker = owner.messagesBox.BeginMark();
1563
						owner.messagesBox.AppendText((tcp.RemotePoint == null) ? "" : tcp.RemotePoint.ToString(),
1564
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1565
						owner.messagesBox.EndMark(serverMarker);
1566
						owner.messagesBox.AppendNewLine();
1567
 
1568
						owner.messagesBox.AppendText("Sent:       ",
1569
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1570
						sentMarker = owner.messagesBox.BeginMark();
1571
						owner.messagesBox.AppendText(tcp.SentBytes.ToString(),
1572
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1573
						owner.messagesBox.EndMark(sentMarker);
1574
						owner.messagesBox.AppendNewLine();
1575
						owner.messagesBox.AppendText("Received:   ",
1576
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1577
						receivedMarker = owner.messagesBox.BeginMark();
1578
						owner.messagesBox.AppendText(tcp.ReceivedBytes.ToString(),
1579
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1580
						owner.messagesBox.EndMark(receivedMarker);
1581
						owner.messagesBox.AppendNewLine();
1582
						owner.messagesBox.AppendNewLine();
1583
 
1584
						messagesEnum = tcp.Messages.GetEnumerator();
1585
 
1586
						textMarker1 = owner.messagesBox.BeginMark();
1587
						owner.messagesBox.EndMark(textMarker1);
1588
 
1589
						owner.messagesBox.AppendNewLine();
1590
						textMarker2 = owner.messagesBox.BeginMark();
1591
						owner.messagesBox.EndMark(textMarker2);
1592
 
1593
						ShowMessages();
1594
					}
1595
				}
1596
				finally
1597
				{
1598
					owner.messagesBox.EndUpdate();
1599
				}
1600
			}
1601
 
1602
			protected override void UpdateView()
1603
			{
1604
				try
1605
				{
1606
					owner.messagesBox.BeginUpdate();
1607
 
1608
					lock(tcp)
1609
					{
1610
						owner.messagesBox.ChangeText(localStateMarker, tcp.LocalState.ToString(),
1611
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1612
						owner.messagesBox.ChangeText(remoteStateMarker, tcp.RemoteState.ToString(),
1613
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1614
 
1615
						owner.messagesBox.ChangeText(startMarker, tcp.StartTimestamp.ToString("HH:mm:ss.ffff"),
1616
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1617
						owner.messagesBox.ChangeText(localEndMarker, tcp.LocalEndTimestamp.ToString("HH:mm:ss.ffff"),
1618
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1619
						owner.messagesBox.ChangeText(remoteEndMarker, tcp.RemoteEndTimestamp.ToString("HH:mm:ss.ffff"),
1620
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1621
 
1622
						owner.messagesBox.ChangeText(clientMarker, (tcp.LocalPoint == null) ? "" : tcp.LocalPoint.ToString(),
1623
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1624
						owner.messagesBox.ChangeText(serverMarker, (tcp.RemotePoint == null) ? "" : tcp.RemotePoint.ToString(),
1625
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1626
 
1627
						owner.messagesBox.ChangeText(sentMarker, tcp.SentBytes.ToString(),
1628
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1629
						owner.messagesBox.ChangeText(receivedMarker, tcp.ReceivedBytes.ToString(),
1630
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1631
 
1632
						ShowMessages();
1633
					}
1634
				}
1635
				finally
1636
				{
1637
					owner.messagesBox.EndUpdate();
1638
				}
1639
			}
1640
 
1641
			private void ShowMessages()
1642
			{
1643
				while(messagesEnum.MoveNext())
1644
				{
1645
					TcpMessage message = (TcpMessage)messagesEnum.Current;
1646
					object     marker  = (owner.tcpShowMode == TcpShowMode.ByTime
1647
						|| message.Direction == TcpMessageDirection.Local) ? textMarker1 : textMarker2;
1648
 
1649
					if(owner.tcpShowMode == TcpShowMode.ByTime)
1650
					{
1651
						owner.messagesBox.InsertText(marker,
1652
							message.Timestamp.ToString("HH:mm:ss.ffff") + " ("	+ message.Length + ")",
1653
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1654
						owner.messagesBox.InsertNewLine(marker);
1655
					}
1656
 
1657
					string str = Utils.BytesToString(message.Bytes, message.Length);
1658
					ArrayList lines = Utils.SplitLine(str);
1659
					for(int i = 0; i < lines.Count; i++)
1660
					{
1661
						owner.messagesBox.InsertText(marker, (string)lines[i],
1662
							message.Direction == TcpMessageDirection.Local ? Color.Green : Color.Blue,
1663
							Color.LightGray, false, false, 0, 0);
1664
 
1665
						if(owner.tcpShowMode == TcpShowMode.ByTime || i != lines.Count - 1)
1666
							owner.messagesBox.InsertNewLine(marker);
1667
					}
1668
				}
1669
			}
1670
 
1671
			public override void WriteLog(StreamWriter writer)
1672
			{
1673
				writer.WriteLine(
1674
					"Start:      " + tcp.StartTimestamp.ToString("HH:mm:ss.ffff")
1675
					+ "\r\nLocal End:  " + tcp.LocalEndTimestamp.ToString("HH:mm:ss.ffff")
1676
					+ "\r\nRemote End: " + tcp.RemoteEndTimestamp.ToString("HH:mm:ss.ffff")
1677
					+ "\r\nClient:     " + ((tcp.LocalPoint  == null) ? "" : tcp.LocalPoint.ToString())
1678
					+ "\r\nServer:     " + ((tcp.RemotePoint == null) ? "" : tcp.RemotePoint.ToString())
1679
					+ "\r\nSent:       " + tcp.SentBytes
1680
					+ "\r\nReceived:   " + tcp.ReceivedBytes);
1681
 
1682
				foreach(TcpMessage message in tcp.Messages)
1683
				{
1684
					string str = Utils.BytesToString(message.Bytes, message.Length);
1685
					if(!str.EndsWith("\n")) str += "\r\n";
1686
 
1687
					writer.WriteLine();
1688
					if(message.Direction == TcpMessageDirection.Local)
1689
						writer.WriteLine(">>> {0:HH:mm:ss.ffff} >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", message.Timestamp);
1690
					else
1691
						writer.WriteLine("<<< {0:HH:mm:ss.ffff} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", message.Timestamp);
1692
					writer.Write(str);
1693
				}
1694
				writer.WriteLine("===============================================================");
1695
				writer.WriteLine();
1696
			}
1697
		}
1698
 
1699
		private class HttpNodeData : TreeNodeData
1700
		{
1701
			private HttpMessage http;
1702
			private bool        requestXmlShown  = false;
1703
			private bool        responseXmlShown = false;
1704
 
1705
			private object      stateMarker               = null;
1125 dev 1706
			private object      requestStartMarker        = null;
1092 dev 1707
			private object      requestMethodMarker       = null;
1708
			private object      requestUriMarker          = null;
1709
			private object      requestVersionMarker      = null;
1710
			private object      requestLengthMarker       = null;
1711
			private object      requestEncodingMarker     = null;
1712
			private object      requestContentTypeMarker  = null;
1713
			private object      requestCharsetMarker      = null;
1714
			private object      requestHeadersMarker      = null;
1125 dev 1715
			private object      responseStartMarker       = null;
1092 dev 1716
			private object      responseVersionMarker     = null;
1717
			private object      responseStatusMarker      = null;
1718
			private object      responseLengthMarker      = null;
1719
			private object      responseEncodingMarker    = null;
1720
			private object      responseContentTypeMarker = null;
1721
			private object      responseCharsetMarker     = null;
1722
			private object      responseHeadersMarker     = null;
1723
			private object      requestBodyMarker         = null;
1724
			private object      responseBodyMarker        = null;
1725
			private IEnumerator requestHeadersEnum        = null;
1726
			private IEnumerator responseHeadersEnum       = null;
1727
 
1728
			public HttpMessage Http
1729
			{
1730
				get { return http; }
1731
				set { http = value; }
1732
			}
1733
 
1734
			public bool RequestXmlShown
1735
			{
1736
				get { return requestXmlShown; }
1737
				set { requestXmlShown = value; }
1738
			}
1739
 
1740
			public bool ResponseXmlShown
1741
			{
1742
				get { return responseXmlShown; }
1743
				set { responseXmlShown = value; }
1744
			}
1745
 
1746
			public HttpNodeData(MainForm owner, TreeNode node) : base(owner, node)
1747
			{
1748
			}
1749
 
1750
			private string EncodingToString(HttpEncoding encoding)
1751
			{
1752
				switch(encoding)
1753
				{
1754
					case HttpEncoding.Identify: return "identify";
1755
					case HttpEncoding.Gzip:     return "gzip";
1756
					case HttpEncoding.Compress: return "compress";
1757
					case HttpEncoding.Deflate:  return "deflate";
1758
					default:                    return "<unknown>";
1759
				}
1760
			}
1761
 
1762
			protected override void InitView()
1763
			{
1764
				try
1765
				{
1766
					lock(http)
1767
					{
1768
						owner.messagesBox.Clear();
1769
 
1770
						owner.messagesBox.AppendNewLine();
1771
						owner.messagesBox.AppendText("Complete:                  ",
1772
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1773
						stateMarker = owner.messagesBox.BeginMark();
1774
						owner.messagesBox.AppendText(http.RequestComplete && http.ResponseComplete ? "YES" : "NO",
1775
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1776
						owner.messagesBox.EndMark(stateMarker);
1777
						owner.messagesBox.AppendNewLine();
1778
						owner.messagesBox.AppendNewLine();
1779
 
1780
						// request info
1125 dev 1781
						owner.messagesBox.AppendText("Request Start:             ",
1782
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1783
						requestStartMarker = owner.messagesBox.BeginMark();
1784
						owner.messagesBox.AppendText(http.RequestStartTimestamp == DateTime.MinValue
1785
							? "<unknown>" : http.RequestStartTimestamp.ToString("HH:mm:ss.ffff"),
1786
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1787
						owner.messagesBox.EndMark(requestStartMarker);
1788
						owner.messagesBox.AppendNewLine();
1789
 
1092 dev 1790
						owner.messagesBox.AppendText("Request Method:            ",
1791
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1792
						requestMethodMarker = owner.messagesBox.BeginMark();
1793
						owner.messagesBox.AppendText(http.RequestMethod,
1794
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1795
						owner.messagesBox.EndMark(requestMethodMarker);
1796
						owner.messagesBox.AppendNewLine();
1797
 
1798
						owner.messagesBox.AppendText("Request URI:               ",
1799
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1800
						requestUriMarker = owner.messagesBox.BeginMark();
1801
						owner.messagesBox.AppendText(http.RequestUri,
1802
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1803
						owner.messagesBox.EndMark(requestUriMarker);
1804
						owner.messagesBox.AppendNewLine();
1805
 
1806
						owner.messagesBox.AppendText("Request Version:           ",
1807
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1808
						requestVersionMarker = owner.messagesBox.BeginMark();
1809
						owner.messagesBox.AppendText(http.RequestVersion == HttpVersion.V0_9 ? "HTTP/0.9"
1810
							: http.RequestVersion == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1",
1811
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1812
						owner.messagesBox.EndMark(requestVersionMarker);
1813
						owner.messagesBox.AppendNewLine();
1814
 
1815
						owner.messagesBox.AppendText("Request Content Length:    ",
1816
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1817
						requestLengthMarker = owner.messagesBox.BeginMark();
1818
						owner.messagesBox.AppendText(http.RequestLength < 0 ? "<unknown>" : http.RequestLength.ToString(),
1819
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1820
						owner.messagesBox.EndMark(requestLengthMarker);
1821
						owner.messagesBox.AppendNewLine();
1822
 
1823
						owner.messagesBox.AppendText("Request Content Encoding:  ",
1824
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1825
						requestEncodingMarker = owner.messagesBox.BeginMark();
1826
						owner.messagesBox.AppendText(EncodingToString(http.RequestEncoding),
1827
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1828
						owner.messagesBox.EndMark(requestEncodingMarker);
1829
						owner.messagesBox.AppendNewLine();
1830
 
1831
						owner.messagesBox.AppendText("Request Content Type:      ",
1832
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1833
						requestContentTypeMarker = owner.messagesBox.BeginMark();
1834
						owner.messagesBox.AppendText(http.RequestContentType == null ? "<unknown>"
1835
							: http.RequestContentType + "/" + http.RequestContentSubtype,
1836
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1837
						owner.messagesBox.EndMark(requestContentTypeMarker);
1838
						owner.messagesBox.AppendNewLine();
1839
 
1840
						owner.messagesBox.AppendText("Request Content Charset:   ",
1841
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1842
						requestCharsetMarker = owner.messagesBox.BeginMark();
1843
						owner.messagesBox.AppendText(http.RequestCharset == null ? "<unknown>" : http.RequestCharset,
1844
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1845
						owner.messagesBox.EndMark(requestCharsetMarker);
1846
						owner.messagesBox.AppendNewLine();
1847
 
1848
						owner.messagesBox.AppendText("Request Headers:",
1849
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1850
						owner.messagesBox.AppendNewLine();
1851
						requestHeadersMarker = owner.messagesBox.BeginMark();
1852
						owner.messagesBox.EndMark(requestHeadersMarker);
1853
 
1854
						requestHeadersEnum = http.RequestHeaders.GetEnumerator();
1855
						ShowHeaders(requestHeadersEnum, requestHeadersMarker);
1856
 
1857
						// response info
1858
						owner.messagesBox.AppendNewLine();
1125 dev 1859
						owner.messagesBox.AppendText("Response Start:            ",
1860
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1861
						responseStartMarker = owner.messagesBox.BeginMark();
1862
						owner.messagesBox.AppendText(http.ResponseStartTimestamp == DateTime.MinValue
1863
							? "<unknown>" : http.ResponseStartTimestamp.ToString("HH:mm:ss.ffff"),
1864
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1865
						owner.messagesBox.EndMark(responseStartMarker);
1866
						owner.messagesBox.AppendNewLine();
1867
 
1092 dev 1868
						owner.messagesBox.AppendText("Response Version:          ",
1869
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1870
						responseVersionMarker = owner.messagesBox.BeginMark();
1871
						owner.messagesBox.AppendText(http.ResponseVersion == HttpVersion.V0_9
1872
							? "HTTP/0.9" : http.ResponseVersion == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1",
1873
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1874
						owner.messagesBox.EndMark(responseVersionMarker);
1875
						owner.messagesBox.AppendNewLine();
1876
 
1877
						owner.messagesBox.AppendText("Response Status:           ",
1878
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1879
						responseStatusMarker = owner.messagesBox.BeginMark();
1880
						owner.messagesBox.AppendText(http.ResponseStatusCode + " " + http.ResponseStatusMessage,
1881
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1882
						owner.messagesBox.EndMark(responseStatusMarker);
1883
						owner.messagesBox.AppendNewLine();
1884
 
1885
						owner.messagesBox.AppendText("Response Content Length:   ",
1886
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1887
						responseLengthMarker = owner.messagesBox.BeginMark();
1888
						owner.messagesBox.AppendText(http.ResponseLength < 0 ? "<unknown>" : http.ResponseLength.ToString(),
1889
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1890
						owner.messagesBox.EndMark(responseLengthMarker);
1891
						owner.messagesBox.AppendNewLine();
1892
 
1893
						owner.messagesBox.AppendText("Response Content Encoding: ",
1894
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1895
						responseEncodingMarker = owner.messagesBox.BeginMark();
1896
						owner.messagesBox.AppendText(EncodingToString(http.ResponseEncoding),
1897
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1898
						owner.messagesBox.EndMark(responseEncodingMarker);
1899
						owner.messagesBox.AppendNewLine();
1900
 
1901
						owner.messagesBox.AppendText("Response Content Type:     ",
1902
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1903
						responseContentTypeMarker = owner.messagesBox.BeginMark();
1904
						owner.messagesBox.AppendText(http.ResponseContentType == null ? "<unknown>"
1905
							: http.ResponseContentType + "/" + http.ResponseContentSubtype,
1906
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1907
						owner.messagesBox.EndMark(responseContentTypeMarker);
1908
						owner.messagesBox.AppendNewLine();
1909
 
1910
						owner.messagesBox.AppendText("Response Content Charset:  ",
1911
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1912
						responseCharsetMarker = owner.messagesBox.BeginMark();
1913
						owner.messagesBox.AppendText(http.ResponseCharset == null ? "<unknown>" : http.ResponseCharset,
1914
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1915
						owner.messagesBox.EndMark(responseCharsetMarker);
1916
						owner.messagesBox.AppendNewLine();
1917
 
1918
						owner.messagesBox.AppendText("Response Headers:",
1919
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1920
						owner.messagesBox.AppendNewLine();
1921
						responseHeadersMarker = owner.messagesBox.BeginMark();
1922
						owner.messagesBox.EndMark(responseHeadersMarker);
1923
 
1924
						responseHeadersEnum = http.ResponseHeaders.GetEnumerator();
1925
						ShowHeaders(responseHeadersEnum, responseHeadersMarker);
1926
 
1927
						owner.messagesBox.AppendNewLine();
1928
						requestBodyMarker = owner.messagesBox.BeginMark();
1929
						owner.messagesBox.EndMark(requestBodyMarker);
1930
						ShowBody(requestBodyMarker, http.RequestBody, http.RequestLength, http.RequestText, Color.Green);
1931
 
1932
						owner.messagesBox.AppendNewLine();
1933
						responseBodyMarker = owner.messagesBox.BeginMark();
1934
						owner.messagesBox.EndMark(responseBodyMarker);
1935
						ShowBody(responseBodyMarker, http.ResponseBody, http.ResponseLength, http.ResponseText, Color.Blue);
1936
					}
1937
				}
1938
				finally
1939
				{
1940
					owner.messagesBox.EndUpdate();
1941
				}
1942
			}
1943
 
1944
			protected override void UpdateView()
1945
			{
1946
				try
1947
				{
1948
					owner.messagesBox.BeginUpdate();
1949
 
1950
					lock(http)
1951
					{
1952
						owner.messagesBox.ChangeText(stateMarker, http.RequestComplete && http.ResponseComplete ? "YES" : "NO",
1953
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1954
						owner.messagesBox.ChangeText(requestMethodMarker, http.RequestMethod,
1955
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1956
						owner.messagesBox.ChangeText(requestUriMarker, http.RequestUri,
1957
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1958
						owner.messagesBox.ChangeText(requestVersionMarker, http.RequestVersion == HttpVersion.V0_9 ? "HTTP/0.9"
1959
							: http.RequestVersion == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1",
1960
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1961
						owner.messagesBox.ChangeText(requestLengthMarker, http.RequestLength < 0
1962
							? "<unknown>" : http.RequestLength.ToString(),
1963
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1964
						owner.messagesBox.ChangeText(requestEncodingMarker, EncodingToString(http.RequestEncoding),
1965
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1966
						owner.messagesBox.ChangeText(requestContentTypeMarker, http.RequestContentType == null ? "<unknown>"
1967
							: http.RequestContentType + "/" + http.RequestContentSubtype,
1968
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1969
						owner.messagesBox.ChangeText(requestCharsetMarker, http.RequestCharset == null
1970
							? "<unknown>" : http.RequestCharset,
1971
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1972
 
1973
						ShowHeaders(requestHeadersEnum, requestHeadersMarker);
1974
 
1975
						owner.messagesBox.ChangeText(responseVersionMarker, http.ResponseVersion == HttpVersion.V0_9
1976
							? "HTTP/0.9" : http.ResponseVersion == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1",
1977
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1978
						owner.messagesBox.ChangeText(responseStatusMarker, http.ResponseStatusCode + " " + http.ResponseStatusMessage,
1979
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1980
						owner.messagesBox.ChangeText(responseLengthMarker, http.ResponseLength < 0
1981
							? "<unknown>" : http.ResponseLength.ToString(),
1982
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1983
						owner.messagesBox.ChangeText(responseEncodingMarker, EncodingToString(http.ResponseEncoding),
1984
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1985
						owner.messagesBox.ChangeText(responseContentTypeMarker, http.ResponseContentType == null ? "<unknown>"
1986
							: http.ResponseContentType + "/" + http.ResponseContentSubtype,
1987
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1988
						owner.messagesBox.ChangeText(responseCharsetMarker, http.ResponseCharset == null
1989
							? "<unknown>" : http.ResponseCharset,
1990
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1991
 
1992
						ShowHeaders(responseHeadersEnum, responseHeadersMarker);
1993
 
1994
						owner.messagesBox.DeleteText(requestBodyMarker);
1995
						ShowBody(requestBodyMarker, http.RequestBody, http.RequestLength, http.RequestText, Color.Green);
1996
						owner.messagesBox.DeleteText(responseBodyMarker);
1997
						ShowBody(responseBodyMarker, http.ResponseBody, http.ResponseLength, http.ResponseText, Color.Blue);
1998
					}
1999
				}
2000
				finally
2001
				{
2002
					owner.messagesBox.EndUpdate();
2003
				}
2004
			}
2005
 
2006
			private void ShowHeaders(IEnumerator headers, object marker)
2007
			{
2008
				while(headers.MoveNext())
2009
				{
2010
					HttpHeader h = (HttpHeader)headers.Current;
2011
 
2012
					bool first = true;
2013
					foreach(string val in h.Values)
2014
					{
2015
						if(first)
2016
						{
2017
							owner.messagesBox.InsertText(marker, h.Name + ":",
2018
								Color.DarkRed, Color.Transparent, false, false, 4, 4);
2019
							owner.messagesBox.InsertText(marker, null,
2020
								Color.DarkRed, Color.Transparent, false, false, 6 - 4 - 1, 4);
2021
							first = false;
2022
						}
2023
						else
2024
						{
2025
							owner.messagesBox.InsertText(marker, null,
2026
								Color.DarkRed, Color.Transparent, false, false, 6 + h.Name.Length, 6 + h.Name.Length);
2027
						}
2028
						owner.messagesBox.InsertText(marker, val,
2029
							Color.DarkRed, Color.LightGray, false, false, 0, 6 + h.Name.Length);
2030
						owner.messagesBox.InsertNewLine(marker);
2031
					}
2032
				}
2033
			}
2034
 
2035
			private void ShowBody(object marker, byte[] body, int len, string text, Color color)
2036
			{
2037
				if(text != null)
2038
				{
2039
					ArrayList lines = Utils.SplitLine(text);
2040
					for(int i = 0; i < lines.Count; i++)
2041
					{
2042
						owner.messagesBox.InsertText(marker, (string)lines[i], color, Color.LightGray, false, false, 0, 0);
2043
						owner.messagesBox.InsertNewLine(marker);
2044
					}
2045
				}
2046
				else if(body != null)
2047
				{
2048
					ArrayList lines = Utils.SplitLine(Utils.BytesToString(body, len));
2049
					for(int i = 0; i < lines.Count; i++)
2050
					{
2051
						owner.messagesBox.InsertText(marker, (string)lines[i], color, Color.LightGray, false, false, 0, 0);
2052
						owner.messagesBox.InsertNewLine(marker);
2053
					}
2054
				}
2055
			}
2056
 
2057
			public override void WriteLog(StreamWriter writer)
2058
			{
2059
				// request info
2060
				writer.WriteLine(
2061
					"Complete:                  " + (http.RequestComplete && http.ResponseComplete ? "YES" : "NO") + "\r\n"
2062
					+ "\r\nRequest Method:            " + http.RequestMethod
2063
					+ "\r\nRequest URI:               " + http.RequestUri
2064
					+ "\r\nRequest Version:           " + (http.RequestVersion == HttpVersion.V0_9 ? "HTTP/0.9"
2065
						: http.RequestVersion == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1")
2066
					+ "\r\nRequest Content Length:    " + (http.RequestLength < 0 ? "<unknown>" : http.RequestLength.ToString())
2067
					+ "\r\nRequest Content Encoding:  " + EncodingToString(http.RequestEncoding)
2068
					+ "\r\nRequest Content Type:      " + (http.RequestContentType == null ? "<unknown>"
2069
						: http.RequestContentType + "/" + http.RequestContentSubtype)
2070
					+ "\r\nRequest Content Charset:   " + (http.RequestCharset == null ? "<unknown>" : http.RequestCharset)
2071
					+ "\r\nRequest Headers:");
2072
 
2073
				foreach(HttpHeader h in http.RequestHeaders)
2074
				{
2075
					int indent = 0;
2076
					foreach(string val in h.Values)
2077
					{
2078
						if(indent == 0)
2079
						{
2080
							writer.WriteLine("    {0}: {1}", h.Name, val);
2081
							indent = 6 + h.Name.Length;
2082
						}
2083
						else
2084
						{
2085
							writer.WriteLine("{0," + indent + "}{1}", " ", val);
2086
						}
2087
					}
2088
				}
2089
 
2090
				// response info
2091
				writer.WriteLine(
2092
					"\r\nResponse Version:          " + (http.ResponseVersion == HttpVersion.V0_9
2093
						? "HTTP/0.9" : http.ResponseVersion == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1")
2094
					+ "\r\nResponse Status:           " + http.ResponseStatusCode + " " + http.ResponseStatusMessage
2095
					+ "\r\nResponse Content Length:   " + (http.ResponseLength < 0
2096
						? "<unknown>" : http.ResponseLength.ToString())
2097
					+ "\r\nResponse Content Encoding: " + EncodingToString(http.ResponseEncoding)
2098
					+ "\r\nResponse Content Type:     " + (http.ResponseContentType == null ? "<unknown>"
2099
						: http.ResponseContentType + "/" + http.ResponseContentSubtype)
2100
					+ "\r\nResponse Content Charset:  " + (http.ResponseCharset == null ? "<unknown>" : http.ResponseCharset)
2101
					+ "\r\nResponse Headers:");
2102
 
2103
				foreach(HttpHeader h in http.ResponseHeaders)
2104
				{
2105
					int indent = 0;
2106
					foreach(string val in h.Values)
2107
					{
2108
						if(indent == 0)
2109
						{
2110
							writer.WriteLine("    {0}: {1}", h.Name, val);
2111
							indent = 6 + h.Name.Length;
2112
						}
2113
						else
2114
						{
2115
							writer.WriteLine("{0," + indent + "}{1}", " ", val);
2116
						}
2117
					}
2118
				}
2119
				writer.WriteLine();
2120
 
2121
				// request body
2122
				if(http.RequestText != null)
2123
				{
2124
					writer.WriteLine(http.RequestText);
2125
				}
2126
				else if(http.RequestBody != null)
2127
				{
2128
					writer.WriteLine(Utils.BytesToString(http.RequestBody, http.RequestLength));
2129
				}
2130
 
2131
				// response body
2132
				if(http.ResponseText != null)
2133
				{
2134
					writer.WriteLine(http.ResponseText);
2135
				}
2136
				else if(http.ResponseBody != null)
2137
				{
2138
					writer.WriteLine(Utils.BytesToString(http.ResponseBody, http.ResponseLength));
2139
				}
2140
 
2141
				writer.WriteLine("===============================================================");
2142
				writer.WriteLine();
2143
			}
2144
		}
2145
 
2146
		private class XmlNodeData : TreeNodeData
2147
		{
2148
			private XmlMessage xml;
2149
 
2150
			public XmlMessage Xml
2151
			{
2152
				get { return xml; }
2153
				set { xml = value; }
2154
			}
2155
 
2156
			public XmlNodeData(MainForm owner, TreeNode node) : base(owner, node)
2157
			{
2158
			}
2159
 
2160
			protected override void InitView()
2161
			{
2162
				try
2163
				{
2164
					// update main screen if necessary
2165
					owner.messagesBox.BeginUpdate();
2166
 
2167
					lock(xml)
2168
					{
2169
						owner.messagesBox.Clear();
2170
						if(xml.ParseException != null)
2171
						{
2172
							owner.messagesBox.AppendText("Cannot parse XML:",
2173
								Color.Red, Color.Transparent, false, false, 0, 0);
2174
							owner.messagesBox.AppendNewLine();
2175
							owner.messagesBox.AppendText(xml.ParseException.Message,
2176
								Color.Red, Color.Transparent, false, false, 2, 2);
2177
							owner.messagesBox.AppendNewLine();
2178
						}
2179
						else if(xml.Xml != null)
2180
						{
2181
							ShowXmlNode(xml.Xml, 0);
2182
						}
2183
					}
2184
				}
2185
				finally
2186
				{
2187
					owner.messagesBox.EndUpdate();
2188
				}
2189
			}
2190
 
2191
			protected override void UpdateView()
2192
			{
2193
			}
2194
 
2195
			private void ShowXmlNode(XmlNode node, int indent)
2196
			{
2197
				if(node.NodeType == XmlNodeType.Document)
2198
				{
2199
					foreach(XmlNode subnode in node.ChildNodes)
2200
					{
2201
						ShowXmlNode(subnode, indent);
2202
					}
2203
				}
2204
				else if(node.NodeType == XmlNodeType.XmlDeclaration)
2205
				{
2206
					owner.messagesBox.AppendText("<?" + node.Name + " " + node.Value + " ?>",
2207
						Color.Blue, Color.Transparent, false, false, indent, indent+2);
2208
					owner.messagesBox.AppendNewLine();
2209
				}
2210
				else if(node.NodeType == XmlNodeType.Comment)
2211
				{
2212
					owner.messagesBox.AppendText("<!--", Color.Gray, Color.Transparent, false, false, indent, indent + 2);
2213
					ShowNormalizedXmlValue(node.Value, Color.Gray, Color.Thistle, false, false, indent);
2214
					owner.messagesBox.AppendText("-->", Color.Gray, Color.Transparent, false, false, 0, indent + 2);
2215
					owner.messagesBox.AppendNewLine();
2216
				}
2217
				else if(node.NodeType == XmlNodeType.Element)
2218
				{
2219
					owner.messagesBox.AppendText("<", Color.Blue, Color.Transparent, false, false, indent, indent + 2);
2220
					owner.messagesBox.AppendText(node.Name, Color.DarkRed, Color.Transparent, false, false, 0, indent + 2);
2221
 
2222
					foreach(XmlAttribute attr in node.Attributes)
2223
					{
2224
						bool xmlAttr = attr.Name.StartsWith("xml");
2225
						owner.messagesBox.AppendText(attr.Name, xmlAttr ? Color.Red : Color.DarkRed, Color.Transparent, false, false, 1, indent + 2);
2226
						owner.messagesBox.AppendText("=\"", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2227
						owner.messagesBox.AppendText(attr.Value, xmlAttr ? Color.Red : Color.DarkRed, Color.Transparent, false, false, 0, indent + 2);
2228
						owner.messagesBox.AppendText("\"", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2229
					}
2230
 
2231
					if(!node.HasChildNodes)
2232
					{
2233
						owner.messagesBox.AppendText(" />", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2234
						owner.messagesBox.AppendNewLine();
2235
					}
2236
					else
2237
					{
2238
						owner.messagesBox.AppendText(">", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2239
 
2240
						bool elementExists = false;
2241
						bool lastText      = true;
2242
						foreach(XmlNode subnode in node.ChildNodes)
2243
						{
2244
							if(subnode.NodeType == XmlNodeType.Text)
2245
							{
2246
								if(elementExists) owner.messagesBox.AppendNewLine();
2247
								ShowNormalizedXmlValue(subnode.Value, Color.Black, Color.LightGray, false, false, indent);
2248
								lastText = true;
2249
							}
2250
							else
2251
							{
2252
								if(lastText) owner.messagesBox.AppendNewLine();
2253
								ShowXmlNode(subnode, indent + 2);
2254
								elementExists = true;
2255
								lastText      = false;
2256
							}
2257
						}
2258
 
2259
						if(elementExists) owner.messagesBox.AppendText(null, Color.Black, Color.Transparent, false, false, indent, indent + 2);
2260
						owner.messagesBox.AppendText("</", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2261
						owner.messagesBox.AppendText(node.Name, Color.DarkRed, Color.Transparent, false, false, 0, indent + 2);
2262
						owner.messagesBox.AppendText(">", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2263
						owner.messagesBox.AppendNewLine();
2264
					}
2265
				}
2266
			}
2267
 
2268
			private void ShowNormalizedXmlValue(string s, Color color, Color backColor, bool italic, bool bold, int indent)
2269
			{
2270
				int begin;
2271
				int end;
2272
 
2273
				bool newLineFound = false;
2274
				foreach(char c in s)
2275
				{
2276
					if(c == '\n')
2277
					{
2278
						newLineFound = true;
2279
						break;
2280
					}
2281
				}
2282
 
2283
				if(newLineFound)
2284
				{
2285
					owner.messagesBox.AppendNewLine();
2286
					owner.messagesBox.AppendText(null, color, Color.Transparent, italic, bold, indent, indent);
2287
					owner.messagesBox.AppendText(null, color, backColor, italic, bold, 2, 2);
2288
				}
2289
 
2290
				// trim
2291
				for(begin = 0; begin < s.Length; begin++)
2292
				{
2293
					char c = s[begin];
2294
					if(c != '\n' && c != '\r' && c != '\t' && c != ' ') break;
2295
				}
2296
				for(end = s.Length-1; end >= 0; end--)
2297
				{
2298
					char c = s[end];
2299
					if(c != '\n' && c != '\r' && c != '\t' && c != ' ') break;
2300
				}
2301
 
2302
				StringBuilder b = new StringBuilder(s.Length);
2303
				for(int i = begin; i <= end; i++)
2304
				{
2305
					char c = s[i];
2306
 
2307
					switch(c)
2308
					{
2309
						case '\n':
2310
							if(b.Length > 0)
2311
							{
2312
								owner.messagesBox.AppendText(b.ToString(), color, backColor, italic, bold, 0, indent + 2);
2313
								b.Length = 0;
2314
							}
2315
 
2316
							owner.messagesBox.AppendNewLine();
2317
							owner.messagesBox.AppendText(null, color, Color.Transparent, italic, bold, indent, indent);
2318
							owner.messagesBox.AppendText(null, color, backColor, italic, bold, 2, 2);
2319
							break;
2320
 
2321
						case '\r':
2322
							break;
2323
 
2324
						case '\t':
2325
							b.Append("  ");
2326
							break;
2327
 
2328
						default:
2329
							b.Append(c);
2330
							break;
2331
					}
2332
				}
2333
 
2334
				if(b.Length > 0)
2335
					owner.messagesBox.AppendText(b.ToString(), color, backColor, italic, bold, 0, indent + 2);
2336
 
2337
				if(newLineFound)
2338
				{
2339
					owner.messagesBox.AppendNewLine();
2340
					owner.messagesBox.AppendText(null, color, Color.Transparent, italic, bold, indent, indent + 2);
2341
				}
2342
			}
2343
 
2344
			public override void WriteLog(StreamWriter writer)
2345
			{
2346
				WriteXmlNode(writer, xml.Xml, "");
2347
				writer.WriteLine("===============================================================");
2348
				writer.WriteLine();
2349
			}
2350
 
2351
			private void WriteXmlNode(StreamWriter writer, XmlNode node, string indent)
2352
			{
2353
				if(node.NodeType == XmlNodeType.Document)
2354
				{
2355
					foreach(XmlNode subnode in node.ChildNodes)
2356
					{
2357
						WriteXmlNode(writer, subnode, indent);
2358
					}
2359
				}
2360
				else if(node.NodeType == XmlNodeType.XmlDeclaration)
2361
				{
2362
					writer.WriteLine(indent + "<?" + node.Name + " " + node.Value + " ?>");
2363
				}
2364
				else if(node.NodeType == XmlNodeType.Comment)
2365
				{
2366
					writer.Write(indent + "<!--");
2367
					WriteNormalizedXmlValue(writer, node.Value, indent);
2368
					writer.WriteLine("-->");
2369
				}
2370
				else if(node.NodeType == XmlNodeType.Element)
2371
				{
2372
					writer.Write(indent + "<" + node.Name);
2373
 
2374
					foreach(XmlAttribute attr in node.Attributes)
2375
					{
2376
						bool xmlAttr = attr.Name.StartsWith("xml");
2377
						writer.Write(" " + attr.Name + "=\"" + attr.Value + "\"");
2378
					}
2379
 
2380
					if(!node.HasChildNodes)
2381
					{
2382
						writer.WriteLine(" />");
2383
					}
2384
					else
2385
					{
2386
						writer.Write(">");
2387
 
2388
						bool elementExists = false;
2389
						bool lastText      = true;
2390
						foreach(XmlNode subnode in node.ChildNodes)
2391
						{
2392
							if(subnode.NodeType == XmlNodeType.Text)
2393
							{
2394
								if(elementExists) writer.WriteLine();
2395
								WriteNormalizedXmlValue(writer, subnode.Value, indent);
2396
								lastText = true;
2397
							}
2398
							else
2399
							{
2400
								if(lastText) writer.WriteLine();
2401
								WriteXmlNode(writer, subnode, indent + "  ");
2402
								elementExists = true;
2403
								lastText      = false;
2404
							}
2405
						}
2406
 
2407
						if(elementExists) writer.Write(indent);
2408
						writer.WriteLine("</" + node.Name + ">");
2409
					}
2410
				}
2411
			}
2412
 
2413
			private void WriteNormalizedXmlValue(StreamWriter writer, string s, string indent)
2414
			{
2415
				int begin;
2416
				int end;
2417
 
2418
				bool newLineFound = false;
2419
				foreach(char c in s)
2420
				{
2421
					if(c == '\n')
2422
					{
2423
						newLineFound = true;
2424
						break;
2425
					}
2426
				}
2427
 
2428
				if(newLineFound)
2429
				{
2430
					writer.WriteLine();
2431
					writer.Write(indent + "  ");
2432
				}
2433
 
2434
				// trim
2435
				for(begin = 0; begin < s.Length; begin++)
2436
				{
2437
					char c = s[begin];
2438
					if(c != '\n' && c != '\r' && c != '\t' && c != ' ') break;
2439
				}
2440
				for(end = s.Length-1; end >= 0; end--)
2441
				{
2442
					char c = s[end];
2443
					if(c != '\n' && c != '\r' && c != '\t' && c != ' ') break;
2444
				}
2445
 
2446
				StringBuilder b = new StringBuilder(s.Length);
2447
				for(int i = begin; i <= end; i++)
2448
				{
2449
					char c = s[i];
2450
 
2451
					switch(c)
2452
					{
2453
						case '\n':
2454
							if(b.Length > 0)
2455
							{
2456
								writer.Write(b.ToString());
2457
								b.Length = 0;
2458
							}
2459
 
2460
							writer.WriteLine();
2461
							writer.Write(indent + "  ");
2462
							break;
2463
 
2464
						case '\r':
2465
							break;
2466
 
2467
						case '\t':
2468
							b.Append("  ");
2469
							break;
2470
 
2471
						case '&':
2472
							b.Append("&amp;");
2473
							break;
2474
 
2475
						case '<':
2476
							b.Append("&lt;");
2477
							break;
2478
 
2479
						case '>':
2480
							b.Append("&gt;");
2481
							break;
2482
 
2483
						default:
2484
							b.Append(c);
2485
							break;
2486
					}
2487
				}
2488
 
2489
				if(b.Length > 0)
2490
					writer.Write(b.ToString());
2491
 
2492
				if(newLineFound)
2493
				{
2494
					writer.WriteLine();
2495
					writer.Write(indent + "  ");
2496
				}
2497
			}
2498
		}
2499
 
2500
		#endregion node display classes
2501
 
2502
		#region other classes
2503
		private abstract class Utils
2504
		{
2505
			public static string BytesToString(byte[] bytes, int length)
2506
			{
2507
				if(bytes == null) return null;
2508
 
2509
				char[]  chars   = new char[length + 1];
2510
				Decoder decoder = System.Text.Encoding.UTF8.GetDecoder();
2511
				int     charLen = decoder.GetChars(bytes, 0, length, chars, 0);
2512
 
2513
				for(int i = 0; i < charLen; i++)
2514
				{
2515
					char c = chars[i];
2516
					if(c != '\n' && c != '\r' && Char.IsControl(c)) chars[i] = '.';
2517
				}
2518
 
2519
				return (new System.String(chars)).Substring(0, charLen);
2520
			}
2521
 
2522
			public static ArrayList SplitLine(string line)
2523
			{
2524
				if(line == null) return null;
2525
 
2526
				ArrayList    res = new ArrayList();
2527
				StringBuilder b  = new StringBuilder(200);
2528
 
2529
				foreach(char c in line)
2530
				{
2531
					switch(c)
2532
					{
2533
						case '\r':
2534
							break;
2535
 
2536
						case '\n':
2537
							res.Add(b.ToString());
2538
							b.Length = 0;
2539
							break;
2540
 
2541
						default:
2542
							b.Append(c);
2543
							break;
2544
					}
2545
				}
2546
 
2547
				res.Add(b.ToString());
2548
 
2549
				return res;
2550
			}
2551
		}
2552
		#endregion other classes
2553
	}
2554
 
2555
	public class LogMessages
2556
	{
2557
		private ArrayList messages = new ArrayList();
2558
		private ListBox   logBox;
2559
		private LogLevel  level = LogLevel.Debug;
2560
 
2561
		public LogLevel Level
2562
		{
2563
			get { return level; }
2564
			set { level = value; Update(); }
2565
		}
2566
 
2567
		public LogMessages(ListBox logBox)
2568
		{
2569
			this.logBox = logBox;
2570
		}
2571
 
2572
		public ArrayList Messages
2573
		{
2574
			get { return new ArrayList(messages); }
2575
		}
2576
 
2577
		public void Add(LogMessage message)
2578
		{
2579
			messages.Add(message);
2580
			if(Show(message))
2581
				logBox.TopIndex = logBox.Items.Count - 1;
2582
		}
2583
 
2584
		public void Clear()
2585
		{
2586
			messages.Clear();
2587
			logBox.Items.Clear();
2588
		}
2589
 
2590
		public void Update()
2591
		{
2592
			logBox.BeginUpdate();
2593
 
2594
			logBox.Items.Clear();
2595
			foreach(LogMessage message in messages)
2596
			{
2597
				Show(message);
2598
			}
2599
			logBox.TopIndex = logBox.Items.Count - 1;
2600
 
2601
			logBox.EndUpdate();
2602
		}
2603
 
2604
		private bool Show(LogMessage message)
2605
		{
2606
			if(message.Level > this.level) return false;
2607
 
2608
			try
2609
			{
2610
				logBox.Items.Add(message.ToString());
2611
			}
2612
			catch(ObjectDisposedException) {}
2613
 
2614
			return true;
2615
		}
2616
	}
2617
 
2618
	public class LogMessage
2619
	{
2620
		private TcpConnection tcp;
2621
		private LogLevel      level;
2622
		private string        message;
2623
		private Exception     exception;
2624
		private DateTime      timestamp = DateTime.Now;
2625
 
2626
		public TcpConnection Tcp
2627
		{
2628
			get { return tcp; }
2629
			set { tcp = value; }
2630
		}
2631
 
2632
		public LogLevel Level
2633
		{
2634
			get { return level; }
2635
			set { level = value; }
2636
		}
2637
 
2638
		public string Message
2639
		{
2640
			get { return message; }
2641
			set { message = value; }
2642
		}
2643
 
2644
		public Exception Exception
2645
		{
2646
			get { return exception; }
2647
			set { exception = value; }
2648
		}
2649
 
2650
		public DateTime Timestamp
2651
		{
2652
			get { return timestamp; }
2653
			set { timestamp = value; }
2654
		}
2655
 
2656
		public LogMessage(TcpConnection tcp, LogLevel level, string message, Exception exception)
2657
		{
2658
			this.tcp       = tcp;
2659
			this.level     = level;
2660
			this.message   = message;
2661
			this.exception = exception;
2662
		}
2663
 
2664
		public override string ToString()
2665
		{
2666
			string l = "     ";
2667
			switch(level)
2668
			{
2669
				case LogLevel.Debug:     l = "debug"; break;
2670
				case LogLevel.Info:      l = "info "; break;
2671
				case LogLevel.Important: l = "Imp  "; break;
2672
				case LogLevel.Warning:   l = "Warn "; break;
2673
				case LogLevel.Error:     l = "ERROR"; break;
2674
				case LogLevel.Critical:  l = "CRIT "; break;
2675
			}
2676
 
2677
			return (tcp == null ? "...." : tcp.Id) + " " + l + " " + timestamp.ToString("HH:mm:ss.ffff") + " "
2678
				+ (exception != null ? exception.Message : message);
2679
		}
2680
	}
2681
 
2682
	public enum TcpShowMode
2683
	{
2684
		ByDirection,
2685
		ByTime
2686
	}
1194 dev 2687
 
2688
	public class RecentItem : IComparable
2689
	{
2690
		private int listenPort;
2691
 
2692
		public int ListenPort
2693
		{
2694
			get { return listenPort; }
2695
			set { listenPort = value; }
2696
		}
2697
 
2698
		private string resendHost;
2699
 
2700
		public string ResendHost
2701
		{
2702
			get { return resendHost; }
2703
			set { resendHost = value; }
2704
		}
2705
 
2706
		private int resendPort;
2707
 
2708
		public int ResendPort
2709
		{
2710
			get { return resendPort; }
2711
			set { resendPort = value; }
2712
		}
2713
 
2714
		private DateTime timestamp;
2715
 
2716
		public DateTime Timestamp
2717
		{
2718
			get { return timestamp; }
2719
		}
2720
 
2721
		public RecentItem(int listenPort, string resendHost, int resendPort)
2722
		{
2723
			this.listenPort = listenPort;
2724
			this.resendHost = resendHost;
2725
			this.resendPort = resendPort;
2726
		}
2727
 
2728
		public override string ToString()
2729
		{
1197 dev 2730
			return string.Format("{0} to {1}:{2} at {3:HH:mm:ss.ff}",
1194 dev 2731
				listenPort, resendHost, resendPort, timestamp);
2732
		}
2733
 
2734
		public override bool Equals(object obj)
2735
		{
2736
			if(!(obj is RecentItem)) return false;
2737
 
2738
			RecentItem i2 = (RecentItem)obj;
2739
 
2740
			return (i2.listenPort == this.listenPort) && (i2.resendHost == this.resendHost)
2741
				&& (i2.resendPort == this.resendPort);
2742
		}
2743
 
2744
		public override int GetHashCode()
2745
		{
2746
			return this.resendHost.GetHashCode();
2747
		}
2748
 
2749
		public string SaveToRegistry()
2750
		{
1197 dev 2751
			return string.Format("{0}:{1}:{2}:{3}",
1194 dev 2752
				listenPort, resendPort, timestamp.Ticks, resendHost);
2753
		}
2754
 
2755
		public static RecentItem LoadFromRegistry(string str)
2756
		{
2757
			Regex re = new Regex(@"^(\d+):(\d+):(\d+):(.+)$");
2758
			Match m  = re.Match(str);
2759
			if(!m.Success) throw new Exception("Cannot parse recent item");
2760
 
1197 dev 2761
			RecentItem item = new RecentItem(int.Parse(m.Groups[1].Value),
1194 dev 2762
				m.Groups[4].Value, int.Parse(m.Groups[2].Value));
2763
 
2764
			item.timestamp = new DateTime(long.Parse(m.Groups[3].Value));
2765
 
2766
			return item;
2767
		}
2768
 
2769
		public void UpdateTimestamp()
2770
		{
2771
			timestamp = DateTime.Now;
2772
		}
2773
 
2774
		public void UpdateTimestamp(RecentItem second)
2775
		{
2776
			if(second.timestamp > timestamp)
2777
				timestamp = second.timestamp;
2778
		}
2779
 
2780
		#region IComparable Members
2781
 
2782
		int IComparable.CompareTo(object obj)
2783
		{
2784
			if(!(obj is RecentItem))
2785
				throw new Exception("Cannot compare");
2786
 
2787
			return this.timestamp.CompareTo(((RecentItem)obj).timestamp);
2788
		}
2789
 
2790
		#endregion
2791
	}
1092 dev 2792
}