• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jstedfast / MailKit / 4.11.0.1379

08 Apr 2025 07:24PM UTC coverage: 93.354% (-0.008%) from 93.362%
4.11.0.1379

push

coveralls.net

jstedfast
Bump System.Formats.Asn1 to 8.0.2

23965 of 25671 relevant lines covered (93.35%)

0.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.21
/MailKit/Net/NetworkStream.cs
1
//
2
// NetworkStream.cs
3
//
4
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
5
//
6
// Copyright (c) 2013-2025 .NET Foundation and Contributors
7
//
8
// Permission is hereby granted, free of charge, to any person obtaining a copy
9
// of this software and associated documentation files (the "Software"), to deal
10
// in the Software without restriction, including without limitation the rights
11
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
// copies of the Software, and to permit persons to whom the Software is
13
// furnished to do so, subject to the following conditions:
14
//
15
// The above copyright notice and this permission notice shall be included in
16
// all copies or substantial portions of the Software.
17
//
18
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
// THE SOFTWARE.
25
//
26

27
using System;
28
using System.IO;
29
using System.Threading;
30
using System.Net.Sockets;
31
using System.Threading.Tasks;
32

33
namespace MailKit.Net
34
{
35
        class NetworkStream : Stream
36
        {
37
                SocketAsyncEventArgs send;
38
                SocketAsyncEventArgs recv;
39
                bool ownsSocket;
40
                bool connected;
41

42
                public NetworkStream (Socket socket, bool ownsSocket)
1✔
43
                {
1✔
44
                        send = new SocketAsyncEventArgs ();
1✔
45
                        send.Completed += AsyncOperationCompleted;
1✔
46
                        send.AcceptSocket = socket;
1✔
47

48
                        recv = new SocketAsyncEventArgs ();
1✔
49
                        recv.Completed += AsyncOperationCompleted;
1✔
50
                        recv.AcceptSocket = socket;
1✔
51

52
                        this.ownsSocket = ownsSocket;
1✔
53
                        connected = socket.Connected;
1✔
54
                        Socket = socket;
1✔
55
                }
1✔
56

57
                public Socket Socket {
58
                        get; private set;
59
                }
60

61
                public bool DataAvailable {
62
                        get { return connected && Socket.Available > 0; }
1✔
63
                }
64

65
                public override bool CanRead {
66
                        get { return connected; }
1✔
67
                }
68

69
                public override bool CanWrite {
70
                        get { return connected; }
1✔
71
                }
72

73
                public override bool CanSeek {
74
                        get { return false; }
1✔
75
                }
76

77
                public override bool CanTimeout {
78
                        get { return connected; }
1✔
79
                }
80

81
                public override long Length {
82
                        get { throw new NotSupportedException (); }
1✔
83
                }
84

85
                public override long Position {
86
                        get { throw new NotSupportedException (); }
1✔
87
                        set { throw new NotSupportedException (); }
1✔
88
                }
89

90
                public override int ReadTimeout {
91
                        get {
1✔
92
                                int timeout = Socket.ReceiveTimeout;
1✔
93

94
                                return timeout == 0 ? Timeout.Infinite : timeout;
1✔
95
                        }
1✔
96
                        set {
1✔
97
                                if (value <= 0 && value != Timeout.Infinite)
1✔
98
                                        throw new ArgumentOutOfRangeException (nameof (value));
1✔
99

100
                                Socket.ReceiveTimeout = value;
1✔
101
                        }
1✔
102
                }
103

104
                public override int WriteTimeout {
105
                        get {
1✔
106
                                int timeout = Socket.SendTimeout;
1✔
107

108
                                return timeout == 0 ? Timeout.Infinite : timeout;
1✔
109
                        }
1✔
110
                        set {
1✔
111
                                if (value <= 0 && value != Timeout.Infinite)
1✔
112
                                        throw new ArgumentOutOfRangeException (nameof (value));
1✔
113

114
                                Socket.SendTimeout = value;
1✔
115
                        }
1✔
116
                }
117

118
                void AsyncOperationCompleted (object sender, SocketAsyncEventArgs args)
119
                {
1✔
120
                        var tcs = (TaskCompletionSource<bool>) args.UserToken;
1✔
121

122
                        if (args.SocketError == SocketError.Success) {
1✔
123
                                tcs.TrySetResult (true);
1✔
124
                                return;
1✔
125
                        }
126

127
                        tcs.TrySetException (new SocketException ((int) args.SocketError));
×
128
                }
1✔
129

130
                void Cleanup ()
131
                {
1✔
132
                        if (send != null) {
1✔
133
                                send.Completed -= AsyncOperationCompleted;
1✔
134
                                send.AcceptSocket = null;
1✔
135
                                send?.Dispose ();
1✔
136
                                send = null;
1✔
137
                        }
1✔
138

139
                        if (recv != null) {
1✔
140
                                recv.Completed -= AsyncOperationCompleted;
1✔
141
                                recv.AcceptSocket = null;
1✔
142
                                recv.Dispose ();
1✔
143
                                recv = null;
1✔
144
                        }
1✔
145
                }
1✔
146

147
                void Disconnect ()
148
                {
1✔
149
                        try {
1✔
150
                                Socket.Disconnect (false);
1✔
151
                                Socket.Dispose ();
1✔
152
                        } catch {
1✔
153
                                return;
1✔
154
                        } finally {
1✔
155
                                connected = false;
1✔
156
                                Cleanup ();
1✔
157
                        }
1✔
158
                }
1✔
159

160
                public override int Read (byte[] buffer, int offset, int count)
161
                {
1✔
162
                        try {
1✔
163
                                return Socket.Receive (buffer, offset, count, SocketFlags.None);
1✔
164
                        } catch (SocketException ex) {
×
165
                                throw new IOException (ex.Message, ex);
×
166
                        }
167
                }
1✔
168

169
                public override async Task<int> ReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
170
                {
1✔
171
                        cancellationToken.ThrowIfCancellationRequested ();
1✔
172

173
                        var tcs = new TaskCompletionSource<bool> ();
1✔
174

175
                        // Capture the ReadTimeout so even if we get an exception and disconnect the socket, we still have it.
176
                        int readTimeout = ReadTimeout;
1✔
177

178
                        using (var timeout = new CancellationTokenSource (readTimeout)) {
1✔
179
                                using (var linked = CancellationTokenSource.CreateLinkedTokenSource (cancellationToken, timeout.Token)) {
1✔
180
                                        using (var registration = linked.Token.Register (() => tcs.TrySetCanceled (), false)) {
1✔
181
                                                recv.SetBuffer (buffer, offset, count);
1✔
182
                                                recv.UserToken = tcs;
1✔
183

184
                                                if (!Socket.ReceiveAsync (recv))
1✔
185
                                                        AsyncOperationCompleted (null, recv);
1✔
186

187
                                                try {
1✔
188
                                                        await tcs.Task.ConfigureAwait (false);
1✔
189
                                                        return recv.BytesTransferred;
1✔
190
                                                } catch (OperationCanceledException ex) {
×
191
                                                        Disconnect ();
×
192
                                                        if (timeout.IsCancellationRequested)
×
193
                                                                throw new TimeoutException ($"Operation timed out after {readTimeout} milliseconds", ex);
×
194
                                                        throw;
×
195
                                                } catch (Exception ex) {
×
196
                                                        Disconnect ();
×
197
                                                        if (ex is SocketException)
×
198
                                                                throw new IOException (ex.Message, ex);
×
199
                                                        throw;
×
200
                                                }
201
                                        }
202
                                }
203
                        }
204
                }
1✔
205

206
                public override void Write (byte[] buffer, int offset, int count)
207
                {
1✔
208
                        try {
1✔
209
                                Socket.Send (buffer, offset, count, SocketFlags.None);
1✔
210
                        } catch (SocketException ex) {
×
211
                                throw new IOException (ex.Message, ex);
×
212
                        }
213
                }
1✔
214

215
                public override async Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
216
                {
1✔
217
                        cancellationToken.ThrowIfCancellationRequested ();
1✔
218

219
                        var tcs = new TaskCompletionSource<bool> ();
1✔
220

221
                        // Capture the WriteTimeout so even if we get an exception and disconnect the socket, we still have it.
222
                        int writeTimeout = WriteTimeout;
1✔
223

224
                        using (var timeout = new CancellationTokenSource (writeTimeout)) {
1✔
225
                                using (var linked = CancellationTokenSource.CreateLinkedTokenSource (cancellationToken, timeout.Token)) {
1✔
226
                                        using (var registration = linked.Token.Register (() => tcs.TrySetCanceled (), false)) {
1✔
227
                                                send.SetBuffer (buffer, offset, count);
1✔
228
                                                send.UserToken = tcs;
1✔
229

230
                                                if (!Socket.SendAsync (send))
1✔
231
                                                        AsyncOperationCompleted (null, send);
1✔
232

233
                                                try {
1✔
234
                                                        await tcs.Task.ConfigureAwait (false);
1✔
235
                                                } catch (OperationCanceledException ex) {
×
236
                                                        Disconnect ();
×
237
                                                        if (timeout.IsCancellationRequested)
×
238
                                                                throw new TimeoutException ($"Operation timed out after {writeTimeout} milliseconds", ex);
×
239
                                                        throw;
×
240
                                                } catch (Exception ex) {
×
241
                                                        Disconnect ();
×
242
                                                        if (ex is SocketException)
×
243
                                                                throw new IOException (ex.Message, ex);
×
244
                                                        throw;
×
245
                                                }
246
                                        }
1✔
247
                                }
1✔
248
                        }
1✔
249
                }
1✔
250

251
                public override void Flush ()
252
                {
1✔
253
                }
1✔
254

255
                public override Task FlushAsync (CancellationToken cancellationToken)
256
                {
1✔
257
                        return Task.CompletedTask;
1✔
258
                }
1✔
259

260
                public override long Seek (long offset, SeekOrigin origin)
261
                {
1✔
262
                        throw new NotSupportedException ();
1✔
263
                }
264

265
                public override void SetLength (long value)
266
                {
1✔
267
                        throw new NotSupportedException ();
1✔
268
                }
269

270
                public static NetworkStream Get (Stream stream)
271
                {
1✔
272
#if !MAILKIT_LITE
273
                        if (stream is CompressedStream compressed)
1✔
274
                                stream = compressed.InnerStream;
1✔
275
#endif
276

277
                        if (stream is SslStream ssl)
1✔
278
                                stream = ssl.InnerStream;
1✔
279

280
                        return stream as NetworkStream;
1✔
281
                }
1✔
282

283
                public void Poll (SelectMode mode, CancellationToken cancellationToken)
284
                {
1✔
285
                        if (!cancellationToken.CanBeCanceled)
1✔
286
                                return;
1✔
287

288
                        do {
1✔
289
                                cancellationToken.ThrowIfCancellationRequested ();
1✔
290
                                // wait 1/4 second and then re-check for cancellation
291
                        } while (!Socket.Poll (250000, mode));
1✔
292

293
                        cancellationToken.ThrowIfCancellationRequested ();
1✔
294
                }
1✔
295

296
                protected override void Dispose (bool disposing)
297
                {
1✔
298
                        if (disposing) {
1✔
299
                                if (ownsSocket && connected) {
1✔
300
                                        ownsSocket = false;
1✔
301
                                        Disconnect ();
1✔
302
                                } else {
1✔
303
                                        Cleanup ();
1✔
304
                                }
1✔
305
                        }
1✔
306

307
                        base.Dispose (disposing);
1✔
308
                }
1✔
309
        }
310
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc