]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | /** |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, | |
13 | * software distributed under the License is distributed on an | |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | * KIND, either express or implied. See the License for the | |
16 | * specific language governing permissions and limitations | |
17 | * under the License. | |
18 | * | |
19 | * Contains some contributions under the Thrift Software License. | |
20 | * Please see doc/old-thrift-license.txt in the Thrift distribution for | |
21 | * details. | |
22 | */ | |
23 | ||
24 | using System; | |
25 | using System.IO; | |
26 | ||
27 | namespace Thrift.Transport | |
28 | { | |
29 | public abstract class TTransport : IDisposable | |
30 | { | |
31 | public abstract bool IsOpen | |
32 | { | |
33 | get; | |
34 | } | |
35 | ||
36 | private byte[] _peekBuffer = new byte[1]; | |
37 | private bool _hasPeekByte; | |
38 | ||
39 | public bool Peek() | |
40 | { | |
41 | //If we already have a byte read but not consumed, do nothing. | |
42 | if (_hasPeekByte) | |
43 | return true; | |
44 | ||
45 | //If transport closed we can't peek. | |
46 | if (!IsOpen) | |
47 | return false; | |
48 | ||
49 | //Try to read one byte. If succeeds we will need to store it for the next read. | |
50 | try | |
51 | { | |
52 | int bytes = Read(_peekBuffer, 0, 1); | |
53 | if (bytes == 0) | |
54 | return false; | |
55 | } | |
56 | catch (IOException) | |
57 | { | |
58 | return false; | |
59 | } | |
60 | ||
61 | _hasPeekByte = true; | |
62 | return true; | |
63 | } | |
64 | ||
65 | public abstract void Open(); | |
66 | ||
67 | public abstract void Close(); | |
68 | ||
69 | protected static void ValidateBufferArgs(byte[] buf, int off, int len) | |
70 | { | |
71 | if (buf == null) | |
72 | throw new ArgumentNullException("buf"); | |
73 | if (off < 0) | |
74 | throw new ArgumentOutOfRangeException("Buffer offset is smaller than zero."); | |
75 | if (len < 0) | |
76 | throw new ArgumentOutOfRangeException("Buffer length is smaller than zero."); | |
77 | if (off + len > buf.Length) | |
78 | throw new ArgumentOutOfRangeException("Not enough data."); | |
79 | } | |
80 | ||
81 | public abstract int Read(byte[] buf, int off, int len); | |
82 | ||
83 | public int ReadAll(byte[] buf, int off, int len) | |
84 | { | |
85 | ValidateBufferArgs(buf, off, len); | |
86 | int got = 0; | |
87 | ||
88 | //If we previously peeked a byte, we need to use that first. | |
89 | if (_hasPeekByte) | |
90 | { | |
91 | buf[off + got++] = _peekBuffer[0]; | |
92 | _hasPeekByte = false; | |
93 | } | |
94 | ||
95 | while (got < len) | |
96 | { | |
97 | int ret = Read(buf, off + got, len - got); | |
98 | if (ret <= 0) | |
99 | { | |
100 | throw new TTransportException( | |
101 | TTransportException.ExceptionType.EndOfFile, | |
102 | "Cannot read, Remote side has closed"); | |
103 | } | |
104 | got += ret; | |
105 | } | |
106 | return got; | |
107 | } | |
108 | ||
109 | public virtual void Write(byte[] buf) | |
110 | { | |
111 | Write(buf, 0, buf.Length); | |
112 | } | |
113 | ||
114 | public abstract void Write(byte[] buf, int off, int len); | |
115 | ||
116 | public virtual void Flush() | |
117 | { | |
118 | } | |
119 | ||
120 | public virtual IAsyncResult BeginFlush(AsyncCallback callback, object state) | |
121 | { | |
122 | throw new TTransportException( | |
123 | TTransportException.ExceptionType.Unknown, | |
124 | "Asynchronous operations are not supported by this transport."); | |
125 | } | |
126 | ||
127 | public virtual void EndFlush(IAsyncResult asyncResult) | |
128 | { | |
129 | throw new TTransportException( | |
130 | TTransportException.ExceptionType.Unknown, | |
131 | "Asynchronous operations are not supported by this transport."); | |
132 | } | |
133 | ||
134 | #region " IDisposable Support " | |
135 | // IDisposable | |
136 | protected abstract void Dispose(bool disposing); | |
137 | ||
138 | public void Dispose() | |
139 | { | |
140 | // Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above. | |
141 | Dispose(true); | |
142 | GC.SuppressFinalize(this); | |
143 | } | |
144 | #endregion | |
145 | } | |
146 | } |