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

lextudio / sharpsnmplib / 11823966615

13 Nov 2024 06:58PM UTC coverage: 49.626% (-3.4%) from 53.042%
11823966615

push

github

lextm
Removed .NET 6.

819 of 1881 branches covered (43.54%)

Branch coverage included in aggregate %.

2232 of 4267 relevant lines covered (52.31%)

15136.2 hits per line

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

0.0
/SharpSnmpLib/Messaging/Net6SnmpMessageExtension.cs
1
// SNMP message extension class.
2
// Copyright (C) 2008-2010 Malcolm Crowe, Lex Li, and other contributors.
3
// 
4
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
5
// software and associated documentation files (the "Software"), to deal in the Software
6
// without restriction, including without limitation the rights to use, copy, modify, merge,
7
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
8
// to whom the Software is furnished to do so, subject to the following conditions:
9
// 
10
// The above copyright notice and this permission notice shall be included in all copies or
11
// substantial portions of the Software.
12
// 
13
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
15
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
16
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18
// DEALINGS IN THE SOFTWARE.
19

20
#if NET6_0_OR_GREATER
21
using System;
22
using System.Diagnostics.CodeAnalysis;
23
using System.Globalization;
24
using System.Net;
25
using System.Net.Sockets;
26
using System.Runtime.InteropServices;
27
using System.Threading;
28
using System.Threading.Tasks;
29
using Lextm.SharpSnmpLib.Security;
30

31
namespace Lextm.SharpSnmpLib.Messaging
32
{
33
    /// <summary>
34
    /// Extension methods for <see cref="ISnmpMessage"/>.
35
    /// </summary>
36
    public static partial class SnmpMessageExtension
37
    {
38
        #region async methods
39

40
        /// <summary>
41
        /// Sends an <see cref="ISnmpMessage"/>.
42
        /// </summary>
43
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
44
        /// <param name="manager">Manager</param>
45
        /// <param name="token">The cancellation token.</param>
46
        public static async Task SendAsync(this ISnmpMessage message, EndPoint manager, CancellationToken token)
47
        {
48
            if (message == null)
×
49
            {
50
                throw new ArgumentNullException(nameof(message));
×
51
            }
52

53
            if (manager == null)
×
54
            {
55
                throw new ArgumentNullException(nameof(manager));
×
56
            }
57

58
            var code = message.TypeCode();
×
59
            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
×
60
            {
61
                throw new InvalidOperationException(string.Format(
×
62
                    CultureInfo.InvariantCulture,
×
63
                    "not a trap message: {0}",
×
64
                    code));
×
65
            }
66

67
            using var socket = manager.GetSocket();
×
68
            await message.SendAsync(manager, socket, token).ConfigureAwait(false);
×
69
        }
×
70

71
        /// <summary>
72
        /// Sends an <see cref="ISnmpMessage"/>.
73
        /// </summary>
74
        /// <param name="message">The <see cref="ISnmpMessage"/>.</param>
75
        /// <param name="manager">Manager</param>
76
        /// <param name="socket">The socket.</param>
77
        /// <param name="token">The cancellation token.</param>
78
        public static async Task SendAsync(this ISnmpMessage message, EndPoint manager, Socket socket, CancellationToken token)
79
        {
80
            if (message == null)
×
81
            {
82
                throw new ArgumentNullException(nameof(message));
×
83
            }
84

85
            if (socket == null)
×
86
            {
87
                throw new ArgumentNullException(nameof(socket));
×
88
            }
89

90
            if (manager == null)
×
91
            {
92
                throw new ArgumentNullException(nameof(manager));
×
93
            }
94

95
            var code = message.TypeCode();
×
96
            if ((code != SnmpType.TrapV1Pdu && code != SnmpType.TrapV2Pdu) && code != SnmpType.ReportPdu)
×
97
            {
98
                throw new InvalidOperationException(string.Format(
×
99
                    CultureInfo.InvariantCulture,
×
100
                    "not a trap message: {0}",
×
101
                    code));
×
102
            }
103

104
            var buffer = new ArraySegment<byte>(message.ToBytes());
×
105
            await socket.SendToAsync(buffer, SocketFlags.None, manager, token);
×
106
        }
×
107

108
        /// <summary>
109
        /// Sends this <see cref="ISnmpMessage"/> and handles the response from agent.
110
        /// </summary>
111
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
112
        /// <param name="receiver">Port number.</param>
113
        /// <param name="registry">User registry.</param>
114
        /// <param name="token">The cancellation token.</param>
115
        /// <returns></returns>
116
        [RequiresUnreferencedCode("GetResponseAsync is incompatible with trimming.")]
117
        public static async Task<ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, UserRegistry registry, CancellationToken token)
118
        {
119
            // TODO: make more usage of UserRegistry.
120
            if (request == null)
×
121
            {
122
                throw new ArgumentNullException(nameof(request));
×
123
            }
124

125
            if (receiver == null)
×
126
            {
127
                throw new ArgumentNullException(nameof(receiver));
×
128
            }
129

130
            var code = request.TypeCode();
×
131
            if (code == SnmpType.TrapV1Pdu || code == SnmpType.TrapV2Pdu || code == SnmpType.ReportPdu)
×
132
            {
133
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", code));
×
134
            }
135

136
            using var socket = receiver.GetSocket();
×
137
            return await request.GetResponseAsync(receiver, registry, socket, token).ConfigureAwait(false);
×
138
        }
×
139

140
        /// <summary>
141
        /// Sends this <see cref="ISnmpMessage"/> and handles the response from agent.
142
        /// </summary>
143
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
144
        /// <param name="receiver">Port number.</param>
145
        /// <param name="token">The cancellation token.</param>
146
        /// <returns></returns>
147
        [RequiresUnreferencedCode("GetResponseAsync is incompatible with trimming.")]
148
        public static async Task<ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, CancellationToken token)
