Subversion Repositories general

Rev

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