Subversion Repositories general

Rev

Rev 1289 | 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
 
1290 dev 615
 
616
		    messagesBox.BeginUpdate();
617
            messagesBox.Clear();
618
 
619
            for(int i = 0; i < 50; ++i) {
620
                messagesBox.AppendNewLine();
621
                messagesBox.AppendText(String.Format("Line {0} 12345689 12345689 12345689 12345689 12345689 12345689 12345689 12345689 12345689 12345689 12345689",
622
                    i+1), Color.Black, Color.Transparent, false, false, 0, 0);
623
            }
624
 
625
            messagesBox.EndUpdate();
626
        }
627
 
1194 dev 628
		protected override void Dispose(bool disposing)
1092 dev 629
		{
1240 dev 630
			clearing = true;
631
 
1194 dev 632
			if(tcpListener != null) {
1092 dev 633
				tcpListener.StopListening();    // stop listening
634
				tcpListener.CancelAll();        // cancel all open connections
635
			}
636
 
1194 dev 637
			// save settings
1197 dev 638
			SaveToRegistry();
1194 dev 639
			SaveRecentItemsToRegistry();
1092 dev 640
 
641
			if( disposing )
642
			{
643
				if (components != null)
644
				{
645
					components.Dispose();
646
				}
647
			}
648
			base.Dispose( disposing );
1232 dev 649
 
650
			ThreadDebugger.PrintStatus();
1092 dev 651
		}
652
 
653
		[STAThread]
654
		static void Main()
655
		{
656
			Application.Run(new MainForm());
657
		}
658
 
1194 dev 659
		private void startMenuItem_Click(object sender, System.EventArgs e)
660
		{
661
			IPAddress resendIp;
662
 
1197 dev 663
			if(!listenForm.Execute(this,
1194 dev 664
				ref listenPort, ref resendHost, out resendIp, ref resendPort)) return;
665
 
666
			StartListening(listenPort, resendIp, resendPort);
667
		}
668
 
669
		private void stopMenuItem_Click(object sender, System.EventArgs e)
1092 dev 670
		{
1199 dev 671
			StopListening();
1092 dev 672
		}
673
 
1194 dev 674
		private void clearMenuItem_Click(object sender, System.EventArgs e)
1092 dev 675
		{
1199 dev 676
			ClearAll();
1092 dev 677
		}
678
 
679
		private void selectAllMenuItem_Click(object sender, System.EventArgs e)
680
		{
681
			messagesBox.SelectAll();
682
		}
683
 
684
		private void copyMenuItem_Click(object sender, System.EventArgs e)
685
		{
686
			string sel = messagesBox.SelectedText;
687
			if(sel != null) Clipboard.SetDataObject(sel);
688
		}
689
 
690
		private void wordWrapMenuItem_Click(object sender, System.EventArgs e)
691
		{
1194 dev 692
			messagesBox.WordWrap         = !messagesBox.WordWrap;
693
			wordWrapMenuItem.Checked     = messagesBox.WordWrap;
694
			wordWrapMainMenuItem.Checked = messagesBox.WordWrap;
1092 dev 695
		}
696
 
697
		private void autoExpandMenuItem_Click(object sender, System.EventArgs e)
698
		{
1201 dev 699
			autoExpand                     = !autoExpand;
700
			autoExpandMenuItem.Checked     = autoExpand;
701
			autoExpandMainMenuItem.Checked = autoExpand;
1092 dev 702
		}
703
 
1194 dev 704
		private void aboutMenuItem_Click(object sender, EventArgs e)
705
		{
706
			(new AboutForm()).ShowDialog(this);
707
		}
708
 
1200 dev 709
		private void messageView_BeforeSelect(object sender, TreeViewCancelEventArgs e)
1092 dev 710
		{
1288 dev 711
            messageView.Tag = null; // clear the right-click item
712
 
1092 dev 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.SaveViewState();
720
			}
721
		}
722
 
1200 dev 723
		private void messageView_AfterSelect(object sender, TreeViewEventArgs e)
1092 dev 724
		{
725
			if(messageView.SelectedNode == null) return;
726
 
727
			object tag = messageView.SelectedNode.Tag;
728
			if(tag is TreeNodeData)
729
			{
730
				TreeNodeData data = (TreeNodeData)tag;
731
				data.Show();
732
			}
733
		}
734
 
735
		private void closeConnectionMenuItem_Click(object sender, System.EventArgs e)
736
		{
1288 dev 737
            TreeNode node;
738
            if(messageView.Tag != null) {
739
                node = messageView.GetNodeAt((Point)messageView.Tag);
740
            }
741
            else {
742
                node = messageView.SelectedNode;
743
            }
1092 dev 744
 
1288 dev 745
			if(node != null)
746
            {
747
                object tag = node.Tag;
748
			    if(tag is TcpNodeData)
749
				    CloseTcpConnection(((TcpNodeData)tag).Tcp);
750
			    else if(tag is TcpNodeData)
751
				    CloseTcpConnection(((TcpNodeData)node.Parent.Tag).Tcp);
752
			    else if(tag is XmlNodeData)
753
				    CloseTcpConnection(((TcpNodeData)node.Parent.Parent.Tag).Tcp);
754
            }
1092 dev 755
		}
756
 
1288 dev 757
        private void messageView_MouseDown(object sender, MouseEventArgs e)
758
        {
759
            if(e.Button == MouseButtons.Right) {
760
                messageView.Tag = new Point(e.X, e.Y); // save mouse click coord
761
            }
762
        }
763
 
1092 dev 764
		private void tcpShowByDirectionMenuItem_Click(object sender, System.EventArgs e)
765
		{
766
			tcpShowMode = TcpShowMode.ByDirection;
1194 dev 767
			tcpShowByDirectionMenuItem.Checked = true;
768
			tcpShowByTimeMenuItem.Checked      = false;
1092 dev 769
 
1288 dev 770
            TreeNode node;
771
            if(messageView.Tag != null) {
772
                node = messageView.GetNodeAt((Point)messageView.Tag);
773
            }
774
            else {
775
                node = messageView.SelectedNode;
776
            }
1092 dev 777
 
1288 dev 778
			if(node != null)
779
            {
780
			    object tag = node.Tag;
781
			    if(tag is TcpNodeData)
782
				    UpdateTcpNodeInternal(((TcpNodeData)tag).Tcp);
783
            }
1092 dev 784
		}
785
 
786
		private void tcpShowByTimeMenuItem_Click(object sender, System.EventArgs e)
787
		{
788
			tcpShowMode = TcpShowMode.ByTime;
1194 dev 789
			tcpShowByDirectionMenuItem.Checked = false;
790
			tcpShowByTimeMenuItem.Checked      = true;
1092 dev 791
 
792
			if(messageView.SelectedNode == null) return;
793
 
1288 dev 794
            TreeNode node;
795
            if(messageView.Tag != null) {
796
                node = messageView.GetNodeAt((Point)messageView.Tag);
797
            }
798
            else {
799
                node = messageView.SelectedNode;
800
            }
801
 
802
			if(node != null)
803
            {
804
			    object tag = node.Tag;
805
			    if(tag is TcpNodeData)
806
				    UpdateTcpNodeInternal(((TcpNodeData)tag).Tcp);
807
            }
1092 dev 808
		}
809
 
810
		private void saveLogMenuItem_Click(object sender, System.EventArgs e)
811
		{
1201 dev 812
			if(saveLogDialog.ShowDialog() == DialogResult.OK) {
813
				try {
814
					SaveLog(saveLogDialog.FileName);
815
				}
816
				catch(Exception ex) {
817
					MessageBox.Show("Cannot save log to file " + saveLogDialog.FileName
818
						+ ":\n" + ex.Message, "TCPproxy",
819
						MessageBoxButtons.OK, MessageBoxIcon.Error);
820
				}
1092 dev 821
			}
822
		}
823
 
824
		private void saveTcpMenuItem_Click(object sender, System.EventArgs e)
825
		{
1201 dev 826
			if(saveLogDialog.ShowDialog() == DialogResult.OK) {
827
				try {
828
					SaveTcp(saveLogDialog.FileName);
829
				}
830
				catch(Exception ex) {
831
					MessageBox.Show("Cannot save TCP log to file " + saveLogDialog.FileName
832
						+ ":\n" + ex.Message, "TCPproxy",
833
						MessageBoxButtons.OK, MessageBoxIcon.Error);
834
				}
1092 dev 835
			}
836
		}
837
 
838
		private void saveHttpMenuItem_Click(object sender, System.EventArgs e)
839
		{
1201 dev 840
			if(saveLogDialog.ShowDialog() == DialogResult.OK) {
841
				try {
842
					SaveHttp(saveLogDialog.FileName);
843
				}
844
				catch(Exception ex) {
845
					MessageBox.Show("Cannot save HTTP log to file " + saveLogDialog.FileName
846
						+ ":\n" + ex.Message, "TCPproxy",
847
						MessageBoxButtons.OK, MessageBoxIcon.Error);
848
				}
1092 dev 849
			}
850
		}
851
 
852
		private void saveXmlMenuItem_Click(object sender, System.EventArgs e)
853
		{
1201 dev 854
			if(saveLogDialog.ShowDialog() == DialogResult.OK) {
855
				try {
856
					SaveXml(saveLogDialog.FileName);
857
				}
858
				catch(Exception ex) {
859
					MessageBox.Show("Cannot save XML log to file " + saveLogDialog.FileName
860
						+ ":\n" + ex.Message, "TCPproxy",
861
						MessageBoxButtons.OK, MessageBoxIcon.Error);
862
				}
1092 dev 863
			}
864
		}
865
 
1199 dev 866
		private void saveBinLogMenuItem_Click(object sender, EventArgs e)
867
		{
1201 dev 868
			if(saveBinLogDialog.ShowDialog() == DialogResult.OK) {
869
				try {
870
					SaveBinLog(saveBinLogDialog.FileName);
871
				}
872
				catch(Exception ex) {
873
					MessageBox.Show("Cannot save binary log to file " + saveBinLogDialog.FileName
874
						+ ":\n" + ex.Message, "TCPproxy",
875
						MessageBoxButtons.OK, MessageBoxIcon.Error);
876
				}
877
			}
1199 dev 878
		}
879
 
880
		private void loadBinLogMenuItem_Click(object sender, EventArgs e)
881
		{
1201 dev 882
			if(loadBinLogDialog.ShowDialog() == DialogResult.OK) {
883
				try {
884
					LoadBinLog(loadBinLogDialog.FileName);
885
				}
886
				catch(Exception ex) {
887
					MessageBox.Show("Cannot load binary log from file " + loadBinLogDialog.FileName
888
						+ ":\n" + ex.Message, "TCPproxy",
889
						MessageBoxButtons.OK, MessageBoxIcon.Error);
890
				}
891
			}
1199 dev 892
		}
893
 
1194 dev 894
		private void messagesMenuItem_Click(object sender, EventArgs e)
1092 dev 895
		{
1194 dev 896
			if(sender == importantMessagesMenuItem)
897
				logMessages.Level = LogLevel.Important;
898
			else if(sender == infoMessagesMenuItem)
899
				logMessages.Level = LogLevel.Info;
900
			else
901
				logMessages.Level = LogLevel.Debug;
1092 dev 902
 
1194 dev 903
			UpdateMessagesMenuItems();
904
		}
1092 dev 905
 
1194 dev 906
		private void recentMenuItem_Click(object sender, EventArgs e)
