コード例 #1
0
            public void Add(string service, EchoResult result)
            {
                UdpResults.TryAdd(service, new ConcurrentQueue <EchoResult>());
                var queue = UdpResults[service];

                queue.Enqueue(result);
            }
コード例 #2
0
            public static EchoResult MakeFailed(Exception e, double time, string value = "")
            {
                var retval = new EchoResult()
                {
                    Succeeded     = State.Failed,
                    ExtendedError = e,
                    Value         = value,
                    TimeInSeconds = time
                };

                return(retval);
            }
コード例 #3
0
            public static EchoResult MakeSucceeded(string value, double time)
            {
                var retval = new EchoResult()
                {
                    Succeeded     = State.Succeeded,
                    ExtendedError = null,
                    Value         = value,
                    TimeInSeconds = time
                };

                return(retval);
            }
コード例 #4
0
        public async Task <EchoResult> WriteAsync(HostName address, string service, ProtocolType protocolType, string data)
        {
            switch (protocolType)
            {
            case ProtocolType.Tcp:
                return(await WriteTcpAsync(address, service, data));

            case ProtocolType.Udp:
                return(await WriteUdpAsync(address, service, data));
            }
            return(EchoResult.MakeFailed(SocketErrorStatus.SocketTypeNotSupported, 0.0));
        }
コード例 #5
0
            public static EchoResult MakeInProgress(double time)
            {
                var retval = new EchoResult()
                {
                    Succeeded     = State.InProgress,
                    ExtendedError = null,
                    Value         = "",
                    TimeInSeconds = time
                };

                return(retval);
            }
コード例 #6
0
            public bool TryRemove(string service, out EchoResult echoResult)
            {
                echoResult = null;
                if (!UdpResults.ContainsKey(service))
                {
                    return(false);
                }
                var queue     = UdpResults[service]; // We never remove a list from the collection, so this is safe
                var didremove = queue.TryDequeue(out echoResult);

                return(didremove);
            }
コード例 #7
0
            public static EchoResult MakeFailed(SocketErrorStatus status, double time, string value = "")
            {
                var retval = new EchoResult()
                {
                    Succeeded          = State.Failed,
                    ExtendedError      = null,
                    _ManuallySetStatus = status,
                    Value         = value,
                    TimeInSeconds = time
                };

                return(retval);
            }
コード例 #8
0
        /// <summary>
        /// Ensures that the socket is made. Will return a failure EchoResult on failure
        /// and will return NULL for a success.
        /// </summary>
        /// <param name="address"></param>
        /// <param name="service"></param>
        /// <returns></returns>
        private async Task <EchoResult> EnsureUdpSocket(HostName address, string service)
        {
            bool mustConnect = false;

            lock (this)
            {
                if (udpSocket == null)
                {
                    udpSocket = new DatagramSocket();
                    udpSocket.MessageReceived += UdpSocket_MessageReceived;
                    mustConnect = true;
                }
            }
            if (mustConnect)
            {
                try
                {
                    // Can't do the await inside a lock; it's not allowed in C#.
                    await udpSocket.ConnectAsync(address, service);

                    udpDw = new DataWriter(udpSocket.OutputStream);
                }
                catch (Exception ex)
                {
                    udpSocket = null;
                    Stats.NExceptions++;
                    Log($"ERROR: Client: Creating UDP socket to {address} exception {ex.Message}");
                    var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds;
                    return(EchoResult.MakeFailed(ex, delta));
                }
            }

            // must be in a race condition to make the socket and get the udpDw
            //TODO: remove magic number and verify and explain this code.
            while (udpSocket != null && udpDw == null)
            {
                await Task.Delay(10);
            }

            // We made a socket and then making the datawriter somehow failed.
            // Just give up; there's no path that will get us into a better place.
            if (udpSocket == null || udpDw == null)
            {
                return(EchoResult.MakeFailed(SocketErrorStatus.CannotAssignRequestedAddress, 0));
            }

            return(null);
        }
コード例 #9
0
        private EchoResult ReadUdp(DataReader dr)
        {
            uint count = dr.UnconsumedBufferLength;

            if (count > 0)
            {
                byte[] buffer = new byte[dr.UnconsumedBufferLength];
                dr.ReadBytes(buffer);
                var stringresult = BufferToString.ToString(buffer);
                LogEchoBuffer(buffer);
                var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds;
                return(EchoResult.MakeSucceeded(stringresult, delta));
            }
            else // socket is done
            {
                var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds;
                return(EchoResult.MakeFailed(SocketErrorStatus.HttpInvalidServerResponse, delta));
            }
        }
