Subversion Repositories general

Rev

Rev 1238 | Rev 1240 | 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) {
1239 dev 1025
				this.recentListeningMenu.MenuItems.RemoveAt(recentItems.Count - existingIdx - 1);
1198 dev 1026
				recentItems.RemoveAt(existingIdx);
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) {
1239 dev 1042
				this.recentListeningMenu.MenuItems.RemoveAt(recentItems.Count - 1);
1198 dev 1043
				recentItems.RemoveAt(0);
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();
1239 dev 1073
 
1074
			messageView.BeginUpdate();
1199 dev 1075
			messageView.Nodes.Clear();
1239 dev 1076
			messageView.EndUpdate();
1077
 
1199 dev 1078
			messagesBox.Clear();
1079
			logMessages.Clear();
1080
		}
1081
 
1092 dev 1082
		private void Start(int listenPort, IPAddress resendHost, int resendPort)
1083
		{
1084
			if(tcpListener != null) tcpListener.StopListening();
1085
 
1086
			tcpListener = new TcpListener(listenPort, resendHost, resendPort);
1087
			tcpListener.Log    += new TcpLogEventHandler(TcpConnectionLog);
1088
			tcpListener.NewTcp += new TcpConnectionEventHandler(AddTcpConnetion);
1089
			tcpListener.StartListening();
1090
		}
1091
 
1199 dev 1092
		private void StartListening(int listenPort, IPAddress resendIp, int resendPort)
1093
		{
1094
			// listen to the port
1095
			try
1096
			{
1097
				Start(listenPort, resendIp, resendPort);
1098
			}
1099
			catch(Exception ex)
1100
			{
1101
				MessageBox.Show("Cannot start listening: " + ex.Message, "TCPproxy",
1102
					MessageBoxButtons.OK, MessageBoxIcon.Error);
1103
				Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1104
				return;
1105
			}
1106
 
1107
			AddRecentItem(listenPort, resendHost, resendPort);
1108
 
1109
			startMenuItem.Enabled = false;
1110
			stopMenuItem.Enabled  = true;
1111
 
1112
			foreach(MenuItem subitem in recentListeningMenu.MenuItems) {
1113
				subitem.Enabled = false;
1114
			}
1115
 
1116
			this.Text = string.Format("{0}: {1} to {2}:{3}",
1117
				defaultCaption, listenPort, resendHost, resendPort);
1118
		}
1119
 
1120
		private void StopListening()
1121
		{
1122
			if(tcpListener != null) tcpListener.StopListening();
1123
 
1124
			startMenuItem.Enabled = true;
1125
			stopMenuItem.Enabled  = false;
1126
 
1127
			if(recentItems.Count > 0) {
1128
				foreach(MenuItem subitem in recentListeningMenu.MenuItems) {
1129
					subitem.Enabled = true;
1130
				}
1131
			}
1132
 
1133
			this.Text = defaultCaption;
1134
		}
1135
 
1092 dev 1136
		private void CloseTcpConnection(TcpConnection tcp)
1137
		{
1138
			if(tcp == null) return;
1139
 
1140
			tcp.Cancel();
1141
		}
1142
 
1143
		private void SaveLog(string fileName)
1144
		{
1145
			StreamWriter writer = new StreamWriter(fileName);
1146
 
1147
			foreach(LogMessage message in logMessages.Messages)
1148
			{
1149
				writer.WriteLine(message);
1150
			}
1151
 
1152
			writer.Close();
1153
		}
1154
 
1155
		private void SaveTcp(string fileName)
1156
		{
1157
			StreamWriter writer = new StreamWriter(fileName);
1158
 
1159
			foreach(TreeNode tcpNode in messageView.Nodes)
1160
			{
1161
				TcpNodeData data = (TcpNodeData)tcpNode.Tag;
1162
				data.WriteLog(writer);
1163
			}
1164
 
1165
			writer.Close();
1166
		}
1167
 
1168
		private void SaveHttp(string fileName)
1169
		{
1170
			StreamWriter writer = new StreamWriter(fileName);
1171
 
1172
			foreach(TreeNode tcpNode in messageView.Nodes)
1173
			{
1174
				foreach(TreeNode httpNode in tcpNode.Nodes)
1175
				{
1176
					HttpNodeData data = (HttpNodeData)httpNode.Tag;
1177
					data.WriteLog(writer);
1178
				}
1179
			}
1180
 
1181
			writer.Close();
1182
		}
1183
 
1184
		private void SaveXml(string fileName)
1185
		{
1186
			StreamWriter writer = new StreamWriter(fileName);
1187
 
1188
			foreach(TreeNode tcpNode in messageView.Nodes)
1189
			{
1190
				foreach(TreeNode httpNode in tcpNode.Nodes)
1191
				{
1192
					foreach(TreeNode xmlNode in httpNode.Nodes)
1193
					{
1194
						XmlNodeData data = (XmlNodeData)xmlNode.Tag;
1195
						data.WriteLog(writer);
1196
					}
1197
				}
1198
			}
1199
 
1200
			writer.Close();
1201
		}
1202
 
1199 dev 1203
		private void SaveBinLog(string fileName)
1204
		{
1205
			FileStream   file   = new FileStream(fileName, FileMode.Create);
1206
			BinaryWriter writer = new BinaryWriter(file);
1207
 
1208
			// header
1209
			writer.Write(Encoding.ASCII.GetBytes(LOG_BIN_HEADER));
1210
			writer.Write(LOG_TYPE_BIN);
1211
 
1212
			// for each tcp connection
1213
			foreach(TreeNode tcpNode in messageView.Nodes)
1214
				((TcpNodeData)tcpNode.Tag).Tcp.WriteBinLog(writer);
1215
 
1216
			// end of stream
1217
			writer.Write((byte)BinLogTypes.None);
1218
 
1219
			writer.Close();
1220
			file.Close();
1221
		}
1222
 
1223
		private void LoadBinLog(string fileName)
1224
		{
1225
			StopListening();
1226
			ClearAll();
1227
 
1232 dev 1228
			FileStream   file   = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
1199 dev 1229
			BinaryReader reader = new BinaryReader(file);
1230
 
1231
			// header
1232
			byte[] bufExpect = Encoding.ASCII.GetBytes(LOG_BIN_HEADER);
1201 dev 1233
			if(file.Length < (bufExpect.Length + 1 /* the type */))
1199 dev 1234
				throw new Exception("The file is too short");
1235
 
1236
			byte[] bufRead = reader.ReadBytes(bufExpect.Length);
1237
			for(int i = 0; i < bufRead.Length; i++)
1238
				if(bufRead[i] != bufExpect[i])
1239
					throw new Exception("Wrong header of the file");
1240
 
1241
			if(reader.ReadByte() != LOG_TYPE_BIN)
1242
				throw new Exception("Unknown log type");
1243
 
1244
			tcpListener = new TcpListener(0, null, 0);
1245
			tcpListener.Log    += new TcpLogEventHandler(TcpConnectionLog);
1246
			tcpListener.NewTcp += new TcpConnectionEventHandler(AddTcpConnetion);
1247
			tcpListener.ReadBinLog(reader); // it will send us usual event
1248
 
1249
			reader.Close();
1250
			file.Close();
1251
		}
1252
 
1092 dev 1253
		#endregion core methods
1254
 
1255
		#region network events handlers
1256
		private void TcpConnectionLog(object sender, TcpLogEventArgs e)
1257
		{
1125 dev 1258
			lock(this)
1259
			{
1260
				TcpConnection tcp = sender as TcpConnection;
1261
				LogMessage message = new LogMessage(tcp, e.Level, e.Message, e.Exception);
1092 dev 1262
 
1125 dev 1263
				try
1264
				{
1265
					this.BeginInvoke(new AddLogMessageHandler(AddLogMessageInternal), new object[] { message } );
1266
				}
1267
				catch(InvalidOperationException ex)
1268
				{
1269
					if(!this.Disposing && !this.IsDisposed)
1270
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1271
				}
1092 dev 1272
			}
1273
		}
1274
 
1275
		private void AddTcpConnetion(object sender, TcpConnectionEventArgs e)
1276
		{
1125 dev 1277
			lock(this)
1278
			{
1279
				e.Tcp.Log     += new TcpLogEventHandler(TcpConnectionLog);
1280
				e.Tcp.Update  += new TcpEventHandler(UpdateTcpNode);
1281
				e.Tcp.Close   += new TcpEventHandler(UpdateTcpNode);
1282
				e.Tcp.NewHttp += new TcpHttpEventHandler(AddHttpMessageNode);
1092 dev 1283
 
1125 dev 1284
				try
1285
				{
1286
					this.BeginInvoke(new AddTcpNodeHandler(AddTcpNodeInternal), new object[] { e.Tcp } );
1287
				}
1288
				catch(InvalidOperationException ex)
1289
				{
1290
					if(!this.Disposing && !this.IsDisposed)
1291
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1292
				}
1092 dev 1293
			}
1294
		}