149
        {
150
            if (request == null)
×
151
            {
152
                throw new ArgumentNullException(nameof(request));
×
153
            }
154

155
            if (receiver == null)
×
156
            {
157
                throw new ArgumentNullException(nameof(receiver));
×
158
            }
159

160
            var code = request.TypeCode();
×
161
            if (code == SnmpType.TrapV1Pdu || code == SnmpType.TrapV2Pdu || code == SnmpType.ReportPdu)
×
162
            {
163
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", code));
×
164
            }
165

166
            using var socket = receiver.GetSocket();
×
167
            return await request.GetResponseAsync(receiver, socket, token).ConfigureAwait(false);
×
168
        }
×
169

170
        /// <summary>
171
        /// Sends this <see cref="ISnmpMessage"/> and handles the response from agent.
172
        /// </summary>
173
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
174
        /// <param name="receiver">Agent.</param>
175
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
176
        /// <param name="token">The cancellation token.</param>
177
        /// <returns></returns>
178
        [RequiresUnreferencedCode("GetResponseAsync is incompatible with trimming.")]
179
        public static async Task<ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, Socket udpSocket, CancellationToken token)
180
        {
181
            if (request == null)
×
182
            {
183
                throw new ArgumentNullException(nameof(request));
×
184
            }
185

186
            if (receiver == null)
×
187
            {
188
                throw new ArgumentNullException(nameof(receiver));
×
189
            }
190

191
            if (udpSocket == null)
×
192
            {
193
                throw new ArgumentNullException(nameof(udpSocket));
×
194
            }
195

196
            var registry = new UserRegistry();
×
197
            if (request.Version == VersionCode.V3)
×
198
            {
199
                registry.Add(request.Parameters.UserName, request.Privacy);
×
200
            }
201

202
            return await request.GetResponseAsync(receiver, registry, udpSocket, token).ConfigureAwait(false);
×
203
        }
×
204

205
        /// <summary>
206
        /// Sends an <see cref="ISnmpMessage"/> and handles the response from agent.
207
        /// </summary>
