예제 #1
0
        public void RasGetConnectionStatisticsAsExpected()
        {
            var hRasConn     = new IntPtr(1);
            var lpStatistics = new RAS_STATS();

            api.Setup(o => o.RasGetConnectionStatistics(hRasConn, ref It.Ref <RAS_STATS> .IsAny)).Returns(SUCCESS);

            eventLoggingPolicy.Setup(o => o.LogEvent(It.IsAny <EventLevel>(), It.IsAny <PInvokeInt32CallCompletedTraceEvent>())).Callback(new LogEventCallback(
                                                                                                                                              (level, o1) =>
            {
                Assert.AreEqual(EventLevel.Verbose, level);

                var eventData = (PInvokeInt32CallCompletedTraceEvent)o1;
                Assert.True(eventData.Args.ContainsKey(nameof(hRasConn)));
                Assert.True(eventData.OutArgs.ContainsKey(nameof(lpStatistics)));
                Assert.True(eventData.Duration > TimeSpan.Zero);
                Assert.AreEqual(SUCCESS, eventData.Result);
            })).Verifiable();

            var target = new RasApi32LoggingAdvice(api.Object, eventLoggingPolicy.Object);
            var result = target.RasGetConnectionStatistics(hRasConn, ref lpStatistics);

            eventLoggingPolicy.Verify();
            Assert.AreEqual(SUCCESS, result);
        }
예제 #2
0
 private RAS_STATS GetStatDelta(RAS_STATS stat, RAS_STATS prevStat) => new RAS_STATS
 {
     dwBytesXmited        = GetUintDelta(stat.dwBytesXmited, prevStat.dwBytesXmited),
     dwBytesRcved         = GetUintDelta(stat.dwBytesRcved, prevStat.dwBytesRcved),
     dwBufferOverrunErr   = GetUintDelta(stat.dwBufferOverrunErr, prevStat.dwBufferOverrunErr),
     dwCrcErr             = GetUintDelta(stat.dwCrcErr, prevStat.dwCrcErr),
     dwFramingErr         = GetUintDelta(stat.dwFramingErr, prevStat.dwFramingErr),
     dwHardwareOverrunErr = GetUintDelta(stat.dwHardwareOverrunErr, prevStat.dwHardwareOverrunErr),
     dwTimeoutErr         = GetUintDelta(stat.dwTimeoutErr, prevStat.dwTimeoutErr),
     dwAlignmentErr       = GetUintDelta(stat.dwAlignmentErr, prevStat.dwAlignmentErr),
 };
예제 #3
0
        public int RasGetConnectionStatistics(IntPtr hRasConn, ref RAS_STATS lpStatistics)
        {
            var stopwatch = Stopwatch.StartNew();
            var result    = AttachedObject.RasGetConnectionStatistics(hRasConn, ref lpStatistics);

            stopwatch.Stop();

            var callEvent = new PInvokeInt32CallCompletedTraceEvent
            {
                DllName    = RasApi32Dll,
                Duration   = stopwatch.Elapsed,
                MethodName = nameof(RasGetConnectionStatistics),
                Result     = result
            };

            callEvent.Args.Add(nameof(hRasConn), hRasConn);
            callEvent.OutArgs.Add(nameof(lpStatistics), lpStatistics);

            LogVerbose(callEvent);
            return(result);
        }
예제 #4
0
 public static extern int RasGetConnectionStatistics(
     IntPtr hRasConn,
     [In, Out] ref RAS_STATS lpStatistics);
예제 #5
0
 public int RasGetConnectionStatistics(IntPtr hRasConn, ref RAS_STATS lpStatistics)
 {
     return(SafeNativeMethods.RasGetConnectionStatistics(hRasConn, ref lpStatistics));
 }
