Subversion Repositories general

Rev

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