OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
AgentHandlers.cs
Go to the documentation of this file.
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.Generic;
31 using System.Collections.Specialized;
32 using System.IO;
33 using System.IO.Compression;
34 using System.Reflection;
35 using System.Net;
36 using System.Text;
37 using System.Web;
38 
39 using OpenSim.Server.Base;
40 using OpenSim.Server.Handlers.Base;
41 using OpenSim.Services.Interfaces;
43 using OpenSim.Framework;
44 using OpenSim.Framework.Servers.HttpServer;
45 
46 using OpenMetaverse;
47 using OpenMetaverse.StructuredData;
48 using Nini.Config;
49 using log4net;
50 
51 
52 namespace OpenSim.Server.Handlers.Simulation
53 {
54  public class AgentHandler
55  {
56  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57 
58  private ISimulationService m_SimulationService;
59 
60  public AgentHandler() { }
61 
63  {
64  m_SimulationService = sim;
65  }
66 
67  public Hashtable Handler(Hashtable request)
68  {
69 // m_log.Debug("[CONNECTION DEBUGGING]: AgentHandler Called");
70 //
71 // m_log.Debug("---------------------------");
72 // m_log.Debug(" >> uri=" + request["uri"]);
73 // m_log.Debug(" >> content-type=" + request["content-type"]);
74 // m_log.Debug(" >> http-method=" + request["http-method"]);
75 // m_log.Debug("---------------------------\n");
76 
77  Hashtable responsedata = new Hashtable();
78  responsedata["content_type"] = "text/html";
79  responsedata["keepalive"] = false;
80 
81 
82  UUID agentID;
83  UUID regionID;
84  string action;
85  if (!Utils.GetParams((string)request["uri"], out agentID, out regionID, out action))
86  {
87  m_log.InfoFormat("[AGENT HANDLER]: Invalid parameters for agent message {0}", request["uri"]);
88  responsedata["int_response_code"] = 404;
89  responsedata["str_response_string"] = "false";
90 
91  return responsedata;
92  }
93 
94  // Next, let's parse the verb
95  string method = (string)request["http-method"];
96  if (method.Equals("DELETE"))
97  {
98  string auth_token = string.Empty;
99  if (request.ContainsKey("auth"))
100  auth_token = request["auth"].ToString();
101 
102  DoAgentDelete(request, responsedata, agentID, action, regionID, auth_token);
103  return responsedata;
104  }
105  else if (method.Equals("QUERYACCESS"))
106  {
107  DoQueryAccess(request, responsedata, agentID, regionID);
108  return responsedata;
109  }
110  else
111  {
112  m_log.ErrorFormat("[AGENT HANDLER]: method {0} not supported in agent message {1} (caller is {2})", method, (string)request["uri"], Util.GetCallerIP(request));
113  responsedata["int_response_code"] = HttpStatusCode.MethodNotAllowed;
114  responsedata["str_response_string"] = "Method not allowed";
115 
116  return responsedata;
117  }
118 
119  }
120 
121  protected virtual void DoQueryAccess(Hashtable request, Hashtable responsedata, UUID agentID, UUID regionID)
122  {
124 
125  if (m_SimulationService == null)
126  {
127  m_log.Debug("[AGENT HANDLER]: Agent QUERY called. Harmless but useless.");
128  responsedata["content_type"] = "application/json";
129  responsedata["int_response_code"] = HttpStatusCode.NotImplemented;
130  responsedata["str_response_string"] = string.Empty;
131 
132  return;
133  }
134 
135  // m_log.DebugFormat("[AGENT HANDLER]: Received QUERYACCESS with {0}", (string)request["body"]);
136  OSDMap args = Utils.GetOSDMap((string)request["body"]);
137 
138  bool viaTeleport = true;
139  if (args.ContainsKey("viaTeleport"))
140  viaTeleport = args["viaTeleport"].AsBoolean();
141 
142  Vector3 position = Vector3.Zero;
143  if (args.ContainsKey("position"))
144  position = Vector3.Parse(args["position"].AsString());
145 
146  string agentHomeURI = null;
147  if (args.ContainsKey("agent_home_uri"))
148  agentHomeURI = args["agent_home_uri"].AsString();
149 
150  // Decode the legacy (string) version and extract the number
151  float theirVersion = 0f;
152  if (args.ContainsKey("my_version"))
153  {
154  string theirVersionStr = args["my_version"].AsString();
155  string[] parts = theirVersionStr.Split(new char[] {'/'});
156  if (parts.Length > 1)
157  theirVersion = float.Parse(parts[1]);
158  }
159 
160  if (args.ContainsKey("context"))
161  ctx.Unpack((OSDMap)args["context"]);
162 
163  // Decode the new versioning data
164  float minVersionRequired = 0f;
165  float maxVersionRequired = 0f;
166  float minVersionProvided = 0f;
167  float maxVersionProvided = 0f;
168 
169  if (args.ContainsKey("simulation_service_supported_min"))
170  minVersionProvided = (float)args["simulation_service_supported_min"].AsReal();
171  if (args.ContainsKey("simulation_service_supported_max"))
172  maxVersionProvided = (float)args["simulation_service_supported_max"].AsReal();
173 
174  if (args.ContainsKey("simulation_service_accepted_min"))
175  minVersionRequired = (float)args["simulation_service_accepted_min"].AsReal();
176  if (args.ContainsKey("simulation_service_accepted_max"))
177  maxVersionRequired = (float)args["simulation_service_accepted_max"].AsReal();
178 
179  responsedata["int_response_code"] = HttpStatusCode.OK;
180  OSDMap resp = new OSDMap(3);
181 
182  float version = 0f;
183 
184  float outboundVersion = 0f;
185  float inboundVersion = 0f;
186 
187  if (minVersionProvided == 0f) // string version or older
188  {
189  // If there is no version in the packet at all we're looking at 0.6 or
190  // even more ancient. Refuse it.
191  if(theirVersion == 0f)
192  {
193  resp["success"] = OSD.FromBoolean(false);
194  resp["reason"] = OSD.FromString("Your region is running a old version of opensim no longer supported. Consider updating it");
195  responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp, true);
196  return;
197  }
198 
199  version = theirVersion;
200 
203  {
204  resp["success"] = OSD.FromBoolean(false);
205  resp["reason"] = OSD.FromString(String.Format("Your region protocol version is {0} and we accept only {1} - {2}. No version overlap.", theirVersion, VersionInfo.SimulationServiceVersionAcceptedMin, VersionInfo.SimulationServiceVersionAcceptedMax));
206  responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp, true);
207  return;
208  }
209  }
210  else
211  {
212  // Test for no overlap
213  if (minVersionProvided > VersionInfo.SimulationServiceVersionAcceptedMax ||
215  {
216  resp["success"] = OSD.FromBoolean(false);
217  resp["reason"] = OSD.FromString(String.Format("Your region provide protocol versions {0} - {1} and we accept only {2} - {3}. No version overlap.", minVersionProvided, maxVersionProvided, VersionInfo.SimulationServiceVersionAcceptedMin, VersionInfo.SimulationServiceVersionAcceptedMax));
218  responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp, true);
219  return;
220  }
221  if (minVersionRequired > VersionInfo.SimulationServiceVersionSupportedMax ||
223  {
224  resp["success"] = OSD.FromBoolean(false);
225  resp["reason"] = OSD.FromString(String.Format("You require region protocol versions {0} - {1} and we provide only {2} - {3}. No version overlap.", minVersionRequired, maxVersionRequired, VersionInfo.SimulationServiceVersionSupportedMin, VersionInfo.SimulationServiceVersionSupportedMax));
226  responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp, true);
227  return;
228  }
229 
230  // Determine versions to use
231  // This is intentionally inverted. Inbound and Outbound refer to the direction of the transfer.
232  // Therefore outbound means from the sender to the receier and inbound means from the receiver to the sender.
233  // So outbound is what we will accept and inbound is what we will send. Confused yet?
234  outboundVersion = Math.Min(maxVersionProvided, VersionInfo.SimulationServiceVersionAcceptedMax);
235  inboundVersion = Math.Min(maxVersionRequired, VersionInfo.SimulationServiceVersionSupportedMax);
236  }
237 
238  List<UUID> features = new List<UUID>();
239 
240  if (args.ContainsKey("features"))
241  {
242  OSDArray array = (OSDArray)args["features"];
243 
244  foreach (OSD o in array)
245  features.Add(new UUID(o.AsString()));
246  }
247 
248  GridRegion destination = new GridRegion();
249  destination.RegionID = regionID;
250 
251  string reason;
252  // We're sending the version numbers down to the local connector to do the varregion check.
253  ctx.InboundVersion = inboundVersion;
254  ctx.OutboundVersion = outboundVersion;
255  if (minVersionProvided == 0f)
256  {
257  ctx.InboundVersion = version;
258  ctx.OutboundVersion = version;
259  }
260 
261  bool result = m_SimulationService.QueryAccess(destination, agentID, agentHomeURI, viaTeleport, position, features, ctx, out reason);
262 
263  resp["success"] = OSD.FromBoolean(result);
264  resp["reason"] = OSD.FromString(reason);
265  string legacyVersion = String.Format("SIMULATION/{0}", version);
266  resp["version"] = OSD.FromString(legacyVersion);
267  resp["negotiated_inbound_version"] = OSD.FromReal(inboundVersion);
268  resp["negotiated_outbound_version"] = OSD.FromReal(outboundVersion);
269 
270  OSDArray featuresWanted = new OSDArray();
271  foreach (UUID feature in features)
272  featuresWanted.Add(OSD.FromString(feature.ToString()));
273 
274  resp["features"] = featuresWanted;
275 
276  // We must preserve defaults here, otherwise a false "success" will not be put into the JSON map!
277  responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp, true);
278 
279 // Console.WriteLine("str_response_string [{0}]", responsedata["str_response_string"]);
280  }
281 
282  protected void DoAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, UUID regionID, string auth_token)
283  {
284  if (string.IsNullOrEmpty(action))
285  m_log.DebugFormat("[AGENT HANDLER]: >>> DELETE <<< RegionID: {0}; from: {1}; auth_code: {2}", regionID, Util.GetCallerIP(request), auth_token);
286  else
287  m_log.DebugFormat("[AGENT HANDLER]: Release {0} to RegionID: {1}", id, regionID);
288 
289  GridRegion destination = new GridRegion();
290  destination.RegionID = regionID;
291 
292  if (action.Equals("release"))
293  ReleaseAgent(regionID, id);
294  else
295  Util.FireAndForget(
296  o => m_SimulationService.CloseAgent(destination, id, auth_token), null, "AgentHandler.DoAgentDelete");
297 
298  responsedata["int_response_code"] = HttpStatusCode.OK;
299  responsedata["str_response_string"] = "OpenSim agent " + id.ToString();
300 
301  //m_log.DebugFormat("[AGENT HANDLER]: Agent {0} Released/Deleted from region {1}", id, regionID);
302  }
303 
304  protected virtual void ReleaseAgent(UUID regionID, UUID id)
305  {
306  m_SimulationService.ReleaseAgent(regionID, id, "");
307  }
308  }
309 
311  {
312  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
313 
314  private ISimulationService m_SimulationService;
315  protected bool m_Proxy = false;
316 
318  base("POST", "/agent")
319  {
320  m_SimulationService = service;
321  }
322 
323  public AgentPostHandler(string path) :
324  base("POST", path)
325  {
326  m_SimulationService = null;
327  }
328 
329  protected override byte[] ProcessRequest(string path, Stream request,
330  IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
331  {
332 // m_log.DebugFormat("[SIMULATION]: Stream handler called");
333 
334  Hashtable keysvals = new Hashtable();
335  Hashtable headervals = new Hashtable();
336 
337  string[] querystringkeys = httpRequest.QueryString.AllKeys;
338  string[] rHeaders = httpRequest.Headers.AllKeys;
339 
340  keysvals.Add("uri", httpRequest.RawUrl);
341  keysvals.Add("content-type", httpRequest.ContentType);
342  keysvals.Add("http-method", httpRequest.HttpMethod);
343 
344  foreach (string queryname in querystringkeys)
345  keysvals.Add(queryname, httpRequest.QueryString[queryname]);
346 
347  foreach (string headername in rHeaders)
348  headervals[headername] = httpRequest.Headers[headername];
349 
350  keysvals.Add("headers", headervals);
351  keysvals.Add("querystringkeys", querystringkeys);
352 
353  httpResponse.StatusCode = 200;
354  httpResponse.ContentType = "text/html";
355  httpResponse.KeepAlive = false;
356  Encoding encoding = Encoding.UTF8;
357 
358  if (httpRequest.ContentType != "application/json")
359  {
360  httpResponse.StatusCode = 406;
361  return encoding.GetBytes("false");
362  }
363 
364  string requestBody;
365 
366  Stream inputStream = request;
367  Stream innerStream = null;
368  try
369  {
370  if ((httpRequest.ContentType == "application/x-gzip" || httpRequest.Headers["Content-Encoding"] == "gzip") || (httpRequest.Headers["X-Content-Encoding"] == "gzip"))
371  {
372  innerStream = inputStream;
373  inputStream = new GZipStream(innerStream, CompressionMode.Decompress);
374  }
375 
376  using (StreamReader reader = new StreamReader(inputStream, encoding))
377  {
378  requestBody = reader.ReadToEnd();
379  }
380  }
381  finally
382  {
383  if (innerStream != null)
384  innerStream.Dispose();
385  inputStream.Dispose();
386  }
387 
388  keysvals.Add("body", requestBody);
389 
390  Hashtable responsedata = new Hashtable();
391 
392  UUID agentID;
393  UUID regionID;
394  string action;
395 
396  if (!Utils.GetParams((string)keysvals["uri"], out agentID, out regionID, out action))
397  {
398  m_log.InfoFormat("[AGENT HANDLER]: Invalid parameters for agent message {0}", keysvals["uri"]);
399 
400  httpResponse.StatusCode = 404;
401 
402  return encoding.GetBytes("false");
403  }
404 
405  DoAgentPost(keysvals, responsedata, agentID);
406 
407  httpResponse.StatusCode = (int)responsedata["int_response_code"];
408  return encoding.GetBytes((string)responsedata["str_response_string"]);
409  }
410 
411  protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id)
412  {
414 
415  OSDMap args = Utils.GetOSDMap((string)request["body"]);
416  if (args == null)
417  {
418  responsedata["int_response_code"] = HttpStatusCode.BadRequest;
419  responsedata["str_response_string"] = "Bad request";
420  return;
421  }
422 
423  if (args.ContainsKey("context"))
424  ctx.Unpack((OSDMap)args["context"]);
425 
426  AgentDestinationData data = CreateAgentDestinationData();
427  UnpackData(args, data, request);
428 
429  GridRegion destination = new GridRegion();
430  destination.RegionID = data.uuid;
431  destination.RegionLocX = data.x;
432  destination.RegionLocY = data.y;
433  destination.RegionName = data.name;
434 
435  GridRegion gatekeeper = ExtractGatekeeper(data);
436 
437  AgentCircuitData aCircuit = new AgentCircuitData();
438  try
439  {
440  aCircuit.UnpackAgentCircuitData(args);
441  }
442  catch (Exception ex)
443  {
444  m_log.InfoFormat("[AGENT HANDLER]: exception on unpacking ChildCreate message {0}", ex.Message);
445  responsedata["int_response_code"] = HttpStatusCode.BadRequest;
446  responsedata["str_response_string"] = "Bad request";
447  return;
448  }
449 
450  GridRegion source = null;
451 
452  if (args.ContainsKey("source_uuid"))
453  {
454  source = new GridRegion();
455  source.RegionLocX = Int32.Parse(args["source_x"].AsString());
456  source.RegionLocY = Int32.Parse(args["source_y"].AsString());
457  source.RegionName = args["source_name"].AsString();
458  source.RegionID = UUID.Parse(args["source_uuid"].AsString());
459 
460  if (args.ContainsKey("source_server_uri"))
461  source.RawServerURI = args["source_server_uri"].AsString();
462  else
463  source.RawServerURI = null;
464  }
465 
466  OSDMap resp = new OSDMap(2);
467  string reason = String.Empty;
468 
469  // This is the meaning of POST agent
470  //m_regionClient.AdjustUserInformation(aCircuit);
471  //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason);
472 
473  bool result = CreateAgent(source, gatekeeper, destination, aCircuit, data.flags, data.fromLogin, ctx, out reason);
474 
475  resp["reason"] = OSD.FromString(reason);
476  resp["success"] = OSD.FromBoolean(result);
477  // Let's also send out the IP address of the caller back to the caller (HG 1.5)
478  resp["your_ip"] = OSD.FromString(GetCallerIP(request));
479 
480  // TODO: add reason if not String.Empty?
481  responsedata["int_response_code"] = HttpStatusCode.OK;
482  responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
483  }
484 
486  {
487  return new AgentDestinationData();
488  }
489 
490  protected virtual void UnpackData(OSDMap args, AgentDestinationData data, Hashtable request)
491  {
492  // retrieve the input arguments
493  if (args.ContainsKey("destination_x") && args["destination_x"] != null)
494  Int32.TryParse(args["destination_x"].AsString(), out data.x);
495  else
496  m_log.WarnFormat(" -- request didn't have destination_x");
497  if (args.ContainsKey("destination_y") && args["destination_y"] != null)
498  Int32.TryParse(args["destination_y"].AsString(), out data.y);
499  else
500  m_log.WarnFormat(" -- request didn't have destination_y");
501  if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
502  UUID.TryParse(args["destination_uuid"].AsString(), out data.uuid);
503  if (args.ContainsKey("destination_name") && args["destination_name"] != null)
504  data.name = args["destination_name"].ToString();
505  if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null)
506  data.flags = args["teleport_flags"].AsUInteger();
507  }
508 
510  {
511  return null;
512  }
513 
514  protected string GetCallerIP(Hashtable request)
515  {
516  if (!m_Proxy)
517  return Util.GetCallerIP(request);
518 
519  // We're behind a proxy
520  Hashtable headers = (Hashtable)request["headers"];
521 
523  //foreach (object o in headers.Keys)
524  // m_log.DebugFormat("XXX {0} = {1}", o.ToString(), (headers[o] == null? "null" : headers[o].ToString()));
525 
526  string xff = "X-Forwarded-For";
527  if (headers.ContainsKey(xff.ToLower()))
528  xff = xff.ToLower();
529 
530  if (!headers.ContainsKey(xff) || headers[xff] == null)
531  {
532  m_log.WarnFormat("[AGENT HANDLER]: No XFF header");
533  return Util.GetCallerIP(request);
534  }
535 
536  m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]);
537 
538  IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]);
539  if (ep != null)
540  return ep.Address.ToString();
541 
542  // Oops
543  return Util.GetCallerIP(request);
544  }
545 
546  // subclasses can override this
547  protected virtual bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination,
548  AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, EntityTransferContext ctx, out string reason)
549  {
550  reason = String.Empty;
551  // The data and protocols are already defined so this is just a dummy to satisfy the interface
552  // TODO: make this end-to-end
553 
554 /* this needs to be sync
555  if ((teleportFlags & (uint)TeleportFlags.ViaLogin) == 0)
556  {
557  Util.FireAndForget(x =>
558  {
559  string r;
560  m_SimulationService.CreateAgent(source, destination, aCircuit, teleportFlags, ctx, out r);
561  m_log.DebugFormat("[AGENT HANDLER]: ASYNC CreateAgent {0}", r);
562  });
563 
564  return true;
565  }
566  else
567  {
568 */
569 
570  bool ret = m_SimulationService.CreateAgent(source, destination, aCircuit, teleportFlags, ctx, out reason);
571 // m_log.DebugFormat("[AGENT HANDLER]: SYNC CreateAgent {0} {1}", ret.ToString(), reason);
572  return ret;
573 // }
574  }
575  }
576 
578  {
579  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
580 
581  private ISimulationService m_SimulationService;
582  protected bool m_Proxy = false;
583 
585  base("PUT", "/agent")
586  {
587  m_SimulationService = service;
588  }
589 
590  public AgentPutHandler(string path) :
591  base("PUT", path)
592  {
593  m_SimulationService = null;
594  }
595 
596  protected override byte[] ProcessRequest(string path, Stream request,
597  IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
598  {
599 // m_log.DebugFormat("[SIMULATION]: Stream handler called");
600 
601  Hashtable keysvals = new Hashtable();
602  Hashtable headervals = new Hashtable();
603 
604  string[] querystringkeys = httpRequest.QueryString.AllKeys;
605  string[] rHeaders = httpRequest.Headers.AllKeys;
606 
607  keysvals.Add("uri", httpRequest.RawUrl);
608  keysvals.Add("content-type", httpRequest.ContentType);
609  keysvals.Add("http-method", httpRequest.HttpMethod);
610 
611  foreach (string queryname in querystringkeys)
612  keysvals.Add(queryname, httpRequest.QueryString[queryname]);
613 
614  foreach (string headername in rHeaders)
615  headervals[headername] = httpRequest.Headers[headername];
616 
617  keysvals.Add("headers", headervals);
618  keysvals.Add("querystringkeys", querystringkeys);
619 
620  String requestBody;
621  Encoding encoding = Encoding.UTF8;
622 
623  Stream inputStream = request;
624  Stream innerStream = null;
625  try
626  {
627  if ((httpRequest.ContentType == "application/x-gzip" || httpRequest.Headers["Content-Encoding"] == "gzip") || (httpRequest.Headers["X-Content-Encoding"] == "gzip"))
628  {
629  innerStream = inputStream;
630  inputStream = new GZipStream(innerStream, CompressionMode.Decompress);
631  }
632 
633  using (StreamReader reader = new StreamReader(inputStream, encoding))
634  {
635  requestBody = reader.ReadToEnd();
636  }
637  }
638  finally
639  {
640  if (innerStream != null)
641  innerStream.Dispose();
642  inputStream.Dispose();
643  }
644 
645  keysvals.Add("body", requestBody);
646 
647  httpResponse.StatusCode = 200;
648  httpResponse.ContentType = "text/html";
649  httpResponse.KeepAlive = false;
650 
651  Hashtable responsedata = new Hashtable();
652 
653  UUID agentID;
654  UUID regionID;
655  string action;
656 
657  if (!Utils.GetParams((string)keysvals["uri"], out agentID, out regionID, out action))
658  {
659  m_log.InfoFormat("[AGENT HANDLER]: Invalid parameters for agent message {0}", keysvals["uri"]);
660 
661  httpResponse.StatusCode = 404;
662 
663  return encoding.GetBytes("false");
664  }
665 
666  DoAgentPut(keysvals, responsedata);
667 
668  httpResponse.StatusCode = (int)responsedata["int_response_code"];
669  return encoding.GetBytes((string)responsedata["str_response_string"]);
670  }
671 
672  protected void DoAgentPut(Hashtable request, Hashtable responsedata)
673  {
674  // TODO: Encode the ENtityTransferContext
676 
677  OSDMap args = Utils.GetOSDMap((string)request["body"]);
678  if (args == null)
679  {
680  responsedata["int_response_code"] = HttpStatusCode.BadRequest;
681  responsedata["str_response_string"] = "Bad request";
682  return;
683  }
684 
685  // retrieve the input arguments
686  int x = 0, y = 0;
687  UUID uuid = UUID.Zero;
688  string regionname = string.Empty;
689  if (args.ContainsKey("destination_x") && args["destination_x"] != null)
690  Int32.TryParse(args["destination_x"].AsString(), out x);
691  if (args.ContainsKey("destination_y") && args["destination_y"] != null)
692  Int32.TryParse(args["destination_y"].AsString(), out y);
693  if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
694  UUID.TryParse(args["destination_uuid"].AsString(), out uuid);
695  if (args.ContainsKey("destination_name") && args["destination_name"] != null)
696  regionname = args["destination_name"].ToString();
697  if (args.ContainsKey("context"))
698  ctx.Unpack((OSDMap)args["context"]);
699 
700  GridRegion destination = new GridRegion();
701  destination.RegionID = uuid;
702  destination.RegionLocX = x;
703  destination.RegionLocY = y;
704  destination.RegionName = regionname;
705 
706  string messageType;
707  if (args["message_type"] != null)
708  messageType = args["message_type"].AsString();
709  else
710  {
711  m_log.Warn("[AGENT HANDLER]: Agent Put Message Type not found. ");
712  messageType = "AgentData";
713  }
714 
715  bool result = true;
716  if ("AgentData".Equals(messageType))
717  {
718  AgentData agent = new AgentData();
719  try
720  {
721  agent.Unpack(args, m_SimulationService.GetScene(destination.RegionID), ctx);
722  }
723  catch (Exception ex)
724  {
725  m_log.InfoFormat("[AGENT HANDLER]: exception on unpacking ChildAgentUpdate message {0}", ex.Message);
726  responsedata["int_response_code"] = HttpStatusCode.BadRequest;
727  responsedata["str_response_string"] = "Bad request";
728  return;
729  }
730 
731  //agent.Dump();
732  // This is one of the meanings of PUT agent
733  result = UpdateAgent(destination, agent);
734  }
735  else if ("AgentPosition".Equals(messageType))
736  {
737  AgentPosition agent = new AgentPosition();
738  try
739  {
740  agent.Unpack(args, m_SimulationService.GetScene(destination.RegionID), ctx);
741  }
742  catch (Exception ex)
743  {
744  m_log.InfoFormat("[AGENT HANDLER]: exception on unpacking ChildAgentUpdate message {0}", ex.Message);
745  return;
746  }
747  //agent.Dump();
748  // This is one of the meanings of PUT agent
749  result = m_SimulationService.UpdateAgent(destination, agent);
750 
751  }
752 
753  responsedata["int_response_code"] = HttpStatusCode.OK;
754  responsedata["str_response_string"] = result.ToString();
755  //responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); ??? instead
756  }
757 
758  // subclasses can override this
759  protected virtual bool UpdateAgent(GridRegion destination, AgentData agent)
760  {
761  // The data and protocols are already defined so this is just a dummy to satisfy the interface
762  // TODO: make this end-to-end
764  return m_SimulationService.UpdateAgent(destination, agent, ctx);
765  }
766  }
767 
768  public class AgentDestinationData
769  {
770  public int x;
771  public int y;
772  public string name;
773  public UUID uuid;
774  public uint flags;
775  public bool fromLogin;
776  }
777 }
virtual GridRegion ExtractGatekeeper(AgentDestinationData data)
OpenMetaverse.StructuredData.OSDArray OSDArray
virtual bool UpdateAgent(GridRegion destination, AgentData agent)
void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id)
override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
OpenMetaverse.StructuredData.OSDMap OSDMap
static readonly float SimulationServiceVersionAcceptedMax
Definition: VersionInfo.cs:88
virtual void ReleaseAgent(UUID regionID, UUID id)
static readonly float SimulationServiceVersionSupportedMin
Definition: VersionInfo.cs:89
Ionic.Zlib.GZipStream GZipStream
virtual bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, EntityTransferContext ctx, out string reason)
string RawServerURI
Provides direct access to the 'm_serverURI' field, without returning a generated URL if m_serverURI i...
void DoAgentPut(Hashtable request, Hashtable responsedata)
virtual void DoQueryAccess(Hashtable request, Hashtable responsedata, UUID agentID, UUID regionID)
static bool GetParams(string uri, out UUID uuid, out UUID regionID, out string action)
Extract the param from an uri.
Definition: Utils.cs:49
virtual void UnpackData(OSDMap args, AgentDestinationData data, Hashtable request)
static readonly float SimulationServiceVersionSupportedMax
Definition: VersionInfo.cs:90
Circuit data for an agent. Connection information shared between regions that accept UDP connections ...
virtual AgentDestinationData CreateAgentDestinationData()
OpenMetaverse.StructuredData.OSD OSD
delegate void UpdateAgent(IClientAPI remoteClient, AgentUpdateArgs agentData)
string GetCallerIP(Hashtable request)
Replacement for ChildAgentDataUpdate. Used over RESTComms and LocalComms.
AgentPostHandler(string path)
static readonly float SimulationServiceVersionAcceptedMin
This rules versioning regarding teleports, and compatibility between simulators in that regard...
Definition: VersionInfo.cs:87
Interactive OpenSim region server
Definition: OpenSim.cs:55
override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
Ionic.Zlib.CompressionMode CompressionMode
AgentPostHandler(ISimulationService service)
OpenSim.Services.Interfaces.GridRegion GridRegion
void DoAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, UUID regionID, string auth_token)