aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers/HttpServer
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Servers/HttpServer')
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs87
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs4
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs137
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs175
4 files changed, 383 insertions, 20 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index eb7c578..74954cc 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -395,6 +395,7 @@ namespace OpenSim.Framework.Servers.HttpServer
395 StreamReader reader = new StreamReader(requestStream, encoding); 395 StreamReader reader = new StreamReader(requestStream, encoding);
396 396
397 string requestBody = reader.ReadToEnd(); 397 string requestBody = reader.ReadToEnd();
398 reader.Close();
398 399
399 Hashtable keysvals = new Hashtable(); 400 Hashtable keysvals = new Hashtable();
400 Hashtable headervals = new Hashtable(); 401 Hashtable headervals = new Hashtable();
@@ -736,7 +737,7 @@ namespace OpenSim.Framework.Servers.HttpServer
736 // Every month or so this will wrap and give bad numbers, not really a problem 737 // Every month or so this will wrap and give bad numbers, not really a problem
737 // since its just for reporting 738 // since its just for reporting
738 int tickdiff = requestEndTick - requestStartTick; 739 int tickdiff = requestEndTick - requestStartTick;
739 if (tickdiff > 3000 && requestHandler != null && requestHandler.Name != "GetTexture") 740 if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture"))
740 { 741 {
741 m_log.InfoFormat( 742 m_log.InfoFormat(
742 "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", 743 "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
@@ -1657,10 +1658,40 @@ namespace OpenSim.Framework.Servers.HttpServer
1657 1658
1658 internal byte[] DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response) 1659 internal byte[] DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response)
1659 { 1660 {
1660 //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); 1661 int responsecode;
1661 int responsecode = (int)responsedata["int_response_code"]; 1662 string responseString = String.Empty;
1662 string responseString = (string)responsedata["str_response_string"]; 1663 byte[] responseData = null;
1663 string contentType = (string)responsedata["content_type"]; 1664 string contentType;
1665
1666 if (responsedata == null)
1667 {
1668 responsecode = 500;
1669 responseString = "No response could be obtained";
1670 contentType = "text/plain";
1671 responsedata = new Hashtable();
1672 }
1673 else
1674 {
1675 try
1676 {
1677 //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response");
1678 responsecode = (int)responsedata["int_response_code"];
1679 if (responsedata["bin_response_data"] != null)
1680 responseData = (byte[])responsedata["bin_response_data"];
1681 else
1682 responseString = (string)responsedata["str_response_string"];
1683 contentType = (string)responsedata["content_type"];
1684 if (responseString == null)
1685 responseString = String.Empty;
1686 }
1687 catch
1688 {
1689 responsecode = 500;
1690 responseString = "No response could be obtained";
1691 contentType = "text/plain";
1692 responsedata = new Hashtable();
1693 }
1694 }
1664 1695
1665 if (responsedata.ContainsKey("error_status_text")) 1696 if (responsedata.ContainsKey("error_status_text"))
1666 { 1697 {
@@ -1705,25 +1736,40 @@ namespace OpenSim.Framework.Servers.HttpServer
1705 1736
1706 response.AddHeader("Content-Type", contentType); 1737 response.AddHeader("Content-Type", contentType);
1707 1738
1739 if (responsedata.ContainsKey("headers"))
1740 {
1741 Hashtable headerdata = (Hashtable)responsedata["headers"];
1742
1743 foreach (string header in headerdata.Keys)
1744 response.AddHeader(header, (string)headerdata[header]);
1745 }
1746
1708 byte[] buffer; 1747 byte[] buffer;
1709 1748
1710 if (!(contentType.Contains("image") 1749 if (responseData != null)
1711 || contentType.Contains("x-shockwave-flash")
1712 || contentType.Contains("application/x-oar")
1713 || contentType.Contains("application/vnd.ll.mesh")))
1714 { 1750 {
1715 // Text 1751 buffer = responseData;
1716 buffer = Encoding.UTF8.GetBytes(responseString);
1717 } 1752 }
1718 else 1753 else
1719 { 1754 {
1720 // Binary! 1755 if (!(contentType.Contains("image")
1721 buffer = Convert.FromBase64String(responseString); 1756 || contentType.Contains("x-shockwave-flash")
1722 } 1757 || contentType.Contains("application/x-oar")
1758 || contentType.Contains("application/vnd.ll.mesh")))
1759 {
1760 // Text
1761 buffer = Encoding.UTF8.GetBytes(responseString);
1762 }
1763 else
1764 {
1765 // Binary!
1766 buffer = Convert.FromBase64String(responseString);
1767 }
1723 1768
1724 response.SendChunked = false; 1769 response.SendChunked = false;
1725 response.ContentLength64 = buffer.Length; 1770 response.ContentLength64 = buffer.Length;
1726 response.ContentEncoding = Encoding.UTF8; 1771 response.ContentEncoding = Encoding.UTF8;
1772 }
1727 1773
1728 return buffer; 1774 return buffer;
1729 } 1775 }
@@ -1804,7 +1850,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1804 m_httpListener2.Start(64); 1850 m_httpListener2.Start(64);
1805 1851
1806 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events 1852 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
1807 m_PollServiceManager = new PollServiceRequestManager(this, 3, 25000); 1853// m_PollServiceManager = new PollServiceRequestManager(this, 3, 25000);
1854 m_PollServiceManager = new PollServiceRequestManager(this, 4, 25000);
1808 HTTPDRunning = true; 1855 HTTPDRunning = true;
1809 1856
1810 //HttpListenerContext context; 1857 //HttpListenerContext context;
@@ -1838,7 +1885,9 @@ namespace OpenSim.Framework.Servers.HttpServer
1838 1885
1839 public void httpServerException(object source, Exception exception) 1886 public void httpServerException(object source, Exception exception)
1840 { 1887 {
1841 m_log.Error(String.Format("[BASE HTTP SERVER]: {0} had an exception: {1} ", source.ToString(), exception.Message), exception); 1888 if (source.ToString() == "HttpServer.HttpListener" && exception.ToString().StartsWith("Mono.Security.Protocol.Tls.TlsException"))
1889 return;
1890 m_log.ErrorFormat("[BASE HTTP SERVER]: {0} had an exception {1}", source.ToString(), exception.ToString());
1842 /* 1891 /*
1843 if (HTTPDRunning)// && NotSocketErrors > 5) 1892 if (HTTPDRunning)// && NotSocketErrors > 5)
1844 { 1893 {
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index 3079a7e..c19ac32 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
@@ -52,7 +52,9 @@ namespace OpenSim.Framework.Servers.HttpServer
52 { 52 {
53 Normal = 0, 53 Normal = 0,
54 LslHttp = 1, 54 LslHttp = 1,
55 Inventory = 2 55 Inventory = 2,
56 Texture = 3,
57 Mesh = 4
56 } 58 }
57 59
58 public PollServiceEventArgs( 60 public PollServiceEventArgs(
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index a5380c1..7628e23 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -34,6 +34,143 @@ using HttpServer;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Monitoring; 35using OpenSim.Framework.Monitoring;
36using Amib.Threading; 36using Amib.Threading;
37
38
39/*
40namespace OpenSim.Framework.Servers.HttpServer
41{
42
43 public class PollServiceRequestManager
44 {
45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 private readonly BaseHttpServer m_server;
48 private static Queue m_requests = Queue.Synchronized(new Queue());
49 private static ManualResetEvent m_ev = new ManualResetEvent(false);
50 private uint m_WorkerThreadCount = 0;
51 private Thread[] m_workerThreads;
52 private PollServiceWorkerThread[] m_PollServiceWorkerThreads;
53 private volatile bool m_running = true;
54 private int m_pollTimeout;
55
56 public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout)
57 {
58 m_server = pSrv;
59 m_WorkerThreadCount = pWorkerThreadCount;
60 m_pollTimeout = pTimeout;
61 }
62
63 public void Start()
64 {
65 m_running = true;
66 m_workerThreads = new Thread[m_WorkerThreadCount];
67 m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount];
68
69 //startup worker threads
70 for (uint i = 0; i < m_WorkerThreadCount; i++)
71 {
72 m_PollServiceWorkerThreads[i] = new PollServiceWorkerThread(m_server, m_pollTimeout);
73 m_PollServiceWorkerThreads[i].ReQueue += ReQueueEvent;
74
75 m_workerThreads[i]
76 = Watchdog.StartThread(
77 m_PollServiceWorkerThreads[i].ThreadStart,
78 String.Format("PollServiceWorkerThread{0}", i),
79 ThreadPriority.Normal,
80 false,
81 true,
82 int.MaxValue);
83 }
84
85 Watchdog.StartThread(
86 this.ThreadStart,
87 "PollServiceWatcherThread",
88 ThreadPriority.Normal,
89 false,
90 true,
91 1000 * 60 * 10);
92 }
93
94 internal void ReQueueEvent(PollServiceHttpRequest req)
95 {
96 // Do accounting stuff here
97 Enqueue(req);
98 }
99
100 public void Enqueue(PollServiceHttpRequest req)
101 {
102 lock (m_requests)
103 m_requests.Enqueue(req);
104 m_ev.Set();
105 }
106
107 public void ThreadStart()
108 {
109 while (m_running)
110 {
111 m_ev.WaitOne(1000);
112 m_ev.Reset();
113 Watchdog.UpdateThread();
114 ProcessQueuedRequests();
115 }
116 }
117
118 private void ProcessQueuedRequests()
119 {
120 lock (m_requests)
121 {
122 if (m_requests.Count == 0)
123 return;
124
125// m_log.DebugFormat("[POLL SERVICE REQUEST MANAGER]: Processing {0} requests", m_requests.Count);
126
127 int reqperthread = (int) (m_requests.Count/m_WorkerThreadCount) + 1;
128
129 // For Each WorkerThread
130 for (int tc = 0; tc < m_WorkerThreadCount && m_requests.Count > 0; tc++)
131 {
132 //Loop over number of requests each thread handles.
133 for (int i = 0; i < reqperthread && m_requests.Count > 0; i++)
134 {
135 try
136 {
137 m_PollServiceWorkerThreads[tc].Enqueue((PollServiceHttpRequest)m_requests.Dequeue());
138 }
139 catch (InvalidOperationException)
140 {
141 // The queue is empty, we did our calculations wrong!
142 return;
143 }
144
145 }
146 }
147 }
148
149 }
150
151 public void Stop()
152 {
153 m_running = false;
154
155 foreach (object o in m_requests)
156 {
157 PollServiceHttpRequest req = (PollServiceHttpRequest) o;
158 m_server.DoHTTPGruntWork(
159 req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id),
160 new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext));
161 }
162
163 m_requests.Clear();
164
165 foreach (Thread t in m_workerThreads)
166 {
167 t.Abort();
168 }
169 }
170 }
171}
172 */
173
37using System.IO; 174using System.IO;
38using System.Text; 175using System.Text;
39using System.Collections.Generic; 176using System.Collections.Generic;
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs
new file mode 100644
index 0000000..1c529b6
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs
@@ -0,0 +1,175 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/* Ubit work moved to PollServiceRequestManager
29
30using System;
31using System.Collections;
32using System.Collections.Generic;
33using System.IO;
34using System.Text;
35using HttpServer;
36using OpenMetaverse;
37using System.Reflection;
38using log4net;
39using OpenSim.Framework.Monitoring;
40
41namespace OpenSim.Framework.Servers.HttpServer
42{
43 public delegate void ReQueuePollServiceItem(PollServiceHttpRequest req);
44
45 public class PollServiceWorkerThread
46 {
47 private static readonly ILog m_log =
48 LogManager.GetLogger(
49 MethodBase.GetCurrentMethod().DeclaringType);
50
51 public event ReQueuePollServiceItem ReQueue;
52
53 private readonly BaseHttpServer m_server;
54 private BlockingQueue<PollServiceHttpRequest> m_request;
55 private bool m_running = true;
56 private int m_timeout = 250;
57
58 public PollServiceWorkerThread(BaseHttpServer pSrv, int pTimeout)
59 {
60 m_request = new BlockingQueue<PollServiceHttpRequest>();
61 m_server = pSrv;
62 m_timeout = pTimeout;
63 }
64
65 public void ThreadStart()
66 {
67 Run();
68 }
69
70 public void Run()
71 {
72 while (m_running)
73 {
74 PollServiceHttpRequest req = m_request.Dequeue();
75
76 Watchdog.UpdateThread();
77
78 try
79 {
80 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
81 {
82 StreamReader str;
83 try
84 {
85 str = new StreamReader(req.Request.Body);
86 }
87 catch (System.ArgumentException)
88 {
89 // Stream was not readable means a child agent
90 // was closed due to logout, leaving the
91 // Event Queue request orphaned.
92 continue;
93 }
94
95 try
96 {
97 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id, str.ReadToEnd());
98 DoHTTPGruntWork(m_server, req, responsedata);
99 }
100 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
101 {
102 // Ignore it, no need to reply
103 }
104 }
105 else
106 {
107 if ((Environment.TickCount - req.RequestTime) > m_timeout)
108 {
109 DoHTTPGruntWork(
110 m_server,
111 req,
112 req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
113 }
114 else
115 {
116 ReQueuePollServiceItem reQueueItem = ReQueue;
117 if (reQueueItem != null)
118 reQueueItem(req);
119 }
120 }
121 }
122 catch (Exception e)
123 {
124 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
125 }
126 }
127 }
128
129 internal void Enqueue(PollServiceHttpRequest pPollServiceHttpRequest)
130 {
131 m_request.Enqueue(pPollServiceHttpRequest);
132 }
133
134 /// <summary>
135 /// FIXME: This should be part of BaseHttpServer
136 /// </summary>
137 internal static void DoHTTPGruntWork(BaseHttpServer server, PollServiceHttpRequest req, Hashtable responsedata)
138 {
139 OSHttpResponse response
140 = new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext);
141
142 byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
143
144 response.SendChunked = false;
145 response.ContentLength64 = buffer.Length;
146 response.ContentEncoding = Encoding.UTF8;
147
148 try
149 {
150 response.OutputStream.Write(buffer, 0, buffer.Length);
151 }
152 catch (Exception ex)
153 {
154 m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
155 }
156 finally
157 {
158 //response.OutputStream.Close();
159 try
160 {
161 response.OutputStream.Flush();
162 response.Send();
163
164 //if (!response.KeepAlive && response.ReuseContext)
165 // response.FreeContext();
166 }
167 catch (Exception e)
168 {
169 m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
170 }
171 }
172 }
173 }
174}
175*/ \ No newline at end of file