Esempio n. 1
0
        /// <summary>
        /// Based on the time it took a request to run, we adjust the priority
        /// of future requests sent by an object
        /// </summary>
        /// <param name="req"></param>
        private void AdjustObjectPriority(HttpRequestObject req)
        {
            Amib.Threading.WorkItemPriority prio = GetObjectPriority(req.SogID);

            if (req.RequestDuration >= SLOW_SCRIPT_TIME)
            {
                if (prio > Amib.Threading.WorkItemPriority.Lowest)
                {
                    prio--;
                    SetObjectPriority(req.SogID, prio);
                }
            }
            else if (req.RequestDuration < NORMAL_SCRIPT_TIME)
            {
                if (prio < Amib.Threading.WorkItemPriority.Normal)
                {
                    prio++;
                    SetObjectPriority(req.SogID, prio);
                }
            }
            else
            {
                //just ping the timestamp if it exists
                UpdatePriorityTimestamp(req.SogID);
            }

            //also if this request was low priority, maintain the counts
            --m_numLowPriorityQueued;
        }
Esempio n. 2
0
        private void ProcessRequest(HttpRequestObject req)
        {
            req.Process();

            lock (m_httpListLock)
            {
                m_pendingRequests.Remove(req.ReqID);
                m_completedRequests.Enqueue(req);

                DecrementObjectQueue(req.SogID);
                AdjustObjectPriority(req);
                MaintainPriorityQueue();
            }
        }
