Initial commit.
[BoarSSL] / Twrch / 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 /*
29 * This class merges two underlying streams (one for reading, the other
30 * for writing) into a single Stream object. It can also optionally dump
31 * all read and written bytes, in hexadecimal, on an provided text
32 * stream (for debugging purposes).
33 */
34
35 internal class MergeStream : Stream {
36
37 Stream subIn, subOut;
38
39 internal TextWriter Debug {
40 get; set;
41 }
42
43 internal MergeStream(Stream subIn, Stream subOut)
44 {
45 this.subIn = subIn;
46 this.subOut = subOut;
47 }
48
49 public override int ReadByte()
50 {
51 int x = subIn.ReadByte();
52 if (Debug != null) {
53 if (x >= 0) {
54 Debug.WriteLine("recv:");
55 Debug.WriteLine(" {0:x2}", x);
56 } else {
57 Debug.WriteLine("recv: EOF");
58 }
59 }
60 return x;
61 }
62
63 public override int Read(byte[] buf, int off, int len)
64 {
65 int rlen = subIn.Read(buf, off, len);
66 if (Debug != null) {
67 if (rlen <= 0) {
68 Debug.WriteLine("recv: EOF");
69 } else {
70 Debug.Write("recv:");
71 for (int i = 0; i < rlen; i ++) {
72 if ((i & 15) == 0) {
73 Debug.WriteLine();
74 Debug.Write(" ");
75 } else if ((i & 7) == 0) {
76 Debug.Write(" ");
77 } else {
78 Debug.Write(" ");
79 }
80 Debug.Write("{0:x2}", buf[i]);
81 }
82 Debug.WriteLine();
83 }
84 }
85 return rlen;
86 }
87
88 public override void WriteByte(byte x)
89 {
90 if (Debug != null) {
91 Debug.WriteLine("send:");
92 Debug.WriteLine(" {0:x2}", x);
93 }
94 subOut.WriteByte(x);
95 }
96
97 public override void Write(byte[] buf, int off, int len)
98 {
99 if (Debug != null) {
100 Debug.Write("send:");
101 for (int i = 0; i < len; i ++) {
102 if ((i & 15) == 0) {
103 Debug.WriteLine();
104 Debug.Write(" ");
105 } else if ((i & 7) == 0) {
106 Debug.Write(" ");
107 } else {
108 Debug.Write(" ");
109 }
110 Debug.Write("{0:x2}", buf[i]);
111 }
112 Debug.WriteLine();
113 }
114 subOut.Write(buf, off, len);
115 }
116
117 public override void Flush()
118 {
119 subOut.Flush();
120 }
121
122 public override void Close()
123 {
124 Exception ex1 = null, ex2 = null;
125 try {
126 subIn.Close();
127 } catch (Exception ex) {
128 ex1 = ex;
129 }
130 try {
131 subOut.Close();
132 } catch (Exception ex) {
133 ex2 = ex;
134 }
135 if (ex2 != null) {
136 throw ex2;
137 } else if (ex1 != null) {
138 throw ex1;
139 }
140 }
141
142 public override long Seek(long off, SeekOrigin origin)
143 {
144 throw new NotSupportedException();
145 }
146
147 public override void SetLength(long len)
148 {
149 throw new NotSupportedException();
150 }
151
152 public override bool CanRead {
153 get {
154 return subIn.CanRead;
155 }
156 }
157
158 public override bool CanWrite {
159 get {
160 return subOut.CanWrite;
161 }
162 }
163
164 public override bool CanSeek {
165 get {
166 return false;
167 }
168 }
169
170 public override long Length {
171 get {
172 throw new NotSupportedException();
173 }
174 }
175
176 public override long Position {
177 get {
178 throw new NotSupportedException();
179 }
180 set {
181 throw new NotSupportedException();
182 }
183 }
184 }