diff options
Diffstat (limited to 'OpenSim/Framework/Servers/BaseHttpServer.cs')
-rw-r--r-- | OpenSim/Framework/Servers/BaseHttpServer.cs | 448 |
1 files changed, 224 insertions, 224 deletions
diff --git a/OpenSim/Framework/Servers/BaseHttpServer.cs b/OpenSim/Framework/Servers/BaseHttpServer.cs index f790477..4b3b3de 100644 --- a/OpenSim/Framework/Servers/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/BaseHttpServer.cs | |||
@@ -1,224 +1,224 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://www.openmetaverse.org/ | 2 | * Copyright (c) Contributors, http://www.openmetaverse.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyright | 9 | * * Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of the OpenSim Project nor the | 12 | * * Neither the name of the OpenSim Project nor the |
13 | * names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | * derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 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 | 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 | 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 | 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. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * | 26 | * |
27 | */ | 27 | */ |
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.IO; | 31 | using System.IO; |
32 | using System.Net; | 32 | using System.Net; |
33 | using System.Text; | 33 | using System.Text; |
34 | using System.Text.RegularExpressions; | 34 | using System.Text.RegularExpressions; |
35 | using System.Threading; | 35 | using System.Threading; |
36 | using Nwc.XmlRpc; | 36 | using Nwc.XmlRpc; |
37 | using OpenSim.Framework.Console; | 37 | using OpenSim.Framework.Console; |
38 | 38 | ||
39 | namespace OpenSim.Framework.Servers | 39 | namespace OpenSim.Framework.Servers |
40 | { | 40 | { |
41 | public class BaseHttpServer | 41 | public class BaseHttpServer |
42 | { | 42 | { |
43 | protected Thread m_workerThread; | 43 | protected Thread m_workerThread; |
44 | protected HttpListener m_httpListener; | 44 | protected HttpListener m_httpListener; |
45 | protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>(); | 45 | protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>(); |
46 | protected Dictionary<string, IStreamHandler> m_streamHandlers = new Dictionary<string, IStreamHandler>(); | 46 | protected Dictionary<string, IStreamHandler> m_streamHandlers = new Dictionary<string, IStreamHandler>(); |
47 | protected int m_port; | 47 | protected int m_port; |
48 | protected bool m_firstcaps = true; | 48 | protected bool m_firstcaps = true; |
49 | 49 | ||
50 | public BaseHttpServer(int port) | 50 | public BaseHttpServer(int port) |
51 | { | 51 | { |
52 | m_port = port; | 52 | m_port = port; |
53 | } | 53 | } |
54 | 54 | ||
55 | public void AddStreamHandler( IStreamHandler handler) | 55 | public void AddStreamHandler( IStreamHandler handler) |
56 | { | 56 | { |
57 | string httpMethod = handler.HttpMethod; | 57 | string httpMethod = handler.HttpMethod; |
58 | string path = handler.Path; | 58 | string path = handler.Path; |
59 | 59 | ||
60 | string handlerKey = GetHandlerKey(httpMethod, path); | 60 | string handlerKey = GetHandlerKey(httpMethod, path); |
61 | m_streamHandlers.Add(handlerKey, handler); | 61 | m_streamHandlers.Add(handlerKey, handler); |
62 | } | 62 | } |
63 | 63 | ||
64 | private static string GetHandlerKey(string httpMethod, string path) | 64 | private static string GetHandlerKey(string httpMethod, string path) |
65 | { | 65 | { |
66 | return httpMethod + ":" + path; | 66 | return httpMethod + ":" + path; |
67 | } | 67 | } |
68 | 68 | ||
69 | public bool AddXmlRPCHandler(string method, XmlRpcMethod handler) | 69 | public bool AddXmlRPCHandler(string method, XmlRpcMethod handler) |
70 | { | 70 | { |
71 | if (!this.m_rpcHandlers.ContainsKey(method)) | 71 | if (!this.m_rpcHandlers.ContainsKey(method)) |
72 | { | 72 | { |
73 | this.m_rpcHandlers.Add(method, handler); | 73 | this.m_rpcHandlers.Add(method, handler); |
74 | return true; | 74 | return true; |
75 | } | 75 | } |
76 | 76 | ||
77 | //must already have a handler for that path so return false | 77 | //must already have a handler for that path so return false |
78 | return false; | 78 | return false; |
79 | } | 79 | } |
80 | 80 | ||
81 | 81 | ||
82 | public virtual void HandleRequest(Object stateinfo) | 82 | public virtual void HandleRequest(Object stateinfo) |
83 | { | 83 | { |
84 | HttpListenerContext context = (HttpListenerContext)stateinfo; | 84 | HttpListenerContext context = (HttpListenerContext)stateinfo; |
85 | 85 | ||
86 | HttpListenerRequest request = context.Request; | 86 | HttpListenerRequest request = context.Request; |
87 | HttpListenerResponse response = context.Response; | 87 | HttpListenerResponse response = context.Response; |
88 | 88 | ||
89 | response.KeepAlive = false; | 89 | response.KeepAlive = false; |
90 | response.SendChunked = false; | 90 | response.SendChunked = false; |
91 | 91 | ||
92 | string path = request.RawUrl; | 92 | string path = request.RawUrl; |
93 | string handlerKey = GetHandlerKey( request.HttpMethod, path ); | 93 | string handlerKey = GetHandlerKey( request.HttpMethod, path ); |
94 | 94 | ||
95 | IStreamHandler streamHandler; | 95 | IStreamHandler streamHandler; |
96 | 96 | ||
97 | if (TryGetStreamHandler( handlerKey, out streamHandler)) | 97 | if (TryGetStreamHandler( handlerKey, out streamHandler)) |
98 | { | 98 | { |
99 | byte[] buffer = streamHandler.Handle(path, request.InputStream); | 99 | byte[] buffer = streamHandler.Handle(path, request.InputStream); |
100 | request.InputStream.Close(); | 100 | request.InputStream.Close(); |
101 | 101 | ||
102 | response.ContentType = streamHandler.ContentType; | 102 | response.ContentType = streamHandler.ContentType; |
103 | response.ContentLength64 = buffer.LongLength; | 103 | response.ContentLength64 = buffer.LongLength; |
104 | response.OutputStream.Write(buffer, 0, buffer.Length); | 104 | response.OutputStream.Write(buffer, 0, buffer.Length); |
105 | response.OutputStream.Close(); | 105 | response.OutputStream.Close(); |
106 | } | 106 | } |
107 | else | 107 | else |
108 | { | 108 | { |
109 | HandleXmlRpcRequests(request, response); | 109 | HandleXmlRpcRequests(request, response); |
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
113 | private bool TryGetStreamHandler(string handlerKey, out IStreamHandler streamHandler) | 113 | private bool TryGetStreamHandler(string handlerKey, out IStreamHandler streamHandler) |
114 | { | 114 | { |
115 | string bestMatch = null; | 115 | string bestMatch = null; |
116 | 116 | ||
117 | foreach (string pattern in m_streamHandlers.Keys) | 117 | foreach (string pattern in m_streamHandlers.Keys) |
118 | { | 118 | { |
119 | if (handlerKey.StartsWith(pattern)) | 119 | if (handlerKey.StartsWith(pattern)) |
120 | { | 120 | { |
121 | if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) | 121 | if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) |
122 | { | 122 | { |
123 | bestMatch = pattern; | 123 | bestMatch = pattern; |
124 | } | 124 | } |
125 | } | 125 | } |
126 | } | 126 | } |
127 | 127 | ||
128 | if (String.IsNullOrEmpty(bestMatch)) | 128 | if (String.IsNullOrEmpty(bestMatch)) |
129 | { | 129 | { |
130 | streamHandler = null; | 130 | streamHandler = null; |
131 | return false; | 131 | return false; |
132 | } | 132 | } |
133 | else | 133 | else |
134 | { | 134 | { |
135 | streamHandler = m_streamHandlers[bestMatch]; | 135 | streamHandler = m_streamHandlers[bestMatch]; |
136 | return true; | 136 | return true; |
137 | } | 137 | } |
138 | } | 138 | } |
139 | 139 | ||
140 | private void HandleXmlRpcRequests(HttpListenerRequest request, HttpListenerResponse response) | 140 | private void HandleXmlRpcRequests(HttpListenerRequest request, HttpListenerResponse response) |
141 | { | 141 | { |
142 | Stream requestStream = request.InputStream; | 142 | Stream requestStream = request.InputStream; |
143 | 143 | ||
144 | Encoding encoding = Encoding.UTF8; | 144 | Encoding encoding = Encoding.UTF8; |
145 | StreamReader reader = new StreamReader(requestStream, encoding); | 145 | StreamReader reader = new StreamReader(requestStream, encoding); |
146 | 146 | ||
147 | string requestBody = reader.ReadToEnd(); | 147 | string requestBody = reader.ReadToEnd(); |
148 | reader.Close(); | 148 | reader.Close(); |
149 | requestStream.Close(); | 149 | requestStream.Close(); |
150 | 150 | ||
151 | XmlRpcRequest xmlRprcRequest = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(requestBody); | 151 | XmlRpcRequest xmlRprcRequest = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(requestBody); |
152 | 152 | ||
153 | string methodName = xmlRprcRequest.MethodName; | 153 | string methodName = xmlRprcRequest.MethodName; |
154 | 154 | ||
155 | XmlRpcResponse xmlRpcResponse; | 155 | XmlRpcResponse xmlRpcResponse; |
156 | 156 | ||
157 | XmlRpcMethod method; | 157 | XmlRpcMethod method; |
158 | if (this.m_rpcHandlers.TryGetValue(methodName, out method)) | 158 | if (this.m_rpcHandlers.TryGetValue(methodName, out method)) |
159 | { | 159 | { |
160 | xmlRpcResponse = method(xmlRprcRequest); | 160 | xmlRpcResponse = method(xmlRprcRequest); |
161 | } | 161 | } |
162 | else | 162 | else |
163 | { | 163 | { |
164 | xmlRpcResponse = new XmlRpcResponse(); | 164 | xmlRpcResponse = new XmlRpcResponse(); |
165 | Hashtable unknownMethodError = new Hashtable(); | 165 | Hashtable unknownMethodError = new Hashtable(); |
166 | unknownMethodError["reason"] = "XmlRequest"; ; | 166 | unknownMethodError["reason"] = "XmlRequest"; ; |
167 | unknownMethodError["message"] = "Unknown Rpc Request ["+methodName+"]"; | 167 | unknownMethodError["message"] = "Unknown Rpc Request ["+methodName+"]"; |
168 | unknownMethodError["login"] = "false"; | 168 | unknownMethodError["login"] = "false"; |
169 | xmlRpcResponse.Value = unknownMethodError; | 169 | xmlRpcResponse.Value = unknownMethodError; |
170 | } | 170 | } |
171 | 171 | ||
172 | response.AddHeader("Content-type", "text/xml"); | 172 | response.AddHeader("Content-type", "text/xml"); |
173 | 173 | ||
174 | string responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse); | 174 | string responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse); |
175 | 175 | ||
176 | byte[] buffer = Encoding.UTF8.GetBytes(responseString); | 176 | byte[] buffer = Encoding.UTF8.GetBytes(responseString); |
177 | 177 | ||
178 | response.SendChunked = false; | 178 | response.SendChunked = false; |
179 | response.ContentLength64 = buffer.Length; | 179 | response.ContentLength64 = buffer.Length; |
180 | response.ContentEncoding = Encoding.UTF8; | 180 | response.ContentEncoding = Encoding.UTF8; |
181 | 181 | ||
182 | response.OutputStream.Write(buffer, 0, buffer.Length); | 182 | response.OutputStream.Write(buffer, 0, buffer.Length); |
183 | response.OutputStream.Close(); | 183 | response.OutputStream.Close(); |
184 | } | 184 | } |
185 | 185 | ||
186 | public void Start() | 186 | public void Start() |
187 | { | 187 | { |
188 | MainLog.Instance.WriteLine(LogPriority.LOW, "BaseHttpServer.cs: Starting up HTTP Server"); | 188 | MainLog.Instance.WriteLine(LogPriority.LOW, "BaseHttpServer.cs: Starting up HTTP Server"); |
189 | 189 | ||
190 | m_workerThread = new Thread(new ThreadStart(StartHTTP)); | 190 | m_workerThread = new Thread(new ThreadStart(StartHTTP)); |
191 | m_workerThread.IsBackground = true; | 191 | m_workerThread.IsBackground = true; |
192 | m_workerThread.Start(); | 192 | m_workerThread.Start(); |
193 | } | 193 | } |
194 | 194 | ||
195 | private void StartHTTP() | 195 | private void StartHTTP() |
196 | { | 196 | { |
197 | try | 197 | try |
198 | { | 198 | { |
199 | MainLog.Instance.WriteLine(LogPriority.LOW, "BaseHttpServer.cs: StartHTTP() - Spawned main thread OK"); | 199 | MainLog.Instance.WriteLine(LogPriority.LOW, "BaseHttpServer.cs: StartHTTP() - Spawned main thread OK"); |
200 | m_httpListener = new HttpListener(); | 200 | m_httpListener = new HttpListener(); |
201 | 201 | ||
202 | m_httpListener.Prefixes.Add("http://+:" + m_port + "/"); | 202 | m_httpListener.Prefixes.Add("http://+:" + m_port + "/"); |
203 | m_httpListener.Start(); | 203 | m_httpListener.Start(); |
204 | 204 | ||
205 | HttpListenerContext context; | 205 | HttpListenerContext context; |
206 | while (true) | 206 | while (true) |
207 | { | 207 | { |
208 | context = m_httpListener.GetContext(); | 208 | context = m_httpListener.GetContext(); |
209 | ThreadPool.QueueUserWorkItem(new WaitCallback(HandleRequest), context); | 209 | ThreadPool.QueueUserWorkItem(new WaitCallback(HandleRequest), context); |
210 | } | 210 | } |
211 | } | 211 | } |
212 | catch (Exception e) | 212 | catch (Exception e) |
213 | { | 213 | { |
214 | MainLog.Instance.WriteLine(LogPriority.MEDIUM, e.Message); | 214 | MainLog.Instance.WriteLine(LogPriority.MEDIUM, e.Message); |
215 | } | 215 | } |
216 | } | 216 | } |
217 | 217 | ||
218 | 218 | ||
219 | public void RemoveStreamHandler(string httpMethod, string path) | 219 | public void RemoveStreamHandler(string httpMethod, string path) |
220 | { | 220 | { |
221 | m_streamHandlers.Remove(GetHandlerKey(httpMethod, path)); | 221 | m_streamHandlers.Remove(GetHandlerKey(httpMethod, path)); |
222 | } | 222 | } |
223 | } | 223 | } |
224 | } | 224 | } |