Esempio n. 3
0
        public UUID StartHttpRequest(UUID sogId, uint localID, UUID itemID, string url, string[] parms, Dictionary <string, string> headers, string body)
        {
            //if there are already too many requests globally, reject this one
            if (RequestQueueFreeSpacePercentage == 0.0f)
            {
                return(UUID.Zero);
            }

            // fast exit for the common case of scripter error passing an empty URL
            if (String.IsNullOrEmpty(url))
            {
                return(UUID.Zero);
            }

            if (BlockedByBlacklist(url))
            {
                return(UUID.Zero);
            }

            UUID reqID            = UUID.Random();
            HttpRequestObject htc = new HttpRequestObject();

            // Partial implementation: support for parameter flags needed
            //   see http://wiki.secondlife.com/wiki/LlHTTPRequest
            //
            // Parameters are expected in {key, value, ... , key, value}
            try
            {
                int i = 0;
                while (i < parms.Length)
                {
                    switch (Int32.Parse(parms[i++]))
                    {
                    case (int)HttpRequestConstants.HTTP_METHOD:
                        // This one was validated to be one of the valid values for method in LSLSystemAPI.cs
                        htc.HttpMethod = parms[i++];
                        break;

                    case (int)HttpRequestConstants.HTTP_MIMETYPE:
                        htc.HttpMIMEType = parms[i++];
                        break;

                    case (int)HttpRequestConstants.HTTP_BODY_MAXLENGTH:
                        htc.HttpBodyMaxLength = int.Parse(parms[i++]);
                        break;

                    case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
                        htc.HttpVerifyCert = (int.Parse(parms[i++]) != 0);
                        break;

                    case (int)HttpRequestConstants.HTTP_VERBOSE_THROTTLE:
                        htc.HttpVerboseThrottle = (int.Parse(parms[i++]) != 0);
                        break;

                    case (int)HttpRequestConstants.HTTP_CUSTOM_HEADER:
                        string key   = parms[i++];
                        string value = parms[i++];
                        // The script is not allowed to override some of the headers.
                        if (ScriptCanChangeHeader(key))
                        {
                            if (headers.ContainsKey(key))
                            {
                                // In SL, duplicate headers add to the existing header after a comma+space
                                headers[key] += ", " + value;
                            }
                            else
                            {
                                headers.Add(key, value);
                            }
                        }
                        break;

                    case (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE:
                        // What if there is more than one pragma header defined?
                        bool noCache = (int.Parse(parms[i++]) != 0);
                        if (noCache == true)
                        {
                            headers.Add("Pragma", "no-cache");
                        }
                        else if (headers.ContainsKey("Pragma"))
                        {
                            headers.Remove("Pragma");
                        }
                        break;

                    default:
                        // Invalid Parameter Type.  Log an error?
                        // Fail the request by returning a Null Key
                        return(UUID.Zero);
                    }
                }
            }
            catch (System.IndexOutOfRangeException)
            {
                // They passed us junk, we stepped past the end of the array.
                // We'll fail the request by returning a NULL_KEY
                return(UUID.Zero);
            }

            if (m_debugLevel >= 1)
            {
                MainConsole.Instance.OutputFormat("httprequest: LocalID={0} URL={1}", localID, url);
            }

            htc.LocalID         = localID;
            htc.ItemID          = itemID;
            htc.SogID           = sogId;
            htc.Url             = url;
            htc.ReqID           = reqID;
            htc.HttpTimeout     = HTTP_TIMEOUT;
            htc.OutboundBody    = body;
            htc.ResponseHeaders = headers;
            htc.proxyurl        = m_proxyurl;
            htc.proxyexcepts    = m_proxyexcepts;

            Amib.Threading.WorkItemPriority prio;
            lock (m_httpListLock)
            {
                //if there are already too many requests for this script running, reject this one
                if (!TryIncrementObjectQueue(sogId))
                {
                    return(UUID.Zero);
                }

                prio = GetObjectPriority(sogId);
                if (prio == Amib.Threading.WorkItemPriority.Lowest)
                {
                    if (m_numLowPriorityQueued < MAX_SLOW_REQUEST_QUEUE_SIZE)
                    {
                        htc.IsLowPriority = true;
                        ++m_numLowPriorityQueued;
                    }
                    else
                    {
                        DecrementObjectQueue(sogId);
                        return(UUID.Zero);
                    }
                }

                m_pendingRequests.Add(reqID, htc);
            }

            if (prio > Amib.Threading.WorkItemPriority.Lowest)
            {
                _threadPool.QueueWorkItem(() => this.ProcessRequest(htc));
            }
            else
            {
                _slowPool.QueueWorkItem(() => this.ProcessRequest(htc));
            }

            return(reqID);
        }
        /// <summary>
        /// Based on the time it took a request to run, we adjust the priority
        /// of future requests sent by an object
        /// </summary>
        /// <param name="req"></param>
        private void AdjustObjectPriority(HttpRequestObject req)
        {
            Amib.Threading.WorkItemPriority prio = GetObjectPriority(req.SogID);

            if (req.RequestDuration >= SLOW_SCRIPT_TIME)
            {
                if (prio > Amib.Threading.WorkItemPriority.Lowest)
                {
                    prio--;
                    SetObjectPriority(req.SogID, prio);
                }
            }
            else if (req.RequestDuration < NORMAL_SCRIPT_TIME)
            {
                if (prio < Amib.Threading.WorkItemPriority.Normal)
                {
                    prio++;
                    SetObjectPriority(req.SogID, prio);
                }
            }
            else
            {
                //just ping the timestamp if it exists
                UpdatePriorityTimestamp(req.SogID);
            }

            //also if this request was low priority, maintain the counts
            --m_numLowPriorityQueued;
        }
        private void ProcessRequest(HttpRequestObject req)
        {
            req.Process();

            lock (m_httpListLock)
            {
                m_pendingRequests.Remove(req.ReqID);
                m_completedRequests.Enqueue(req);

                DecrementObjectQueue(req.SogID);
                AdjustObjectPriority(req);
                MaintainPriorityQueue();
            }
        }
        public UUID StartHttpRequest(UUID sogId, uint localID, UUID itemID, string url, string[] parms, Dictionary<string, string> headers, string body)
        {
            //if there are already too many requests globally, reject this one
            if (RequestQueueFreeSpacePercentage == 0.0f) return UUID.Zero;

            // fast exit for the common case of scripter error passing an empty URL
            if (url == String.Empty) return UUID.Zero;

            if (BlockedByBlacklist(url)) return UUID.Zero;

            UUID reqID = UUID.Random();
            HttpRequestObject htc = new HttpRequestObject();

            // Partial implementation: support for parameter flags needed
            //   see http://wiki.secondlife.com/wiki/LlHTTPRequest
            //
            // Parameters are expected in {key, value, ... , key, value}
            try
            {
                int i = 0;
                while (i < parms.Length)
                {
                    switch (Int32.Parse(parms[i++]))
                    {
                        case (int)HttpRequestConstants.HTTP_METHOD:
                            // This one was validated to be one of the valid values for method in LSLSystemAPI.cs
                            htc.HttpMethod = parms[i++];
                            break;

                        case (int)HttpRequestConstants.HTTP_MIMETYPE:
                            htc.HttpMIMEType = parms[i++];
                            break;

                        case (int)HttpRequestConstants.HTTP_BODY_MAXLENGTH:
                            htc.HttpBodyMaxLength = int.Parse(parms[i++]);
                            break;

                        case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
                            htc.HttpVerifyCert = (int.Parse(parms[i++]) != 0);
                            break;

                        case (int)HttpRequestConstants.HTTP_VERBOSE_THROTTLE:
                            htc.HttpVerboseThrottle = (int.Parse(parms[i++]) != 0);
                            break;

                        case (int)HttpRequestConstants.HTTP_CUSTOM_HEADER:
                            string key = parms[i++];
                            string value = parms[i++];
                            // Don't overwrite values.  Keeps us from clobbering
                            // The standard X-Secondlife params with user ones.
                            if (headers.ContainsKey(key) == false)
                                headers.Add(key, value);
                            break;

                        case (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE:
                            // What if there is more than one pragma header defined?
                            bool noCache = (int.Parse(parms[i++]) != 0);
                            if (noCache == true)
                                headers.Add("Pragma", "no-cache");
                            else if (headers.ContainsKey("Pragma"))
                                headers.Remove("Pragma");
                            break;

                        default:
                            // Invalid Parameter Type.  Log an error?
                            // Fail the request by returning a Null Key
                            return UUID.Zero;
                    }
                }
            }
            catch (System.IndexOutOfRangeException)
            {
                // They passed us junk, we stepped past the end of the array.
                // We'll fail the request by returning a NULL_KEY
                return UUID.Zero;
            }

            if (m_debugLevel >= 1)
                MainConsole.Instance.OutputFormat("httprequest: LocalID={0} URL={1}", localID, url);

            htc.LocalID = localID;
            htc.ItemID = itemID;
            htc.SogID = sogId;
            htc.Url = url;
            htc.ReqID = reqID;
            htc.HttpTimeout = HTTP_TIMEOUT;
            htc.OutboundBody = body;
            htc.ResponseHeaders = headers;
            htc.proxyurl = m_proxyurl;
            htc.proxyexcepts = m_proxyexcepts;

            Amib.Threading.WorkItemPriority prio;
            lock (m_httpListLock)
            {
                //if there are already too many requests for this script running, reject this one
                if (!TryIncrementObjectQueue(sogId))
                {
                    return UUID.Zero;
                }

                prio = GetObjectPriority(sogId);
                if (prio == Amib.Threading.WorkItemPriority.Lowest)
                {
                    if (m_numLowPriorityQueued < MAX_SLOW_REQUEST_QUEUE_SIZE)
                    {
                        htc.IsLowPriority = true;
                        ++m_numLowPriorityQueued;
                    }
                    else
                    {
                        return UUID.Zero;
                    }
                }

                m_pendingRequests.Add(reqID, htc);
            }

            if (prio > Amib.Threading.WorkItemPriority.Lowest)
            {
                _threadPool.QueueWorkItem(() => this.ProcessRequest(htc));
            }
            else
            {
                _slowPool.QueueWorkItem(() => this.ProcessRequest(htc));
            }

            return reqID;
        }