208
        /// <param name="request">The <see cref="ISnmpMessage"/>.</param>
209
        /// <param name="receiver">Agent.</param>
210
        /// <param name="udpSocket">The UDP <see cref="Socket"/> to use to send/receive.</param>
211
        /// <param name="registry">The user registry.</param>
212
        /// <param name="token">The cancellation token.</param>
213
        /// <returns></returns>
214
        [RequiresUnreferencedCode("GetResponseAsync is incompatible with trimming.")]
215
        public static async Task<ISnmpMessage> GetResponseAsync(this ISnmpMessage request, IPEndPoint receiver, UserRegistry registry, Socket udpSocket, CancellationToken token)
216
        {
217
            if (request == null)
×
218
            {
219
                throw new ArgumentNullException(nameof(request));
×
220
            }
221

222
            if (udpSocket == null)
×
223
            {
224
                throw new ArgumentNullException(nameof(udpSocket));
×
225
            }
226

227
            if (registry == null)
×
228
            {
229
                throw new ArgumentNullException(nameof(registry));
×
230
            }
231

232
            var requestCode = request.TypeCode();
×
233
            if (requestCode == SnmpType.TrapV1Pdu || requestCode == SnmpType.TrapV2Pdu || requestCode == SnmpType.ReportPdu)
×
234
            {
235
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "not a request message: {0}", requestCode));
×
236
            }
237

238
            var bytes = request.ToBytes();
×
239
            var bufSize = udpSocket.ReceiveBufferSize = Messenger.MaxMessageSize;
×
240

241
            // Whatever you change, try to keep the Send and the Receive close to each other.
242
            var buffer = new ArraySegment<byte>(bytes);
×
243
            await udpSocket.SendToAsync(buffer, SocketFlags.None, receiver ?? throw new ArgumentNullException(nameof(receiver)), token);
×
244

245
            int count;
246
            byte[] reply = new byte[bufSize];
×
247

248
            // IMPORTANT: follow http://blogs.msdn.com/b/pfxteam/archive/2011/12/15/10248293.aspx
249
            var remoteAddress = udpSocket.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any;
×
250
            EndPoint remote = new IPEndPoint(remoteAddress, 0);
×
251

252
            try
253
            {
254
                var result = await udpSocket.ReceiveMessageFromAsync(new ArraySegment<byte>(reply), SocketFlags.None, remote, token);
×
255
                count = result.ReceivedBytes;
×
256
            }
×
257
            catch (SocketException ex)
×
258
            {
259
                // IMPORTANT: Mono behavior (https://bugzilla.novell.com/show_bug.cgi?id=599488)
260
                if (IsRunningOnMono() && ex.SocketErrorCode == SocketError.WouldBlock)
×
261
                {
262
                    throw TimeoutException.Create(receiver.Address, 0);
×
263
                }
264

265
                if (ex.SocketErrorCode == SocketError.TimedOut)
×
266
                {
267
                    throw TimeoutException.Create(receiver.Address, 0);
×
268
                }
269

270
                throw;
×
271
            }
272

273
            // Passing 'count' is not necessary because ParseMessages should ignore it, but it offer extra safety (and would avoid an issue if parsing >1 response).
274
            var response = MessageFactory.ParseMessages(reply, 0, count, registry)[0];
×
275
            var responseCode = response.TypeCode();
×
276
            if (responseCode == SnmpType.ResponsePdu || responseCode == SnmpType.ReportPdu)
×
277
            {
278
                var requestId = request.MessageId();
×
279
                var responseId = response.MessageId();
×
280
                if (responseId != requestId)
×
281
                {
282
                    throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response sequence: expected {0}, received {1}", requestId, responseId), receiver.Address);
×
283
                }
284

285
                return response;
×
286
            }
287

288
            throw OperationException.Create(string.Format(CultureInfo.InvariantCulture, "wrong response type: {0}", responseCode), receiver.Address);
×
289
        }
×
290

291
        #endregion
292

293
    }
294
}
295
#endif
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