diff options
-rw-r--r-- | OpenSim/Framework/Servers/BaseHttpServer.cs | 129 | ||||
-rw-r--r-- | OpenSim/Framework/Servers/IHttpAgentHandler.cs | 39 |
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 | |||
28 | using System.Collections; | ||
29 | using System.IO; | ||
30 | using System.Net; | ||
31 | |||
32 | namespace OpenSim.Framework.Servers | ||
33 | { | ||
34 | public interface IHttpAgentHandler | ||
35 | { | ||
36 | void Handle(OSHttpRequest req, OSHttpResponse resp); | ||
37 | bool Match(string agent); | ||
38 | } | ||
39 | } | ||