Added command-line client (for debug only).
[BoarSSL] / IO / MergeStream.cs
1 /*
2 * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 using System;
26 using System.IO;
27
28 namespace IO {
29
30 /*
31 * This class merges two underlying streams (one for reading, the other
32 * for writing) into a single Stream object. It can also optionally dump
33 * all read and written bytes, in hexadecimal, on an provided text
34 * stream (for debugging purposes).
35 */
36
37 public class MergeStream : Stream {
38
39 Stream subIn, subOut;
40
41 /*
42 * Text stream on which to write an hexadecimal dump of the data
43 * which is read from or written to this stream. If null (the
44 * default), then no dump is written.
45 */
46 public TextWriter Debug {
47 get; set;
48 }
49
50 /*
51 * Create this stream over the two underlying substreams:
52 * 'subIn', from which data is read, and 'subOut', to which data
53 * is written. The two substreams may be the same object.
54 */
55 public MergeStream(Stream subIn, Stream subOut)
56 {
57 this.subIn = subIn;
58 this.subOut = subOut;
59 }
60
61 public override int ReadByte()
62 {
63 int x = subIn.ReadByte();
64 if (Debug != null) {
65 if (x >= 0) {
66 Debug.WriteLine("recv:");
67 Debug.WriteLine(" {0:x2}", x);
68 } else {
69 Debug.WriteLine("recv: EOF");
70 }
71 }
72 return x;
73 }
74
75 public override int Read(byte[] buf, int off, int len)
76 {
77 int rlen = subIn.Read(buf, off, len);
78 if (Debug != null) {
79 if (rlen <= 0) {
80 Debug.WriteLine("recv: EOF");
81 } else {
82 Debug.Write("recv:");
83 for (int i = 0; i < rlen; i ++) {
84 if ((i & 15) == 0) {
85 Debug.WriteLine();
86 Debug.Write(" ");
87 } else if ((i & 7) == 0) {
88 Debug.Write(" ");
89 } else {
90 Debug.Write(" ");
91 }
92 Debug.Write("{0:x2}", buf[i]);
93 }
94 Debug.WriteLine();
95 }
96 }
97 return rlen;
98 }
99
100 public override void WriteByte(byte x)
101 {
102 if (Debug != null) {
103 Debug.WriteLine("send:");
104 Debug.WriteLine(" {0:x2}", x);
105 }
106 subOut.WriteByte(x);
107 }
108
109 public override void Write(byte[] buf, int off, int len)
110 {
111 if (Debug != null) {
112 Debug.Write("send:");
113 for (int i = 0; i < len; i ++) {
114 if ((i & 15) == 0) {
115 Debug.WriteLine();
116 Debug.Write(" ");
117 } else if ((i & 7) == 0) {
118 Debug.Write(" ");
119 } else {
120 Debug.Write(" ");
121 }
122 Debug.Write("{0:x2}", buf[i]);
123 }
124 Debug.WriteLine();
125 }
126 subOut.Write(buf, off, len);
127 }
128
129 public override void Flush()
130 {
131 subOut.Flush();
132 }
133
134 public override void Close()
135 {
136 Exception ex1 = null, ex2 = null;
137 try {
138 subIn.Close();
139 } catch (Exception ex) {
140 ex1 = ex;
141 }
142 try {
143 subOut.Close();
144 } catch (Exception ex) {
145 ex2 = ex;
146 }
147 if (ex2 != null) {
148 throw ex2;
149 } else if (ex1 != null) {
150 throw ex1;
151 }
152 }
153
154 public override long Seek(long off, SeekOrigin origin)
155 {
156 throw new NotSupportedException();
157 }
158
159 public override void SetLength(long len)
160 {
161 throw new NotSupportedException();
162 }
163
164 public override bool CanRead {
165 get {
166 return subIn.CanRead;
167 }
168 }
169
170 public override bool CanWrite {
171 get {
172 return subOut.CanWrite;
173 }
174 }
175
176 public override bool CanSeek {
177 get {
178 return false;
179 }
180 }
181
182 public override long Length {
183 get {
184 throw new NotSupportedException();
185 }
186 }
187
188 public override long Position {
189 get {
190 throw new NotSupportedException();
191 }
192 set {
193 throw new NotSupportedException();
194 }
195 }
196 }
197
198 }