clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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 using System;
29 using System.Collections;
30 using System.Collections.Specialized;
31 using System.IO;
32 using System.IO.Compression;
33 using System.Reflection;
34 using System.Net;
35 using System.Text;
36 using System.Web;
37  
38 using OpenSim.Server.Base;
39 using OpenSim.Server.Handlers.Base;
40 using OpenSim.Services.Interfaces;
41 using GridRegion = OpenSim.Services.Interfaces.GridRegion;
42 using OpenSim.Framework;
43 using OpenSim.Framework.Servers.HttpServer;
44  
45 using OpenMetaverse;
46 using OpenMetaverse.StructuredData;
47 using Nini.Config;
48 using log4net;
49  
50  
51 namespace OpenSim.Server.Handlers.Simulation
52 {
53 public class AgentHandler
54 {
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56  
57 private ISimulationService m_SimulationService;
58  
59 public AgentHandler() { }
60  
61 public AgentHandler(ISimulationService sim)
62 {
63 m_SimulationService = sim;
64 }
65  
66 public Hashtable Handler(Hashtable request)
67 {
68 // m_log.Debug("[CONNECTION DEBUGGING]: AgentHandler Called");
69 //
70 // m_log.Debug("---------------------------");
71 // m_log.Debug(" >> uri=" + request["uri"]);
72 // m_log.Debug(" >> content-type=" + request["content-type"]);
73 // m_log.Debug(" >> http-method=" + request["http-method"]);
74 // m_log.Debug("---------------------------\n");
75  
76 Hashtable responsedata = new Hashtable();
77 responsedata["content_type"] = "text/html";
78 responsedata["keepalive"] = false;
79  
80  
81 UUID agentID;
82 UUID regionID;
83 string action;
84 if (!Utils.GetParams((string)request["uri"], out agentID, out regionID, out action))
85 {
86 m_log.InfoFormat("[AGENT HANDLER]: Invalid parameters for agent message {0}", request["uri"]);
87 responsedata["int_response_code"] = 404;
88 responsedata["str_response_string"] = "false";
89  
90 return responsedata;
91 }
92  
93 // Next, let's parse the verb
94 string method = (string)request["http-method"];
95 if (method.Equals("DELETE"))
96 {
97 string auth_token = string.Empty;
98 if (request.ContainsKey("auth"))
99 auth_token = request["auth"].ToString();
100  
101 DoAgentDelete(request, responsedata, agentID, action, regionID, auth_token);
102 return responsedata;
103 }
104 else if (method.Equals("QUERYACCESS"))
105 {
106 DoQueryAccess(request, responsedata, agentID, regionID);
107 return responsedata;
108 }
109 else
110 {
111 m_log.ErrorFormat("[AGENT HANDLER]: method {0} not supported in agent message {1} (caller is {2})", method, (string)request["uri"], Util.GetCallerIP(request));
112 responsedata["int_response_code"] = HttpStatusCode.MethodNotAllowed;
113 responsedata["str_response_string"] = "Method not allowed";
114  
115 return responsedata;
116 }
117  
118 }
119  
120 protected virtual void DoQueryAccess(Hashtable request, Hashtable responsedata, UUID agentID, UUID regionID)
121 {
122 if (m_SimulationService == null)
123 {
124 m_log.Debug("[AGENT HANDLER]: Agent QUERY called. Harmless but useless.");
125 responsedata["content_type"] = "application/json";
126 responsedata["int_response_code"] = HttpStatusCode.NotImplemented;
127 responsedata["str_response_string"] = string.Empty;
128  
129 return;
130 }
131  
132 // m_log.DebugFormat("[AGENT HANDLER]: Received QUERYACCESS with {0}", (string)request["body"]);
133 OSDMap args = Utils.GetOSDMap((string)request["body"]);
134  
135 bool viaTeleport = true;
136 if (args.ContainsKey("viaTeleport"))
137 viaTeleport = args["viaTeleport"].AsBoolean();
138  
139 Vector3 position = Vector3.Zero;
140 if (args.ContainsKey("position"))
141 position = Vector3.Parse(args["position"].AsString());
142  
143 string agentHomeURI = null;
144 if (args.ContainsKey("agent_home_uri"))
145 agentHomeURI = args["agent_home_uri"].AsString();
146  
147 string theirVersion = string.Empty;
148 if (args.ContainsKey("my_version"))
149 theirVersion = args["my_version"].AsString();
150  
151 GridRegion destination = new GridRegion();
152 destination.RegionID = regionID;
153  
154 string reason;
155 string version;
156 bool result = m_SimulationService.QueryAccess(destination, agentID, agentHomeURI, viaTeleport, position, theirVersion, out version, out reason);
157  
158 responsedata["int_response_code"] = HttpStatusCode.OK;
159  
160 OSDMap resp = new OSDMap(3);
161  
162 resp["success"] = OSD.FromBoolean(result);
163 resp["reason"] = OSD.FromString(reason);
164 resp["version"] = OSD.FromString(version);
165  
166 // We must preserve defaults here, otherwise a false "success" will not be put into the JSON map!
167 responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp, true);
168  
169 // Console.WriteLine("str_response_string [{0}]", responsedata["str_response_string"]);
170 }
171  
172 protected void DoAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, UUID regionID, string auth_token)
173 {
174 if (string.IsNullOrEmpty(action))
175 m_log.DebugFormat("[AGENT HANDLER]: >>> DELETE <<< RegionID: {0}; from: {1}; auth_code: {2}", regionID, Util.GetCallerIP(request), auth_token);
176 else
177 m_log.DebugFormat("[AGENT HANDLER]: Release {0} to RegionID: {1}", id, regionID);
178  
179 GridRegion destination = new GridRegion();
180 destination.RegionID = regionID;
181  
182 if (action.Equals("release"))
183 ReleaseAgent(regionID, id);
184 else
185 Util.FireAndForget(delegate { m_SimulationService.CloseAgent(destination, id, auth_token); });
186  
187 responsedata["int_response_code"] = HttpStatusCode.OK;
188 responsedata["str_response_string"] = "OpenSim agent " + id.ToString();
189  
190 //m_log.DebugFormat("[AGENT HANDLER]: Agent {0} Released/Deleted from region {1}", id, regionID);
191 }
192  
193 protected virtual void ReleaseAgent(UUID regionID, UUID id)
194 {
195 m_SimulationService.ReleaseAgent(regionID, id, "");
196 }
197 }
198  
199 public class AgentPostHandler : BaseStreamHandler
200 {
201 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
202  
203 private ISimulationService m_SimulationService;
204 protected bool m_Proxy = false;
205  
206 public AgentPostHandler(ISimulationService service) :
207 base("POST", "/agent")
208 {
209 m_SimulationService = service;
210 }
211  
212 public AgentPostHandler(string path) :
213 base("POST", path)
214 {
215 m_SimulationService = null;
216 }
217  
218 protected override byte[] ProcessRequest(string path, Stream request,
219 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
220 {
221 // m_log.DebugFormat("[SIMULATION]: Stream handler called");
222  
223 Hashtable keysvals = new Hashtable();
224 Hashtable headervals = new Hashtable();
225  
226 string[] querystringkeys = httpRequest.QueryString.AllKeys;
227 string[] rHeaders = httpRequest.Headers.AllKeys;
228  
229 keysvals.Add("uri", httpRequest.RawUrl);
230 keysvals.Add("content-type", httpRequest.ContentType);
231 keysvals.Add("http-method", httpRequest.HttpMethod);
232  
233 foreach (string queryname in querystringkeys)
234 keysvals.Add(queryname, httpRequest.QueryString[queryname]);
235  
236 foreach (string headername in rHeaders)
237 headervals[headername] = httpRequest.Headers[headername];
238  
239 keysvals.Add("headers", headervals);
240 keysvals.Add("querystringkeys", querystringkeys);
241  
242 httpResponse.StatusCode = 200;
243 httpResponse.ContentType = "text/html";
244 httpResponse.KeepAlive = false;
245 Encoding encoding = Encoding.UTF8;
246  
247 if (httpRequest.ContentType != "application/json")
248 {
249 httpResponse.StatusCode = 406;
250 return encoding.GetBytes("false");
251 }
252  
253 string requestBody;
254  
255 Stream inputStream = request;
256 Stream innerStream = null;
257 try
258 {
259 if ((httpRequest.ContentType == "application/x-gzip" || httpRequest.Headers["Content-Encoding"] == "gzip") || (httpRequest.Headers["X-Content-Encoding"] == "gzip"))
260 {
261 innerStream = inputStream;
262 inputStream = new GZipStream(innerStream, CompressionMode.Decompress);
263 }
264  
265 using (StreamReader reader = new StreamReader(inputStream, encoding))
266 {
267 requestBody = reader.ReadToEnd();
268 }
269 }
270 finally
271 {
272 if (innerStream != null)
273 innerStream.Dispose();
274 inputStream.Dispose();
275 }
276  
277 keysvals.Add("body", requestBody);
278  
279 Hashtable responsedata = new Hashtable();
280  
281 UUID agentID;
282 UUID regionID;
283 string action;
284  
285 if (!Utils.GetParams((string)keysvals["uri"], out agentID, out regionID, out action))
286 {
287 m_log.InfoFormat("[AGENT HANDLER]: Invalid parameters for agent message {0}", keysvals["uri"]);
288  
289 httpResponse.StatusCode = 404;
290  
291 return encoding.GetBytes("false");
292 }
293  
294 DoAgentPost(keysvals, responsedata, agentID);
295  
296 httpResponse.StatusCode = (int)responsedata["int_response_code"];
297 return encoding.GetBytes((string)responsedata["str_response_string"]);
298 }
299  
300 protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id)
301 {
302 OSDMap args = Utils.GetOSDMap((string)request["body"]);
303 if (args == null)
304 {
305 responsedata["int_response_code"] = HttpStatusCode.BadRequest;
306 responsedata["str_response_string"] = "Bad request";
307 return;
308 }
309  
310 AgentDestinationData data = CreateAgentDestinationData();
311 UnpackData(args, data, request);
312  
313 GridRegion destination = new GridRegion();
314 destination.RegionID = data.uuid;
315 destination.RegionLocX = data.x;
316 destination.RegionLocY = data.y;
317 destination.RegionName = data.name;
318  
319 GridRegion gatekeeper = ExtractGatekeeper(data);
320  
321 AgentCircuitData aCircuit = new AgentCircuitData();
322 try
323 {
324 aCircuit.UnpackAgentCircuitData(args);
325 }
326 catch (Exception ex)
327 {
328 m_log.InfoFormat("[AGENT HANDLER]: exception on unpacking ChildCreate message {0}", ex.Message);
329 responsedata["int_response_code"] = HttpStatusCode.BadRequest;
330 responsedata["str_response_string"] = "Bad request";
331 return;
332 }
333  
334 GridRegion source = null;
335  
336 if (args.ContainsKey("source_uuid"))
337 {
338 source = new GridRegion();
339 source.RegionLocX = Int32.Parse(args["source_x"].AsString());
340 source.RegionLocY = Int32.Parse(args["source_y"].AsString());
341 source.RegionName = args["source_name"].AsString();
342 source.RegionID = UUID.Parse(args["source_uuid"].AsString());
343  
344 if (args.ContainsKey("source_server_uri"))
345 source.RawServerURI = args["source_server_uri"].AsString();
346 else
347 source.RawServerURI = null;
348 }
349  
350 OSDMap resp = new OSDMap(2);
351 string reason = String.Empty;
352  
353 // This is the meaning of POST agent
354 //m_regionClient.AdjustUserInformation(aCircuit);
355 //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason);
356 bool result = CreateAgent(source, gatekeeper, destination, aCircuit, data.flags, data.fromLogin, out reason);
357  
358 resp["reason"] = OSD.FromString(reason);
359 resp["success"] = OSD.FromBoolean(result);
360 // Let's also send out the IP address of the caller back to the caller (HG 1.5)
361 resp["your_ip"] = OSD.FromString(GetCallerIP(request));
362  
363 // TODO: add reason if not String.Empty?
364 responsedata["int_response_code"] = HttpStatusCode.OK;
365 responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
366 }
367  
368 protected virtual AgentDestinationData CreateAgentDestinationData()
369 {
370 return new AgentDestinationData();
371 }
372  
373 protected virtual void UnpackData(OSDMap args, AgentDestinationData data, Hashtable request)
374 {
375 // retrieve the input arguments
376 if (args.ContainsKey("destination_x") && args["destination_x"] != null)
377 Int32.TryParse(args["destination_x"].AsString(), out data.x);
378 else
379 m_log.WarnFormat(" -- request didn't have destination_x");
380 if (args.ContainsKey("destination_y") && args["destination_y"] != null)
381 Int32.TryParse(args["destination_y"].AsString(), out data.y);
382 else
383 m_log.WarnFormat(" -- request didn't have destination_y");
384 if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
385 UUID.TryParse(args["destination_uuid"].AsString(), out data.uuid);
386 if (args.ContainsKey("destination_name") && args["destination_name"] != null)
387 data.name = args["destination_name"].ToString();
388 if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null)
389 data.flags = args["teleport_flags"].AsUInteger();
390 }
391  
392 protected virtual GridRegion ExtractGatekeeper(AgentDestinationData data)
393 {
394 return null;
395 }
396  
397 protected string GetCallerIP(Hashtable request)
398 {
399 if (!m_Proxy)
400 return Util.GetCallerIP(request);
401  
402 // We're behind a proxy
403 Hashtable headers = (Hashtable)request["headers"];
404  
405 //// DEBUG
406 //foreach (object o in headers.Keys)
407 // m_log.DebugFormat("XXX {0} = {1}", o.ToString(), (headers[o] == null? "null" : headers[o].ToString()));
408  
409 string xff = "X-Forwarded-For";
410 if (headers.ContainsKey(xff.ToLower()))
411 xff = xff.ToLower();
412  
413 if (!headers.ContainsKey(xff) || headers[xff] == null)
414 {
415 m_log.WarnFormat("[AGENT HANDLER]: No XFF header");
416 return Util.GetCallerIP(request);
417 }
418  
419 m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]);
420  
421 IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]);
422 if (ep != null)
423 return ep.Address.ToString();
424  
425 // Oops
426 return Util.GetCallerIP(request);
427 }
428  
429 // subclasses can override this
430 protected virtual bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination,
431 AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
432 {
433 return m_SimulationService.CreateAgent(source, destination, aCircuit, teleportFlags, out reason);
434 }
435 }
436  
437 public class AgentPutHandler : BaseStreamHandler
438 {
439 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
440  
441 private ISimulationService m_SimulationService;
442 protected bool m_Proxy = false;
443  
444 public AgentPutHandler(ISimulationService service) :
445 base("PUT", "/agent")
446 {
447 m_SimulationService = service;
448 }
449  
450 public AgentPutHandler(string path) :
451 base("PUT", path)
452 {
453 m_SimulationService = null;
454 }
455  
456 protected override byte[] ProcessRequest(string path, Stream request,
457 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
458 {
459 // m_log.DebugFormat("[SIMULATION]: Stream handler called");
460  
461 Hashtable keysvals = new Hashtable();
462 Hashtable headervals = new Hashtable();
463  
464 string[] querystringkeys = httpRequest.QueryString.AllKeys;
465 string[] rHeaders = httpRequest.Headers.AllKeys;
466  
467 keysvals.Add("uri", httpRequest.RawUrl);
468 keysvals.Add("content-type", httpRequest.ContentType);
469 keysvals.Add("http-method", httpRequest.HttpMethod);
470  
471 foreach (string queryname in querystringkeys)
472 keysvals.Add(queryname, httpRequest.QueryString[queryname]);
473  
474 foreach (string headername in rHeaders)
475 headervals[headername] = httpRequest.Headers[headername];
476  
477 keysvals.Add("headers", headervals);
478 keysvals.Add("querystringkeys", querystringkeys);
479  
480 String requestBody;
481 Encoding encoding = Encoding.UTF8;
482  
483 Stream inputStream = request;
484 Stream innerStream = null;
485 try
486 {
487 if ((httpRequest.ContentType == "application/x-gzip" || httpRequest.Headers["Content-Encoding"] == "gzip") || (httpRequest.Headers["X-Content-Encoding"] == "gzip"))
488 {
489 innerStream = inputStream;
490 inputStream = new GZipStream(innerStream, CompressionMode.Decompress);
491 }
492  
493 using (StreamReader reader = new StreamReader(inputStream, encoding))
494 {
495 requestBody = reader.ReadToEnd();
496 }
497 }
498 finally
499 {
500 if (innerStream != null)
501 innerStream.Dispose();
502 inputStream.Dispose();
503 }
504  
505 keysvals.Add("body", requestBody);
506  
507 httpResponse.StatusCode = 200;
508 httpResponse.ContentType = "text/html";
509 httpResponse.KeepAlive = false;
510  
511 Hashtable responsedata = new Hashtable();
512  
513 UUID agentID;
514 UUID regionID;
515 string action;
516  
517 if (!Utils.GetParams((string)keysvals["uri"], out agentID, out regionID, out action))
518 {
519 m_log.InfoFormat("[AGENT HANDLER]: Invalid parameters for agent message {0}", keysvals["uri"]);
520  
521 httpResponse.StatusCode = 404;
522  
523 return encoding.GetBytes("false");
524 }
525  
526 DoAgentPut(keysvals, responsedata);
527  
528 httpResponse.StatusCode = (int)responsedata["int_response_code"];
529 return encoding.GetBytes((string)responsedata["str_response_string"]);
530 }
531  
532 protected void DoAgentPut(Hashtable request, Hashtable responsedata)
533 {
534 OSDMap args = Utils.GetOSDMap((string)request["body"]);
535 if (args == null)
536 {
537 responsedata["int_response_code"] = HttpStatusCode.BadRequest;
538 responsedata["str_response_string"] = "Bad request";
539 return;
540 }
541  
542 // retrieve the input arguments
543 int x = 0, y = 0;
544 UUID uuid = UUID.Zero;
545 string regionname = string.Empty;
546 if (args.ContainsKey("destination_x") && args["destination_x"] != null)
547 Int32.TryParse(args["destination_x"].AsString(), out x);
548 if (args.ContainsKey("destination_y") && args["destination_y"] != null)
549 Int32.TryParse(args["destination_y"].AsString(), out y);
550 if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
551 UUID.TryParse(args["destination_uuid"].AsString(), out uuid);
552 if (args.ContainsKey("destination_name") && args["destination_name"] != null)
553 regionname = args["destination_name"].ToString();
554  
555 GridRegion destination = new GridRegion();
556 destination.RegionID = uuid;
557 destination.RegionLocX = x;
558 destination.RegionLocY = y;
559 destination.RegionName = regionname;
560  
561 string messageType;
562 if (args["message_type"] != null)
563 messageType = args["message_type"].AsString();
564 else
565 {
566 m_log.Warn("[AGENT HANDLER]: Agent Put Message Type not found. ");
567 messageType = "AgentData";
568 }
569  
570 bool result = true;
571 if ("AgentData".Equals(messageType))
572 {
573 AgentData agent = new AgentData();
574 try
575 {
576 agent.Unpack(args, m_SimulationService.GetScene(destination.RegionID));
577 }
578 catch (Exception ex)
579 {
580 m_log.InfoFormat("[AGENT HANDLER]: exception on unpacking ChildAgentUpdate message {0}", ex.Message);
581 responsedata["int_response_code"] = HttpStatusCode.BadRequest;
582 responsedata["str_response_string"] = "Bad request";
583 return;
584 }
585  
586 //agent.Dump();
587 // This is one of the meanings of PUT agent
588 result = UpdateAgent(destination, agent);
589 }
590 else if ("AgentPosition".Equals(messageType))
591 {
592 AgentPosition agent = new AgentPosition();
593 try
594 {
595 agent.Unpack(args, m_SimulationService.GetScene(destination.RegionID));
596 }
597 catch (Exception ex)
598 {
599 m_log.InfoFormat("[AGENT HANDLER]: exception on unpacking ChildAgentUpdate message {0}", ex.Message);
600 return;
601 }
602 //agent.Dump();
603 // This is one of the meanings of PUT agent
604 result = m_SimulationService.UpdateAgent(destination, agent);
605  
606 }
607  
608 responsedata["int_response_code"] = HttpStatusCode.OK;
609 responsedata["str_response_string"] = result.ToString();
610 //responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); ??? instead
611 }
612  
613 // subclasses can override this
614 protected virtual bool UpdateAgent(GridRegion destination, AgentData agent)
615 {
616 return m_SimulationService.UpdateAgent(destination, agent);
617 }
618 }
619  
620 public class AgentDestinationData
621 {
622 public int x;
623 public int y;
624 public string name;
625 public UUID uuid;
626 public uint flags;
627 public bool fromLogin;
628 }
629 }