예제 #6
0
        private async Task MaintainConnection(VpnData vpnData, CancellationToken cancellationToken, TaskCompletionSource <bool> firstTime, Action <VpnRuntimeState> onStateChanged)
        {
            Task   awaitConnectionChanged = null;
            IntPtr handle = IntPtr.Zero;

            bool      statInitialized = false;
            RAS_STATS prevStat        = new RAS_STATS();

            string serverIpAddress = null;

            try
            {
                while (!_cts.IsCancellationRequested)
                {
                    try
                    {
                        if (handle == IntPtr.Zero)
                        {
                            Log.Information("VPN Connecting");
                            handle = await ReconnectAsync(vpnData, _cts.Token);

                            var info = VpnApi.GetProjectionInfoEx(handle);
                            serverIpAddress = $"{info.ipv4ServerAddress.addr[0]}.{info.ipv4ServerAddress.addr[1]}.{info.ipv4ServerAddress.addr[2]}.{info.ipv4ServerAddress.addr[3]}";


                            firstTime?.TrySetResult(true);
                            firstTime       = null;
                            statInitialized = false;

                            var eventHandle = VpnApi.RegisterForTermination(handle);
                            awaitConnectionChanged = TaskHelper.WaitOneAsync(eventHandle, "VPN state changed");
                        }

                        if (handle != IntPtr.Zero)
                        {
                            var status = VpnApi.GetState(handle);
                            var stat   = VpnApi.GetStatisitcs(handle);

                            if (status.connectionState != RasConnectionState.Connected)
                            {
                                if (status.errorCode == 0)
                                {
                                    throw new VpnException($"VPN in wrong '{status.connectionState}' state");
                                }
                                else
                                {
                                    throw new VpnException($"VPN error '{VpnApi.RasErrorMessage(status.errorCode)}'");
                                }
                            }

                            if (!statInitialized)
                            {
                                statInitialized = true;
                                prevStat        = stat;
                            }

                            var delta = GetStatDelta(stat, prevStat);
                            prevStat = stat;

                            if (delta.dwTimeoutErr + delta.dwFramingErr + delta.dwCrcErr + delta.dwHardwareOverrunErr + delta.dwBufferOverrunErr + delta.dwAlignmentErr > 0)
                            {
                                Log.Warning($"VPN errors {delta.dwTimeoutErr},{delta.dwFramingErr},{delta.dwCrcErr},{delta.dwHardwareOverrunErr},{delta.dwBufferOverrunErr},{delta.dwAlignmentErr}");
                            }


                            onStateChanged(new VpnRuntimeState
                            {
                                Connected       = true,
                                SentKbs         = (int)delta.dwBytesXmited / (1024 / 8),
                                ReceivedKbs     = (int)delta.dwBytesRcved / (1024 / 8),
                                ServerIpAddress = serverIpAddress
                            });
                        }
                    }
                    catch (Exception e) when(TaskHelper.IsCancellation(e))
                    {
                        Log.Error(e, "VPN cancellation");
                        throw;
                    }
                    catch (Exception e)
                    {
                        Log.Error(e, "VPN maintanance error");
                        firstTime?.TrySetException(e);
                        firstTime       = null;
                        serverIpAddress = null;

                        onStateChanged(new VpnRuntimeState {
                            Connected = false, ErrorMessage = e.Message
                        });

                        await HangUpAsync(handle);

                        handle = IntPtr.Zero;
                        awaitConnectionChanged = null;
                    }

                    var delay = Task.Delay(1000, cancellationToken);
                    if (awaitConnectionChanged != null)
                    {
                        var result = await Task.WhenAny(delay, awaitConnectionChanged);

                        if (result == awaitConnectionChanged)
                        {
                            Log.Information("VPN short wait");
                            awaitConnectionChanged = null; //it is raised once and not usable anymore
                        }
                    }
                    else
                    {
                        await delay;
                    }
                }
            }
            finally
            {
                Log.Information("VPN exiting maintainance");
                await HangUpAsync(handle);

                onStateChanged(new VpnRuntimeState {
                    Connected = false
                });
                _disconnected?.TrySetResult(true);
            }
        }