1295
 
1296
		private void UpdateTcpNode(object sender, TcpEventArgs e)
1297
		{
1125 dev 1298
			lock(this)
1092 dev 1299
			{
1125 dev 1300
				try
1301
				{
1302
					this.BeginInvoke(new UpdateTcpNodeHandler(UpdateTcpNodeInternal), new object[] { (TcpConnection)sender } );
1303
				}
1304
				catch(InvalidOperationException ex)
1305
				{
1306
					if(!this.Disposing && !this.IsDisposed)
1307
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1308
				}
1092 dev 1309
			}
1310
		}
1311
 
1312
		private void AddHttpMessageNode(object sender, TcpHttpEventArgs e)
1313
		{
1125 dev 1314
			lock(this)
1315
			{
1316
				e.Http.Update += new TcpEventHandler(UpdateHttpNode);
1092 dev 1317
 
1125 dev 1318
				try
1319
				{
1320
					this.BeginInvoke(new AddHttpNodeHandler(AddHttpNodeInternal),
1321
						new object[] { (TcpConnection)sender, e.Http } );
1322
				}
1323
				catch(InvalidOperationException ex)
1324
				{
1325
					if(!this.Disposing && !this.IsDisposed)
1326
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1327
				}
1092 dev 1328
			}
1329
		}
1330
 
1331
		private void UpdateHttpNode(object sender, TcpEventArgs e)
1332
		{
1125 dev 1333
			lock(this)
1092 dev 1334
			{
1125 dev 1335
				try
1336
				{
1337
					this.BeginInvoke(new UpdateHttpNodeHandler(UpdateHttpNodeInternal), new object[] { (HttpMessage)sender } );
1338
				}
1339
				catch(InvalidOperationException ex)
1340
				{
1341
					if(!this.Disposing && !this.IsDisposed)
1342
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1343
				}
1092 dev 1344
			}
1345
		}
1346
 
1347
		#endregion network events handlers
1348
 
1349
		#region handlers for async GUI events
1201 dev 1350
 
1351
		// All handlers are called in main application thread only, no locks needed.
1352
		// Other methods which are not running in the main application thread
1353
		// are not allowed no interact with GUI elemenents.
1354
 
1092 dev 1355
		private delegate void AddLogMessageHandler(LogMessage message);
1356
		private delegate void AddTcpNodeHandler(TcpConnection tcp);
1357
		private delegate void UpdateTcpNodeHandler(TcpConnection tcp);
1358
		private delegate void AddHttpNodeHandler(TcpConnection tcp, HttpMessage http);
1359
		private delegate void UpdateHttpNodeHandler(HttpMessage http);
1360
 
1361
		private void AddLogMessageInternal(LogMessage message)
1362
		{
1363
			logMessages.Add(message);
1364
 
1365
			if(message.Exception != null)
1366
			{
1367
				Console.WriteLine(message.Exception.Message + " (" + message.Exception.GetType().Name
1368
					+ ")\n" + message.Exception.StackTrace);
1369
			}
1370
		}
1371
 
1238 dev 1372
        private string TcpNodeTitle(TcpConnection tcp)
1373
        {
1374
            return tcp.Id + " " + tcp.StartTimestamp.ToString("HH:mm:ss.ffff");
1375
        }
1376
 
1377
        private void AddTcpNodeInternal(TcpConnection tcp)
1092 dev 1378
		{
1238 dev 1379
            TreeNode    treeNode = new TreeNode(TcpNodeTitle(tcp));
1092 dev 1380
			TcpNodeData data     = new TcpNodeData(this, treeNode);
1381
 
1238 dev 1382
			data.Tcp                    = tcp;
1092 dev 1383
			treeNode.Tag                = data;
1232 dev 1384
			treeNode.ImageIndex         = (tcp.LocalState == SocketState.Closed
1199 dev 1385
				&& tcp.RemoteState == SocketState.Closed) ? 2 : 1;
1386
			treeNode.SelectedImageIndex = treeNode.ImageIndex;
1238 dev 1387
			treeNodes[tcp]              = data;
1092 dev 1388
 
1389
			messageView.Nodes.Add(treeNode);
1390
			treeNode.EnsureVisible();
1391
		}
1392
 
1393
		private void UpdateTcpNodeInternal(TcpConnection tcp)
1394
		{
1395
			TcpNodeData data = treeNodes[tcp] as TcpNodeData;
1125 dev 1396
			if(data == null) return; // might be call by Cancel
1092 dev 1397
 
1238 dev 1398
			string title = TcpNodeTitle(tcp);
1092 dev 1399
			if(title != data.Node.Text) data.Node.Text = title;
1400
			if(tcp.LocalState == SocketState.Closed && tcp.RemoteState == SocketState.Closed)
1401
			{
1402
				data.Node.ImageIndex         = 2;
1199 dev 1403
				data.Node.SelectedImageIndex = data.Node.ImageIndex;
1092 dev 1404
			}
1405
 
1406
			if(messageView.SelectedNode == null || data != messageView.SelectedNode.Tag)
1407
				data.ViewExpired = true;  // got update for invisible TCP node, update it later
1408
			else
1409
				data.Show();
1410
		}
1411
 
1238 dev 1412
        private string HttpNodeTitle(HttpMessage http)
1413
        {
1414
            return (http.Request.SoapAction != null ? ("SOAP " + http.Request.SoapAction)
1415
                : (http.Request.Method == null ? "" : http.Request.Method) + " " + (http.Request.Uri == null ? "" : http.Request.Uri));
1416
        }
1417
 
1418
        private void AddHttpNodeInternal(TcpConnection tcp, HttpMessage http)
1092 dev 1419
		{
1238 dev 1420
            TreeNode     treeNode = new TreeNode(HttpNodeTitle(http));
1092 dev 1421
			HttpNodeData data     = new HttpNodeData(this, treeNode);
1422
 
1238 dev 1423
			data.Http       = http;
1424
			treeNode.Tag    = data;
1092 dev 1425
			treeNodes[http] = data;
1426
 
1427
			TcpNodeData tcpData = treeNodes[tcp] as TcpNodeData;
1428
			if(tcpData == null) throw new ArgumentException("No node found for TCP message");
1429
 
1430
			tcpData.Node.Nodes.Add(treeNode);
1431
			if(autoExpand) tcpData.Node.Expand();
1432
			tcpData.Node.EnsureVisible();
1433
		}
1434
 
1435
		private void UpdateHttpNodeInternal(HttpMessage http)
1436
		{
1437
			HttpNodeData httpData = treeNodes[http] as HttpNodeData;
1125 dev 1438
			if(httpData == null) return; // might be call by Cancel
1092 dev 1439
 
1238 dev 1440
            string title = HttpNodeTitle(http);
1092 dev 1441
			if(httpData.Node.Text != title) httpData.Node.Text = title;
1442
 
1234 dev 1443
			if(!httpData.RequestXmlShown && http.Request.Xml != null)
1092 dev 1444
			{
1445
				httpData.RequestXmlShown = true;
1234 dev 1446
				AddXmlNode(httpData.Node, "Request XML", http.Request.Xml);
1092 dev 1447
				if(autoExpand) httpData.Node.Expand();
1448
			}
1449
 
1234 dev 1450
			if(!httpData.ResponseXmlShown && http.Response.Xml != null)
1092 dev 1451
			{
1452
				httpData.ResponseXmlShown = true;
1234 dev 1453
				AddXmlNode(httpData.Node, "Response XML", http.Response.Xml);
1092 dev 1454
				if(autoExpand) httpData.Node.Expand();
1455
			}
1456
 
1457
			// update text view
1458
			if(messageView.SelectedNode == null || httpData != messageView.SelectedNode.Tag)
1459
				httpData.ViewExpired = true;
1460
			else
1461
				httpData.Show();
1462
		}
1463
 
1464
		private void AddXmlNode(TreeNode parent, string title, XmlMessage xml)
1465
		{
1466
			TreeNode    treeNode = new TreeNode(title);
1467
			XmlNodeData data = new XmlNodeData(this, treeNode);
1468
 
1469
			data.Xml       = xml;
1470
			treeNode.Tag   = data;
1471
			treeNodes[xml] = data;
1472
 
1473
			parent.Nodes.Add(treeNode);
1474
		}
1475
 
1476
		#endregion handlers for async GUI events
1477
 
1478
		#region node display classes
1479
		private abstract class TreeNodeData
