/// <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 (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); }
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; }