aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Servers
diff options
context:
space:
mode:
authorMW2007-03-29 11:08:42 +0000
committerMW2007-03-29 11:08:42 +0000
commit17b00785ee10a71d290cbcddca9b0152fdf60c8f (patch)
tree88a78c0b9a0357af823e4ecdad25e09a64569f79 /Servers
parentDoh! need to return the response (diff)
downloadopensim-SC-17b00785ee10a71d290cbcddca9b0152fdf60c8f.zip
opensim-SC-17b00785ee10a71d290cbcddca9b0152fdf60c8f.tar.gz
opensim-SC-17b00785ee10a71d290cbcddca9b0152fdf60c8f.tar.bz2
opensim-SC-17b00785ee10a71d290cbcddca9b0152fdf60c8f.tar.xz
Added lbsa71's http server changes.
So it now has a single http listener that passes incoming requests to the correct handler. This means that logins (in sandbox mode) now go through this listener, which for now is listening on the port you set in startup (default 9000). (This needs changing so that the http listener and udp server are not using the same port)
Diffstat (limited to 'Servers')
-rw-r--r--Servers/BaseHttpServer.cs201
-rw-r--r--Servers/IRestHandler.cs11
-rw-r--r--Servers/OpenSim.Servers.csproj2
-rw-r--r--Servers/OpenSim.Servers.dll.build2
-rw-r--r--Servers/XmlRpcMethod.cs7
5 files changed, 223 insertions, 0 deletions
diff --git a/Servers/BaseHttpServer.cs b/Servers/BaseHttpServer.cs
index 28849dc..bac7e86 100644
--- a/Servers/BaseHttpServer.cs
+++ b/Servers/BaseHttpServer.cs
@@ -1,10 +1,211 @@
1using System; 1using System;
2using System.Collections.Generic; 2using System.Collections.Generic;
3using System.Net;
3using System.Text; 4using System.Text;
5using System.Text.RegularExpressions;
6using System.Threading;
7using OpenSim.CAPS;
8using Nwc.XmlRpc;
9using System.Collections;
4 10
5namespace OpenSim.Servers 11namespace OpenSim.Servers
6{ 12{
7 public class BaseHttpServer 13 public class BaseHttpServer
8 { 14 {
15 protected Thread m_workerThread;
16 protected HttpListener m_httpListener;
17 protected Dictionary<string, IRestHandler> m_restHandlers = new Dictionary<string, IRestHandler>();
18 protected Dictionary<string, XmlRpcMethod> m_rpcHandlers = new Dictionary<string, XmlRpcMethod>();
19 protected int m_port;
20
21 public BaseHttpServer(int port)
22 {
23 m_port = port;
24 }
25
26 public bool AddRestHandler(string path, IRestHandler handler)
27 {
28 if (!this.m_restHandlers.ContainsKey(path))
29 {
30 this.m_restHandlers.Add(path, handler);
31 return true;
32 }
33
34 //must already have a handler for that path so return false
35 return false;
36 }
37
38 public bool AddXmlRPCHandler(string method, XmlRpcMethod handler)
39 {
40 if (!this.m_rpcHandlers.ContainsKey(method))
41 {
42 this.m_rpcHandlers.Add(method, handler);
43 return true;
44 }
45
46 //must already have a handler for that path so return false
47 return false;
48 }
49
50 protected virtual string ProcessXMLRPCMethod(string methodName, XmlRpcRequest request)
51 {
52 XmlRpcResponse response;
53
54 XmlRpcMethod method;
55 if( this.m_rpcHandlers.TryGetValue( methodName, out method ) )
56 {
57 response = method(request);
58 }
59 else
60 {
61 response = new XmlRpcResponse();
62 Hashtable unknownMethodError = new Hashtable();
63 unknownMethodError["reason"] = "XmlRequest"; ;
64 unknownMethodError["message"] = "Unknown Rpc request";
65 unknownMethodError["login"] = "false";
66 response.Value = unknownMethodError;
67 }
68
69 return XmlRpcResponseSerializer.Singleton.Serialize(response);
70 }
71
72 protected virtual string ParseREST(string requestBody, string requestURL, string requestMethod)
73 {
74 string[] path;
75 string pathDelimStr = "/";
76 char[] pathDelimiter = pathDelimStr.ToCharArray();
77 path = requestURL.Split(pathDelimiter);
78
79 string responseString = "";
80
81 //path[0] should be empty so we are interested in path[1]
82 if (path.Length > 1)
83 {
84 if ((path[1] != "") && (this.m_restHandlers.ContainsKey(path[1])))
85 {
86 responseString = this.m_restHandlers[path[1]].HandleREST(requestBody, requestURL, requestMethod);
87 }
88 }
89
90 return responseString;
91 }
92
93 protected virtual string ParseLLSDXML(string requestBody)
94 {
95 // dummy function for now - IMPLEMENT ME!
96 return "";
97 }
98
99 protected virtual string ParseXMLRPC(string requestBody)
100 {
101 string responseString = String.Empty;
102
103 try
104 {
105 XmlRpcRequest request = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(requestBody);
106
107 string methodName = request.MethodName;
108
109 responseString = ProcessXMLRPCMethod(methodName, request );
110 }
111 catch (Exception e)
112 {
113 Console.WriteLine(e.ToString());
114 }
115 return responseString;
116 }
117
118 public virtual void HandleRequest(Object stateinfo)
119 {
120 HttpListenerContext context = (HttpListenerContext)stateinfo;
121
122 HttpListenerRequest request = context.Request;
123 HttpListenerResponse response = context.Response;
124
125 response.KeepAlive = false;
126 response.SendChunked = false;
127
128 System.IO.Stream body = request.InputStream;
129 System.Text.Encoding encoding = System.Text.Encoding.UTF8;
130 System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding);
131
132 string requestBody = reader.ReadToEnd();
133 body.Close();
134 reader.Close();
135
136 //Console.WriteLine(request.HttpMethod + " " + request.RawUrl + " Http/" + request.ProtocolVersion.ToString() + " content type: " + request.ContentType);
137 //Console.WriteLine(requestBody);
138
139 string responseString = "";
140 switch (request.ContentType)
141 {
142 case "text/xml":
143 // must be XML-RPC, so pass to the XML-RPC parser
144
145 responseString = ParseXMLRPC(requestBody);
146 responseString = Regex.Replace(responseString, "utf-16", "utf-8");
147
148 response.AddHeader("Content-type", "text/xml");
149 break;
150
151 case "application/xml":
152 // probably LLSD we hope, otherwise it should be ignored by the parser
153 responseString = ParseLLSDXML(requestBody);
154 response.AddHeader("Content-type", "application/xml");
155 break;
156
157 case "application/x-www-form-urlencoded":
158 // a form data POST so send to the REST parser
159 responseString = ParseREST(requestBody, request.RawUrl, request.HttpMethod);
160 response.AddHeader("Content-type", "text/html");
161 break;
162
163 case null:
164 // must be REST or invalid crap, so pass to the REST parser
165 responseString = ParseREST(requestBody, request.RawUrl, request.HttpMethod);
166 response.AddHeader("Content-type", "text/html");
167 break;
168
169 }
170
171 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
172 System.IO.Stream output = response.OutputStream;
173 response.SendChunked = false;
174 response.ContentLength64 = buffer.Length;
175 output.Write(buffer, 0, buffer.Length);
176 output.Close();
177 }
178
179 public void Start()
180 {
181 OpenSim.Framework.Console.MainConsole.Instance.WriteLine("BaseHttpServer.cs: Starting up HTTP Server");
182
183 m_workerThread = new Thread(new ThreadStart(StartHTTP));
184 m_workerThread.IsBackground = true;
185 m_workerThread.Start();
186 }
187
188 private void StartHTTP()
189 {
190 try
191 {
192 OpenSim.Framework.Console.MainConsole.Instance.WriteLine("BaseHttpServer.cs: StartHTTP() - Spawned main thread OK");
193 m_httpListener = new HttpListener();
194
195 m_httpListener.Prefixes.Add("http://+:" + m_port + "/");
196 m_httpListener.Start();
197
198 HttpListenerContext context;
199 while (true)
200 {
201 context = m_httpListener.GetContext();
202 ThreadPool.QueueUserWorkItem(new WaitCallback(HandleRequest), context);
203 }
204 }
205 catch (Exception e)
206 {
207 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(e.Message);
208 }
209 }
9 } 210 }
10} 211}
diff --git a/Servers/IRestHandler.cs b/Servers/IRestHandler.cs
new file mode 100644
index 0000000..f269600
--- /dev/null
+++ b/Servers/IRestHandler.cs
@@ -0,0 +1,11 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4
5namespace OpenSim.CAPS
6{
7 public interface IRestHandler
8 {
9 string HandleREST(string requestBody, string requestURL, string requestMethod);
10 }
11}
diff --git a/Servers/OpenSim.Servers.csproj b/Servers/OpenSim.Servers.csproj
index c983fca..9710f47 100644
--- a/Servers/OpenSim.Servers.csproj
+++ b/Servers/OpenSim.Servers.csproj
@@ -96,6 +96,8 @@
96 <Compile Include="BaseHttpServer.cs"> 96 <Compile Include="BaseHttpServer.cs">
97 <SubType>Code</SubType> 97 <SubType>Code</SubType>
98 </Compile> 98 </Compile>
99 <Compile Include="IRestHandler.cs" />
100 <Compile Include="XmlRpcMethod.cs" />
99 </ItemGroup> 101 </ItemGroup>
100 <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> 102 <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
101 <PropertyGroup> 103 <PropertyGroup>
diff --git a/Servers/OpenSim.Servers.dll.build b/Servers/OpenSim.Servers.dll.build
index 8600ab5..48e8dec 100644
--- a/Servers/OpenSim.Servers.dll.build
+++ b/Servers/OpenSim.Servers.dll.build
@@ -12,6 +12,8 @@
12 </resources> 12 </resources>
13 <sources failonempty="true"> 13 <sources failonempty="true">
14 <include name="BaseHttpServer.cs" /> 14 <include name="BaseHttpServer.cs" />
15 <include name="IRestHandler.cs" />
16 <include name="XmlRpcMethod.cs" />
15 </sources> 17 </sources>
16 <references basedir="${project::get-base-directory()}"> 18 <references basedir="${project::get-base-directory()}">
17 <lib> 19 <lib>
diff --git a/Servers/XmlRpcMethod.cs b/Servers/XmlRpcMethod.cs
new file mode 100644
index 0000000..2295405
--- /dev/null
+++ b/Servers/XmlRpcMethod.cs
@@ -0,0 +1,7 @@
1using System;
2using Nwc.XmlRpc;
3
4namespace OpenSim.Servers
5{
6 public delegate XmlRpcResponse XmlRpcMethod( XmlRpcRequest request );
7}