aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDr Scofield2008-05-19 17:35:29 +0000
committerDr Scofield2008-05-19 17:35:29 +0000
commit3e8adc0d7866fa9dc1b5270d5dbf3994245b6d1c (patch)
treec150d15e9f81555cdd31ad53a874cc2a87042bab
parentAttempt to fix incorrect animations when using ODE (bugs #1320 / #1321) (diff)
downloadopensim-SC-3e8adc0d7866fa9dc1b5270d5dbf3994245b6d1c.zip
opensim-SC-3e8adc0d7866fa9dc1b5270d5dbf3994245b6d1c.tar.gz
opensim-SC-3e8adc0d7866fa9dc1b5270d5dbf3994245b6d1c.tar.bz2
opensim-SC-3e8adc0d7866fa9dc1b5270d5dbf3994245b6d1c.tar.xz
(from awebb)
This patch adds an additional handler to the existing BaseHttpServer. It does not affect any of the existing behaviors except insofar as the new handler may be selected. It is selected first because its Agent-oriented nature means that it should not be pre-empted. The new handler type is defined by IHttpAgentHandler in Framework/Servers and has two interface methods: Match and Handle. The Match function returns a boolean result based upon examination of information presented in the User-Agent header. The Handle function expects to get the request and response instances associated with the flow. The handler is responsible for ALL activity associated with the request except in the event of an unhandled exception, in which case the HandleAgentRequest routine will generate a 500 status message and close the stream. There are two immediateley apparent (and VERY easy to implement) improvements that could be made: 1. The Match call could be allowed to operate over the entire request context., rather than just agent identity. 2. The Handler could return a boolean indication of whether or not the request was actually handled, and if not, the remaining handler mechanism could take a shot at it. This would eliminate issues arising from pre-empted streams.
-rw-r--r--OpenSim/Framework/Servers/BaseHttpServer.cs129
-rw-r--r--OpenSim/Framework/Servers/IHttpAgentHandler.cs39
2 files changed, 142 insertions, 26 deletions
diff --git a/OpenSim/Framework/Servers/BaseHttpServer.cs b/OpenSim/Framework/Servers/BaseHttpServer.cs
index eeb63e1..51cb36e 100644
--- a/OpenSim/Framework/Servers/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/BaseHttpServer.cs
@@ -49,8 +49,9 @@ namespace OpenSim.Framework.Servers
49 protected HttpListener m_httpListener; 49 protected HttpListener m_httpListener;
50 protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>(); 50 protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>();
51 protected LLSDMethod m_llsdHandler = null; 51 protected LLSDMethod m_llsdHandler = null;
52 protected Dictionary<string, IRequestHandler> m_streamHandlers = new Dictionary<string, IRequestHandler>(); 52 protected Dictionary<string, IRequestHandler> m_streamHandlers = new Dictionary<string, IRequestHandler>();
53 protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>(); 53 protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>();
54 protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>();
54 55
55 protected uint m_port; 56 protected uint m_port;
56 protected bool m_ssl = false; 57 protected bool m_ssl = false;
@@ -119,6 +120,18 @@ namespace OpenSim.Framework.Servers
119 return false; 120 return false;
120 } 121 }
121 122
123 public bool AddAgentHandler(string agent, IHttpAgentHandler handler)
124 {
125 if (!m_agentHandlers.ContainsKey(agent))
126 {
127 m_agentHandlers.Add(agent, handler);
128 return true;
129 }
130
131 //must already have a handler for that path so return false
132 return false;
133 }
134
122 public bool SetLLSDHandler(LLSDMethod handler) 135 public bool SetLLSDHandler(LLSDMethod handler)
123 { 136 {
124 m_llsdHandler = handler; 137 m_llsdHandler = handler;
@@ -139,30 +152,43 @@ namespace OpenSim.Framework.Servers
139 OSHttpRequest request = new OSHttpRequest(context.Request); 152 OSHttpRequest request = new OSHttpRequest(context.Request);
140 OSHttpResponse response = new OSHttpResponse(context.Response); 153 OSHttpResponse response = new OSHttpResponse(context.Response);
141 154
142 response.KeepAlive = false; 155 if (request.UserAgent != null)
156 {
157
158 IHttpAgentHandler agentHandler;
159
160 if (TryGetAgentHandler(request.UserAgent, out agentHandler))
161 {
162 m_log.DebugFormat("[HTTP-AGENT] Handler located for {0}", request.UserAgent);
163 HandleAgentRequest(agentHandler, request, response);
164 }
165 return;
166 }
167
168 IRequestHandler requestHandler;
169 response.KeepAlive = false;
143 response.SendChunked = false; 170 response.SendChunked = false;
144 171
145 string path = request.RawUrl; 172 string path = request.RawUrl;
146 string handlerKey = GetHandlerKey(request.HttpMethod, path); 173 string handlerKey = GetHandlerKey(request.HttpMethod, path);
147 174
148 //m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); 175 //m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path);
149 176
150 IRequestHandler requestHandler;
151
152 if (TryGetStreamHandler(handlerKey, out requestHandler)) 177 if (TryGetStreamHandler(handlerKey, out requestHandler))
153 { 178 {
179
154 // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler. 180 // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler.
155 byte[] buffer; 181 byte[] buffer;
156 if (requestHandler is IStreamedRequestHandler) 182 if (requestHandler is IStreamedRequestHandler)
157 { 183 {
158 IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler; 184 IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler;
159 185
160 buffer = streamedRequestHandler.Handle(path, request.InputStream, request, response); 186 buffer = streamedRequestHandler.Handle(path, request.InputStream, request, response);
161 } 187 }
162 else 188 else
163 { 189 {
164 IStreamHandler streamHandler = (IStreamHandler) requestHandler; 190 IStreamHandler streamHandler = (IStreamHandler) requestHandler;
165 191
166 using (MemoryStream memoryStream = new MemoryStream()) 192 using (MemoryStream memoryStream = new MemoryStream())
167 { 193 {
168 streamHandler.Handle(path, request.InputStream, memoryStream, request, response); 194 streamHandler.Handle(path, request.InputStream, memoryStream, request, response);
@@ -170,11 +196,11 @@ namespace OpenSim.Framework.Servers
170 buffer = memoryStream.ToArray(); 196 buffer = memoryStream.ToArray();
171 } 197 }
172 } 198 }
173 199
174 request.InputStream.Close(); 200 request.InputStream.Close();
175 if (!response.IsContentTypeSet) response.ContentType = requestHandler.ContentType; 201 if (!response.IsContentTypeSet) response.ContentType = requestHandler.ContentType;
176 response.ContentLength64 = buffer.LongLength; 202 response.ContentLength64 = buffer.LongLength;
177 203
178 try 204 try
179 { 205 {
180 response.OutputStream.Write(buffer, 0, buffer.Length); 206 response.OutputStream.Write(buffer, 0, buffer.Length);
@@ -184,24 +210,25 @@ namespace OpenSim.Framework.Servers
184 { 210 {
185 m_log.WarnFormat("[BASE HTTP SERVER]: HTTP request abnormally terminated."); 211 m_log.WarnFormat("[BASE HTTP SERVER]: HTTP request abnormally terminated.");
186 } 212 }
213 return;
187 } 214 }
188 else 215
216 switch (request.ContentType)
189 { 217 {
190 switch (request.ContentType) 218 case null:
191 { 219 case "text/html":
192 case null: 220 HandleHTTPRequest(request, response);
193 case "text/html": 221 return;
194 HandleHTTPRequest(request, response); 222
195 break; 223 case "application/xml+llsd":
196 case "application/xml+llsd": 224 HandleLLSDRequests(request, response);
197 HandleLLSDRequests(request, response); 225 return;
198 break; 226
199 case "text/xml": 227 case "text/xml":
200 case "application/xml": 228 case "application/xml":
201 default: 229 default:
202 HandleXmlRpcRequests(request, response); 230 HandleXmlRpcRequests(request, response);
203 break; 231 return;
204 }
205 } 232 }
206 } 233 }
207 catch (SocketException) 234 catch (SocketException)
@@ -274,6 +301,26 @@ namespace OpenSim.Framework.Servers
274 } 301 }
275 } 302 }
276 303
304 private bool TryGetAgentHandler(string agent, out IHttpAgentHandler agentHandler)
305 {
306 agentHandler = null;
307 try
308 {
309 foreach(IHttpAgentHandler handler in m_agentHandlers.Values)
310 {
311 if(handler.Match(agent))
312 {
313 agentHandler = handler;
314 return true;
315 }
316 }
317 }
318 catch(KeyNotFoundException) {}
319
320 return false;
321
322 }
323
277 /// <summary> 324 /// <summary>
278 /// Try all the registered xmlrpc handlers when an xmlrpc request is received. 325 /// Try all the registered xmlrpc handlers when an xmlrpc request is received.
279 /// Sends back an XMLRPC unknown request response if no handler is registered for the requested method. 326 /// Sends back an XMLRPC unknown request response if no handler is registered for the requested method.
@@ -416,6 +463,36 @@ namespace OpenSim.Framework.Servers
416 } 463 }
417 } 464 }
418 465
466 /// <summary>
467 /// A specific agent handler was provided. Such a handler is expecetd to have an
468 /// intimate, and highly specific relationship with the client. Consequently,
469 /// nothing is done here.
470 /// </summary>
471 /// <param name="handler"></param>
472 /// <param name="request"></param>
473 /// <param name="response"></param>
474
475 private void HandleAgentRequest(IHttpAgentHandler handler, OSHttpRequest request, OSHttpResponse response)
476 {
477
478 // In the case of REST, then handler is responsible for ALL aspects of
479 // the request/response handling. Nothing is done here, not even encoding.
480
481 try
482 {
483 handler.Handle(request, response);
484 }
485 catch (Exception e)
486 {
487 m_log.Warn("[HTTP-AGENT]: Error - " + e.Message);
488 response.SendChunked = false;
489 response.KeepAlive = false;
490 response.StatusCode = 500;
491 response.OutputStream.Close();
492 }
493
494 }
495
419 public void HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response) 496 public void HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
420 { 497 {
421 switch (request.HttpMethod) 498 switch (request.HttpMethod)
diff --git a/OpenSim/Framework/Servers/IHttpAgentHandler.cs b/OpenSim/Framework/Servers/IHttpAgentHandler.cs
new file mode 100644
index 0000000..9bca150
--- /dev/null
+++ b/OpenSim/Framework/Servers/IHttpAgentHandler.cs
@@ -0,0 +1,39 @@
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 OpenSim 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
28using System.Collections;
29using System.IO;
30using System.Net;
31
32namespace OpenSim.Framework.Servers
33{
34 public interface IHttpAgentHandler
35 {
36 void Handle(OSHttpRequest req, OSHttpResponse resp);
37 bool Match(string agent);
38 }
39}