Subversion Repositories general

Rev

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

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