1480
		{
1481
			protected TreeNode node;
1482
			protected object   viewState;
1483
			protected bool     viewExpired;
1484
			protected MainForm owner;
1485
			protected bool     shown = false;
1486
 
1487
			public TreeNode Node
1488
			{
1489
				get { return node; }
1490
			}
1491
 
1492
			public TreeNodeData(MainForm owner, TreeNode node)
1493
			{
1494
				this.owner = owner;
1495
				this.node  = node;
1496
			}
1497
 
1498
			public bool ViewExpired
1499
			{
1500
				get { return viewExpired; }
1501
				set { viewExpired = value; }
1502
			}
1503
 
1504
			public void SaveViewState()
1505
			{
1506
				viewState = owner.messagesBox.SaveState(false);
1507
			}
1508
 
1509
			protected virtual bool ForceInitView()
1510
			{
1511
				return false;
1512
			}
1513
 
1514
			protected abstract void InitView();
1515
			protected abstract void UpdateView();
1516
 
1517
			public void Show()
1518
			{
1519
				if(!shown || viewState == null || ForceInitView())
1520
				{
1521
					InitView();
1522
					shown = true;
1523
					if(viewState == null) viewState = owner.messagesBox.SaveState(false);
1524
				}
1525
				else
1526
				{
1527
					owner.messagesBox.RestoreState(viewState, true);
1528
					if(viewExpired) UpdateView();
1529
				}
1530
			}
1531
 
1532
			public abstract void WriteLog(StreamWriter writer);
1533
		}
1534
 
1535
		private class TcpNodeData : TreeNodeData