907
		{
1238 dev 908
			MenuItem   menuItem   = (MenuItem)sender;
909
			RecentItem recentItem = (RecentItem)recentItems[recentItems.Count - menuItem.Index - 1];
1194 dev 910
			IPAddress  resendIp;
911
 
912
			this.listenPort = recentItem.ListenPort;
913
			this.resendHost = recentItem.ResendHost;
914
			this.resendPort = recentItem.ResendPort;
1197 dev 915
 
1194 dev 916
			try
917
			{
918
				resendIp = HostUtils.ResendHostToIp(resendHost);
919
			}
920
			catch(Exception ex)
921
			{
1201 dev 922
				MessageBox.Show("Cannot get host IP: " + ex.Message, "TCPproxy",
923
					MessageBoxButtons.OK, MessageBoxIcon.Error);
1194 dev 924
				return;
925
			}
926
 
927
			StartListening(listenPort, resendIp, resendPort);
928
		}
929
 
1199 dev 930
		#endregion windows forms methods
931
 
932
		#region core methods
933
 
934
		private LogLevel ParseLogLevel(string str)
935
		{
936
			if(str == "Important")
937
				return LogLevel.Important;
938
			else if(str == "Info")
939
				return LogLevel.Info;
940
			else
941
				return LogLevel.Debug;
942
		}
943
 
944
		private void LoadFromRegistry()
945
		{
946
			Microsoft.Win32.RegistryKey subkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(
947
				REGISTRY_KEY);
948
 
949
			if(subkey == null) return;
950
 
951
			listenPort           = (int)subkey.GetValue("Listen Port", 0);
952
			resendHost           = (string)subkey.GetValue("Resend Host", "");
953
			resendPort           = (int)subkey.GetValue("Resend Port", 0);
954
			logMessages.Level    = ParseLogLevel((string)subkey.GetValue("Messages Level", ""));
955
			autoExpand           = (int)subkey.GetValue("Auto Expand", 1) == 1;
956
			messagesBox.WordWrap = (int)subkey.GetValue("Word Wrap", 1) == 1;
957
 
958
			object tcpShowModeStr  = (object)subkey.GetValue("Tcp Show Mode", TcpShowMode.ByDirection);
959
			tcpShowMode            = (tcpShowModeStr as string) == "ByDirection"
960
				? TcpShowMode.ByDirection : TcpShowMode.ByTime;
961
 
962
			int winTop  = (int)subkey.GetValue("Window.Top",  -1);
963
			int winLeft = (int)subkey.GetValue("Window.Left", -1);
964
 
1290 dev 965
			if(winTop < 0 || winLeft < 0
966
                || winTop >= SystemInformation.WorkingArea.Height || winLeft >= SystemInformation.WorkingArea.Width)
967
            {
1199 dev 968
				this.StartPosition = FormStartPosition.WindowsDefaultBounds;
969
			}
970
			else {
971
				this.Top  = winTop;
972
				this.Left = winLeft;
973
				this.ClientSize = new Size(
974
					(int)subkey.GetValue("Window.Width", this.ClientSize.Width),
975
					(int)subkey.GetValue("Window.Hight", this.ClientSize.Height));
1232 dev 976
				this.messageView.Width
1199 dev 977
					= (int)subkey.GetValue("Splitter.Left",   this.messageView.Width);
1232 dev 978
				this.logBox.Height
1199 dev 979
					= (int)subkey.GetValue("Splitter.Bottom", this.logBox.Height);
980
			}
981
		}
982
 
983
		private void LoadRecentItemsFromRegistry()
