Subversion Repositories general

Rev

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

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