1536
		{
1537
			private TcpConnection tcp;
1538
 
1539
			private TcpShowMode lastShowMode;
1540
			private object      localStateMarker  = null;
1541
			private object      remoteStateMarker = null;
1542
			private object      startMarker       = null;
1543
			private object      localEndMarker    = null;
1544
			private object      remoteEndMarker   = null;
1545
			private object      clientMarker      = null;
1546
			private object      serverMarker      = null;
1547
			private object      sentMarker        = null;
1548
			private object      receivedMarker    = null;
1549
			private object      textMarker1       = null;
1550
			private object      textMarker2       = null;
1551
			private IEnumerator messagesEnum      = null;
1552
 
1553
			public TcpConnection Tcp
1554
			{
1555
				get { return tcp; }
1556
				set { tcp = value; }
1557
			}
1558
 
1559
			public TcpNodeData(MainForm owner, TreeNode node)	: base(owner, node)
1560
			{
1561
			}
1562
 
1563
 
1564
			protected override bool ForceInitView()
1565
			{
1566
				return (lastShowMode != owner.tcpShowMode);
1567
			}
1568
 
1569
			protected override void InitView()
1570
			{
1571
				lastShowMode = owner.tcpShowMode;
1572
 
1573
				try
1574
				{
1575
					owner.messagesBox.BeginUpdate();
1576
 
1577
					lock(tcp)
1578
					{
1579
						owner.messagesBox.Clear();
1580
 
1581
						owner.messagesBox.AppendNewLine();
1582
						owner.messagesBox.AppendText("ID:         ",
1583
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1584
						owner.messagesBox.AppendText(tcp.Id,
1585
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1586
						owner.messagesBox.AppendNewLine();
1587
 
1588
						owner.messagesBox.AppendText("State:      ",
1589
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1590
						localStateMarker = owner.messagesBox.BeginMark();
1591
						owner.messagesBox.AppendText(tcp.LocalState.ToString(),
1592
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1593
						owner.messagesBox.EndMark(localStateMarker);
1594
						owner.messagesBox.AppendText(null,
1595
							Color.DarkRed, Color.Transparent, false, false, 1, 12);
1596
						remoteStateMarker = owner.messagesBox.BeginMark();
1597
						owner.messagesBox.AppendText(tcp.RemoteState.ToString(),
1598
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1599
						owner.messagesBox.EndMark(remoteStateMarker);
1600
						owner.messagesBox.AppendNewLine();
1601
 
1602
						owner.messagesBox.AppendText("Start:      ",
1603
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1604
						startMarker = owner.messagesBox.BeginMark();
1605
						owner.messagesBox.AppendText(tcp.StartTimestamp.ToString("HH:mm:ss.ffff"),
1606
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1607
						owner.messagesBox.EndMark(startMarker);
1608
						owner.messagesBox.AppendNewLine();
1609
						owner.messagesBox.AppendText("Local End:  ",
1610
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1611
						localEndMarker = owner.messagesBox.BeginMark();
1612
						owner.messagesBox.AppendText(tcp.LocalEndTimestamp.ToString("HH:mm:ss.ffff"),
1613
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1614
						owner.messagesBox.EndMark(localEndMarker);
1615
						owner.messagesBox.AppendNewLine();
1616
						owner.messagesBox.AppendText("Remote End: ",
1617
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1618
						remoteEndMarker = owner.messagesBox.BeginMark();
1619
						owner.messagesBox.AppendText(tcp.RemoteEndTimestamp.ToString("HH:mm:ss.ffff"),
1620
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1621
						owner.messagesBox.EndMark(remoteEndMarker);
1622
						owner.messagesBox.AppendNewLine();
1623
 
1624
						owner.messagesBox.AppendText("Client:     ",
1625
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1626
						clientMarker = owner.messagesBox.BeginMark();
1627
						owner.messagesBox.AppendText((tcp.LocalPoint == null) ? "" : tcp.LocalPoint.ToString(),
1628
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1629
						owner.messagesBox.EndMark(clientMarker);
1630
						owner.messagesBox.AppendNewLine();
1631
						owner.messagesBox.AppendText("Server:     ",
1632
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1633
						serverMarker = owner.messagesBox.BeginMark();
1634
						owner.messagesBox.AppendText((tcp.RemotePoint == null) ? "" : tcp.RemotePoint.ToString(),
1635
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1636
						owner.messagesBox.EndMark(serverMarker);
1637
						owner.messagesBox.AppendNewLine();
1638
 
1639
						owner.messagesBox.AppendText("Sent:       ",
1640
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1641
						sentMarker = owner.messagesBox.BeginMark();
1642
						owner.messagesBox.AppendText(tcp.SentBytes.ToString(),
1643
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1644
						owner.messagesBox.EndMark(sentMarker);
1645
						owner.messagesBox.AppendNewLine();
1646
						owner.messagesBox.AppendText("Received:   ",
1647
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1648
						receivedMarker = owner.messagesBox.BeginMark();
1649
						owner.messagesBox.AppendText(tcp.ReceivedBytes.ToString(),
1650
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1651
						owner.messagesBox.EndMark(receivedMarker);
1652
						owner.messagesBox.AppendNewLine();
1653
						owner.messagesBox.AppendNewLine();
1654
 
1655
						messagesEnum = tcp.Messages.GetEnumerator();
1656
 
1657
						textMarker1 = owner.messagesBox.BeginMark();
1658
						owner.messagesBox.EndMark(textMarker1);
1659
 
1660
						owner.messagesBox.AppendNewLine();
1661
						textMarker2 = owner.messagesBox.BeginMark();
1662
						owner.messagesBox.EndMark(textMarker2);
1663
 
1664
						ShowMessages();
1665
					}
1666
				}
1667
				finally
1668
				{
1669
					owner.messagesBox.EndUpdate();
1670
				}
1671
			}
1672
 
1673
			protected override void UpdateView()
1674
			{
1675
				try
1676
				{
1677
					owner.messagesBox.BeginUpdate();
1678
 
1679
					lock(tcp)
1680
					{
1681
						owner.messagesBox.ChangeText(localStateMarker, tcp.LocalState.ToString(),
1682
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1683
						owner.messagesBox.ChangeText(remoteStateMarker, tcp.RemoteState.ToString(),
1684
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1685
 
1686
						owner.messagesBox.ChangeText(startMarker, tcp.StartTimestamp.ToString("HH:mm:ss.ffff"),
1687
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1688
						owner.messagesBox.ChangeText(localEndMarker, tcp.LocalEndTimestamp.ToString("HH:mm:ss.ffff"),
1689
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1690
						owner.messagesBox.ChangeText(remoteEndMarker, tcp.RemoteEndTimestamp.ToString("HH:mm:ss.ffff"),
1691
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1692
 
1693
						owner.messagesBox.ChangeText(clientMarker, (tcp.LocalPoint == null) ? "" : tcp.LocalPoint.ToString(),
1694
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1695
						owner.messagesBox.ChangeText(serverMarker, (tcp.RemotePoint == null) ? "" : tcp.RemotePoint.ToString(),
1696
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1697
 
1698
						owner.messagesBox.ChangeText(sentMarker, tcp.SentBytes.ToString(),
1699
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1700
						owner.messagesBox.ChangeText(receivedMarker, tcp.ReceivedBytes.ToString(),
1701
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1702
 
1703
						ShowMessages();
1704
					}
1705
				}
1706
				finally
1707
				{
1708
					owner.messagesBox.EndUpdate();
1709
				}
1710
			}
1711
 
1712
			private void ShowMessages()
1713
			{
1714
				while(messagesEnum.MoveNext())
1715
				{
1716
					TcpMessage message = (TcpMessage)messagesEnum.Current;
1717
					object     marker  = (owner.tcpShowMode == TcpShowMode.ByTime
1718
						|| message.Direction == TcpMessageDirection.Local) ? textMarker1 : textMarker2;
1719
 
1720
					if(owner.tcpShowMode == TcpShowMode.ByTime)
1721
					{
1722
						owner.messagesBox.InsertText(marker,
1723
							message.Timestamp.ToString("HH:mm:ss.ffff") + " ("	+ message.Length + ")",
1724
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1725
						owner.messagesBox.InsertNewLine(marker);
1726
					}
1727
 
1728
					string str = Utils.BytesToString(message.Bytes, message.Length);
1729
					ArrayList lines = Utils.SplitLine(str);
1730
					for(int i = 0; i < lines.Count; i++)
1731
					{
1732
						owner.messagesBox.InsertText(marker, (string)lines[i],
1733
							message.Direction == TcpMessageDirection.Local ? Color.Green : Color.Blue,
1734
							Color.LightGray, false, false, 0, 0);
1735
 
1736
						if(owner.tcpShowMode == TcpShowMode.ByTime || i != lines.Count - 1)
1737
							owner.messagesBox.InsertNewLine(marker);
1738
					}
1739
				}
1740
			}
1741
 
1742
			public override void WriteLog(StreamWriter writer)
1743
			{
1744
				writer.WriteLine(
1745
					"Start:      " + tcp.StartTimestamp.ToString("HH:mm:ss.ffff")
1746
					+ "\r\nLocal End:  " + tcp.LocalEndTimestamp.ToString("HH:mm:ss.ffff")
1747
					+ "\r\nRemote End: " + tcp.RemoteEndTimestamp.ToString("HH:mm:ss.ffff")
1748
					+ "\r\nClient:     " + ((tcp.LocalPoint  == null) ? "" : tcp.LocalPoint.ToString())
1749
					+ "\r\nServer:     " + ((tcp.RemotePoint == null) ? "" : tcp.RemotePoint.ToString())
1750
					+ "\r\nSent:       " + tcp.SentBytes
1751
					+ "\r\nReceived:   " + tcp.ReceivedBytes);
1752
 
1753
				foreach(TcpMessage message in tcp.Messages)
1754
				{
1755
					string str = Utils.BytesToString(message.Bytes, message.Length);
1756
					if(!str.EndsWith("\n")) str += "\r\n";
1757
 
1758
					writer.WriteLine();
1759
					if(message.Direction == TcpMessageDirection.Local)
1760
						writer.WriteLine(">>> {0:HH:mm:ss.ffff} >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", message.Timestamp);
1761
					else
1762
						writer.WriteLine("<<< {0:HH:mm:ss.ffff} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", message.Timestamp);
1763
					writer.Write(str);
1764
				}
1765
				writer.WriteLine("===============================================================");
1766
				writer.WriteLine();
1767
			}
1768
		}
1769
 
1770
		private class HttpNodeData : TreeNodeData
1771
		{
1234 dev 1772
			private class MarkerSet
1773
			{
1774
				public object      start;
1775
				public object      method;
1776
				public object      uri;
1777
				public object      version;
1778
				public object      status;
1779
				public object      transferEncoding;
1780
				public object      length;
1781
				public object      contentEncoding;
1782
				public object      contentType;
1783
				public object      charset;
1784
				public object      headers;
1785
				public object      body;
1786
				public IEnumerator headersEnum;
1787
			}
1788
 
1092 dev 1789
			private HttpMessage http;
1790
			private bool        requestXmlShown  = false;
1791
			private bool        responseXmlShown = false;
1792
 
1234 dev 1793
			private object      stateMarker      = null;
1794
			private MarkerSet   requestMarkers   = new MarkerSet();
1795
			private MarkerSet   responseMarkers  = new MarkerSet();
1092 dev 1796
 
1797
			public HttpMessage Http
1798
			{
1799
				get { return http; }
1800
				set { http = value; }
1801
			}
1802
 
1803
			public bool RequestXmlShown
1804
			{
1805
				get { return requestXmlShown; }
1806
				set { requestXmlShown = value; }
1807
			}
1808
 
1809
			public bool ResponseXmlShown
1810
			{
1811
				get { return responseXmlShown; }
1812
				set { responseXmlShown = value; }
1813
			}
1814
 
1815
			public HttpNodeData(MainForm owner, TreeNode node) : base(owner, node)
1816
			{
1817
			}
1818
 
1233 dev 1819
			private string EncodingToString(HttpTransferEncoding encoding)
1092 dev 1820
			{
1821
				switch(encoding)
1822
				{
1233 dev 1823
					case HttpTransferEncoding.None:     return "none";
1824
					case HttpTransferEncoding.Identity: return "identity";
1825
					case HttpTransferEncoding.Chunked:  return "chunked";
1826
					case HttpTransferEncoding.Gzip:     return "gzip";
1827
					case HttpTransferEncoding.Compress: return "compress";
1828
					case HttpTransferEncoding.Deflate:  return "deflate";
1829
					default:                            return "<unknown>";
1092 dev 1830
				}
1831
			}
1832
 
1233 dev 1833
			private string EncodingToString(HttpContentEncoding encoding)
1834
			{
1835
				switch(encoding)
1836
				{
1837
					case HttpContentEncoding.None:     return "none";
1838
					case HttpContentEncoding.Identity: return "identity";
1839
					case HttpContentEncoding.Gzip:     return "gzip";
1840
					case HttpContentEncoding.Compress: return "compress";
1841
					case HttpContentEncoding.Deflate:  return "deflate";
1842
					default:                           return "<unknown>";
1843
				}
1844
			}
1845
 
1234 dev 1846
			private string VersionToString(HttpVersion version)
1092 dev 1847
			{
1234 dev 1848
				switch(version)
1092 dev 1849
				{
1234 dev 1850
					case HttpVersion.V0_9: return "HTTP/0.9";
1851
					case HttpVersion.V1_0: return "HTTP/1.0";
1852
					default:               return "HTTP/1.1";
1853
				}
1854
			}
1092 dev 1855
 
1234 dev 1856
			private void InitHttpHalfView(HttpHalfMessage half, MarkerSet markers, string title)
1857
			{
1858
				string padding = "";
1092 dev 1859
 
1234 dev 1860
				owner.messagesBox.AppendText(title + " Start:             " + padding,
1861
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1862
				markers.start = owner.messagesBox.BeginMark();
1863
				owner.messagesBox.AppendText(half.StartTimestamp == DateTime.MinValue
1864
					? "<unknown>" : half.StartTimestamp.ToString("HH:mm:ss.ffff"),
1865
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1866
				owner.messagesBox.EndMark(markers.start);
1867
				owner.messagesBox.AppendNewLine();
1125 dev 1868
 
1234 dev 1869
				if(half.IsRequest)
1870
				{
1871
					owner.messagesBox.AppendText(title + " Method:            " + padding,
1872
						Color.DarkRed, Color.Transparent, false, false, 0, 0);
1873
					markers.method = owner.messagesBox.BeginMark();
1874
					owner.messagesBox.AppendText((half as HttpRequest).Method,
1875
						Color.DarkRed, Color.LightGray, false, false, 0, 27);
1876
					owner.messagesBox.EndMark(markers.method);
1877
					owner.messagesBox.AppendNewLine();
1092 dev 1878
 
1234 dev 1879
					owner.messagesBox.AppendText(title + " URI:               " + padding,
1880
						Color.DarkRed, Color.Transparent, false, false, 0, 0);
1881
					markers.uri = owner.messagesBox.BeginMark();
1882
					owner.messagesBox.AppendText((half as HttpRequest).Uri,
1883
						Color.DarkRed, Color.LightGray, false, false, 0, 27);
1884
					owner.messagesBox.EndMark(markers.uri);
1885
					owner.messagesBox.AppendNewLine();
1886
				}
1887
				else 
1888
				{
1889
					owner.messagesBox.AppendText(title + " Status:            " + padding,
1890
						Color.DarkRed, Color.Transparent, false, false, 0, 0);
1891
					markers.status = owner.messagesBox.BeginMark();
1892
					owner.messagesBox.AppendText((half as HttpResponse).StatusCode 
1893
						+ " " + (half as HttpResponse).StatusMessage,
1894
						Color.DarkRed, Color.LightGray, false, false, 0, 27);
1895
					owner.messagesBox.EndMark(markers.status);
1896
					owner.messagesBox.AppendNewLine();
1897
				}
1092 dev 1898
 
1234 dev 1899
				owner.messagesBox.AppendText(title + " Version:           " + padding,
1900
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1901
				markers.version = owner.messagesBox.BeginMark();
1902
				owner.messagesBox.AppendText(VersionToString(half.Version),
1903
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1904
				owner.messagesBox.EndMark(markers.version);
1905
				owner.messagesBox.AppendNewLine();
1092 dev 1906
 
1234 dev 1907
				owner.messagesBox.AppendText(title + " Transfer Encoding: " + padding,
1908
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1909
				markers.transferEncoding = owner.messagesBox.BeginMark();
1910
				owner.messagesBox.AppendText(EncodingToString(half.TransferEncoding),
1911
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1912
				owner.messagesBox.EndMark(markers.transferEncoding);
1913
				owner.messagesBox.AppendNewLine();
1233 dev 1914
 
1234 dev 1915
				owner.messagesBox.AppendText(title + " Content Length:    " + padding,
1916
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1917
				markers.length = owner.messagesBox.BeginMark();
1918
				owner.messagesBox.AppendText(half.Length < 0 ? "<unknown>" : half.Length.ToString(),
1919
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1920
				owner.messagesBox.EndMark(markers.length);
1921
				owner.messagesBox.AppendNewLine();
1092 dev 1922
 
1234 dev 1923
				owner.messagesBox.AppendText(title + " Content Encoding:  " + padding,
1924
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1925
				markers.contentEncoding = owner.messagesBox.BeginMark();
1926
				owner.messagesBox.AppendText(EncodingToString(half.ContentEncoding),
1927
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1928
				owner.messagesBox.EndMark(markers.contentEncoding);
1929
				owner.messagesBox.AppendNewLine();
1092 dev 1930
 
1234 dev 1931
				owner.messagesBox.AppendText(title + " Content Type:      " + padding,
1932
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1933
				markers.contentType = owner.messagesBox.BeginMark();
1934
				owner.messagesBox.AppendText(half.ContentType == null ? "<unknown>"
1935
					: half.ContentType + "/" + half.ContentSubtype,
1936
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1937
				owner.messagesBox.EndMark(markers.contentType);
1938
				owner.messagesBox.AppendNewLine();
1092 dev 1939
 
1234 dev 1940
				owner.messagesBox.AppendText(title + " Content Charset:   " + padding,
1941
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1942
				markers.charset = owner.messagesBox.BeginMark();
1943
				owner.messagesBox.AppendText(half.Charset == null ? "<unknown>" : half.Charset,
1944
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1945
				owner.messagesBox.EndMark(markers.charset);
1946
				owner.messagesBox.AppendNewLine();
1092 dev 1947
 
1234 dev 1948
				owner.messagesBox.AppendText(title + " Headers:",
1949
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1950
				owner.messagesBox.AppendNewLine();
1951
				markers.headers = owner.messagesBox.BeginMark();
1952
				owner.messagesBox.EndMark(markers.headers);
1092 dev 1953
 
1234 dev 1954
				markers.headersEnum = half.Headers.GetEnumerator();
1955
				ShowHeaders(markers.headersEnum, markers.headers);
1956
			}
1092 dev 1957
 
1234 dev 1958
			private void UpdateHttpHalfView(HttpHalfMessage half, MarkerSet markers)
1959
			{
1960
				if(half.IsRequest)
1961
				{
1962
					owner.messagesBox.ChangeText(markers.method, (half as HttpRequest).Method,
1963
						Color.DarkRed, Color.LightGray, false, false, 0, 27);
1964
					owner.messagesBox.ChangeText(markers.uri, (half as HttpRequest).Uri,
1965
						Color.DarkRed, Color.LightGray, false, false, 0, 27);
1966
				}
1967
				else
1968
				{
1969
					owner.messagesBox.ChangeText(markers.status, (half as HttpResponse).StatusCode + " " + (half as HttpResponse).StatusMessage,
1970
						Color.DarkRed, Color.LightGray, false, false, 0, 27);
1971
				}
1125 dev 1972
 
1234 dev 1973
				owner.messagesBox.ChangeText(markers.version, VersionToString(half.Version),
1974
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1975
				owner.messagesBox.ChangeText(markers.transferEncoding, EncodingToString(half.TransferEncoding),
1976
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1977
				owner.messagesBox.ChangeText(markers.length, half.Length < 0
1978
					? "<unknown>" : half.Length.ToString(),
1979
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1980
				owner.messagesBox.ChangeText(markers.contentEncoding, EncodingToString(half.ContentEncoding),
1981
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1982
				owner.messagesBox.ChangeText(markers.contentType, half.ContentType == null ? "<unknown>"
1983
					: half.ContentType + "/" + half.ContentSubtype,
1984
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1985
				owner.messagesBox.ChangeText(markers.charset, half.Charset == null
1986
					? "<unknown>" : half.Charset,
1987
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1092 dev 1988
 
1234 dev 1989
				ShowHeaders(markers.headersEnum, markers.headers);
1990
			}
1092 dev 1991
 
1234 dev 1992
			protected override void InitView()
1993
			{
1994
				try
1995
				{
1996
					lock(http)
1997
					{
1998
						owner.messagesBox.Clear();
1233 dev 1999
 
1234 dev 2000
						// state
1092 dev 2001
						owner.messagesBox.AppendNewLine();
1234 dev 2002
						owner.messagesBox.AppendText("Complete:                   ",
1092 dev 2003
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1234 dev 2004
						stateMarker = owner.messagesBox.BeginMark();
2005
						owner.messagesBox.AppendText(http.Request.Complete && http.Response.Complete ? "YES" : "NO",
1092 dev 2006
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1234 dev 2007
						owner.messagesBox.EndMark(stateMarker);
1092 dev 2008
						owner.messagesBox.AppendNewLine();
2009
						owner.messagesBox.AppendNewLine();
2010
 
1234 dev 2011
						// general info
2012
						InitHttpHalfView(http.Request,  requestMarkers,  "Request");
2013
						InitHttpHalfView(http.Response, responseMarkers, "Response");
1092 dev 2014
 
1234 dev 2015
						// bodies
1092 dev 2016
						owner.messagesBox.AppendNewLine();
1234 dev 2017
						requestMarkers.body = owner.messagesBox.BeginMark();
2018
						owner.messagesBox.EndMark(requestMarkers.body);
2019
						ShowBody(requestMarkers, http.Request, Color.Green);
1092 dev 2020
 
2021
						owner.messagesBox.AppendNewLine();
1234 dev 2022
						responseMarkers.body = owner.messagesBox.BeginMark();
2023
						owner.messagesBox.EndMark(responseMarkers.body);
2024
						ShowBody(responseMarkers, http.Response, Color.Blue);
1092 dev 2025
					}
2026
				}
2027
				finally
2028
				{
2029
					owner.messagesBox.EndUpdate();
2030
				}
2031
			}
2032
 
2033
			protected override void UpdateView()
2034
			{
2035
				try
2036
				{
2037
					owner.messagesBox.BeginUpdate();
2038
 
2039
					lock(http)
2040
					{
1234 dev 2041
						// state
2042
						owner.messagesBox.ChangeText(stateMarker, http.Request.Complete && http.Response.Complete ? "YES" : "NO",
1092 dev 2043
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
2044
 
1234 dev 2045
						// general info
2046
						UpdateHttpHalfView(http.Request,  requestMarkers);
2047
						UpdateHttpHalfView(http.Response, responseMarkers);
1092 dev 2048
 
1234 dev 2049
						// bodies
2050
						owner.messagesBox.DeleteText(requestMarkers.body);
2051
						ShowBody(requestMarkers, http.Request, Color.Green);
2052
						owner.messagesBox.DeleteText(responseMarkers.body);
2053
						ShowBody(responseMarkers, http.Response, Color.Blue);
1092 dev 2054
					}
2055
				}
2056
				finally
2057
				{
2058
					owner.messagesBox.EndUpdate();
2059
				}
2060
			}
2061
 
2062
			private void ShowHeaders(IEnumerator headers, object marker)
2063
			{
2064
				while(headers.MoveNext())
2065
				{
2066
					HttpHeader h = (HttpHeader)headers.Current;
2067
 
2068
					bool first = true;
2069
					foreach(string val in h.Values)
2070
					{
2071
						if(first)
2072
						{
2073
							owner.messagesBox.InsertText(marker, h.Name + ":",
2074
								Color.DarkRed, Color.Transparent, false, false, 4, 4);
2075
							owner.messagesBox.InsertText(marker, null,
2076
								Color.DarkRed, Color.Transparent, false, false, 6 - 4 - 1, 4);
2077
							first = false;
2078
						}
2079
						else
2080
						{
2081
							owner.messagesBox.InsertText(marker, null,
2082
								Color.DarkRed, Color.Transparent, false, false, 6 + h.Name.Length, 6 + h.Name.Length);
2083
						}
2084
						owner.messagesBox.InsertText(marker, val,
2085
							Color.DarkRed, Color.LightGray, false, false, 0, 6 + h.Name.Length);
2086
						owner.messagesBox.InsertNewLine(marker);
2087
					}
2088
				}
2089
			}
2090
 
1234 dev 2091
			private void ShowBody(MarkerSet markers, HttpHalfMessage half, Color color)
1092 dev 2092
			{
1234 dev 2093
				if(half.Text != null)
1092 dev 2094
				{
1234 dev 2095
					ArrayList lines = Utils.SplitLine(half.Text);
1092 dev 2096
					for(int i = 0; i < lines.Count; i++)
2097
					{
1234 dev 2098
						owner.messagesBox.InsertText(markers.body, (string)lines[i], color, Color.LightGray, false, false, 0, 0);
2099
						owner.messagesBox.InsertNewLine(markers.body);
1092 dev 2100
					}
2101
				}
1234 dev 2102
				else if(half.Body != null)
1092 dev 2103
				{
1234 dev 2104
					ArrayList lines = Utils.SplitLine(Utils.BytesToString(half.Body, half.Length));
1092 dev 2105
					for(int i = 0; i < lines.Count; i++)
2106
					{
1234 dev 2107
						owner.messagesBox.InsertText(markers.body, (string)lines[i], color, Color.LightGray, false, false, 0, 0);
2108
						owner.messagesBox.InsertNewLine(markers.body);
1092 dev 2109
					}
2110
				}
2111
			}
2112
 
2113
			public override void WriteLog(StreamWriter writer)
2114
			{
2115
				// request info
2116
				writer.WriteLine(
1234 dev 2117
					"Complete:                   " + (http.Request.Complete && http.Response.Complete ? "YES" : "NO") + "\r\n"
2118
					+ "\r\nRequest Method:             " + http.Request.Method
2119
					+ "\r\nRequest URI:                " + http.Request.Uri
2120
					+ "\r\nRequest Version:            " + (http.Request.Version == HttpVersion.V0_9 ? "HTTP/0.9"
2121
						: http.Request.Version == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1")
2122
					+ "\r\nRequest Transfer Encoding:  " + EncodingToString(http.Request.TransferEncoding)
2123
					+ "\r\nRequest Content Length:     " + (http.Request.Length < 0 ? "<unknown>" : http.Request.Length.ToString())
2124
					+ "\r\nRequest Content Encoding:   " + EncodingToString(http.Request.ContentEncoding)
2125
					+ "\r\nRequest Content Type:       " + (http.Request.ContentType == null ? "<unknown>"
2126
						: http.Request.ContentType + "/" + http.Request.ContentSubtype)
2127
					+ "\r\nRequest Content Charset:    " + (http.Request.Charset == null ? "<unknown>" : http.Request.Charset)
1092 dev 2128
					+ "\r\nRequest Headers:");
2129
 
1234 dev 2130
				foreach(HttpHeader h in http.Request.Headers)
1092 dev 2131
				{
2132
					int indent = 0;
2133
					foreach(string val in h.Values)
2134
					{
2135
						if(indent == 0)
2136
						{
2137
							writer.WriteLine("    {0}: {1}", h.Name, val);
2138
							indent = 6 + h.Name.Length;
2139
						}
2140
						else
2141
						{
2142
							writer.WriteLine("{0," + indent + "}{1}", " ", val);
2143
						}
2144
					}
2145
				}
2146
 
2147
				// response info
2148
				writer.WriteLine(
1234 dev 2149
					"\r\nResponse Version:           " + (http.Response.Version == HttpVersion.V0_9
2150
						? "HTTP/0.9" : http.Response.Version == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1")
2151
					+ "\r\nResponse Status:            " + http.Response.StatusCode + " " + http.Response.StatusMessage
2152
					+ "\r\nResponse Transfer Encoding: " + EncodingToString(http.Response.TransferEncoding)
2153
					+ "\r\nResponse Content Length:    " + (http.Response.Length < 0
2154
						? "<unknown>" : http.Response.Length.ToString())
2155
					+ "\r\nResponse Content Encoding:  " + EncodingToString(http.Response.ContentEncoding)
2156
					+ "\r\nResponse Content Type:      " + (http.Response.ContentType == null ? "<unknown>"
2157
						: http.Response.ContentType + "/" + http.Response.ContentSubtype)
2158
					+ "\r\nResponse Content Charset:   " + (http.Response.Charset == null ? "<unknown>" : http.Response.Charset)
1092 dev 2159
					+ "\r\nResponse Headers:");
2160
 
1234 dev 2161
				foreach(HttpHeader h in http.Response.Headers)
1092 dev 2162
				{
2163
					int indent = 0;
2164
					foreach(string val in h.Values)
2165
					{
2166
						if(indent == 0)
2167
						{
2168
							writer.WriteLine("    {0}: {1}", h.Name, val);
2169
							indent = 6 + h.Name.Length;
2170
						}
2171
						else
2172
						{
2173
							writer.WriteLine("{0," + indent + "}{1}", " ", val);
2174
						}
2175
					}
2176
				}
2177
				writer.WriteLine();
2178
 
2179
				// request body
1234 dev 2180
				if(http.Request.Text != null)
1092 dev 2181
				{
1234 dev 2182
					writer.WriteLine(http.Request.Text);
1092 dev 2183
				}
1234 dev 2184
				else if(http.Request.Body != null)
1092 dev 2185
				{
1234 dev 2186
					writer.WriteLine(Utils.BytesToString(http.Request.Body, http.Request.Length));
1092 dev 2187
				}
2188
 
2189
				// response body
1234 dev 2190
				if(http.Response.Text != null)
1092 dev 2191
				{
1234 dev 2192
					writer.WriteLine(http.Response.Text);
1092 dev 2193
				}
1234 dev 2194
				else if(http.Response.Body != null)
1092 dev 2195
				{
1234 dev 2196
					writer.WriteLine(Utils.BytesToString(http.Response.Body, http.Response.Length));
1092 dev 2197
				}
2198
 
2199
				writer.WriteLine("===============================================================");
2200
				writer.WriteLine();
2201
			}
2202
		}
2203
 
2204
		private class XmlNodeData : TreeNodeData
2205
		{
2206
			private XmlMessage xml;
2207
 
2208
			public XmlMessage Xml
2209
			{
2210
				get { return xml; }
2211
				set { xml = value; }
2212
			}
2213
 
2214
			public XmlNodeData(MainForm owner, TreeNode node) : base(owner, node)
2215
			{
2216
			}
2217
 
2218
			protected override void InitView()
2219
			{
2220
				try
2221
				{
2222
					// update main screen if necessary
2223
					owner.messagesBox.BeginUpdate();
2224
 
2225
					lock(xml)
2226
					{
2227
						owner.messagesBox.Clear();
2228
						if(xml.ParseException != null)
2229
						{
2230
							owner.messagesBox.AppendText("Cannot parse XML:",
2231
								Color.Red, Color.Transparent, false, false, 0, 0);
2232
							owner.messagesBox.AppendNewLine();
2233
							owner.messagesBox.AppendText(xml.ParseException.Message,
2234
								Color.Red, Color.Transparent, false, false, 2, 2);
2235
							owner.messagesBox.AppendNewLine();
2236
						}
2237
						else if(xml.Xml != null)
2238
						{
2239
							ShowXmlNode(xml.Xml, 0);
2240
						}
2241
					}
2242
				}
2243
				finally
2244
				{
2245
					owner.messagesBox.EndUpdate();
2246
				}
2247
			}
2248
 
2249
			protected override void UpdateView()
2250
			{
2251
			}
2252
 
2253
			private void ShowXmlNode(XmlNode node, int indent)
2254
			{
2255
				if(node.NodeType == XmlNodeType.Document)
2256
				{
2257
					foreach(XmlNode subnode in node.ChildNodes)
2258
					{
2259
						ShowXmlNode(subnode, indent);
2260
					}
2261
				}
2262
				else if(node.NodeType == XmlNodeType.XmlDeclaration)
2263
				{
2264
					owner.messagesBox.AppendText("<?" + node.Name + " " + node.Value + " ?>",
2265
						Color.Blue, Color.Transparent, false, false, indent, indent+2);
2266
					owner.messagesBox.AppendNewLine();
2267
				}
2268
				else if(node.NodeType == XmlNodeType.Comment)
2269
				{
2270
					owner.messagesBox.AppendText("<!--", Color.Gray, Color.Transparent, false, false, indent, indent + 2);
2271
					ShowNormalizedXmlValue(node.Value, Color.Gray, Color.Thistle, false, false, indent);
2272
					owner.messagesBox.AppendText("-->", Color.Gray, Color.Transparent, false, false, 0, indent + 2);
2273
					owner.messagesBox.AppendNewLine();
2274
				}
2275
				else if(node.NodeType == XmlNodeType.Element)
2276
				{
2277
					owner.messagesBox.AppendText("<", Color.Blue, Color.Transparent, false, false, indent, indent + 2);
2278
					owner.messagesBox.AppendText(node.Name, Color.DarkRed, Color.Transparent, false, false, 0, indent + 2);
2279
 
2280
					foreach(XmlAttribute attr in node.Attributes)
2281
					{
2282
						bool xmlAttr = attr.Name.StartsWith("xml");
2283
						owner.messagesBox.AppendText(attr.Name, xmlAttr ? Color.Red : Color.DarkRed, Color.Transparent, false, false, 1, indent + 2);
2284
						owner.messagesBox.AppendText("=\"", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2285
						owner.messagesBox.AppendText(attr.Value, xmlAttr ? Color.Red : Color.DarkRed, Color.Transparent, false, false, 0, indent + 2);
2286
						owner.messagesBox.AppendText("\"", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2287
					}
2288
 
2289
					if(!node.HasChildNodes)
2290
					{
2291
						owner.messagesBox.AppendText(" />", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2292
						owner.messagesBox.AppendNewLine();
2293
					}
2294
					else
2295
					{
2296
						owner.messagesBox.AppendText(">", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2297
 
2298
						bool elementExists = false;
2299
						bool lastText      = true;
2300
						foreach(XmlNode subnode in node.ChildNodes)
2301
						{
2302
							if(subnode.NodeType == XmlNodeType.Text)
2303
							{
2304
								if(elementExists) owner.messagesBox.AppendNewLine();
2305
								ShowNormalizedXmlValue(subnode.Value, Color.Black, Color.LightGray, false, false, indent);
2306
								lastText = true;
2307
							}
2308
							else
2309
							{
2310
								if(lastText) owner.messagesBox.AppendNewLine();
2311
								ShowXmlNode(subnode, indent + 2);
2312
								elementExists = true;
2313
								lastText      = false;
2314
							}
2315
						}
2316
 
2317
						if(elementExists) owner.messagesBox.AppendText(null, Color.Black, Color.Transparent, false, false, indent, indent + 2);
2318
						owner.messagesBox.AppendText("</", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2319
						owner.messagesBox.AppendText(node.Name, Color.DarkRed, Color.Transparent, false, false, 0, indent + 2);
2320
						owner.messagesBox.AppendText(">", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2321
						owner.messagesBox.AppendNewLine();
2322
					}
2323
				}
2324
			}
2325
 
2326
			private void ShowNormalizedXmlValue(string s, Color color, Color backColor, bool italic, bool bold, int indent)
2327
			{
2328
				int begin;
2329
				int end;
2330
 
2331
				bool newLineFound = false;
2332
				foreach(char c in s)
2333
				{
2334
					if(c == '\n')
2335
					{
2336
						newLineFound = true;
2337
						break;
2338
					}
2339
				}
2340
 
2341
				if(newLineFound)
2342
				{
2343
					owner.messagesBox.AppendNewLine();
2344
					owner.messagesBox.AppendText(null, color, Color.Transparent, italic, bold, indent, indent);
2345
					owner.messagesBox.AppendText(null, color, backColor, italic, bold, 2, 2);
2346
				}
2347
 
2348
				// trim
2349
				for(begin = 0; begin < s.Length; begin++)
2350
				{
2351
					char c = s[begin];
2352
					if(c != '\n' && c != '\r' && c != '\t' && c != ' ') break;
2353
				}
2354
				for(end = s.Length-1; end >= 0; end--)
2355
				{
2356
					char c = s[end];
2357
					if(c != '\n' && c != '\r' && c != '\t' && c != ' ') break;
2358
				}
2359
 
2360
				StringBuilder b = new StringBuilder(s.Length);
2361
				for(int i = begin; i <= end; i++)
2362
				{
2363
					char c = s[i];
2364
 
2365
					switch(c)
2366
					{
2367
						case '\n':
2368
							if(b.Length > 0)
2369
							{
2370
								owner.messagesBox.AppendText(b.ToString(), color, backColor, italic, bold, 0, indent + 2);
2371
								b.Length = 0;
2372
							}
2373
 
2374
							owner.messagesBox.AppendNewLine();
2375
							owner.messagesBox.AppendText(null, color, Color.Transparent, italic, bold, indent, indent);
2376
							owner.messagesBox.AppendText(null, color, backColor, italic, bold, 2, 2);
2377
							break;
2378
 
2379
						case '\r':
2380
							break;
2381
 
2382
						case '\t':
2383
							b.Append("  ");
2384
							break;
2385
 
2386
						default:
2387
							b.Append(c);
2388
							break;
2389
					}
2390
				}
2391
 
2392
				if(b.Length > 0)
2393
					owner.messagesBox.AppendText(b.ToString(), color, backColor, italic, bold, 0, indent + 2);
2394
 
2395
				if(newLineFound)
2396
				{
2397
					owner.messagesBox.AppendNewLine();
2398
					owner.messagesBox.AppendText(null, color, Color.Transparent, italic, bold, indent, indent + 2);
2399
				}
2400
			}
2401
 
2402
			public override void WriteLog(StreamWriter writer)
2403
			{
2404
				WriteXmlNode(writer, xml.Xml, "");
2405
				writer.WriteLine("===============================================================");
2406
				writer.WriteLine();
2407
			}
2408
 
2409
			private void WriteXmlNode(StreamWriter writer, XmlNode node, string indent)
2410
			{
2411
				if(node.NodeType == XmlNodeType.Document)
2412
				{
2413
					foreach(XmlNode subnode in node.ChildNodes)
2414
					{
2415
						WriteXmlNode(writer, subnode, indent);
2416
					}
2417
				}
2418
				else if(node.NodeType == XmlNodeType.XmlDeclaration)
2419
				{
2420
					writer.WriteLine(indent + "<?" + node.Name + " " + node.Value + " ?>");
2421
				}
2422
				else if(node.NodeType == XmlNodeType.Comment)
2423
				{
2424
					writer.Write(indent + "<!--");
2425
					WriteNormalizedXmlValue(writer, node.Value, indent);
2426
					writer.WriteLine("-->");
2427
				}
2428
				else if(node.NodeType == XmlNodeType.Element)
2429
				{
2430
					writer.Write(indent + "<" + node.Name);
2431
 
2432
					foreach(XmlAttribute attr in node.Attributes)
2433
					{
2434
						bool xmlAttr = attr.Name.StartsWith("xml");
2435
						writer.Write(" " + attr.Name + "=\"" + attr.Value + "\"");
2436
					}
2437
 
2438
					if(!node.HasChildNodes)
2439
					{
2440
						writer.WriteLine(" />");
2441
					}
2442
					else
2443
					{
2444
						writer.Write(">");
2445
 
2446
						bool elementExists = false;
2447
						bool lastText      = true;
2448
						foreach(XmlNode subnode in node.ChildNodes)
2449
						{
2450
							if(subnode.NodeType == XmlNodeType.Text)
2451
							{
2452
								if(elementExists) writer.WriteLine();
2453
								WriteNormalizedXmlValue(writer, subnode.Value, indent);
2454
								lastText = true;
2455
							}
2456
							else
2457
							{
2458
								if(lastText) writer.WriteLine();
2459
								WriteXmlNode(writer, subnode, indent + "  ");
2460
								elementExists = true;
2461
								lastText      = false;
2462
							}
2463
						}
2464
 
2465
						if(elementExists) writer.Write(indent);
2466
						writer.WriteLine("</" + node.Name + ">");
2467
					}
2468
				}
2469
			}
2470
 
2471
			private void WriteNormalizedXmlValue(StreamWriter writer, string s, string indent)
2472
			{
2473
				int begin;
2474
				int end;
2475
 
2476
				bool newLineFound = false;
2477
				foreach(char c in s)
2478
				{
2479
					if(c == '\n')
2480
					{
2481
						newLineFound = true;
2482
						break;
2483
					}
2484
				}
2485
 
2486
				if(newLineFound)
2487
				{
2488
					writer.WriteLine();
2489
					writer.Write(indent + "  ");
2490
				}
2491
 
2492
				// trim
2493
				for(begin = 0; begin < s.Length; begin++)
2494
				{
2495
					char c = s[begin];
2496
					if(c != '\n' && c != '\r' && c != '\t' && c != ' ') break;
2497
				}
2498
				for(end = s.Length-1; end >= 0; end--)
2499
				{
2500
					char c = s[end];
2501
					if(c != '\n' && c != '\r' && c != '\t' && c != ' ') break;
2502
				}
2503
 
2504
				StringBuilder b = new StringBuilder(s.Length);
2505
				for(int i = begin; i <= end; i++)
2506
				{
2507
					char c = s[i];
2508
 
2509
					switch(c)
2510
					{
2511
						case '\n':
2512
							if(b.Length > 0)
2513
							{
2514
								writer.Write(b.ToString());
2515
								b.Length = 0;
2516
							}
2517
 
2518
							writer.WriteLine();
2519
							writer.Write(indent + "  ");
2520
							break;
2521
 
2522
						case '\r':
2523
							break;
2524
 
2525
						case '\t':
2526
							b.Append("  ");
2527
							break;
2528
 
2529
						case '&':
2530
							b.Append("&amp;");
2531
							break;
2532
 
2533
						case '<':
2534
							b.Append("&lt;");
2535
							break;
2536
 
2537
						case '>':
2538
							b.Append("&gt;");
2539
							break;
2540
 
2541
						default:
2542
							b.Append(c);
2543
							break;
2544
					}
2545
				}
2546
 
2547
				if(b.Length > 0)
2548
					writer.Write(b.ToString());
2549
 
2550
				if(newLineFound)
2551
				{
2552
					writer.WriteLine();
2553
					writer.Write(indent + "  ");
2554
				}
2555
			}
2556
		}
2557
 
2558
		#endregion node display classes
2559
 
2560
		#region other classes
2561
		private abstract class Utils
2562
		{
2563
			public static string BytesToString(byte[] bytes, int length)
2564
			{
2565
				if(bytes == null) return null;
2566
 
2567
				char[]  chars   = new char[length + 1];
2568
				Decoder decoder = System.Text.Encoding.UTF8.GetDecoder();
2569
				int     charLen = decoder.GetChars(bytes, 0, length, chars, 0);
2570
 
2571
				for(int i = 0; i < charLen; i++)
2572
				{
2573
					char c = chars[i];
2574
					if(c != '\n' && c != '\r' && Char.IsControl(c)) chars[i] = '.';
2575
				}
2576
 
2577
				return (new System.String(chars)).Substring(0, charLen);
2578
			}
2579
 
2580
			public static ArrayList SplitLine(string line)
2581
			{
2582
				if(line == null) return null;
2583
 
2584
				ArrayList    res = new ArrayList();
2585
				StringBuilder b  = new StringBuilder(200);
2586
 
2587
				foreach(char c in line)
2588
				{
2589
					switch(c)
2590
					{
2591
						case '\r':
2592
							break;
2593
 
2594
						case '\n':
2595
							res.Add(b.ToString());
2596
							b.Length = 0;
2597
							break;
2598
 
2599
						default:
2600
							b.Append(c);
2601
							break;
2602
					}
2603
				}
2604
 
2605
				res.Add(b.ToString());
2606
 
2607
				return res;
2608
			}
2609
		}
2610
		#endregion other classes
2611
	}
2612
 
2613
	public class LogMessages
2614
	{
2615
		private ArrayList messages = new ArrayList();
2616
		private ListBox   logBox;
2617
		private LogLevel  level = LogLevel.Debug;
2618
 
2619
		public LogLevel Level
2620
		{
2621
			get { return level; }
2622
			set { level = value; Update(); }
2623
		}
2624
 
2625
		public LogMessages(ListBox logBox)
2626
		{
2627
			this.logBox = logBox;
2628
		}
2629
 
2630
		public ArrayList Messages
2631
		{
2632
			get { return new ArrayList(messages); }
2633
		}
2634
 
2635
		public void Add(LogMessage message)
2636
		{
2637
			messages.Add(message);
2638
			if(Show(message))
2639
				logBox.TopIndex = logBox.Items.Count - 1;
2640
		}
2641
 
2642
		public void Clear()
2643
		{
2644
			messages.Clear();
2645
			logBox.Items.Clear();
2646
		}
2647
 
2648
		public void Update()
2649
		{
2650
			logBox.BeginUpdate();
2651
 
2652
			logBox.Items.Clear();
2653
			foreach(LogMessage message in messages)
2654
			{
2655
				Show(message);
2656
			}
2657
			logBox.TopIndex = logBox.Items.Count - 1;
2658
 
2659
			logBox.EndUpdate();
2660
		}
2661
 
2662
		private bool Show(LogMessage message)
2663
		{
2664
			if(message.Level > this.level) return false;
2665
 
2666
			try
2667
			{
2668
				logBox.Items.Add(message.ToString());
2669
			}
2670
			catch(ObjectDisposedException) {}
2671
 
2672
			return true;
2673
		}
2674
	}
2675
 
2676
	public class LogMessage
2677
	{
2678
		private TcpConnection tcp;
2679
		private LogLevel      level;
2680
		private string        message;
2681
		private Exception     exception;
2682
		private DateTime      timestamp = DateTime.Now;
2683
 
2684
		public TcpConnection Tcp
2685
		{
2686
			get { return tcp; }
2687
			set { tcp = value; }
2688
		}
2689
 
2690
		public LogLevel Level
2691
		{
2692
			get { return level; }
2693
			set { level = value; }
2694
		}
2695
 
2696
		public string Message
2697
		{
2698
			get { return message; }
2699
			set { message = value; }
2700
		}
2701
 
2702
		public Exception Exception
2703
		{
2704
			get { return exception; }
2705
			set { exception = value; }
2706
		}
2707
 
2708
		public DateTime Timestamp
2709
		{
2710
			get { return timestamp; }
2711
			set { timestamp = value; }
2712
		}
2713
 
2714
		public LogMessage(TcpConnection tcp, LogLevel level, string message, Exception exception)
2715
		{
2716
			this.tcp       = tcp;
2717
			this.level     = level;
2718
			this.message   = message;
2719
			this.exception = exception;
2720
		}
2721
 
2722
		public override string ToString()
2723
		{
2724
			string l = "     ";
2725
			switch(level)
2726
			{
2727
				case LogLevel.Debug:     l = "debug"; break;
2728
				case LogLevel.Info:      l = "info "; break;
2729
				case LogLevel.Important: l = "Imp  "; break;
2730
				case LogLevel.Warning:   l = "Warn "; break;
2731
				case LogLevel.Error:     l = "ERROR"; break;
2732
				case LogLevel.Critical:  l = "CRIT "; break;
2733
			}
2734
 
2735
			return (tcp == null ? "...." : tcp.Id) + " " + l + " " + timestamp.ToString("HH:mm:ss.ffff") + " "
2736
				+ (exception != null ? exception.Message : message);
2737
		}
2738
	}
2739
 
2740
	public enum TcpShowMode
2741
	{
2742
		ByDirection,
2743
		ByTime
2744
	}
1194 dev 2745
 
2746
	public class RecentItem : IComparable
2747
	{
2748
		private int listenPort;
2749
 
2750
		public int ListenPort
2751
		{
2752
			get { return listenPort; }
2753
			set { listenPort = value; }
2754
		}
2755
 
2756
		private string resendHost;
2757
 
2758
		public string ResendHost
2759
		{
2760
			get { return resendHost; }
2761
			set { resendHost = value; }
2762
		}
2763
 
2764
		private int resendPort;
2765
 
2766
		public int ResendPort
2767
		{
2768
			get { return resendPort; }
2769
			set { resendPort = value; }
2770
		}
2771
 
2772
		private DateTime timestamp;
2773
 
2774
		public DateTime Timestamp
2775
		{
2776
			get { return timestamp; }
2777
		}
2778
 
2779
		public RecentItem(int listenPort, string resendHost, int resendPort)
2780
		{
2781
			this.listenPort = listenPort;
2782
			this.resendHost = resendHost;
2783
			this.resendPort = resendPort;
2784
		}
2785
 
2786
		public override string ToString()
2787
		{
1197 dev 2788
			return string.Format("{0} to {1}:{2} at {3:HH:mm:ss.ff}",
1194 dev 2789
				listenPort, resendHost, resendPort, timestamp);
2790
		}
2791
 
2792
		public override bool Equals(object obj)
2793
		{
2794
			if(!(obj is RecentItem)) return false;
2795
 
2796
			RecentItem i2 = (RecentItem)obj;
2797
 
2798
			return (i2.listenPort == this.listenPort) && (i2.resendHost == this.resendHost)
2799
				&& (i2.resendPort == this.resendPort);
2800
		}
2801
 
2802
		public override int GetHashCode()
2803
		{
2804
			return this.resendHost.GetHashCode();
2805
		}
2806
 
2807
		public string SaveToRegistry()
2808
		{
1197 dev 2809
			return string.Format("{0}:{1}:{2}:{3}",
1194 dev 2810
				listenPort, resendPort, timestamp.Ticks, resendHost);
2811
		}
2812
 
2813
		public static RecentItem LoadFromRegistry(string str)
2814
		{
2815
			Regex re = new Regex(@"^(\d+):(\d+):(\d+):(.+)$");
2816
			Match m  = re.Match(str);
2817
			if(!m.Success) throw new Exception("Cannot parse recent item");
2818
 
1197 dev 2819
			RecentItem item = new RecentItem(int.Parse(m.Groups[1].Value),
1194 dev 2820
				m.Groups[4].Value, int.Parse(m.Groups[2].Value));
2821
 
2822
			item.timestamp = new DateTime(long.Parse(m.Groups[3].Value));
2823
 
2824
			return item;
2825
		}
2826
 
2827
		public void UpdateTimestamp()
2828
		{
2829
			timestamp = DateTime.Now;
2830
		}
2831
 
2832
		public void UpdateTimestamp(RecentItem second)
2833
		{
2834
			if(second.timestamp > timestamp)
2835
				timestamp = second.timestamp;
2836
		}
2837
 
2838
		#region IComparable Members
2839
 
2840
		int IComparable.CompareTo(object obj)
2841
		{
2842
			if(!(obj is RecentItem))
2843
				throw new Exception("Cannot compare");
2844
 
2845
			return this.timestamp.CompareTo(((RecentItem)obj).timestamp);
2846
		}
2847
 
2848
		#endregion
2849
	}
1092 dev 2850
}