984
		{
985
			Microsoft.Win32.RegistryKey subkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(
986
				REGISTRY_KEY + @"\" + REGISTRY_RECENT_SUBKEY);
987
 
988
			if(subkey == null) return;
989
 
990
			foreach(string name in subkey.GetValueNames()) {
991
				if(name == "") continue;
992
				AddRecentItem(RecentItem.LoadFromRegistry((string)subkey.GetValue(name, "")));
993
			}
994
		}
995
 
996
		private void SaveToRegistry()
997
		{
998
			Microsoft.Win32.RegistryKey subkey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(
999
				REGISTRY_KEY);
1000
 
1001
			subkey.SetValue("Listen Port",    listenPort);
1002
			subkey.SetValue("Resend Host",    resendHost == null ? "" : resendHost);
1003
			subkey.SetValue("Resend Port",    resendPort);
1004
			subkey.SetValue("Messages Level", logMessages.Level);
1005
			subkey.SetValue("Tcp Show Mode",  tcpShowMode);
1006
			subkey.SetValue("Auto Expand",    autoExpand ? 1 : 0);
1007
			subkey.SetValue("Word Wrap",      messagesBox.WordWrap ? 1 : 0);
1008
 
1009
			subkey.SetValue("Window.Top",      this.Top);
1010
			subkey.SetValue("Window.Left",     this.Left);
1011
			subkey.SetValue("Window.Hight",    this.ClientSize.Height);
1012
			subkey.SetValue("Window.Width",    this.ClientSize.Width);
1013
			subkey.SetValue("Splitter.Left",   this.messageView.Width);
1014
			subkey.SetValue("Splitter.Bottom", this.logBox.Height);
1015
		}
1016
 
1017
		private void SaveRecentItemsToRegistry()
1018
		{
1019
			Microsoft.Win32.RegistryKey subkey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(
1020
				REGISTRY_KEY + @"\" + REGISTRY_RECENT_SUBKEY);
1021
 
1022
			// load existing from registry
1023
			ArrayList old = new ArrayList();
1024
			foreach(string name in subkey.GetValueNames()) {
1025
				if(name == "") continue;
1026
				old.Add(RecentItem.LoadFromRegistry((string)subkey.GetValue(name, "")));
1027
			}
1028
 
1029
			// merge - for the case another program instance has changed the list
1030
			foreach(RecentItem item in old) {
1031
				int existingIdx = recentItems.IndexOf(item);
1032
				if(existingIdx >= 0)
1033
					((RecentItem)recentItems[existingIdx]).UpdateTimestamp(item);
1034
				else
1035
					recentItems.Add(item);
1036
			}
1037
 
1038
			recentItems.Sort();
1039
			if(recentItems.Count > 0) // take tail
1040
				recentItems = recentItems.GetRange(Math.Max(0, recentItems.Count - RECENT_LENGTH),
1041
					Math.Min(recentItems.Count, RECENT_LENGTH));
1042
 
1043
			int count = 0;
1044
			foreach(RecentItem item in recentItems) {
1045
				subkey.SetValue(string.Format("{0:0000}", count++), item.SaveToRegistry());
1046
			}
1047
		}
1048
 
1194 dev 1049
		private void UpdateMessagesMenuItems()
1050
		{
1051
			switch(logMessages.Level) {
1052
				case LogLevel.Critical:
1053
				case LogLevel.Error:
1054
				case LogLevel.Warning:
1055
				case LogLevel.Important:
1056
					importantMessagesMenuItem.Checked = true;
1057
					infoMessagesMenuItem.Checked      = false;
1058
					allMessagesMenuItem.Checked       = false;
1059
					break;
1060
 
1061
				case LogLevel.Info:
1062
					importantMessagesMenuItem.Checked = false;
1063
					infoMessagesMenuItem.Checked      = true;
1064
					allMessagesMenuItem.Checked       = false;
1065
					break;
1066
 
1067
				case LogLevel.Debug:
1068
					importantMessagesMenuItem.Checked = false;
1069
					infoMessagesMenuItem.Checked      = false;
1070
					allMessagesMenuItem.Checked       = true;
1071
					break;
1072
			}
1073
		}
1074
 
1075
		private void AddRecentItem(int listenPort, string resendHost, int resendPort)
1076
		{
1077
			RecentItem recentItem = new RecentItem(listenPort, resendHost, resendPort);
1078
			recentItem.UpdateTimestamp();
1079
			AddRecentItem(recentItem);
1080
		}
1081
 
1082
		private void AddRecentItem(RecentItem recentItem)
1083
		{
1084
			int existingIdx = recentItems.IndexOf(recentItem);
1085
			if(existingIdx >= 0) {
1239 dev 1086
				this.recentListeningMenu.MenuItems.RemoveAt(recentItems.Count - existingIdx - 1);
1198 dev 1087
				recentItems.RemoveAt(existingIdx);
1194 dev 1088
			}
1089
 
1198 dev 1090
			if(recentItems.Count == 0 && this.recentListeningMenu.MenuItems.Count == 1)
1197 dev 1091
				this.recentListeningMenu.MenuItems.RemoveAt(0);
1092
 
1194 dev 1093
			recentItems.Add(recentItem);
1094
 
1197 dev 1095
			MenuItem menuItem = new MenuItem();
1096
			this.recentListeningMenu.MenuItems.Add(0, menuItem);
1199 dev 1097
			menuItem.Text   = string.Format("&1 {0} to {1}:{2}",
1194 dev 1098
				recentItem.ListenPort, recentItem.ResendHost, recentItem.ResendPort);
1099
			menuItem.Click += new System.EventHandler(recentMenuItem_Click);
1198 dev 1100
 
1101
			// check overflow
1102
			if(recentItems.Count > RECENT_LENGTH) {
1239 dev 1103
				this.recentListeningMenu.MenuItems.RemoveAt(recentItems.Count - 1);
1198 dev 1104
				recentItems.RemoveAt(0);
1105
			}
1199 dev 1106
 
1107
			// update hot keys of old items
1108
			int count = 0;
1109
			foreach(MenuItem item in this.recentListeningMenu.MenuItems) {
1238 dev 1110
				RecentItem ri = (RecentItem)recentItems[recentItems.Count - count - 1];
1111
 
1199 dev 1112
				if(count == 0) {
1113
				}
1114
				else if(count < 10)
1238 dev 1115
					item.Text = string.Format("&{3} {0} to {1}:{2}", ri.ListenPort,
1116
						ri.ResendHost, ri.ResendPort, count + 1);
1199 dev 1117
				else
1238 dev 1118
					item.Text = string.Format("{0} to {1}:{2}", ri.ListenPort,
1119
						ri.ResendHost, ri.ResendPort);
1199 dev 1120
				count++;
1121
			}
1194 dev 1122
		}
1123
 
1199 dev 1124
		private void ClearAll()
1125
		{
1240 dev 1126
			clearing = true;
1092 dev 1127
 
1240 dev 1128
			tcpListener.CancelAll();
1199 dev 1129
 
1130
			treeNodes.Clear();
1239 dev 1131
 
1132
			messageView.BeginUpdate();
1199 dev 1133
			messageView.Nodes.Clear();
1239 dev 1134
			messageView.EndUpdate();
1135
 
1199 dev 1136
			messagesBox.Clear();
1137
			logMessages.Clear();
1240 dev 1138
 
1139
			clearing = false;
1199 dev 1140
		}
1141
 
1092 dev 1142
		private void Start(int listenPort, IPAddress resendHost, int resendPort)
1143
		{
1144
			if(tcpListener != null) tcpListener.StopListening();
1145
 
1146
			tcpListener = new TcpListener(listenPort, resendHost, resendPort);
1147
			tcpListener.Log    += new TcpLogEventHandler(TcpConnectionLog);
1289 dev 1148
			tcpListener.NewTcp += new TcpConnectionEventHandler(AddTcpConnection);
1092 dev 1149
			tcpListener.StartListening();
1150
		}
1151
 
1199 dev 1152
		private void StartListening(int listenPort, IPAddress resendIp, int resendPort)
1153
		{
1154
			// listen to the port
1155
			try
1156
			{
1157
				Start(listenPort, resendIp, resendPort);
1158
			}
1159
			catch(Exception ex)
1160
			{
1161
				MessageBox.Show("Cannot start listening: " + ex.Message, "TCPproxy",
1162
					MessageBoxButtons.OK, MessageBoxIcon.Error);
1163
				Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1164
				return;
1165
			}
1166
 
1167
			AddRecentItem(listenPort, resendHost, resendPort);
1168
 
1169
			startMenuItem.Enabled = false;
1170
			stopMenuItem.Enabled  = true;
1171
 
1172
			foreach(MenuItem subitem in recentListeningMenu.MenuItems) {
1173
				subitem.Enabled = false;
1174
			}
1175
 
1176
			this.Text = string.Format("{0}: {1} to {2}:{3}",
1177
				defaultCaption, listenPort, resendHost, resendPort);
1178
		}
1179
 
1180
		private void StopListening()
1181
		{
1182
			if(tcpListener != null) tcpListener.StopListening();
1183
 
1184
			startMenuItem.Enabled = true;
1185
			stopMenuItem.Enabled  = false;
1186
 
1187
			if(recentItems.Count > 0) {
1188
				foreach(MenuItem subitem in recentListeningMenu.MenuItems) {
1189
					subitem.Enabled = true;
1190
				}
1191
			}
1192
 
1193
			this.Text = defaultCaption;
1194
		}
1195
 
1288 dev 1196
        private void CloseTcpConnection(TcpConnection tcp)
1092 dev 1197
		{
1198
			if(tcp == null) return;
1199
 
1200
			tcp.Cancel();
1201
		}
1202
 
1203
		private void SaveLog(string fileName)
1204
		{
1205
			StreamWriter writer = new StreamWriter(fileName);
1206
 
1207
			foreach(LogMessage message in logMessages.Messages)
1208
			{
1209
				writer.WriteLine(message);
1210
			}
1211
 
1212
			writer.Close();
1213
		}
1214
 
1215
		private void SaveTcp(string fileName)
1216
		{
1217
			StreamWriter writer = new StreamWriter(fileName);
1218
 
1219
			foreach(TreeNode tcpNode in messageView.Nodes)
1220
			{
1221
				TcpNodeData data = (TcpNodeData)tcpNode.Tag;
1222
				data.WriteLog(writer);
1223
			}
1224
 
1225
			writer.Close();
1226
		}
1227
 
1228
		private void SaveHttp(string fileName)
1229
		{
1230
			StreamWriter writer = new StreamWriter(fileName);
1231
 
1232
			foreach(TreeNode tcpNode in messageView.Nodes)
1233
			{
1234
				foreach(TreeNode httpNode in tcpNode.Nodes)
1235
				{
1236
					HttpNodeData data = (HttpNodeData)httpNode.Tag;
1237
					data.WriteLog(writer);
1238
				}
1239
			}
1240
 
1241
			writer.Close();
1242
		}
1243
 
1244
		private void SaveXml(string fileName)
1245
		{
1246
			StreamWriter writer = new StreamWriter(fileName);
1247
 
1248
			foreach(TreeNode tcpNode in messageView.Nodes)
1249
			{
1250
				foreach(TreeNode httpNode in tcpNode.Nodes)
1251
				{
1252
					foreach(TreeNode xmlNode in httpNode.Nodes)
1253
					{
1254
						XmlNodeData data = (XmlNodeData)xmlNode.Tag;
1255
						data.WriteLog(writer);
1256
					}
1257
				}
1258
			}
1259
 
1260
			writer.Close();
1261
		}
1262
 
1199 dev 1263
		private void SaveBinLog(string fileName)
1264
		{
1265
			FileStream   file   = new FileStream(fileName, FileMode.Create);
1266
			BinaryWriter writer = new BinaryWriter(file);
1267
 
1268
			// header
1269
			writer.Write(Encoding.ASCII.GetBytes(LOG_BIN_HEADER));
1270
			writer.Write(LOG_TYPE_BIN);
1271
 
1272
			// for each tcp connection
1273
			foreach(TreeNode tcpNode in messageView.Nodes)
1274
				((TcpNodeData)tcpNode.Tag).Tcp.WriteBinLog(writer);
1275
 
1276
			// end of stream
1277
			writer.Write((byte)BinLogTypes.None);
1278
 
1279
			writer.Close();
1280
			file.Close();
1281
		}
1282
 
1283
		private void LoadBinLog(string fileName)
1284
		{
1285
			StopListening();
1286
			ClearAll();
1287
 
1232 dev 1288
			FileStream   file   = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
1199 dev 1289
			BinaryReader reader = new BinaryReader(file);
1290
 
1291
			// header
1292
			byte[] bufExpect = Encoding.ASCII.GetBytes(LOG_BIN_HEADER);
1201 dev 1293
			if(file.Length < (bufExpect.Length + 1 /* the type */))
1199 dev 1294
				throw new Exception("The file is too short");
1295
 
1296
			byte[] bufRead = reader.ReadBytes(bufExpect.Length);
1297
			for(int i = 0; i < bufRead.Length; i++)
1298
				if(bufRead[i] != bufExpect[i])
1299
					throw new Exception("Wrong header of the file");
1300
 
1301
			if(reader.ReadByte() != LOG_TYPE_BIN)
1302
				throw new Exception("Unknown log type");
1303
 
1304
			tcpListener = new TcpListener(0, null, 0);
1305
			tcpListener.Log    += new TcpLogEventHandler(TcpConnectionLog);
1289 dev 1306
			tcpListener.NewTcp += new TcpConnectionEventHandler(AddTcpConnection);
1199 dev 1307
			tcpListener.ReadBinLog(reader); // it will send us usual event
1308
 
1309
			reader.Close();
1310
			file.Close();
1311
		}
1312
 
1092 dev 1313
		#endregion core methods
1314
 
1315
		#region network events handlers
1316
		private void TcpConnectionLog(object sender, TcpLogEventArgs e)
1317
		{
1240 dev 1318
			if(clearing) return;
1319
 
1125 dev 1320
			lock(this)
1321
			{
1322
				TcpConnection tcp = sender as TcpConnection;
1323
				LogMessage message = new LogMessage(tcp, e.Level, e.Message, e.Exception);
1092 dev 1324
 
1125 dev 1325
				try
1326
				{
1327
					this.BeginInvoke(new AddLogMessageHandler(AddLogMessageInternal), new object[] { message } );
1328
				}
1329
				catch(InvalidOperationException ex)
1330
				{
1331
					if(!this.Disposing && !this.IsDisposed)
1332
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1333
				}
1092 dev 1334
			}
1335
		}
1336
 
1289 dev 1337
		private void AddTcpConnection(object sender, TcpConnectionEventArgs e)
1092 dev 1338
		{
1125 dev 1339
			lock(this)
1340
			{
1341
				e.Tcp.Log     += new TcpLogEventHandler(TcpConnectionLog);
1342
				e.Tcp.Update  += new TcpEventHandler(UpdateTcpNode);
1343
				e.Tcp.Close   += new TcpEventHandler(UpdateTcpNode);
1344
				e.Tcp.NewHttp += new TcpHttpEventHandler(AddHttpMessageNode);
1092 dev 1345
 
1125 dev 1346
				try
1347
				{
1348
					this.BeginInvoke(new AddTcpNodeHandler(AddTcpNodeInternal), new object[] { e.Tcp } );
1349
				}
1350
				catch(InvalidOperationException ex)
1351
				{
1352
					if(!this.Disposing && !this.IsDisposed)
1353
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1354
				}
1092 dev 1355
			}
1356
		}
1357
 
1358
		private void UpdateTcpNode(object sender, TcpEventArgs e)
1359
		{
1125 dev 1360
			lock(this)
1092 dev 1361
			{
1125 dev 1362
				try
1363
				{
1364
					this.BeginInvoke(new UpdateTcpNodeHandler(UpdateTcpNodeInternal), new object[] { (TcpConnection)sender } );
1365
				}
1366
				catch(InvalidOperationException ex)
1367
				{
1368
					if(!this.Disposing && !this.IsDisposed)
1369
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1370
				}
1092 dev 1371
			}
1372
		}
1373
 
1374
		private void AddHttpMessageNode(object sender, TcpHttpEventArgs e)
1375
		{
1125 dev 1376
			lock(this)
1377
			{
1378
				e.Http.Update += new TcpEventHandler(UpdateHttpNode);
1092 dev 1379
 
1125 dev 1380
				try
1381
				{
1382
					this.BeginInvoke(new AddHttpNodeHandler(AddHttpNodeInternal),
1383
						new object[] { (TcpConnection)sender, e.Http } );
1384
				}
1385
				catch(InvalidOperationException ex)
1386
				{
1387
					if(!this.Disposing && !this.IsDisposed)
1388
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1389
				}
1092 dev 1390
			}
1391
		}
1392
 
1393
		private void UpdateHttpNode(object sender, TcpEventArgs e)
1394
		{
1125 dev 1395
			lock(this)
1092 dev 1396
			{
1125 dev 1397
				try
1398
				{
1399
					this.BeginInvoke(new UpdateHttpNodeHandler(UpdateHttpNodeInternal), new object[] { (HttpMessage)sender } );
1400
				}
1401
				catch(InvalidOperationException ex)
1402
				{
1403
					if(!this.Disposing && !this.IsDisposed)
1404
						Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
1405
				}
1092 dev 1406
			}
1407
		}
1408
 
1409
		#endregion network events handlers
1410
 
1411
		#region handlers for async GUI events
1201 dev 1412
 
1413
		// All handlers are called in main application thread only, no locks needed.
1414
		// Other methods which are not running in the main application thread
1415
		// are not allowed no interact with GUI elemenents.
1416
 
1092 dev 1417
		private delegate void AddLogMessageHandler(LogMessage message);
1418
		private delegate void AddTcpNodeHandler(TcpConnection tcp);
1419
		private delegate void UpdateTcpNodeHandler(TcpConnection tcp);
1420
		private delegate void AddHttpNodeHandler(TcpConnection tcp, HttpMessage http);
1421
		private delegate void UpdateHttpNodeHandler(HttpMessage http);
1422
 
1423
		private void AddLogMessageInternal(LogMessage message)
1424
		{
1425
			logMessages.Add(message);
1426
 
1427
			if(message.Exception != null)
1428
			{
1429
				Console.WriteLine(message.Exception.Message + " (" + message.Exception.GetType().Name
1430
					+ ")\n" + message.Exception.StackTrace);
1431
			}
1432
		}
1433
 
1238 dev 1434
        private string TcpNodeTitle(TcpConnection tcp)
1435
        {
1436
            return tcp.Id + " " + tcp.StartTimestamp.ToString("HH:mm:ss.ffff");
1437
        }
1438
 
1439
        private void AddTcpNodeInternal(TcpConnection tcp)
1092 dev 1440
		{
1238 dev 1441
            TreeNode    treeNode = new TreeNode(TcpNodeTitle(tcp));
1092 dev 1442
			TcpNodeData data     = new TcpNodeData(this, treeNode);
1443
 
1238 dev 1444
			data.Tcp                    = tcp;
1092 dev 1445
			treeNode.Tag                = data;
1232 dev 1446
			treeNode.ImageIndex         = (tcp.LocalState == SocketState.Closed
1199 dev 1447
				&& tcp.RemoteState == SocketState.Closed) ? 2 : 1;
1448
			treeNode.SelectedImageIndex = treeNode.ImageIndex;
1238 dev 1449
			treeNodes[tcp]              = data;
1092 dev 1450
 
1451
			messageView.Nodes.Add(treeNode);
1452
			treeNode.EnsureVisible();
1289 dev 1453
            if(messageView.Nodes.Count == 1) {
1290 dev 1454
                //messageView.SelectedNode = messageView.Nodes[0];
1289 dev 1455
            }
1092 dev 1456
		}
1457
 
1458
		private void UpdateTcpNodeInternal(TcpConnection tcp)
1459
		{
1460
			TcpNodeData data = treeNodes[tcp] as TcpNodeData;
1125 dev 1461
			if(data == null) return; // might be call by Cancel
1092 dev 1462
 
1238 dev 1463
			string title = TcpNodeTitle(tcp);
1092 dev 1464
			if(title != data.Node.Text) data.Node.Text = title;
1465
			if(tcp.LocalState == SocketState.Closed && tcp.RemoteState == SocketState.Closed)
1466
			{
1467
				data.Node.ImageIndex         = 2;
1199 dev 1468
				data.Node.SelectedImageIndex = data.Node.ImageIndex;
1092 dev 1469
			}
1470
 
1471
			if(messageView.SelectedNode == null || data != messageView.SelectedNode.Tag)
1472
				data.ViewExpired = true;  // got update for invisible TCP node, update it later
1473
			else
1474
				data.Show();
1475
		}
1476
 
1238 dev 1477
        private string HttpNodeTitle(HttpMessage http)
1478
        {
1479
            return (http.Request.SoapAction != null ? ("SOAP " + http.Request.SoapAction)
1480
                : (http.Request.Method == null ? "" : http.Request.Method) + " " + (http.Request.Uri == null ? "" : http.Request.Uri));
1481
        }
1482
 
1483
        private void AddHttpNodeInternal(TcpConnection tcp, HttpMessage http)
1092 dev 1484
		{
1238 dev 1485
            TreeNode     treeNode = new TreeNode(HttpNodeTitle(http));
1092 dev 1486
			HttpNodeData data     = new HttpNodeData(this, treeNode);
1487
 
1238 dev 1488
			data.Http       = http;
1489
			treeNode.Tag    = data;
1092 dev 1490
			treeNodes[http] = data;
1491
 
1492
			TcpNodeData tcpData = treeNodes[tcp] as TcpNodeData;
1493
			if(tcpData == null) throw new ArgumentException("No node found for TCP message");
1494
 
1495
			tcpData.Node.Nodes.Add(treeNode);
1496
			if(autoExpand) tcpData.Node.Expand();
1497
			tcpData.Node.EnsureVisible();
1498
		}
1499
 
1500
		private void UpdateHttpNodeInternal(HttpMessage http)
1501
		{
1502
			HttpNodeData httpData = treeNodes[http] as HttpNodeData;
1125 dev 1503
			if(httpData == null) return; // might be call by Cancel
1092 dev 1504
 
1238 dev 1505
            string title = HttpNodeTitle(http);
1092 dev 1506
			if(httpData.Node.Text != title) httpData.Node.Text = title;
1507
 
1234 dev 1508
			if(!httpData.RequestXmlShown && http.Request.Xml != null)
1092 dev 1509
			{
1510
				httpData.RequestXmlShown = true;
1234 dev 1511
				AddXmlNode(httpData.Node, "Request XML", http.Request.Xml);
1092 dev 1512
				if(autoExpand) httpData.Node.Expand();
1513
			}
1514
 
1234 dev 1515
			if(!httpData.ResponseXmlShown && http.Response.Xml != null)
1092 dev 1516
			{
1517
				httpData.ResponseXmlShown = true;
1234 dev 1518
				AddXmlNode(httpData.Node, "Response XML", http.Response.Xml);
1092 dev 1519
				if(autoExpand) httpData.Node.Expand();
1520
			}
1521
 
1522
			// update text view
1523
			if(messageView.SelectedNode == null || httpData != messageView.SelectedNode.Tag)
1524
				httpData.ViewExpired = true;
1525
			else
1526
				httpData.Show();
1527
		}
1528
 
1529
		private void AddXmlNode(TreeNode parent, string title, XmlMessage xml)
1530
		{
1531
			TreeNode    treeNode = new TreeNode(title);
1532
			XmlNodeData data = new XmlNodeData(this, treeNode);
1533
 
1534
			data.Xml       = xml;
1535
			treeNode.Tag   = data;
1536
			treeNodes[xml] = data;
1537
 
1538
			parent.Nodes.Add(treeNode);
1539
		}
1540
 
1541
		#endregion handlers for async GUI events
1542
 
1543
		#region node display classes
1544
		private abstract class TreeNodeData
1545
		{
1546
			protected TreeNode node;
1547
			protected object   viewState;
1548
			protected bool     viewExpired;
1549
			protected MainForm owner;
1550
			protected bool     shown = false;
1551
 
1552
			public TreeNode Node
1553
			{
1554
				get { return node; }
1555
			}
1556
 
1557
			public TreeNodeData(MainForm owner, TreeNode node)
1558
			{
1559
				this.owner = owner;
1560
				this.node  = node;
1561
			}
1562
 
1563
			public bool ViewExpired
1564
			{
1565
				get { return viewExpired; }
1566
				set { viewExpired = value; }
1567
			}
1568
 
1569
			public void SaveViewState()
1570
			{
1571
				viewState = owner.messagesBox.SaveState(false);
1572
			}
1573
 
1574
			protected virtual bool ForceInitView()
1575
			{
1576
				return false;
1577
			}
1578
 
1579
			protected abstract void InitView();
1580
			protected abstract void UpdateView();
1581
 
1582
			public void Show()
1583
			{
1584
				if(!shown || viewState == null || ForceInitView())
1585
				{
1586
					InitView();
1587
					shown = true;
1588
					if(viewState == null) viewState = owner.messagesBox.SaveState(false);
1589
				}
1590
				else
1591
				{
1592
					owner.messagesBox.RestoreState(viewState, true);
1593
					if(viewExpired) UpdateView();
1594
				}
1595
			}
1596
 
1597
			public abstract void WriteLog(StreamWriter writer);
1598
		}
1599
 
1600
		private class TcpNodeData : TreeNodeData
1601
		{
1602
			private TcpConnection tcp;
1603
 
1604
			private TcpShowMode lastShowMode;
1605
			private object      localStateMarker  = null;
1606
			private object      remoteStateMarker = null;
1607
			private object      startMarker       = null;
1608
			private object      localEndMarker    = null;
1609
			private object      remoteEndMarker   = null;
1610
			private object      clientMarker      = null;
1611
			private object      serverMarker      = null;
1612
			private object      sentMarker        = null;
1613
			private object      receivedMarker    = null;
1614
			private object      textMarker1       = null;
1615
			private object      textMarker2       = null;
1616
			private IEnumerator messagesEnum      = null;
1617
 
1618
			public TcpConnection Tcp
1619
			{
1620
				get { return tcp; }
1621
				set { tcp = value; }
1622
			}
1623
 
1624
			public TcpNodeData(MainForm owner, TreeNode node)	: base(owner, node)
1625
			{
1626
			}
1627
 
1628
 
1629
			protected override bool ForceInitView()
1630
			{
1631
				return (lastShowMode != owner.tcpShowMode);
1632
			}
1633
 
1634
			protected override void InitView()
1635
			{
1636
				lastShowMode = owner.tcpShowMode;
1637
 
1638
				try
1639
				{
1640
					owner.messagesBox.BeginUpdate();
1641
 
1642
					lock(tcp)
1643
					{
1644
						owner.messagesBox.Clear();
1645
 
1646
						owner.messagesBox.AppendNewLine();
1647
						owner.messagesBox.AppendText("ID:         ",
1648
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1649
						owner.messagesBox.AppendText(tcp.Id,
1650
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1651
						owner.messagesBox.AppendNewLine();
1652
 
1653
						owner.messagesBox.AppendText("State:      ",
1654
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1655
						localStateMarker = owner.messagesBox.BeginMark();
1656
						owner.messagesBox.AppendText(tcp.LocalState.ToString(),
1657
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1658
						owner.messagesBox.EndMark(localStateMarker);
1659
						owner.messagesBox.AppendText(null,
1660
							Color.DarkRed, Color.Transparent, false, false, 1, 12);
1661
						remoteStateMarker = owner.messagesBox.BeginMark();
1662
						owner.messagesBox.AppendText(tcp.RemoteState.ToString(),
1663
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1664
						owner.messagesBox.EndMark(remoteStateMarker);
1665
						owner.messagesBox.AppendNewLine();
1666
 
1667
						owner.messagesBox.AppendText("Start:      ",
1668
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1669
						startMarker = owner.messagesBox.BeginMark();
1670
						owner.messagesBox.AppendText(tcp.StartTimestamp.ToString("HH:mm:ss.ffff"),
1671
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1672
						owner.messagesBox.EndMark(startMarker);
1673
						owner.messagesBox.AppendNewLine();
1674
						owner.messagesBox.AppendText("Local End:  ",
1675
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1676
						localEndMarker = owner.messagesBox.BeginMark();
1677
						owner.messagesBox.AppendText(tcp.LocalEndTimestamp.ToString("HH:mm:ss.ffff"),
1678
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1679
						owner.messagesBox.EndMark(localEndMarker);
1680
						owner.messagesBox.AppendNewLine();
1681
						owner.messagesBox.AppendText("Remote End: ",
1682
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1683
						remoteEndMarker = owner.messagesBox.BeginMark();
1684
						owner.messagesBox.AppendText(tcp.RemoteEndTimestamp.ToString("HH:mm:ss.ffff"),
1685
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1686
						owner.messagesBox.EndMark(remoteEndMarker);
1687
						owner.messagesBox.AppendNewLine();
1688
 
1689
						owner.messagesBox.AppendText("Client:     ",
1690
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1691
						clientMarker = owner.messagesBox.BeginMark();
1692
						owner.messagesBox.AppendText((tcp.LocalPoint == null) ? "" : tcp.LocalPoint.ToString(),
1693
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1694
						owner.messagesBox.EndMark(clientMarker);
1695
						owner.messagesBox.AppendNewLine();
1696
						owner.messagesBox.AppendText("Server:     ",
1697
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1698
						serverMarker = owner.messagesBox.BeginMark();
1699
						owner.messagesBox.AppendText((tcp.RemotePoint == null) ? "" : tcp.RemotePoint.ToString(),
1700
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1701
						owner.messagesBox.EndMark(serverMarker);
1702
						owner.messagesBox.AppendNewLine();
1703
 
1704
						owner.messagesBox.AppendText("Sent:       ",
1705
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1706
						sentMarker = owner.messagesBox.BeginMark();
1707
						owner.messagesBox.AppendText(tcp.SentBytes.ToString(),
1708
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1709
						owner.messagesBox.EndMark(sentMarker);
1710
						owner.messagesBox.AppendNewLine();
1711
						owner.messagesBox.AppendText("Received:   ",
1712
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1713
						receivedMarker = owner.messagesBox.BeginMark();
1714
						owner.messagesBox.AppendText(tcp.ReceivedBytes.ToString(),
1715
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1716
						owner.messagesBox.EndMark(receivedMarker);
1717
						owner.messagesBox.AppendNewLine();
1718
						owner.messagesBox.AppendNewLine();
1719
 
1720
						messagesEnum = tcp.Messages.GetEnumerator();
1721
 
1722
						textMarker1 = owner.messagesBox.BeginMark();
1723
						owner.messagesBox.EndMark(textMarker1);
1724
 
1725
						owner.messagesBox.AppendNewLine();
1726
						textMarker2 = owner.messagesBox.BeginMark();
1727
						owner.messagesBox.EndMark(textMarker2);
1728
 
1729
						ShowMessages();
1730
					}
1731
				}
1732
				finally
1733
				{
1734
					owner.messagesBox.EndUpdate();
1735
				}
1736
			}
1737
 
1738
			protected override void UpdateView()
1739
			{
1740
				try
1741
				{
1742
					owner.messagesBox.BeginUpdate();
1743
 
1744
					lock(tcp)
1745
					{
1746
						owner.messagesBox.ChangeText(localStateMarker, tcp.LocalState.ToString(),
1747
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1748
						owner.messagesBox.ChangeText(remoteStateMarker, tcp.RemoteState.ToString(),
1749
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1750
 
1751
						owner.messagesBox.ChangeText(startMarker, tcp.StartTimestamp.ToString("HH:mm:ss.ffff"),
1752
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1753
						owner.messagesBox.ChangeText(localEndMarker, tcp.LocalEndTimestamp.ToString("HH:mm:ss.ffff"),
1754
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1755
						owner.messagesBox.ChangeText(remoteEndMarker, tcp.RemoteEndTimestamp.ToString("HH:mm:ss.ffff"),
1756
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1757
 
1758
						owner.messagesBox.ChangeText(clientMarker, (tcp.LocalPoint == null) ? "" : tcp.LocalPoint.ToString(),
1759
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1760
						owner.messagesBox.ChangeText(serverMarker, (tcp.RemotePoint == null) ? "" : tcp.RemotePoint.ToString(),
1761
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1762
 
1763
						owner.messagesBox.ChangeText(sentMarker, tcp.SentBytes.ToString(),
1764
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1765
						owner.messagesBox.ChangeText(receivedMarker, tcp.ReceivedBytes.ToString(),
1766
							Color.DarkRed, Color.LightGray, false, false, 0, 12);
1767
 
1768
						ShowMessages();
1769
					}
1770
				}
1771
				finally
1772
				{
1773
					owner.messagesBox.EndUpdate();
1774
				}
1775
			}
1776
 
1777
			private void ShowMessages()
1778
			{
1779
				while(messagesEnum.MoveNext())
1780
				{
1781
					TcpMessage message = (TcpMessage)messagesEnum.Current;
1782
					object     marker  = (owner.tcpShowMode == TcpShowMode.ByTime
1783
						|| message.Direction == TcpMessageDirection.Local) ? textMarker1 : textMarker2;
1784
 
1785
					if(owner.tcpShowMode == TcpShowMode.ByTime)
1786
					{
1787
						owner.messagesBox.InsertText(marker,
1788
							message.Timestamp.ToString("HH:mm:ss.ffff") + " ("	+ message.Length + ")",
1789
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1790
						owner.messagesBox.InsertNewLine(marker);
1791
					}
1792
 
1793
					string str = Utils.BytesToString(message.Bytes, message.Length);
1794
					ArrayList lines = Utils.SplitLine(str);
1795
					for(int i = 0; i < lines.Count; i++)
1796
					{
1797
						owner.messagesBox.InsertText(marker, (string)lines[i],
1798
							message.Direction == TcpMessageDirection.Local ? Color.Green : Color.Blue,
1799
							Color.LightGray, false, false, 0, 0);
1800
 
1801
						if(owner.tcpShowMode == TcpShowMode.ByTime || i != lines.Count - 1)
1802
							owner.messagesBox.InsertNewLine(marker);
1803
					}
1804
				}
1805
			}
1806
 
1807
			public override void WriteLog(StreamWriter writer)
1808
			{
1809
				writer.WriteLine(
1810
					"Start:      " + tcp.StartTimestamp.ToString("HH:mm:ss.ffff")
1811
					+ "\r\nLocal End:  " + tcp.LocalEndTimestamp.ToString("HH:mm:ss.ffff")
1812
					+ "\r\nRemote End: " + tcp.RemoteEndTimestamp.ToString("HH:mm:ss.ffff")
1813
					+ "\r\nClient:     " + ((tcp.LocalPoint  == null) ? "" : tcp.LocalPoint.ToString())
1814
					+ "\r\nServer:     " + ((tcp.RemotePoint == null) ? "" : tcp.RemotePoint.ToString())
1815
					+ "\r\nSent:       " + tcp.SentBytes
1816
					+ "\r\nReceived:   " + tcp.ReceivedBytes);
1817
 
1818
				foreach(TcpMessage message in tcp.Messages)
1819
				{
1820
					string str = Utils.BytesToString(message.Bytes, message.Length);
1821
					if(!str.EndsWith("\n")) str += "\r\n";
1822
 
1823
					writer.WriteLine();
1824
					if(message.Direction == TcpMessageDirection.Local)
1825
						writer.WriteLine(">>> {0:HH:mm:ss.ffff} >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", message.Timestamp);
1826
					else
1827
						writer.WriteLine("<<< {0:HH:mm:ss.ffff} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", message.Timestamp);
1828
					writer.Write(str);
1829
				}
1830
				writer.WriteLine("===============================================================");
1831
				writer.WriteLine();
1832
			}
1833
		}
1834
 
1835
		private class HttpNodeData : TreeNodeData
1836
		{
1234 dev 1837
			private class MarkerSet
1838
			{
1839
				public object      start;
1840
				public object      method;
1841
				public object      uri;
1842
				public object      version;
1843
				public object      status;
1844
				public object      transferEncoding;
1845
				public object      length;
1846
				public object      contentEncoding;
1847
				public object      contentType;
1848
				public object      charset;
1849
				public object      headers;
1850
				public object      body;
1851
				public IEnumerator headersEnum;
1852
			}
1853
 
1092 dev 1854
			private HttpMessage http;
1855
			private bool        requestXmlShown  = false;
1856
			private bool        responseXmlShown = false;
1857
 
1234 dev 1858
			private object      stateMarker      = null;
1859
			private MarkerSet   requestMarkers   = new MarkerSet();
1860
			private MarkerSet   responseMarkers  = new MarkerSet();
1092 dev 1861
 
1862
			public HttpMessage Http
1863
			{
1864
				get { return http; }
1865
				set { http = value; }
1866
			}
1867
 
1868
			public bool RequestXmlShown
1869
			{
1870
				get { return requestXmlShown; }
1871
				set { requestXmlShown = value; }
1872
			}
1873
 
1874
			public bool ResponseXmlShown
1875
			{
1876
				get { return responseXmlShown; }
1877
				set { responseXmlShown = value; }
1878
			}
1879
 
1880
			public HttpNodeData(MainForm owner, TreeNode node) : base(owner, node)
1881
			{
1882
			}
1883
 
1233 dev 1884
			private string EncodingToString(HttpTransferEncoding encoding)
1092 dev 1885
			{
1886
				switch(encoding)
1887
				{
1233 dev 1888
					case HttpTransferEncoding.None:     return "none";
1889
					case HttpTransferEncoding.Identity: return "identity";
1890
					case HttpTransferEncoding.Chunked:  return "chunked";
1891
					case HttpTransferEncoding.Gzip:     return "gzip";
1892
					case HttpTransferEncoding.Compress: return "compress";
1893
					case HttpTransferEncoding.Deflate:  return "deflate";
1894
					default:                            return "<unknown>";
1092 dev 1895
				}
1896
			}
1897
 
1233 dev 1898
			private string EncodingToString(HttpContentEncoding encoding)
1899
			{
1900
				switch(encoding)
1901
				{
1902
					case HttpContentEncoding.None:     return "none";
1903
					case HttpContentEncoding.Identity: return "identity";
1904
					case HttpContentEncoding.Gzip:     return "gzip";
1905
					case HttpContentEncoding.Compress: return "compress";
1906
					case HttpContentEncoding.Deflate:  return "deflate";
1907
					default:                           return "<unknown>";
1908
				}
1909
			}
1910
 
1234 dev 1911
			private string VersionToString(HttpVersion version)
1092 dev 1912
			{
1234 dev 1913
				switch(version)
1092 dev 1914
				{
1234 dev 1915
					case HttpVersion.V0_9: return "HTTP/0.9";
1916
					case HttpVersion.V1_0: return "HTTP/1.0";
1917
					default:               return "HTTP/1.1";
1918
				}
1919
			}
1092 dev 1920
 
1234 dev 1921
			private void InitHttpHalfView(HttpHalfMessage half, MarkerSet markers, string title)
1922
			{
1923
				string padding = "";
1092 dev 1924
 
1234 dev 1925
				owner.messagesBox.AppendText(title + " Start:             " + padding,
1926
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1927
				markers.start = owner.messagesBox.BeginMark();
1928
				owner.messagesBox.AppendText(half.StartTimestamp == DateTime.MinValue
1929
					? "<unknown>" : half.StartTimestamp.ToString("HH:mm:ss.ffff"),
1930
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1931
				owner.messagesBox.EndMark(markers.start);
1932
				owner.messagesBox.AppendNewLine();
1125 dev 1933
 
1234 dev 1934
				if(half.IsRequest)
1935
				{
1936
					owner.messagesBox.AppendText(title + " Method:            " + padding,
1937
						Color.DarkRed, Color.Transparent, false, false, 0, 0);
1938
					markers.method = owner.messagesBox.BeginMark();
1939
					owner.messagesBox.AppendText((half as HttpRequest).Method,
1940
						Color.DarkRed, Color.LightGray, false, false, 0, 27);
1941
					owner.messagesBox.EndMark(markers.method);
1942
					owner.messagesBox.AppendNewLine();
1092 dev 1943
 
1234 dev 1944
					owner.messagesBox.AppendText(title + " URI:               " + padding,
1945
						Color.DarkRed, Color.Transparent, false, false, 0, 0);
1946
					markers.uri = owner.messagesBox.BeginMark();
1947
					owner.messagesBox.AppendText((half as HttpRequest).Uri,
1948
						Color.DarkRed, Color.LightGray, false, false, 0, 27);
1949
					owner.messagesBox.EndMark(markers.uri);
1950
					owner.messagesBox.AppendNewLine();
1951
				}
1952
				else 
1953
				{
1954
					owner.messagesBox.AppendText(title + " Status:            " + padding,
1955
						Color.DarkRed, Color.Transparent, false, false, 0, 0);
1956
					markers.status = owner.messagesBox.BeginMark();
1957
					owner.messagesBox.AppendText((half as HttpResponse).StatusCode 
1958
						+ " " + (half as HttpResponse).StatusMessage,
1959
						Color.DarkRed, Color.LightGray, false, false, 0, 27);
1960
					owner.messagesBox.EndMark(markers.status);
1961
					owner.messagesBox.AppendNewLine();
1962
				}
1092 dev 1963
 
1234 dev 1964
				owner.messagesBox.AppendText(title + " Version:           " + padding,
1965
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1966
				markers.version = owner.messagesBox.BeginMark();
1967
				owner.messagesBox.AppendText(VersionToString(half.Version),
1968
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1969
				owner.messagesBox.EndMark(markers.version);
1970
				owner.messagesBox.AppendNewLine();
1092 dev 1971
 
1234 dev 1972
				owner.messagesBox.AppendText(title + " Transfer Encoding: " + padding,
1973
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1974
				markers.transferEncoding = owner.messagesBox.BeginMark();
1975
				owner.messagesBox.AppendText(EncodingToString(half.TransferEncoding),
1976
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1977
				owner.messagesBox.EndMark(markers.transferEncoding);
1978
				owner.messagesBox.AppendNewLine();
1233 dev 1979
 
1234 dev 1980
				owner.messagesBox.AppendText(title + " Content Length:    " + padding,
1981
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1982
				markers.length = owner.messagesBox.BeginMark();
1983
				owner.messagesBox.AppendText(half.Length < 0 ? "<unknown>" : half.Length.ToString(),
1984
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1985
				owner.messagesBox.EndMark(markers.length);
1986
				owner.messagesBox.AppendNewLine();
1092 dev 1987
 
1234 dev 1988
				owner.messagesBox.AppendText(title + " Content Encoding:  " + padding,
1989
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1990
				markers.contentEncoding = owner.messagesBox.BeginMark();
1991
				owner.messagesBox.AppendText(EncodingToString(half.ContentEncoding),
1992
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1993
				owner.messagesBox.EndMark(markers.contentEncoding);
1994
				owner.messagesBox.AppendNewLine();
1092 dev 1995
 
1234 dev 1996
				owner.messagesBox.AppendText(title + " Content Type:      " + padding,
1997
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
1998
				markers.contentType = owner.messagesBox.BeginMark();
1999
				owner.messagesBox.AppendText(half.ContentType == null ? "<unknown>"
2000
					: half.ContentType + "/" + half.ContentSubtype,
2001
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
2002
				owner.messagesBox.EndMark(markers.contentType);
2003
				owner.messagesBox.AppendNewLine();
1092 dev 2004
 
1234 dev 2005
				owner.messagesBox.AppendText(title + " Content Charset:   " + padding,
2006
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
2007
				markers.charset = owner.messagesBox.BeginMark();
2008
				owner.messagesBox.AppendText(half.Charset == null ? "<unknown>" : half.Charset,
2009
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
2010
				owner.messagesBox.EndMark(markers.charset);
2011
				owner.messagesBox.AppendNewLine();
1092 dev 2012
 
1234 dev 2013
				owner.messagesBox.AppendText(title + " Headers:",
2014
					Color.DarkRed, Color.Transparent, false, false, 0, 0);
2015
				owner.messagesBox.AppendNewLine();
2016
				markers.headers = owner.messagesBox.BeginMark();
2017
				owner.messagesBox.EndMark(markers.headers);
1092 dev 2018
 
1234 dev 2019
				markers.headersEnum = half.Headers.GetEnumerator();
2020
				ShowHeaders(markers.headersEnum, markers.headers);
2021
			}
1092 dev 2022
 
1234 dev 2023
			private void UpdateHttpHalfView(HttpHalfMessage half, MarkerSet markers)
2024
			{
2025
				if(half.IsRequest)
2026
				{
2027
					owner.messagesBox.ChangeText(markers.method, (half as HttpRequest).Method,
2028
						Color.DarkRed, Color.LightGray, false, false, 0, 27);
2029
					owner.messagesBox.ChangeText(markers.uri, (half as HttpRequest).Uri,
2030
						Color.DarkRed, Color.LightGray, false, false, 0, 27);
2031
				}
2032
				else
2033
				{
2034
					owner.messagesBox.ChangeText(markers.status, (half as HttpResponse).StatusCode + " " + (half as HttpResponse).StatusMessage,
2035
						Color.DarkRed, Color.LightGray, false, false, 0, 27);
2036
				}
1125 dev 2037
 
1234 dev 2038
				owner.messagesBox.ChangeText(markers.version, VersionToString(half.Version),
2039
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
2040
				owner.messagesBox.ChangeText(markers.transferEncoding, EncodingToString(half.TransferEncoding),
2041
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
2042
				owner.messagesBox.ChangeText(markers.length, half.Length < 0
2043
					? "<unknown>" : half.Length.ToString(),
2044
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
2045
				owner.messagesBox.ChangeText(markers.contentEncoding, EncodingToString(half.ContentEncoding),
2046
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
2047
				owner.messagesBox.ChangeText(markers.contentType, half.ContentType == null ? "<unknown>"
2048
					: half.ContentType + "/" + half.ContentSubtype,
2049
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
2050
				owner.messagesBox.ChangeText(markers.charset, half.Charset == null
2051
					? "<unknown>" : half.Charset,
2052
					Color.DarkRed, Color.LightGray, false, false, 0, 27);
1092 dev 2053
 
1234 dev 2054
				ShowHeaders(markers.headersEnum, markers.headers);
2055
			}
1092 dev 2056
 
1234 dev 2057
			protected override void InitView()
2058
			{
2059
				try
2060
				{
2061
					lock(http)
2062
					{
1289 dev 2063
                        owner.messagesBox.BeginUpdate();
1234 dev 2064
						owner.messagesBox.Clear();
1233 dev 2065
 
1234 dev 2066
						// state
1092 dev 2067
						owner.messagesBox.AppendNewLine();
1234 dev 2068
						owner.messagesBox.AppendText("Complete:                   ",
1092 dev 2069
							Color.DarkRed, Color.Transparent, false, false, 0, 0);
1234 dev 2070
						stateMarker = owner.messagesBox.BeginMark();
2071
						owner.messagesBox.AppendText(http.Request.Complete && http.Response.Complete ? "YES" : "NO",
1092 dev 2072
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
1234 dev 2073
						owner.messagesBox.EndMark(stateMarker);
1092 dev 2074
						owner.messagesBox.AppendNewLine();
2075
						owner.messagesBox.AppendNewLine();
2076
 
1234 dev 2077
						// general info
2078
						InitHttpHalfView(http.Request,  requestMarkers,  "Request");
2079
						InitHttpHalfView(http.Response, responseMarkers, "Response");
1092 dev 2080
 
1234 dev 2081
						// bodies
1092 dev 2082
						owner.messagesBox.AppendNewLine();
1234 dev 2083
						requestMarkers.body = owner.messagesBox.BeginMark();
2084
						owner.messagesBox.EndMark(requestMarkers.body);
2085
						ShowBody(requestMarkers, http.Request, Color.Green);
1092 dev 2086
 
2087
						owner.messagesBox.AppendNewLine();
1234 dev 2088
						responseMarkers.body = owner.messagesBox.BeginMark();
2089
						owner.messagesBox.EndMark(responseMarkers.body);
2090
						ShowBody(responseMarkers, http.Response, Color.Blue);
1092 dev 2091
					}
2092
				}
2093
				finally
2094
				{
2095
					owner.messagesBox.EndUpdate();
2096
				}
2097
			}
2098
 
2099
			protected override void UpdateView()
2100
			{
2101
				try
2102
				{
2103
					owner.messagesBox.BeginUpdate();
2104
 
2105
					lock(http)
2106
					{
1234 dev 2107
						// state
2108
						owner.messagesBox.ChangeText(stateMarker, http.Request.Complete && http.Response.Complete ? "YES" : "NO",
1092 dev 2109
							Color.DarkRed, Color.LightGray, false, false, 0, 27);
2110
 
1234 dev 2111
						// general info
2112
						UpdateHttpHalfView(http.Request,  requestMarkers);
2113
						UpdateHttpHalfView(http.Response, responseMarkers);
1092 dev 2114
 
1234 dev 2115
						// bodies
2116
						owner.messagesBox.DeleteText(requestMarkers.body);
2117
						ShowBody(requestMarkers, http.Request, Color.Green);
2118
						owner.messagesBox.DeleteText(responseMarkers.body);
2119
						ShowBody(responseMarkers, http.Response, Color.Blue);
1092 dev 2120
					}
2121
				}
2122
				finally
2123
				{
2124
					owner.messagesBox.EndUpdate();
2125
				}
2126
			}
2127
 
2128
			private void ShowHeaders(IEnumerator headers, object marker)
2129
			{
2130
				while(headers.MoveNext())
2131
				{
2132
					HttpHeader h = (HttpHeader)headers.Current;
2133
 
2134
					bool first = true;
2135
					foreach(string val in h.Values)
2136
					{
2137
						if(first)
2138
						{
2139
							owner.messagesBox.InsertText(marker, h.Name + ":",
2140
								Color.DarkRed, Color.Transparent, false, false, 4, 4);
2141
							owner.messagesBox.InsertText(marker, null,
2142
								Color.DarkRed, Color.Transparent, false, false, 6 - 4 - 1, 4);
2143
							first = false;
2144
						}
2145
						else
2146
						{
2147
							owner.messagesBox.InsertText(marker, null,
2148
								Color.DarkRed, Color.Transparent, false, false, 6 + h.Name.Length, 6 + h.Name.Length);
2149
						}
2150
						owner.messagesBox.InsertText(marker, val,
2151
							Color.DarkRed, Color.LightGray, false, false, 0, 6 + h.Name.Length);
2152
						owner.messagesBox.InsertNewLine(marker);
2153
					}
2154
				}
2155
			}
2156
 
1234 dev 2157
			private void ShowBody(MarkerSet markers, HttpHalfMessage half, Color color)
1092 dev 2158
			{
1234 dev 2159
				if(half.Text != null)
1092 dev 2160
				{
1234 dev 2161
					ArrayList lines = Utils.SplitLine(half.Text);
1092 dev 2162
					for(int i = 0; i < lines.Count; i++)
2163
					{
1234 dev 2164
						owner.messagesBox.InsertText(markers.body, (string)lines[i], color, Color.LightGray, false, false, 0, 0);
2165
						owner.messagesBox.InsertNewLine(markers.body);
1092 dev 2166
					}
2167
				}
1234 dev 2168
				else if(half.Body != null)
1092 dev 2169
				{
1234 dev 2170
					ArrayList lines = Utils.SplitLine(Utils.BytesToString(half.Body, half.Length));
1092 dev 2171
					for(int i = 0; i < lines.Count; i++)
2172
					{
1234 dev 2173
						owner.messagesBox.InsertText(markers.body, (string)lines[i], color, Color.LightGray, false, false, 0, 0);
2174
						owner.messagesBox.InsertNewLine(markers.body);
1092 dev 2175
					}
2176
				}
2177
			}
2178
 
2179
			public override void WriteLog(StreamWriter writer)
2180
			{
2181
				// request info
2182
				writer.WriteLine(
1234 dev 2183
					"Complete:                   " + (http.Request.Complete && http.Response.Complete ? "YES" : "NO") + "\r\n"
2184
					+ "\r\nRequest Method:             " + http.Request.Method
2185
					+ "\r\nRequest URI:                " + http.Request.Uri
2186
					+ "\r\nRequest Version:            " + (http.Request.Version == HttpVersion.V0_9 ? "HTTP/0.9"
2187
						: http.Request.Version == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1")
2188
					+ "\r\nRequest Transfer Encoding:  " + EncodingToString(http.Request.TransferEncoding)
2189
					+ "\r\nRequest Content Length:     " + (http.Request.Length < 0 ? "<unknown>" : http.Request.Length.ToString())
2190
					+ "\r\nRequest Content Encoding:   " + EncodingToString(http.Request.ContentEncoding)
2191
					+ "\r\nRequest Content Type:       " + (http.Request.ContentType == null ? "<unknown>"
2192
						: http.Request.ContentType + "/" + http.Request.ContentSubtype)
2193
					+ "\r\nRequest Content Charset:    " + (http.Request.Charset == null ? "<unknown>" : http.Request.Charset)
1092 dev 2194
					+ "\r\nRequest Headers:");
2195
 
1234 dev 2196
				foreach(HttpHeader h in http.Request.Headers)
1092 dev 2197
				{
2198
					int indent = 0;
2199
					foreach(string val in h.Values)
2200
					{
2201
						if(indent == 0)
2202
						{
2203
							writer.WriteLine("    {0}: {1}", h.Name, val);
2204
							indent = 6 + h.Name.Length;
2205
						}
2206
						else
2207
						{
2208
							writer.WriteLine("{0," + indent + "}{1}", " ", val);
2209
						}
2210
					}
2211
				}
2212
 
2213
				// response info
2214
				writer.WriteLine(
1234 dev 2215
					"\r\nResponse Version:           " + (http.Response.Version == HttpVersion.V0_9
2216
						? "HTTP/0.9" : http.Response.Version == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1")
2217
					+ "\r\nResponse Status:            " + http.Response.StatusCode + " " + http.Response.StatusMessage
2218
					+ "\r\nResponse Transfer Encoding: " + EncodingToString(http.Response.TransferEncoding)
2219
					+ "\r\nResponse Content Length:    " + (http.Response.Length < 0
2220
						? "<unknown>" : http.Response.Length.ToString())
2221
					+ "\r\nResponse Content Encoding:  " + EncodingToString(http.Response.ContentEncoding)
2222
					+ "\r\nResponse Content Type:      " + (http.Response.ContentType == null ? "<unknown>"
2223
						: http.Response.ContentType + "/" + http.Response.ContentSubtype)
2224
					+ "\r\nResponse Content Charset:   " + (http.Response.Charset == null ? "<unknown>" : http.Response.Charset)
1092 dev 2225
					+ "\r\nResponse Headers:");
2226
 
1234 dev 2227
				foreach(HttpHeader h in http.Response.Headers)
1092 dev 2228
				{
2229
					int indent = 0;
2230
					foreach(string val in h.Values)
2231
					{
2232
						if(indent == 0)
2233
						{
2234
							writer.WriteLine("    {0}: {1}", h.Name, val);
2235
							indent = 6 + h.Name.Length;
2236
						}
2237
						else
2238
						{
2239
							writer.WriteLine("{0," + indent + "}{1}", " ", val);
2240
						}
2241
					}
2242
				}
2243
				writer.WriteLine();
2244
 
2245
				// request body
1234 dev 2246
				if(http.Request.Text != null)
1092 dev 2247
				{
1234 dev 2248
					writer.WriteLine(http.Request.Text);
1092 dev 2249
				}
1234 dev 2250
				else if(http.Request.Body != null)
1092 dev 2251
				{
1234 dev 2252
					writer.WriteLine(Utils.BytesToString(http.Request.Body, http.Request.Length));
1092 dev 2253
				}
2254
 
2255
				// response body
1234 dev 2256
				if(http.Response.Text != null)
1092 dev 2257
				{
1234 dev 2258
					writer.WriteLine(http.Response.Text);
1092 dev 2259
				}
1234 dev 2260
				else if(http.Response.Body != null)
1092 dev 2261
				{
1234 dev 2262
					writer.WriteLine(Utils.BytesToString(http.Response.Body, http.Response.Length));
1092 dev 2263
				}
2264
 
2265
				writer.WriteLine("===============================================================");
2266
				writer.WriteLine();
2267
			}
2268
		}
2269
 
2270
		private class XmlNodeData : TreeNodeData
2271
		{
2272
			private XmlMessage xml;
2273
 
2274
			public XmlMessage Xml
2275
			{
2276
				get { return xml; }
2277
				set { xml = value; }
2278
			}
2279
 
2280
			public XmlNodeData(MainForm owner, TreeNode node) : base(owner, node)
2281
			{
2282
			}
2283
 
2284
			protected override void InitView()
2285
			{
2286
				try
2287
				{
2288
					// update main screen if necessary
2289
					owner.messagesBox.BeginUpdate();
2290
 
2291
					lock(xml)
2292
					{
2293
						owner.messagesBox.Clear();
2294
						if(xml.ParseException != null)
2295
						{
2296
							owner.messagesBox.AppendText("Cannot parse XML:",
2297
								Color.Red, Color.Transparent, false, false, 0, 0);
2298
							owner.messagesBox.AppendNewLine();
2299
							owner.messagesBox.AppendText(xml.ParseException.Message,
2300
								Color.Red, Color.Transparent, false, false, 2, 2);
2301
							owner.messagesBox.AppendNewLine();
2302
						}
2303
						else if(xml.Xml != null)
2304
						{
2305
							ShowXmlNode(xml.Xml, 0);
2306
						}
2307
					}
2308
				}
2309
				finally
2310
				{
2311
					owner.messagesBox.EndUpdate();
2312
				}
2313
			}
2314
 
2315
			protected override void UpdateView()
2316
			{
2317
			}
2318
 
2319
			private void ShowXmlNode(XmlNode node, int indent)
2320
			{
2321
				if(node.NodeType == XmlNodeType.Document)
2322
				{
2323
					foreach(XmlNode subnode in node.ChildNodes)
2324
					{
2325
						ShowXmlNode(subnode, indent);
2326
					}
2327
				}
2328
				else if(node.NodeType == XmlNodeType.XmlDeclaration)
2329
				{
2330
					owner.messagesBox.AppendText("<?" + node.Name + " " + node.Value + " ?>",
2331
						Color.Blue, Color.Transparent, false, false, indent, indent+2);
2332
					owner.messagesBox.AppendNewLine();
2333
				}
2334
				else if(node.NodeType == XmlNodeType.Comment)
2335
				{
2336
					owner.messagesBox.AppendText("<!--", Color.Gray, Color.Transparent, false, false, indent, indent + 2);
2337
					ShowNormalizedXmlValue(node.Value, Color.Gray, Color.Thistle, false, false, indent);
2338
					owner.messagesBox.AppendText("-->", Color.Gray, Color.Transparent, false, false, 0, indent + 2);
2339
					owner.messagesBox.AppendNewLine();
2340
				}
2341
				else if(node.NodeType == XmlNodeType.Element)
2342
				{
2343
					owner.messagesBox.AppendText("<", Color.Blue, Color.Transparent, false, false, indent, indent + 2);
2344
					owner.messagesBox.AppendText(node.Name, Color.DarkRed, Color.Transparent, false, false, 0, indent + 2);
2345
 
2346
					foreach(XmlAttribute attr in node.Attributes)
2347
					{
2348
						bool xmlAttr = attr.Name.StartsWith("xml");
2349
						owner.messagesBox.AppendText(attr.Name, xmlAttr ? Color.Red : Color.DarkRed, Color.Transparent, false, false, 1, indent + 2);
2350
						owner.messagesBox.AppendText("=\"", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2351
						owner.messagesBox.AppendText(attr.Value, xmlAttr ? Color.Red : Color.DarkRed, Color.Transparent, false, false, 0, indent + 2);
2352
						owner.messagesBox.AppendText("\"", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2353
					}
2354
 
2355
					if(!node.HasChildNodes)
2356
					{
2357
						owner.messagesBox.AppendText(" />", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2358
						owner.messagesBox.AppendNewLine();
2359
					}
2360
					else
2361
					{
2362
						owner.messagesBox.AppendText(">", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2363
 
2364
						bool elementExists = false;
2365
						bool lastText      = true;
2366
						foreach(XmlNode subnode in node.ChildNodes)
2367
						{
2368
							if(subnode.NodeType == XmlNodeType.Text)
2369
							{
2370
								if(elementExists) owner.messagesBox.AppendNewLine();
2371
								ShowNormalizedXmlValue(subnode.Value, Color.Black, Color.LightGray, false, false, indent);
2372
								lastText = true;
2373
							}
2374
							else
2375
							{
2376
								if(lastText) owner.messagesBox.AppendNewLine();
2377
								ShowXmlNode(subnode, indent + 2);
2378
								elementExists = true;
2379
								lastText      = false;
2380
							}
2381
						}
2382
 
2383
						if(elementExists) owner.messagesBox.AppendText(null, Color.Black, Color.Transparent, false, false, indent, indent + 2);
2384
						owner.messagesBox.AppendText("</", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2385
						owner.messagesBox.AppendText(node.Name, Color.DarkRed, Color.Transparent, false, false, 0, indent + 2);
2386
						owner.messagesBox.AppendText(">", Color.Blue, Color.Transparent, false, false, 0, indent + 2);
2387
						owner.messagesBox.AppendNewLine();
2388
					}
2389
				}
2390
			}
2391
 
2392
			private void ShowNormalizedXmlValue(string s, Color color, Color backColor, bool italic, bool bold, int indent)
2393
			{
2394
				int begin;
2395
				int end;
2396
 
2397
				bool newLineFound = false;
2398
				foreach(char c in s)
2399
				{
2400
					if(c == '\n')
2401
					{
2402
						newLineFound = true;
2403
						break;
2404
					}
2405
				}
2406
 
2407
				if(newLineFound)
2408
				{
2409
					owner.messagesBox.AppendNewLine();
2410
					owner.messagesBox.AppendText(null, color, Color.Transparent, italic, bold, indent, indent);
2411
					owner.messagesBox.AppendText(null, color, backColor, italic, bold, 2, 2);
2412
				}
2413
 
2414
				// trim
2415
				for(begin = 0; begin < s.Length; begin++)
2416
				{
2417
					char c = s[begin];
2418
					if(c != '\n' && c != '\r' && c != '\t' && c != ' ') break;
2419
				}
2420
				for(end = s.Length-1; end >= 0; end--)
2421
				{
2422
					char c = s[end];
2423
					if(c != '\n' && c != '\r' && c != '\t' && c != ' ') break;
2424
				}
2425
 
2426
				StringBuilder b = new StringBuilder(s.Length);
2427
				for(int i = begin; i <= end; i++)
2428
				{
2429
					char c = s[i];
2430
 
2431
					switch(c)
2432
					{
2433
						case '\n':
2434
							if(b.Length > 0)
2435
							{
2436
								owner.messagesBox.AppendText(b.ToString(), color, backColor, italic, bold, 0, indent + 2);
2437
								b.Length = 0;
2438
							}
2439
 
2440
							owner.messagesBox.AppendNewLine();
2441
							owner.messagesBox.AppendText(null, color, Color.Transparent, italic, bold, indent, indent);
2442
							owner.messagesBox.AppendText(null, color, backColor, italic, bold, 2, 2);
2443
							break;
2444
 
2445
						case '\r':
2446
							break;
2447
 
2448
						case '\t':
2449
							b.Append("  ");
2450
							break;
2451
 
2452
						default:
2453
							b.Append(c);
2454
							break;
2455
					}
2456
				}
2457
 
2458
				if(b.Length > 0)
2459
					owner.messagesBox.AppendText(b.ToString(), color, backColor, italic, bold, 0, indent + 2);
2460
 
2461
				if(newLineFound)
2462
				{
2463
					owner.messagesBox.AppendNewLine();
2464
					owner.messagesBox.AppendText(null, color, Color.Transparent, italic, bold, indent, indent + 2);
2465
				}
2466
			}
2467
 
2468
			public override void WriteLog(StreamWriter writer)
2469
			{
2470
				WriteXmlNode(writer, xml.Xml, "");
2471
				writer.WriteLine("===============================================================");
2472
				writer.WriteLine();
2473
			}
2474
 
2475
			private void WriteXmlNode(StreamWriter writer, XmlNode node, string indent)
2476
			{
2477
				if(node.NodeType == XmlNodeType.Document)
2478
				{
2479
					foreach(XmlNode subnode in node.ChildNodes)
2480
					{
2481
						WriteXmlNode(writer, subnode, indent);
2482
					}
2483
				}
2484
				else if(node.NodeType == XmlNodeType.XmlDeclaration)
2485
				{
2486
					writer.WriteLine(indent + "<?" + node.Name + " " + node.Value + " ?>");
2487
				}
2488
				else if(node.NodeType == XmlNodeType.Comment)
2489
				{
2490
					writer.Write(indent + "<!--");
2491
					WriteNormalizedXmlValue(writer, node.Value, indent);
2492
					writer.WriteLine("-->");
2493
				}
2494
				else if(node.NodeType == XmlNodeType.Element)
2495
				{
2496
					writer.Write(indent + "<" + node.Name);
2497
 
2498
					foreach(XmlAttribute attr in node.Attributes)
2499
					{
2500
						bool xmlAttr = attr.Name.StartsWith("xml");
2501
						writer.Write(" " + attr.Name + "=\"" + attr.Value + "\"");
2502
					}
2503
 
2504
					if(!node.HasChildNodes)
2505
					{
2506
						writer.WriteLine(" />");
2507
					}
2508
					else
2509
					{
2510
						writer.Write(">");
2511
 
2512
						bool elementExists = false;
2513
						bool lastText      = true;
2514
						foreach(XmlNode subnode in node.ChildNodes)
2515
						{
2516
							if(subnode.NodeType == XmlNodeType.Text)
2517
							{
2518
								if(elementExists) writer.WriteLine();
2519
								WriteNormalizedXmlValue(writer, subnode.Value, indent);
2520
								lastText = true;
2521
							}
2522
							else
2523
							{
2524
								if(lastText) writer.WriteLine();
2525
								WriteXmlNode(writer, subnode, indent + "  ");
2526
								elementExists = true;
2527
								lastText      = false;
2528
							}
2529
						}
2530
 
2531
						if(elementExists) writer.Write(indent);
2532
						writer.WriteLine("</" + node.Name + ">");
2533
					}
2534
				}
2535
			}
2536
 
2537
			private void WriteNormalizedXmlValue(StreamWriter writer, string s, string indent)
2538
			{
2539
				int begin;
2540
				int end;
2541
 
2542
				bool newLineFound = false;
2543
				foreach(char c in s)
2544
				{
2545
					if(c == '\n')
2546
					{
2547
						newLineFound = true;
2548
						break;
2549
					}
2550
				}
2551
 
2552
				if(newLineFound)
2553
				{
2554
					writer.WriteLine();
2555
					writer.Write(indent + "  ");
2556
				}
2557
 
2558
				// trim
2559
				for(begin = 0; begin < s.Length; begin++)
2560
				{
2561
					char c = s[begin];
2562
					if(c != '\n' && c != '\r' && c != '\t' && c != ' ') break;
2563
				}
2564
				for(end = s.Length-1; end >= 0; end--)
2565
				{
2566
					char c = s[end];
2567
					if(c != '\n' && c != '\r' && c != '\t' && c != ' ') break;
2568
				}
2569
 
2570
				StringBuilder b = new StringBuilder(s.Length);
2571
				for(int i = begin; i <= end; i++)
2572
				{
2573
					char c = s[i];
2574
 
2575
					switch(c)
2576
					{
2577
						case '\n':
2578
							if(b.Length > 0)
2579
							{
2580
								writer.Write(b.ToString());
2581
								b.Length = 0;
2582
							}
2583
 
2584
							writer.WriteLine();
2585
							writer.Write(indent + "  ");
2586
							break;
2587
 
2588
						case '\r':
2589
							break;
2590
 
2591
						case '\t':
2592
							b.Append("  ");
2593
							break;
2594
 
2595
						case '&':
2596
							b.Append("&amp;");
2597
							break;
2598
 
2599
						case '<':
2600
							b.Append("&lt;");
2601
							break;
2602
 
2603
						case '>':
2604
							b.Append("&gt;");
2605
							break;
2606
 
2607
						default:
2608
							b.Append(c);
2609
							break;
2610
					}
2611
				}
2612
 
2613
				if(b.Length > 0)
2614
					writer.Write(b.ToString());
2615
 
2616
				if(newLineFound)
2617
				{
2618
					writer.WriteLine();
2619
					writer.Write(indent + "  ");
2620
				}
2621
			}
2622
		}
2623
 
2624
		#endregion node display classes
2625
 
2626
		#region other classes
2627
		private abstract class Utils
2628
		{
2629
			public static string BytesToString(byte[] bytes, int length)
2630
			{
2631
				if(bytes == null) return null;
2632
 
2633
				char[]  chars   = new char[length + 1];
2634
				Decoder decoder = System.Text.Encoding.UTF8.GetDecoder();
2635
				int     charLen = decoder.GetChars(bytes, 0, length, chars, 0);
2636
 
2637
				for(int i = 0; i < charLen; i++)
2638
				{
2639
					char c = chars[i];
2640
					if(c != '\n' && c != '\r' && Char.IsControl(c)) chars[i] = '.';
2641
				}
2642
 
2643
				return (new System.String(chars)).Substring(0, charLen);
2644
			}
2645
 
2646
			public static ArrayList SplitLine(string line)
2647
			{
2648
				if(line == null) return null;
2649
 
2650
				ArrayList    res = new ArrayList();
2651
				StringBuilder b  = new StringBuilder(200);
2652
 
2653
				foreach(char c in line)
2654
				{
2655
					switch(c)
2656
					{
2657
						case '\r':
2658
							break;
2659
 
2660
						case '\n':
2661
							res.Add(b.ToString());
2662
							b.Length = 0;
2663
							break;
2664
 
2665
						default:
2666
							b.Append(c);
2667
							break;
2668
					}
2669
				}
2670
 
2671
				res.Add(b.ToString());
2672
 
2673
				return res;
2674
			}
2675
		}
2676
		#endregion other classes
2677
 
1288 dev 2678
    }
2679
 
1092 dev 2680
	public class LogMessages
2681
	{
2682
		private ArrayList messages = new ArrayList();
2683
		private ListBox   logBox;
2684
		private LogLevel  level = LogLevel.Debug;
2685
 
2686
		public LogLevel Level
2687
		{
2688
			get { return level; }
2689
			set { level = value; Update(); }
2690
		}
2691
 
2692
		public LogMessages(ListBox logBox)
2693
		{
2694
			this.logBox = logBox;
2695
		}
2696
 
2697
		public ArrayList Messages
2698
		{
2699
			get { return new ArrayList(messages); }
2700
		}
2701
 
2702
		public void Add(LogMessage message)
2703
		{
2704
			messages.Add(message);
2705
			if(Show(message))
2706
				logBox.TopIndex = logBox.Items.Count - 1;
2707
		}
2708
 
2709
		public void Clear()
2710
		{
2711
			messages.Clear();
2712
			logBox.Items.Clear();
2713
		}
2714
 
2715
		public void Update()
2716
		{
2717
			logBox.BeginUpdate();
2718
 
2719
			logBox.Items.Clear();
2720
			foreach(LogMessage message in messages)
2721
			{
2722
				Show(message);
2723
			}
2724
			logBox.TopIndex = logBox.Items.Count - 1;
2725
 
2726
			logBox.EndUpdate();
2727
		}
2728
 
2729
		private bool Show(LogMessage message)
2730
		{
2731
			if(message.Level > this.level) return false;
2732
 
2733
			try
2734
			{
2735
				logBox.Items.Add(message.ToString());
2736
			}
2737
			catch(ObjectDisposedException) {}
2738
 
2739
			return true;
2740
		}
2741
	}
2742
 
2743
	public class LogMessage
2744
	{
2745
		private TcpConnection tcp;
2746
		private LogLevel      level;
2747
		private string        message;
2748
		private Exception     exception;
2749
		private DateTime      timestamp = DateTime.Now;
2750
 
2751
		public TcpConnection Tcp
2752
		{
2753
			get { return tcp; }
2754
			set { tcp = value; }
2755
		}
2756
 
2757
		public LogLevel Level
2758
		{
2759
			get { return level; }
2760
			set { level = value; }
2761
		}
2762
 
2763
		public string Message
2764
		{
2765
			get { return message; }
2766
			set { message = value; }
2767
		}
2768
 
2769
		public Exception Exception
2770
		{
2771
			get { return exception; }
2772
			set { exception = value; }
2773
		}
2774
 
2775
		public DateTime Timestamp
2776
		{
2777
			get { return timestamp; }
2778
			set { timestamp = value; }
2779
		}
2780
 
2781
		public LogMessage(TcpConnection tcp, LogLevel level, string message, Exception exception)
2782
		{
2783
			this.tcp       = tcp;
2784
			this.level     = level;
2785
			this.message   = message;
2786
			this.exception = exception;
2787
		}
2788
 
2789
		public override string ToString()
2790
		{
2791
			string l = "     ";
2792
			switch(level)
2793
			{
2794
				case LogLevel.Debug:     l = "debug"; break;
2795
				case LogLevel.Info:      l = "info "; break;
2796
				case LogLevel.Important: l = "Imp  "; break;
2797
				case LogLevel.Warning:   l = "Warn "; break;
2798
				case LogLevel.Error:     l = "ERROR"; break;
2799
				case LogLevel.Critical:  l = "CRIT "; break;
2800
			}
2801
 
2802
			return (tcp == null ? "...." : tcp.Id) + " " + l + " " + timestamp.ToString("HH:mm:ss.ffff") + " "
2803
				+ (exception != null ? exception.Message : message);
2804
		}
2805
	}
2806
 
2807
	public enum TcpShowMode
2808
	{
2809
		ByDirection,
2810
		ByTime
2811
	}
1194 dev 2812
 
2813
	public class RecentItem : IComparable
2814
	{
2815
		private int listenPort;
2816
 
2817
		public int ListenPort
2818
		{
2819
			get { return listenPort; }
2820
			set { listenPort = value; }
2821
		}
2822
 
2823
		private string resendHost;
2824
 
2825
		public string ResendHost
2826
		{
2827
			get { return resendHost; }
2828
			set { resendHost = value; }
2829
		}
2830
 
2831
		private int resendPort;
2832
 
2833
		public int ResendPort
2834
		{
2835
			get { return resendPort; }
2836
			set { resendPort = value; }
2837
		}
2838
 
2839
		private DateTime timestamp;
2840
 
2841
		public DateTime Timestamp
2842
		{
2843
			get { return timestamp; }
2844
		}
2845
 
2846
		public RecentItem(int listenPort, string resendHost, int resendPort)
2847
		{
2848
			this.listenPort = listenPort;
2849
			this.resendHost = resendHost;
2850
			this.resendPort = resendPort;
2851
		}
2852
 
2853
		public override string ToString()
2854
		{
1197 dev 2855
			return string.Format("{0} to {1}:{2} at {3:HH:mm:ss.ff}",
1194 dev 2856
				listenPort, resendHost, resendPort, timestamp);
2857
		}
2858
 
2859
		public override bool Equals(object obj)
2860
		{
2861
			if(!(obj is RecentItem)) return false;
2862
 
2863
			RecentItem i2 = (RecentItem)obj;
2864
 
2865
			return (i2.listenPort == this.listenPort) && (i2.resendHost == this.resendHost)
2866
				&& (i2.resendPort == this.resendPort);
2867
		}
2868
 
2869
		public override int GetHashCode()
2870
		{
2871
			return this.resendHost.GetHashCode();
2872
		}
2873
 
2874
		public string SaveToRegistry()
2875
		{
1197 dev 2876
			return string.Format("{0}:{1}:{2}:{3}",
1194 dev 2877
				listenPort, resendPort, timestamp.Ticks, resendHost);
2878
		}
2879
 
2880
		public static RecentItem LoadFromRegistry(string str)
2881
		{
2882
			Regex re = new Regex(@"^(\d+):(\d+):(\d+):(.+)$");
2883
			Match m  = re.Match(str);
2884
			if(!m.Success) throw new Exception("Cannot parse recent item");
2885
 
1197 dev 2886
			RecentItem item = new RecentItem(int.Parse(m.Groups[1].Value),
1194 dev 2887
				m.Groups[4].Value, int.Parse(m.Groups[2].Value));
2888
 
2889
			item.timestamp = new DateTime(long.Parse(m.Groups[3].Value));
2890
 
2891
			return item;
2892
		}
2893
 
2894
		public void UpdateTimestamp()
2895
		{
2896
			timestamp = DateTime.Now;
2897
		}
2898
 
2899
		public void UpdateTimestamp(RecentItem second)
2900
		{
2901
			if(second.timestamp > timestamp)
2902
				timestamp = second.timestamp;
2903
		}
2904
 
2905
		#region IComparable Members
2906
 
2907
		int IComparable.CompareTo(object obj)
2908
		{
2909
			if(!(obj is RecentItem))
2910
				throw new Exception("Cannot compare");
2911
 
2912
			return this.timestamp.CompareTo(((RecentItem)obj).timestamp);
2913
		}
2914
 
2915
		#endregion
2916
	}
1092 dev 2917
}