Пример #1
0
        public QosJob(IList <QosServer> qosServers, string title) : this()
        {
            // Copy the QoS Servers into the job, converting all the IP/Port to NetworkEndPoint and DateTime to ticks.
            m_QosServers = new NativeArray <InternalQosServer>(qosServers?.Count ?? 0, Allocator.Persistent);
            if (qosServers != null)
            {
                for (int i = 0; i < m_QosServers.Length; ++i)
                {
                    // Indexing NativeArray returns temporary values, so can't edit in place.
                    m_QosServers[i] = new InternalQosServer(qosServers[i].ipv4, qosServers[i].port, qosServers[i].BackoffUntilUtc);
                }
            }

            m_VisitedQosServers = new NativeArray <ulong>(qosServers?.Count ?? 0, Allocator.Persistent);

            // Indexes into QosResults correspond to indexes into qosServers/m_QosServers
            QosResults = new NativeArray <QosResult>(m_QosServers.Length, Allocator.Persistent);

            // Convert the title to a NativeArray of bytes (since everything in the job has to be a value-type)
            byte[] utf8Title = Encoding.UTF8.GetBytes(title);
            m_TitleBytesUtf8 = new NativeArray <byte>(utf8Title.Length, Allocator.Persistent);
            m_TitleBytesUtf8.CopyFrom(utf8Title);
        }
Пример #2
0
        public void Execute()
        {
            if (m_QosServers.Length == 0)
            {
                return;    // Nothing to do.
            }
            m_JobExpireTimeUtc = DateTime.UtcNow.AddMilliseconds(TimeoutMs);

            // Create the local socket
            int errorcode = 0;

            (m_Socket, errorcode) = CreateAndBindSocket();
            if (m_Socket == -1 || errorcode != 0)
            {
                // Can't run the job
                Debug.LogError("Failed to create and bind the local socket for QoS Check");
            }
            else
            {
                m_Identifier = (ushort)new Random().Next(ushort.MinValue, ushort.MaxValue);
                for (int i = 0; i < m_QosServers.Length; ++i)
                {
                    QosResult         result = QosResults[i];
                    InternalQosServer server = m_QosServers[i];

                    if (QosHelper.ExpiredUtc(m_JobExpireTimeUtc))
                    {
                        Debug.LogWarning($"Ran out of time to finish remaining QoS Check for endpoint {i}.");
                        break;
                    }

                    // If we've already visited this server, just copy those results here.
                    if (QosServerVisited(server.Id))
                    {
                        if (TryCopyResult(server.Id, ref result) == false)
                        {
                            Debug.LogError($"Visited server must have a previous result available");
                            break;
                        }
                    }
                    else if (DateTime.UtcNow > server.BackoffUntilUtc) // Only contact this server if we are allowed
                    {
                        // For each iteration of the loop, give the remaining endpoints an equal fraction of the remaining
                        // overall job time.  For example if there are five endpoints that each get 1000ms (5000ms total),
                        // and the first endpoint finishes in 200ms, the remaining endpoints will get 1200ms to complete
                        // (4800ms remaining / 4 endpoints = 1200ms/endpoint).
                        double   allottedTimeMs = QosHelper.RemainingUtc(m_JobExpireTimeUtc).TotalMilliseconds / (m_QosServers.Length - i);
                        DateTime startTimeUtc   = DateTime.UtcNow;
                        DateTime expireTimeUtc  = DateTime.UtcNow.AddMilliseconds(allottedTimeMs);

#if UNITY_EDITOR || DEVELOPMENT_BUILD
                        Debug.Log($"QoS Check {i} gets {(expireTimeUtc - DateTime.UtcNow).TotalMilliseconds:F0}ms to complete.");
#endif

                        ++m_Identifier;
                        int err = SendQosRequests(server.RemoteEndpoint, m_Identifier, expireTimeUtc, ref result);
                        if (err != 0)
                        {
                            Debug.LogError($"Error {err} sending QoS requests.  Will attempt to receive responses anyway.");
                        }
                        err = RecvQosResponses(server.RemoteEndpoint, m_Identifier, expireTimeUtc, ref result);
                        if (err != 0)
                        {
                            Debug.LogError($"Error {err} receiving QoS responses. Will attempt to continue anyway.");
                        }

                        Debug.Log($"Received {result.ResponsesReceived}/{result.RequestsSent} responses from endpoint {i} in {(DateTime.UtcNow - startTimeUtc).TotalMilliseconds:F0}ms");

                        // Mark this server as visited

                        SetQosServerVisited(server.Id);
                    }
                    else
                    {
                        Debug.LogWarning($"Did not contact endpoint {i} due to backoff restrictions.");
                    }

                    // Save the result (even if we didn't contact the server)
                    QosResults[i] = result;
                }
            }

            NativeBindings.network_close(ref m_Socket, ref errorcode);
        }