コード例 #10
0
 private void UdpSocket_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
 {
     try
     {
         var dr = args.GetDataReader();
         dr.InputStreamOptions = InputStreamOptions.Partial; // | InputStreamOptions.ReadAhead;
         var udpResult = ReadUdp(dr);
         UdpResults.Add(sender.Information.LocalPort, udpResult);
     }
     catch (Exception ex)
     {
         // This can happen when we send a packet to a correct host (like localhost) but with an
         // incorrect service. The packet will "bounce", resuluting in a MessageReceived event
         // but with an args with no real data.
         Stats.NExceptions++;
         var delta     = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds;
         var udpResult = EchoResult.MakeFailed(ex, delta);
         UdpResults.Add(sender.Information.LocalPort, udpResult);
     }
 }
コード例 #11
0
        private async Task <EchoResult> WriteTcpAsync(HostName address, string service, string data)
        {
            var startTime = DateTime.UtcNow;

            try
            {
                if (tcpSocket == null)
                {
                    tcpSocket = new StreamSocket();
                    await tcpSocket.ConnectAsync(address, service);

                    tcpDw           = new DataWriter(tcpSocket.OutputStream);
                    SocketStartTime = startTime;

                    // Now read everything
                    TcpReadEchoResult = EchoResult.MakeInProgress(0); // Taken no time at all so far :-)
                    var dr = new DataReader(tcpSocket.InputStream);
                    dr.InputStreamOptions = InputStreamOptions.Partial;
                    TcpReadTask           = ReadTcpAsync(dr);
                }

                tcpDw.WriteString(data);
                await tcpDw.StoreAsync();

                Stats.NWrites++;

                var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds;
                return(EchoResult.MakeInProgress(delta));
            }
            catch (Exception ex)
            {
                Stats.NExceptions++;
                Log($"ERROR: Client: Writing {data} to {address} exception {ex.Message}");
                var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds;
                return(EchoResult.MakeFailed(ex, delta));
            }
        }
コード例 #12
0
        private async Task <EchoResult> WriteUdpAsync(HostName address, string service, string data)
        {
            SocketStartTime = DateTime.UtcNow;
            try
            {
                var result = await EnsureUdpSocket(address, service);

                if (result != null)
                {
                    // EnsureUdpSocket only returns non-null result after a failure.
                    return(result);
                }

                if (string.IsNullOrEmpty(data))
                {
                    // A blank string, when written to a data writer, won't actually result in a
                    // UDP packet being sent. For the special case of not sending any data,
                    // use the WriteAsync on the socket's OutputStream directly.
                    var b = new Windows.Storage.Streams.Buffer(0);
                    await udpSocket.OutputStream.WriteAsync(b);

                    Stats.NWrites++;
                }
                else
                {
                    udpDw.WriteString(data);
                    await udpDw.StoreAsync();

                    Stats.NWrites++;
                }
                Log(ClientOptions.Verbosity.Verbose, $"Client: UDP: Sent request on local port {udpSocket.Information.LocalPort} request {data}");


                //
                // Wait for an answer
                //
                const int START_DELAY_MS = 10;
                int       currTotalDelay = 0;
                int       currDelay      = START_DELAY_MS;

                EchoResult udpResult = null;
                while (!UdpResults.TryRemove(udpSocket.Information.LocalPort, out udpResult))
                {
                    await Task.Delay(currDelay);

                    currTotalDelay += currDelay;
                    currDelay       = Math.Min(currDelay * 2, Options.MaxPollLoopInMilliseconds); // Do an exponential backup up to max (10 seconds)
                    if (currTotalDelay >= Options.MaxWaitInMilliseconds)
                    {
                        Log($"ERROR: Client: reply from {address} took too long (outgoing data={data})");
                        var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds;
                        udpResult = EchoResult.MakeFailed(SocketErrorStatus.ConnectionTimedOut, delta);
                        break;
                    }
                }
                return(udpResult);
            }
            catch (Exception ex)
            {
                Stats.NExceptions++;
                Log($"ERROR: Client: Writing {data} to {address} exception {ex.Message}");
                var delta = DateTime.UtcNow.Subtract(SocketStartTime).TotalSeconds;
                return(EchoResult.MakeFailed(ex, delta));
            }
        }